你的位置:首页 > Java教程

[Java教程]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     prefixUrl: "./lib/openseadragon/images/", //openseadragon插件资源路径 6     tileSources: "./image/earth.//openseadragon 图片资源 7     showNavigator:true //是否显示控制按钮 8   }); 9   console.log(viewer);10 })(window);

 

效果图

 

 openseadragon

 

      对,你没有看错,使用openseadragon.js,只需要copy一段初始化代码,初始化代码格式基本固定,只有tileSources是需要变化的,想显示哪个图,就写哪个图的

      那么这个

     笔者从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 ; 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 + ".); 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 245    * @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(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\" );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.

     需要注意的是,*_files文件夹必须和

     想要预览openseadragon.js效果,必须在真实的http容器中,不可以直接在文件中打开。

     打包的openseadragon.js笔者做了一些UI上的美化,个人觉得漂亮些,如果读者不喜欢,可以用包里的原版。

 

openseadragon.js 世界地图案例

 

openseadragon.js+java源码打包下载