java 旋轉圖片

来源:http://www.cnblogs.com/tanghai/archive/2017/11/23/th-java-xuanzhuan-img.html
-Advertisement-
Play Games

java 使用metadata-extractor 旋轉圖片 ...


package test;

import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.channels.FileChannel;
import java.util.Iterator;

import org.apache.log4j.Logger;

import com.drew.imaging.ImageMetadataReader;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.exif.ExifIFD0Directory;
import com.sun.image.codec.jpeg.ImageFormatException;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

public class Test {
	private static Logger logger = Logger.getLogger(Test.class);

	public static void main(String args[]) {
	    String src = "d:/2.jpg";
		//獲取圖片旋轉角度
		int angel = getRotateAngleForPhoto(src);
		if (angel>0) {
			rotateImage(new File(src), angel);
		}
	}


	/**
	 * 圖片翻轉時,計算圖片翻轉到正常顯示需旋轉角度 
	 */
	public static int getRotateAngleForPhoto(String fileName){
		
		File file = new File(fileName);
		
		int angel = 0;
		InputStream is = null;
		try {
			is = new FileInputStream(file);
		} catch (FileNotFoundException e1) {
			e1.printStackTrace();
		}
		
		try{
			//核心對象操作對象
			Metadata metadata = ImageMetadataReader.readMetadata(is);
			//獲取所有不同類型的Directory,如ExifSubIFDDirectory, ExifInteropDirectory, ExifThumbnailDirectory等,這些類均為ExifDirectoryBase extends Directory子類
			//分別遍歷每一個Directory,根據Directory的Tags就可以讀取到相應的信息
			int orientation = 0;
			Iterable<Directory> iterable = metadata.getDirectories();
			for (Iterator<Directory> iter = iterable.iterator();iter.hasNext();) {
				Directory dr = iter.next();
				if (dr.getString(ExifIFD0Directory.TAG_ORIENTATION)!=null) {
					orientation = dr.getInt(ExifIFD0Directory.TAG_ORIENTATION);
				}
				logger.debug("orientation=="+orientation);
				/*Collection<Tag> tags = dr.getTags();
				for (Tag tag : tags) {
					System.out.println(tag.getTagName() + ": " + tag.getDescription());
				}*/
			}
			if(orientation==0||orientation==1) {
				angel=360;  
			}  
			else if(orientation==3) {
				angel=180;  
			}  
			else if(orientation==6) { 
				angel=90;  
			}  
			else if(orientation==8) {
				angel=270;  
			}  
		} catch(Exception e){
			e.printStackTrace();
		}
		logger.info("圖片旋轉角度:" + angel);
		return angel;
	}


	/**
	 * 旋轉圖片為指定角度
	 * 
	 * @param bufferedimage
	 *            目標圖像
	 * @param degree
	 *            旋轉角度
	 * @return
	 */
	public static File rotateImage(File file, final int angel) {
		BufferedImage src = InputImage(file.getPath());
		BufferedImage  bi = null;  
		/*int w = bufferedimage.getWidth();
		int h = bufferedimage.getHeight();
		int type = bufferedimage.getColorModel().getTransparency();
		BufferedImage img;
		Graphics2D graphics2d;
		(graphics2d = (img = new BufferedImage(w, h, type))
				.createGraphics()).setRenderingHint(
				RenderingHints.KEY_INTERPOLATION,
				RenderingHints.VALUE_INTERPOLATION_BILINEAR);
		graphics2d.rotate(Math.toRadians(degree), w * 0.99, h * 0.99);
		graphics2d.drawImage(bufferedimage, 0, 0, null);
		graphics2d.dispose();*/
		 int src_width = src.getWidth(null);  
	     int src_height = src.getHeight(null);  
	     Rectangle rect_des = CalcRotatedSize(new Rectangle(new Dimension(src_width, src_height)), angel);  
	        
	     bi = new BufferedImage(rect_des.width, rect_des.height,BufferedImage.TYPE_INT_RGB);  
	     Graphics2D g2 = bi.createGraphics();  

	     g2.translate((rect_des.width - src_width) / 2,  
	                 (rect_des.height - src_height) / 2);  
	     g2.rotate(Math.toRadians(angel), src_width / 2, src_height / 2);  

	     g2.drawImage(src, null, null);
		// 調用方法輸出圖片文件
	    OutImage(file.getPath(), bi, (float)0.5);
		return file;
	}


	/**
	* 計算旋轉參數
	*/
	public static Rectangle CalcRotatedSize(Rectangle src,int angel){
		// if angel is greater than 90 degree,we need to do some conversion.
		if(angel > 90){
			if(angel / 9%2 ==1){
				int temp = src.height;
				src.height = src.width;
				src.width = temp;
			}
			angel = angel % 90;
		}
		
		double r = Math.sqrt(src.height * src.height + src.width * src.width ) / 2 ;
		double len = 2 * Math.sin(Math.toRadians(angel) / 2) * r;
		double angel_alpha = (Math.PI - Math.toRadians(angel)) / 2;  
		double angel_dalta_width = Math.atan((double) src.height / src.width);  
		double angel_dalta_height = Math.atan((double) src.width / src.height);  

		int len_dalta_width = (int) (len * Math.cos(Math.PI - angel_alpha  
				- angel_dalta_width));  
		int len_dalta_height = (int) (len * Math.cos(Math.PI - angel_alpha  
				- angel_dalta_height));  
		int des_width = src.width + len_dalta_width * 2;  
		int des_height = src.height + len_dalta_height * 2;  
		return new java.awt.Rectangle(new Dimension(des_width, des_height));  
	}
	

	/**
	 * * 將圖片文件輸出到指定的路徑,並可設定壓縮質量
	 * 
	 * @param outImgPath
	 * @param newImg
	 * @param per
	 */
	private static void OutImage(String outImgPath, BufferedImage newImg,
			float per) {
		// 判斷輸出的文件夾路徑是否存在,不存在則創建
		File file = new File(outImgPath);
		if (!file.getParentFile().exists()) {
			file.getParentFile().mkdirs();
		}// 輸出到文件流
		
		FileChannel fc= null; 
		try {
			FileOutputStream newimage = new FileOutputStream(outImgPath);
			//獲取圖片大小
			fc= newimage.getChannel();  
			logger.info("圖片大小:"+fc.size()/1024/1024+"M"); 
			if (fc.size()>1*1024*1024) {//1M
				per = (float) (1*1024*1024.00/fc.size()*0.5);
			}
			
			JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(newimage);
			JPEGEncodeParam jep = JPEGCodec.getDefaultJPEGEncodeParam(newImg);
			// 壓縮質量
			jep.setQuality(per, true);
			encoder.encode(newImg, jep);
			newimage.close();
		} catch (FileNotFoundException e) {
			logger.error(e);
			// TODO Auto-generated catch blocke.printStackTrace();
		} catch (ImageFormatException e) {
			logger.error(e);
			// TODO Auto-generated catch blocke.printStackTrace();
		} catch (IOException e) {
			logger.error(e);
			// TODO Auto-generated catch blocke.printStackTrace();
		}
	}

	/**
	 * * 圖片文件讀取
	 * 
	 * @param srcImgPath
	 * @return
	 */
	public static BufferedImage InputImage(String srcImgPath) {
        //logger.debug(srcImgPath);
		BufferedImage srcImage = null;
		File file = new File(srcImgPath);
		try {
			// 構造BufferedImage對象
			FileInputStream in = new FileInputStream(file);
			byte[] b = new byte[5];
			in.read(b);
			srcImage = javax.imageio.ImageIO.read(file);
		} catch (IOException e) {
			 System.out.println("讀取圖片文件出錯!" + e.getMessage());
			 e.printStackTrace();
		}
		return srcImage;
	}
}


附件下載(附metadata-extractor-2.8.1.jar,xmpcore-5.1.2.jar)

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1:Websocket有java、nodejs、python、PHP、等版本 ,我現在使用的是C3版本,伺服器端是Fleck。客戶端和伺服器端來使用websocket的,下麵開始講解如何使用: 2:在開始之前我們先來看看哪些瀏覽器支持websocket: Websocket伺服器支持: 3:接下來我 ...
  • Jenkins介紹 Jenkins是基於Java開發的一種持續集成工具,用於監控持續重覆的工作,功能包括: 1、持續的軟體版本發佈/測試項目。 2、監控外部調用執行的工作。 安裝環境 操作系統:linux(centOS) 軟體:jdk 軟體:tomcat 軟體:jenkins(2.7.1版) 安裝步 ...
  • image.png 程式計數器 作用:當前線程所執行的位元組碼的行號指示器。 在虛擬機的概念模型里,位元組碼解釋器工作時就是通過改變這個計數器的值來選取下一條需要執行的位元組碼指令,分支、迴圈、跳轉、異常處理、線程恢復等基礎功能都需要依賴這個計數器來完成。 註:如果線程正在執行一個java方法,計數器記錄 ...
  • 對於功能變數名稱解析相信很多小伙伴都瞭解過,就是我們在萬網購買一個功能變數名稱,比如hpugs.com,然後呢?我們希望功能變數名稱與我們的伺服器綁定,然後通過功能變數名稱直接訪問我們的項目,這就是本篇要和大家一起探討的問題。下麵開始我們的工作: 1、首先是功能變數名稱,登錄萬維網官網,填寫我們想要購買的功能變數名稱,然後就是查詢是否已被搶註,如 ...
  • substr(string,start,length) 參數:1,string 即你要截取的字元串2,start 即要截取的開始位置(0表示從從前往後數 第一個字元開始,負數表示從從後往前數) eg:start=1,表示從從前往後開始的第二個數開始截取,start=-1,表示從從後往前開始的第一(是 ...
  • 我學習SSE指令的初衷就是為了實現RGB<->RGBA, YUV<->RGBA、RGB,這些轉換的指令優化。 在學習指令優化的過程中總是會看到SIMD(Single Instructions Multi Data), 單指令多數據:在一個指令周期內使用一條指令處理多個數據。這是Intel早期開發MM ...
  • (1)如果只是看i++和++i,這兩個是等價的,都等同於i=i+1,都是變數自身加1。 (2)在一般情況下,它們都是跟賦值聯繫在一起。 比如:int a; a=i++;//將i的值賦值給a,即a=i;然後再執行i=i+1;也就是【a=i++;】與【a=i; i=i+1;】等價 a=++i;//將i+ ...
  • pandas可以讀寫如下格式的數據類型: 具體詳見:http://pandas.pydata.org/pandas docs/version/0.20/io.html 讀取csv文件 我們準備了一個csv文件,格式類似為: 要讀取此csv文件,方法為: 輸出為: 這裡我第一次嘗試運行時,由於沒有設置 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...