亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

openseadragon.js與deep zoom java實現藝術品圖片展示

2019-11-15 00:19:17
字體:
來源:轉載
供稿:網友
openseadragon.js與deep zoom java實現藝術品圖片展示

openseadragon.js 是一款用來做圖像縮放的插件,它可以用來做圖片展示,做展示的插件很多,也很優秀,但大多數都解決不了圖片尺寸過大的問題。

藝術品圖像展示就是最簡單的例子,展示此類圖片一般要求比較精細,所以圖片尺寸很大,如果按照普通的方式直接將整個圖片加載,要耗費巨大的帶寬。

openseadragon.js 即為此而生,它展示的圖像,必須經過切割處理,當放大圖像時,才去加載更大的尺寸,真正做到了按需加載。

值得一提的是,openseadragon.js是微軟公司的一款開源產品,非常難得。

openseadragon.js用法很簡單。

定義html容器

1 <div id="container" style="width: 100%; height: 600px;"></div>

初始化openseadragon.js

 1 (function(win){ 2     var viewer = OpenSeadragon({ 3         // debugMode: true, 4         id: "container",  //容器id 5         xml",  //openseadragon 圖片資源xml 7         showNavigator:true  //是否顯示控制按鈕 8     }); 9     console.log(viewer);10 })(window);

效果圖

openseadragon

對,你沒有看錯,使用openseadragon.js,只需要copy一段初始化代碼,初始化代碼格式基本固定,只有tileSources是需要變化的,想顯示哪個圖,就寫哪個圖的xml鏈接。

那么這個xml是個什么東西呢?這是微軟定義的一套Deep Zoom技術,或者叫規范,通過圖像分割,然后配上一個xml文件,即可按照用戶縮放的尺寸,按需加載圖像,直到最清晰為止。這本來是微軟Silverlight里的技術,它的JavaScript實現就是openseadragon.js。

筆者從google code上找到了一份java程序,專門用來生成Deep Zoom。筆者在原作基礎上做了一些小小的改進,原作有些錯誤。。。

Deep Zoom For Java

  1 import java.awt.Graphics2D;  2 import java.awt.RenderingHints;  3 import java.awt.image.BufferedImage;  4 import java.io.File;  5 import java.io.FileOutputStream;  6 import java.io.IOException;  7 import java.nio.ByteBuffer;  8 import java.nio.channels.FileChannel;  9 import javax.imageio.ImageIO; 10  11 /** 12  * Deep Zoom Converter 13  *  14  * @author 楊元 15  * 16  */ 17 public class DeepZoomUtil { 18     static final String xmlHeader = "<?xml version=/"1.0/" encoding=/"utf-8/"?>"; 19     static final String schemaName = "http://schemas.microsoft.com/deepzoom/2009"; 20  21     static Boolean deleteExisting = true; 22     static String tileFormat = "jpg"; 23  24     // settings 25     static int tileSize = 256; 26     static int tileOverlap = 1; 27     static Boolean verboseMode = false; 28     static Boolean debugMode = false; 29  30     /** 31      * @param args the command line arguments 32      */ 33     public static void main(String[] args) { 34        35         try { 36             processImageFile(new File("d:/earth.jpg"), new File("d:/earth")); 37         } catch (Exception e) { 38             e.printStackTrace(); 39         } 40     } 41  42     /** 43      * Process the given image file, producing its Deep Zoom output files 44      * in a subdirectory of the given output directory. 45      * @param inFile the file containing the image 46      * @param outputDir the output directory 47      */ 48     private static void processImageFile(File inFile, File outputDir) throws IOException { 49         if (verboseMode) 50              System.out.printf("Processing image file: %s/n", inFile); 51  52         String fileName = inFile.getName(); 53         String nameWithoutExtension = fileName.substring(0, fileName.lastIndexOf('.')); 54         String pathWithoutExtension = outputDir + File.separator + nameWithoutExtension; 55  56         BufferedImage image = loadImage(inFile); 57  58         int originalWidth = image.getWidth(); 59         int originalHeight = image.getHeight(); 60  61         double maxDim = Math.max(originalWidth, originalHeight); 62  63         int nLevels = (int)Math.ceil(Math.log(maxDim) / Math.log(2)); 64  65         if (debugMode) 66             System.out.printf("nLevels=%d/n", nLevels); 67  68         // Delete any existing output files and folders for this image 69  70         File descriptor = new File(pathWithoutExtension + ".xml"); 71         if (descriptor.exists()) { 72             if (deleteExisting) 73                 deleteFile(descriptor); 74             else 75                 throw new IOException("File already exists in output dir: " + descriptor); 76         } 77  78         File imgDir = new File(pathWithoutExtension); 79         if (imgDir.exists()) { 80             if (deleteExisting) { 81                 if (debugMode) 82                     System.out.printf("Deleting directory: %s/n", imgDir); 83                 deleteDir(imgDir); 84             } else 85                 throw new IOException("Image directory already exists in output dir: " + imgDir); 86         } 87  88         imgDir = createDir(outputDir, nameWithoutExtension.concat("_files")); 89  90         double width = originalWidth; 91         double height = originalHeight; 92  93         for (int level = nLevels; level >= 0; level--) { 94             int nCols = (int)Math.ceil(width / tileSize); 95             int nRows = (int)Math.ceil(height / tileSize); 96             if (debugMode) 97                 System.out.printf("level=%d w/h=%f/%f cols/rows=%d/%d/n", 98                                    level, width, height, nCols, nRows); 99             100             File dir = createDir(imgDir, Integer.toString(level));101             for (int col = 0; col < nCols; col++) {102                 for (int row = 0; row < nRows; row++) {103                     BufferedImage tile = getTile(image, row, col);104                     saveImage(tile, dir + File.separator + col + '_' + row);105                 }106             }107 108             // Scale down image for next level109             width = Math.ceil(width / 2);110             height = Math.ceil(height / 2);111             if (width > 10 && height > 10) {112                 // resize in stages to improve quality113                 image = resizeImage(image, width * 1.66, height * 1.66);114                 image = resizeImage(image, width * 1.33, height * 1.33);115             }116             image = resizeImage(image, width, height);117         }118 119         saveImageDescriptor(originalWidth, originalHeight, descriptor);120     }121 122 123     /**124      * Delete a file125      * @param path the path of the directory to be deleted126      */127     private static void deleteFile(File file) throws IOException {128          if (!file.delete())129              throw new IOException("Failed to delete file: " + file);130     }131 132     /**133      * Recursively deletes a directory134      * @param path the path of the directory to be deleted135      */136     private static void deleteDir(File dir) throws IOException {137         if (!dir.isDirectory())138             deleteFile(dir);139         else {140             for (File file : dir.listFiles()) {141                if (file.isDirectory())142                    deleteDir(file);143                else144                    deleteFile(file);145             }146             if (!dir.delete())147                 throw new IOException("Failed to delete directory: " + dir);148         }149     }150 151     /**152      * Creates a directory153      * @param parent the parent directory for the new directory154      * @param name the new directory name155      */156     private static File createDir(File parent, String name) throws IOException {157         assert(parent.isDirectory());158         File result = new File(parent + File.separator + name);159         if (!result.mkdir())160            throw new IOException("Unable to create directory: " + result);161         return result;162     }163 164     /**165      * Loads image from file166      * @param file the file containing the image167      */168     private static BufferedImage loadImage(File file) throws IOException {169         BufferedImage result = null;170         try {171             result = ImageIO.read(file);172         } catch (Exception e) {173             throw new IOException("Cannot read image file: " + file);174         }175         return result;176     }177 178     /**179      * Gets an image containing the tile at the given row and column180      * for the given image.181      * @param img - the input image from whihc the tile is taken182      * @param row - the tile's row (i.e. y) index183      * @param col - the tile's column (i.e. x) index184      */185     private static BufferedImage getTile(BufferedImage img, int row, int col) {186         int x = col * tileSize - (col == 0 ? 0 : tileOverlap);187         int y = row * tileSize - (row == 0 ? 0 : tileOverlap);188         int w = tileSize + (col == 0 ? 1 : 2) * tileOverlap;189         int h = tileSize + (row == 0 ? 1 : 2) * tileOverlap;190 191         if (x + w > img.getWidth())192             w = img.getWidth() - x;193         if (y + h > img.getHeight())194             h = img.getHeight() - y;195 196         if (debugMode)197             System.out.printf("getTile: row=%d, col=%d, x=%d, y=%d, w=%d, h=%d/n",198                               row, col, x, y, w, h);199         200         assert(w > 0);201         assert(h > 0);202 203         BufferedImage result = new BufferedImage(w, h, img.getType());204         Graphics2D g = result.createGraphics();205         g.drawImage(img, 0, 0, w, h, x, y, x+w, y+h, null);206 207         return result;208     }209 210     /**211      * Returns resized image212      * NB - useful reference on high quality image resizing can be found here:213      *   http://today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html214      * @param width the required width215      * @param height the frequired height216      * @param img the image to be resized217      */218     private static BufferedImage resizeImage(BufferedImage img, double width, double height) {219         int w = (int)width;220         int h = (int)height;221         BufferedImage result = new BufferedImage(w, h, img.getType());222         Graphics2D g = result.createGraphics();223         g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,224                            RenderingHints.VALUE_INTERPOLATION_BICUBIC);225         g.drawImage(img, 0, 0, w, h, 0, 0, img.getWidth(), img.getHeight(), null);226         return result;227     }228 229     /**230      * Saves image to the given file231      * @param img the image to be saved232      * @param path the path of the file to which it is saved (less the extension)233      */234     private static void saveImage(BufferedImage img, String path) throws IOException {235         File outputFile = new File(path + "." + tileFormat);236         try {237             ImageIO.write(img, tileFormat, outputFile);238         } catch (IOException e) {239             throw new IOException("Unable to save image file: " + outputFile);240         }241     }242 243     /**244      * Write image descriptor XML file245      * @param width image width246      * @param height image height247      * @param file the file to which it is saved248      */249     private static void saveImageDescriptor(int width, int height, File file) throws IOException {250         StringBuilder sb = new StringBuilder(256);251         sb.append(xmlHeader);252         sb.append("<Image TileSize=/"");253         sb.append(tileSize);254         sb.append("/" Overlap=/"");255         sb.append(tileOverlap);256         sb.append("/" Format=/"");257         sb.append(tileFormat);258         sb.append("/" ServerFormat=/"Default/" xmlns=/"");259         sb.append(schemaName);260         sb.append("/">");261         sb.append("<Size Width=/"");262         sb.append(width);263         sb.append("/" Height=/"");264         sb.append(height);265         sb.append("/" />");266         sb.append("</Image>");267         saveText(sb.toString().getBytes("UTF-8"), file);268     }269 270     /**271      * Saves strings as text to the given file272      * @param bytes the image to be saved273      * @param file the file to which it is saved274      */275     private static void saveText(byte[] bytes, File file) throws IOException {276         try {277             //輸出流278             FileOutputStream fos = new FileOutputStream(file);279             //從輸出流中創建寫通道280             FileChannel writeChannel = fos.getChannel();281             //將既有數組作為buffer內存空間282             ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);283             //將buffer寫到磁盤284             writeChannel.write(byteBuffer);285             286             writeChannel.close();287         } catch (IOException e) {288             throw new IOException("Unable to write to text file: " + file);289         }290     }291 }
View Code

調用非常簡單,只有一句話:processImageFile(new File("d:/earth.jpg"), new File("d:/earth"));,第一個參數是圖片路徑,第二個參數是生成的Deep Zoom保存路徑。本例將會在d:/earth目錄下生成一個earth.xml文件和一個earth_files文件夾,xml的文件名默認和圖片的文件名一致,然后直接把earth.xml的url返回給前端的openseadragon.js,就可以實現圖像縮放。

需要注意的是,*_files文件夾必須和xml文件在同一目錄,并且*要和xml文件名保持一致。

想要預覽openseadragon.js效果,必須在真實的http容器中,不可以直接在文件中打開。

打包的openseadragon.js筆者做了一些UI上的美化,個人覺得漂亮些,如果讀者不喜歡,可以用包里的原版。

openseadragon.js 世界地圖案例

openseadragon.js+java源碼打包下載


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
在线丨暗呦小u女国产精品| 91美女福利视频高清| 91精品久久久久久久久久另类| 亚洲free性xxxx护士白浆| 亚洲人成电影在线观看天堂色| 欧美久久精品一级黑人c片| 日韩高清免费在线| 久久久精品影院| 午夜精品久久久99热福利| 精品久久久久久亚洲精品| 在线观看亚洲区| 91久久久久久久| 亚洲а∨天堂久久精品喷水| 日韩高清有码在线| 国产精品视频免费在线| 亚洲伊人第一页| 欧美激情一区二区三区在线视频观看| 日韩av影视在线| 欧美精品在线观看91| 成人福利视频在线观看| 日韩美女福利视频| 国产精品视频久久久久| 亚洲欧美国产高清va在线播| 91国内在线视频| 欧美另类在线播放| 亚洲自拍偷拍色片视频| 久久久999精品视频| 欧美日韩xxxxx| 精品激情国产视频| 精品美女永久免费视频| 亚洲日韩中文字幕| 日本久久中文字幕| 日韩精品一区二区三区第95| 久久夜精品香蕉| 国产精品∨欧美精品v日韩精品| 久久久欧美一区二区| 欧美日韩激情视频| 亚洲加勒比久久88色综合| 精品久久久久久久久久ntr影视| 国产在线观看精品一区二区三区| 国产成人在线一区二区| 成人黄色免费片| 日韩欧美成人免费视频| 久久久亚洲精选| 日韩精品久久久久久久玫瑰园| 日产精品99久久久久久| 欧美高清无遮挡| 精品福利在线观看| 97色在线视频| 91精品久久久久久久久不口人| 成人av在线天堂| 性金发美女69hd大尺寸| 国产日产欧美精品| 欧美一级淫片aaaaaaa视频| 亚洲欧美一区二区三区久久| 国产香蕉97碰碰久久人人| 中文字幕亚洲第一| 欧美亚洲另类视频| 欧美极品少妇xxxxⅹ喷水| 狠狠做深爱婷婷久久综合一区| 色综合久综合久久综合久鬼88| 国产亚洲欧美视频| 日韩久久午夜影院| 国产不卡在线观看| 中文字幕欧美日韩| 色妞在线综合亚洲欧美| 日韩在线观看免费高清| 亚洲精品欧美一区二区三区| 亚洲福利在线播放| 欧美视频一二三| 欧美成人午夜影院| 久久久国产精品免费| 亚洲日本成人网| 亚洲美女av在线| www.99久久热国产日韩欧美.com| 国产欧美精品在线播放| 亚洲国产高潮在线观看| 97国产suv精品一区二区62| 久久全国免费视频| 久热精品视频在线观看一区| 久久人人爽人人爽爽久久| 欧美激情欧美激情在线五月| 国产日韩欧美成人| 欧美高清不卡在线| 最近2019年手机中文字幕| 91在线视频九色| 日韩av电影在线网| 一本色道久久综合狠狠躁篇的优点| 日韩中文理论片| 国产精品久久久久一区二区| 国产精品久久久久久久久久小说| 亚洲aa中文字幕| 欧美成人精品不卡视频在线观看| 亚洲欧洲第一视频| 欧美高清视频在线播放| 成人免费在线视频网站| 91精品久久久久久久久久入口| 成人两性免费视频| 亚洲国产福利在线| 91夜夜未满十八勿入爽爽影院| 亚洲欧洲第一视频| 久久精品福利视频| 日韩大胆人体377p| 亚洲成人网在线| 久久久免费高清电视剧观看| 久久精品91久久久久久再现| 欧美午夜精品久久久久久久| 国产精品一区二区3区| 日韩中文字幕在线免费观看| 亚洲影院在线看| 久久免费视频在线观看| 日韩欧美亚洲范冰冰与中字| 中文字幕成人在线| 亚洲精品福利在线观看| 啪一啪鲁一鲁2019在线视频| 成人激情综合网| 久久99久久99精品中文字幕| 精品香蕉在线观看视频一| 在线观看国产成人av片| 亚洲免费成人av电影| 久久久久久久久久久av| 久久久精品影院| 色妞色视频一区二区三区四区| 久久视频免费在线播放| 97高清免费视频| 久久久精品一区二区三区| 久久影视三级福利片| 精品一区二区电影| 91精品久久久久久久久久久久久久| 中文字幕精品在线| 国产成人精品视频在线观看| 欧美激情精品久久久久久免费印度| 亚洲精品狠狠操| 亚洲精品www久久久久久广东| 久久久免费电影| 国产亚洲欧洲黄色| xvideos成人免费中文版| 久久精彩免费视频| 国产日韩在线精品av| 国产精品视频yy9099| 欧美日韩在线第一页| 日韩电影在线观看中文字幕| 91成人天堂久久成人| 亚洲国产精品女人久久久| 成人免费淫片视频软件| 91探花福利精品国产自产在线| 欧美黑人巨大xxx极品| 国产成人91久久精品| 久久久久久国产精品美女| 欧美日韩在线视频首页| 久久韩剧网电视剧| 国产精品一区二区久久| 中文字幕欧美日韩在线| 亚洲视频在线观看| 亚洲人成在线观看| 97av在线视频| 精品久久久香蕉免费精品视频| 亚洲欧美一区二区激情| 国产精品aaa| 欧洲午夜精品久久久| 亚洲精品成人久久电影| 中文字幕av一区中文字幕天堂| 亚洲影院污污.| 久久精品亚洲一区|