日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java水印图片_JAVA实用案例之图片水印开发

發(fā)布時間:2023/12/10 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java水印图片_JAVA实用案例之图片水印开发 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

寫在最前面

上周零零碎碎花了一周的時間研究水印的開發(fā),現(xiàn)在終于寫了個入門級的Demo,做下筆記同時分享出來供大家參考。

Demo是在我上次寫的 JAVA實用案例之文件導(dǎo)入導(dǎo)出(POI方式) 框架基礎(chǔ)上搭建的,基于Spring+SpringMVC。如果有錯誤還請大家指正。

簡單介紹

水印開發(fā)是web開發(fā)中一種比較常見的功能,實現(xiàn)的代碼很簡單,具體的實現(xiàn)步驟我也會以代碼為基礎(chǔ)詳細(xì)講述。其實以我個人的理解,我把水印的類型和開發(fā)流程分為以下幾種。

水印的類型:

單文字水印

單圖片水印

多文字水印

多圖片水印

水印的開發(fā)流程:

創(chuàng)建圖片緩存對象

創(chuàng)建Java繪圖工具對象

使用繪圖工具工具對象將原圖繪制到緩存圖片對象

使用繪圖工具對象將水印(文字/圖片)繪制到緩存圖片

創(chuàng)建圖像編碼工具類

使用圖像編碼工具類,輸出緩存圖像到目標(biāo)文件

效果圖:

上傳頁:

原圖:

單文字水印:

單圖片水印:

多文字水印:

多圖片水印:

單文字水印開發(fā)

所謂單文字水印,就是在一張圖片上添加一條文字水印。其中我們主要的流程是通過ImageIO工具類解碼對應(yīng)的圖片,然后創(chuàng)建BufferImage對象,通過BufferImage對象創(chuàng)建Graphics2D對象,再通過Graphics2D對象繪制原圖到BufferImage對象。然后,我們還可以使用Graphics2D對象來設(shè)置水印的相關(guān)信息,如水印內(nèi)容、字體大小、字體風(fēng)格等。

這里需要說明的是我們需要計算水印文本的寬度,中文長度即文本寬度,英文長度為文本寬度的二分之一。具體可以參考我源碼中的相關(guān)內(nèi)容。

//計算水印文本長度

//1、中文長度即文本長度 2、英文長度為文本長度二分之一

public int getTextLength(String text){

//水印文字長度

int length = text.length();

for (int i = 0; i < text.length(); i++) {

String s =String.valueOf(text.charAt(i));

if (s.getBytes().length>1) {

length++;

}

}

length = length%2==0?length/2:length/2+1;

return length;

}

//添加單條文字水印方法

public String textWaterMark(MultipartFile myFile,String imageFileName) {

InputStream is =null;

OutputStream os =null;

int X = 636;

int Y = 700;

try {

//使用ImageIO解碼圖片

Image image = ImageIO.read(myFile.getInputStream());

//計算原始圖片寬度長度

int width = image.getWidth(null);

int height = image.getHeight(null);

//創(chuàng)建圖片緩存對象

BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

//創(chuàng)建java繪圖工具對象

Graphics2D graphics2d = bufferedImage.createGraphics();

//參數(shù)主要是,原圖,坐標(biāo),寬高

graphics2d.drawImage(image, 0, 0, width, height, null);

graphics2d.setFont(new Font(FONT_NAME, FONT_STYLE, FONT_SIZE));

graphics2d.setColor(FONT_COLOR);

//使用繪圖工具將水印繪制到圖片上

//計算文字水印寬高值

int waterWidth = FONT_SIZE*getTextLength(MARK_TEXT);

int waterHeight = FONT_SIZE;

//計算水印與原圖高寬差

int widthDiff = width-waterWidth;

int heightDiff = height-waterHeight;

//水印坐標(biāo)設(shè)置

if (X > widthDiff) {

X = widthDiff;

}

if (Y > heightDiff) {

Y = heightDiff;

}

//水印透明設(shè)置

graphics2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, ALPHA));

//縱坐標(biāo)在下方,不增加字體高度會靠上

graphics2d.drawString(MARK_TEXT, X, Y+FONT_SIZE);

graphics2d.dispose();

os = new FileOutputStream(UPLOAD_PATH+"/"+imageFileName);

//創(chuàng)建圖像編碼工具類

JPEGImageEncoder en = JPEGCodec.createJPEGEncoder(os);

//使用圖像編碼工具類,輸出緩存圖像到目標(biāo)文件

en.encode(bufferedImage);

if(is!=null){

is.close();

}

if(os!=null){

os.close();

}

} catch (IOException e) {

e.printStackTrace();

}

return "success";

}

單圖片水印開發(fā)

單圖片水印和上面單文字的代碼流程大致一致,這里只講解不同之處。

首先我們需要獲得水印圖片的路徑,然后創(chuàng)建水印文件對象,同樣通過ImageIO工具類解碼水印圖片,中間我們就不需要計算文本長寬了,因為單文字中的長寬即是我們水印圖片的長寬。

//水印圖片路徑

//水印坐標(biāo)設(shè)置

String logoPath = "/img/logo.png";

String realPath = request.getSession().getServletContext().getRealPath(logoPath);

File logo = new File(realPath);

Image imageLogo = ImageIO.read(logo);

int widthLogo = imageLogo.getWidth(null);

int heightLogo = imageLogo.getHeight(null);

int widthDiff = width-widthLogo;

int heightDiff = height-heightLogo;

//水印坐標(biāo)設(shè)置

if (X > widthDiff) {

X = widthDiff;

}

if (Y > heightDiff) {

Y = heightDiff;

}

//水印透明設(shè)置

graphics2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, ALPHA));

graphics2d.drawImage(imageLogo, X, Y, null);

多文字水印開發(fā)

其實多文字水印開發(fā)和單文字也是類似的,主要的不同點是我們需要將BufferImage對象進(jìn)行旋轉(zhuǎn)。因為繪制水印并不支持旋轉(zhuǎn)水印繪制,所以我們需要對原圖進(jìn)行旋轉(zhuǎn)繪制,然后通過循環(huán),我們就可以將一個文字水印多次繪制在原圖上了。

//旋轉(zhuǎn)原圖,注意旋轉(zhuǎn)角度為弧度制。后面兩個參數(shù)為旋轉(zhuǎn)的坐標(biāo)中心

graphics2d.rotate(Math.toRadians(30), bufferedImage.getWidth()/2, bufferedImage.getHeight()/2);

int x = -width/2;

int y = -height/2;

while(x < width*1.5){

y = -height/2;

while(y < height*1.5){

graphics2d.drawString(MARK_TEXT, x, y);

y+=waterHeight+100;

}

x+=waterWidth+100;

}

多圖片水印開發(fā)

與上文相同,多圖片水印需要先讀取水印圖片,然后對水印設(shè)置透明度,在對原圖進(jìn)行旋轉(zhuǎn),然后通過循環(huán),我們就可以將一個圖片水印多次繪制在原圖上。

//水印圖片路徑

String logoPath = "/img/logo.png";

String realPath = request.getSession().getServletContext().getRealPath(logoPath);

File logo = new File(realPath);

Image imageLogo = ImageIO.read(logo);

int widthLogo = imageLogo.getWidth(null);

int heightLogo = imageLogo.getHeight(null);

//水印透明設(shè)置

graphics2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, ALPHA));

graphics2d.rotate(Math.toRadians(30), bufferedImage.getWidth()/2, bufferedImage.getHeight()/2);

int x = -width/2;

int y = -height/2;

while(x < width*1.5){

y = -height/2;

while(y < height*1.5){

graphics2d.drawImage(imageLogo, x, y, null);

y+=heightLogo+100;

}

x+=widthLogo+100;

}

業(yè)務(wù)類完整代碼:

import java.awt.AlphaComposite;

import java.awt.Color;

import java.awt.Font;

import java.awt.Graphics2D;

import java.awt.Image;

import java.awt.image.BufferedImage;

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import javax.imageio.ImageIO;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Service;

import org.springframework.web.multipart.MultipartFile;

import com.allan.service.WaterMarkService;

import com.sun.image.codec.jpeg.JPEGCodec;

import com.sun.image.codec.jpeg.JPEGImageEncoder;

@Service

public class WaterMarkServiceImpl implements WaterMarkService{

//定義上傳的文件夾

private static final String UPLOAD_PATH = "E:/save";

//定義水印文字樣式

private static final String MARK_TEXT = "小賣鋪的老爺爺";

private static final String FONT_NAME = "微軟雅黑";

private static final int FONT_STYLE = Font.BOLD;

private static final int FONT_SIZE = 60;

private static final Color FONT_COLOR = Color.black;

private static final float ALPHA = 0.3F;

//1、上傳圖片

public String uploadImage(MultipartFile myFile,String imageFileName) {

InputStream is =null;

OutputStream os =null;

try{

is = myFile.getInputStream();

os = new FileOutputStream(UPLOAD_PATH+"/"+imageFileName);

byte[] buffer =new byte[1024];

int len = 0;

while ((len=is.read(buffer))>0){

os.write(buffer);

}

}catch(Exception e){

e.printStackTrace();

}finally{

if(is!=null){

try {

is.close();

} catch (IOException e) {

e.printStackTrace();

}

}

if(os!=null){

try {

os.close();

} catch (IOException e2) {

e2.printStackTrace();

}

}

}

return "success";

}

//添加單條文字水印

public String textWaterMark(MultipartFile myFile,String imageFileName) {

InputStream is =null;

OutputStream os =null;

int X = 636;

int Y = 700;

try {

Image image = ImageIO.read(myFile.getInputStream());

//計算原始圖片寬度長度

int width = image.getWidth(null);

int height = image.getHeight(null);

//創(chuàng)建圖片緩存對象

BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

//創(chuàng)建java繪圖工具對象

Graphics2D graphics2d = bufferedImage.createGraphics();

//參數(shù)主要是,原圖,坐標(biāo),寬高

graphics2d.drawImage(image, 0, 0, width, height, null);

graphics2d.setFont(new Font(FONT_NAME, FONT_STYLE, FONT_SIZE));

graphics2d.setColor(FONT_COLOR);

//使用繪圖工具將水印繪制到圖片上

//計算文字水印寬高值

int waterWidth = FONT_SIZE*getTextLength(MARK_TEXT);

int waterHeight = FONT_SIZE;

//計算水印與原圖高寬差

int widthDiff = width-waterWidth;

int heightDiff = height-waterHeight;

//水印坐標(biāo)設(shè)置

if (X > widthDiff) {

X = widthDiff;

}

if (Y > heightDiff) {

Y = heightDiff;

}

//水印透明設(shè)置

graphics2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, ALPHA));

graphics2d.drawString(MARK_TEXT, X, Y+FONT_SIZE);

graphics2d.dispose();

os = new FileOutputStream(UPLOAD_PATH+"/"+imageFileName);

//創(chuàng)建圖像編碼工具類

JPEGImageEncoder en = JPEGCodec.createJPEGEncoder(os);

//使用圖像編碼工具類,輸出緩存圖像到目標(biāo)文件

en.encode(bufferedImage);

if(is!=null){

is.close();

}

if(os!=null){

os.close();

}

} catch (IOException e) {

e.printStackTrace();

}

return "success";

}

//添加單圖片水印

public String imageWaterMark(MultipartFile myFile,String imageFileName,HttpServletRequest request) {

InputStream is =null;

OutputStream os =null;

int X = 636;

int Y = 763;

try {

Image image = ImageIO.read(myFile.getInputStream());

//計算原始圖片寬度長度

int width = image.getWidth(null);

int height = image.getHeight(null);

//創(chuàng)建圖片緩存對象

BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

//創(chuàng)建java繪圖工具對象

Graphics2D graphics2d = bufferedImage.createGraphics();

//參數(shù)主要是,原圖,坐標(biāo),寬高

graphics2d.drawImage(image, 0, 0, width, height, null);

graphics2d.setFont(new Font(FONT_NAME, FONT_STYLE, FONT_SIZE));

graphics2d.setColor(FONT_COLOR);

//水印圖片路徑

String logoPath = "/img/logo.png";

String realPath = request.getSession().getServletContext().getRealPath(logoPath);

File logo = new File(realPath);

Image imageLogo = ImageIO.read(logo);

int widthLogo = imageLogo.getWidth(null);

int heightLogo = imageLogo.getHeight(null);

int widthDiff = width-widthLogo;

int heightDiff = height-heightLogo;

//水印坐標(biāo)設(shè)置

if (X > widthDiff) {

X = widthDiff;

}

if (Y > heightDiff) {

Y = heightDiff;

}

//水印透明設(shè)置

graphics2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, ALPHA));

graphics2d.drawImage(imageLogo, X, Y, null);

graphics2d.dispose();

os = new FileOutputStream(UPLOAD_PATH+"/"+imageFileName);

//創(chuàng)建圖像編碼工具類

JPEGImageEncoder en = JPEGCodec.createJPEGEncoder(os);

//使用圖像編碼工具類,輸出緩存圖像到目標(biāo)文件

en.encode(bufferedImage);

if(is!=null){

is.close();

}

if(os!=null){

os.close();

}

} catch (IOException e) {

e.printStackTrace();

}

return "success";

}

//添加多條文字水印

public String moreTextWaterMark(MultipartFile myFile,String imageFileName) {

InputStream is =null;

OutputStream os =null;

int X = 636;

int Y = 763;

try {

Image image = ImageIO.read(myFile.getInputStream());

//計算原始圖片寬度長度

int width = image.getWidth(null);

int height = image.getHeight(null);

//創(chuàng)建圖片緩存對象

BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

//創(chuàng)建java繪圖工具對象

Graphics2D graphics2d = bufferedImage.createGraphics();

//參數(shù)主要是,原圖,坐標(biāo),寬高

graphics2d.drawImage(image, 0, 0, width, height, null);

graphics2d.setFont(new Font(FONT_NAME, FONT_STYLE, FONT_SIZE));

graphics2d.setColor(FONT_COLOR);

//使用繪圖工具將水印繪制到圖片上

//計算文字水印寬高值

int waterWidth = FONT_SIZE*getTextLength(MARK_TEXT);

int waterHeight = FONT_SIZE;

//水印透明設(shè)置

graphics2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, ALPHA));

graphics2d.rotate(Math.toRadians(30), bufferedImage.getWidth()/2, bufferedImage.getHeight()/2);

int x = -width/2;

int y = -height/2;

while(x < width*1.5){

y = -height/2;

while(y < height*1.5){

graphics2d.drawString(MARK_TEXT, x, y);

y+=waterHeight+100;

}

x+=waterWidth+100;

}

graphics2d.dispose();

os = new FileOutputStream(UPLOAD_PATH+"/"+imageFileName);

//創(chuàng)建圖像編碼工具類

JPEGImageEncoder en = JPEGCodec.createJPEGEncoder(os);

//使用圖像編碼工具類,輸出緩存圖像到目標(biāo)文件

en.encode(bufferedImage);

if(is!=null){

is.close();

}

if(os!=null){

os.close();

}

} catch (IOException e) {

e.printStackTrace();

}

return "success";

}

//多圖片水印

public String moreImageWaterMark(MultipartFile myFile,String imageFileName,HttpServletRequest request) {

InputStream is =null;

OutputStream os =null;

int X = 636;

int Y = 763;

try {

Image image = ImageIO.read(myFile.getInputStream());

//計算原始圖片寬度長度

int width = image.getWidth(null);

int height = image.getHeight(null);

//創(chuàng)建圖片緩存對象

BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

//創(chuàng)建java繪圖工具對象

Graphics2D graphics2d = bufferedImage.createGraphics();

//參數(shù)主要是,原圖,坐標(biāo),寬高

graphics2d.drawImage(image, 0, 0, width, height, null);

graphics2d.setFont(new Font(FONT_NAME, FONT_STYLE, FONT_SIZE));

graphics2d.setColor(FONT_COLOR);

//水印圖片路徑

String logoPath = "/img/logo.png";

String realPath = request.getSession().getServletContext().getRealPath(logoPath);

File logo = new File(realPath);

Image imageLogo = ImageIO.read(logo);

int widthLogo = imageLogo.getWidth(null);

int heightLogo = imageLogo.getHeight(null);

//水印透明設(shè)置

graphics2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, ALPHA));

graphics2d.rotate(Math.toRadians(30), bufferedImage.getWidth()/2, bufferedImage.getHeight()/2);

int x = -width/2;

int y = -height/2;

while(x < width*1.5){

y = -height/2;

while(y < height*1.5){

graphics2d.drawImage(imageLogo, x, y, null);

y+=heightLogo+100;

}

x+=widthLogo+100;

}

graphics2d.dispose();

os = new FileOutputStream(UPLOAD_PATH+"/"+imageFileName);

//創(chuàng)建圖像編碼工具類

JPEGImageEncoder en = JPEGCodec.createJPEGEncoder(os);

//使用圖像編碼工具類,輸出緩存圖像到目標(biāo)文件

en.encode(bufferedImage);

if(is!=null){

is.close();

}

if(os!=null){

os.close();

}

} catch (IOException e) {

e.printStackTrace();

}

return "success";

}

//計算水印文本長度

//1、中文長度即文本長度 2、英文長度為文本長度二分之一

public int getTextLength(String text){

//水印文字長度

int length = text.length();

for (int i = 0; i < text.length(); i++) {

String s =String.valueOf(text.charAt(i));

if (s.getBytes().length>1) {

length++;

}

}

length = length%2==0?length/2:length/2+1;

return length;

}

}

最后再說明下,本Demo是在上次的文件導(dǎo)入導(dǎo)出的框架基礎(chǔ)上編寫的,源碼中有些其它Demo的代碼,本文主要使用的類有WaterMarkController.java、WaterMarkService.java、WaterMarkServiceImpl.java,因為代碼中我是硬編碼到E:/save文件夾下的,如果要運行的話,還請先新建此文件夾,或者改為其他文件夾也行。

源碼地址:https://github.com/allanzhuo/myport.git

總結(jié)

以上是生活随笔為你收集整理的java水印图片_JAVA实用案例之图片水印开发的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。