java 讀取圖片的縮圖和dpi
阿新 • • 發佈:2019-02-08
最近幫朋友做了個管理圖片的小軟體,要求實現的功能就是對大量的jpg圖片生成縮圖顯示,自動計算圖片的平方數以便計費。最初感覺從圖片讀取資訊應該是很簡單的問題,哪知道還是花了好幾天才搞定,杯具啊!
剛開始我呼叫ImageIcon來生成縮圖,才發現對於幾百張圖片來說這是不可能完成任務,google一把才發現,jpg圖片中的exif中會包括縮圖和dpi,但是當我使用JpegMetadataReader類去讀dpi的時候竟然發現有時跟windows的讀取的結果不一樣,要知道程式這東西就怕“有時出問題” 這種情況。走到絕處時竟然下了exif的標準文件來看,不過還好最後發現了Sanselan類可以彌補JpegMetadataReader的不足,長話短說直接看程式碼吧,本程式碼並不完美,望體諒。
JpegMetadataReader 來自 metadata-extractor-2.3.1.jar
Sanselan 來自 sanselan-0.97-incubator.jar
該程式碼中很多區域性變數的申明沒有貼出來,希望沒有影響到你的閱讀。
String [] temp = file.getName().split("\\."); String type = temp[temp.length - 1]; // 讀取圖片型別 for(String img : images){ if(img.equalsIgnoreCase(type)){ // 判斷檔案型別是否能處理 log4j.debug("will add file name:[" + file.getName() + "]"); JPanel imagePanel = new JPanel(); // 該部分的功能是實現像windows那樣顯示縮圖,並顯示圖片尺寸大小。所以用了JPanel imagePanel.setLayout(new BorderLayout()); imagePanel.setSize(IMAGE_LABEL_WIDTH,IMAGE_LABEL_HEIGHT); // WIDTH,HEIGHT // 為本地變數 JLabel label = new JLabel(); JLabel tempField = new JLabel(); ImageIcon icon = new ImageIcon(); try{ ImageInfo imageInfo = Sanselan.getImageInfo(file); Metadata metadata = JpegMetadataReader.readMetadata(file); Iterator directories = metadata.getDirectoryIterator(); if(directories.hasNext()){ Directory directory = (Directory) directories.next(); Directory exifDirectory = metadata.getDirectory(ExifDirectory.class); try{ // 從exif中讀取縮圖 byte[] dataBuffer = exifDirectory.getByteArray(TAG_THUMBNAIL_DATA_TYPE); icon = new ImageIcon(dataBuffer); }catch (com.drew.metadata.MetadataException e) {// 如果沒有自動生成 icon = new ImageIcon("./disappoint.jpg"); if(icon.getIconWidth() > IMAGE_LABEL_WIDTH){ icon = new ImageIcon(icon.getImage().getScaledInstance(IMAGE_LABEL_WIDTH,IMAGE_LABEL_WIDTH, Image.SCALE_DEFAULT)); } } label.setIcon(icon); BigDecimal dipx,dipy; // 如果 imageInfo中無法讀取,從exif中讀取dpi if(imageInfo.getPhysicalWidthDpi() <= 0 || imageInfo.getPhysicalHeightDpi() <= 0){ dipx = new BigDecimal(directory.getString(ExifDirectory.TAG_X_RESOLUTION)); dipy = new BigDecimal(directory.getString(ExifDirectory.TAG_Y_RESOLUTION)); if(dipx.equals(new BigDecimal(72)) || dipy.equals(new BigDecimal(72)))// 如果dpi為72的話,丟擲錯誤,因為暫時無法確定從exif中讀出的資料是對的 throw new Exception("dpi is equal zore"); }else{ dipx = new BigDecimal(imageInfo.getPhysicalWidthDpi()); dipy = new BigDecimal(imageInfo.getPhysicalHeightDpi()); } BigDecimal inch = new BigDecimal(INCH_TO_CM); // 計算圖片的寬度和長度,單位釐米 BigDecimal width = new BigDecimal(imageInfo.getWidth()).multiply(inch,MC).divide(dipx, LENGTH_SCALE, RoundingMode.HALF_UP); BigDecimal height = new BigDecimal(imageInfo.getHeight()).multiply(inch, MC).divide(dipy,LENGTH_SCALE,RoundingMode.HALF_UP); log4j.debug("width:[" + width + "] height:[" + height + "]"); String spec = width +"cm x "+ height + "cm"; tempField = new JLabel("<html>"+ file.getName() + "<br>" + spec + "</html>" ); } }catch (Exception e) { // 處理出錯 log4j.error(e.getMessage(), e); icon = new ImageIcon("./error.jpg"); if(icon.getIconWidth() > IMAGE_LABEL_WIDTH){ icon = new ImageIcon(icon.getImage().getScaledInstance(IMAGE_LABEL_WIDTH,IMAGE_LABEL_WIDTH, Image.SCALE_DEFAULT)); } label.setIcon(icon); tempField.setText("<html>" + file.getName() + " <br>圖片資訊讀取出錯</html>"); } imagePanel.add(label, BorderLayout.CENTER); imagePanel.add(tempField, BorderLayout.SOUTH); showPanel.add(imagePanel); break; }