1. 程式人生 > >java 讀取圖片的縮圖和dpi

java 讀取圖片的縮圖和dpi

最近幫朋友做了個管理圖片的小軟體,要求實現的功能就是對大量的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;
				}