Die Entwicklung von Wasserzeichen ist eine häufige Funktion in der Webentwicklung, und der implementierte Code ist sehr einfach. In diesem Artikel werden hauptsächlich Fälle zur Entwicklung von JAVA-Bildwasserzeichen vorgestellt, die einen gewissen Referenzwert haben.
Schreiben Sie es vorne
Letzte Woche habe ich eine Woche lang nacheinander über die Entwicklung von Wasserzeichen recherchiert, und jetzt habe ich endlich eine Demo für Einsteiger geschrieben und mir Notizen gemacht .
Die Demo basiert auf dem Dateiimport- und -export-Framework (POI-Methode) des JAVA-Praxisbeispiels, das ich letztes Mal geschrieben habe, und basiert auf Spring+SpringMVC. Bitte korrigieren Sie mich, wenn es Fehler gibt.
Eine kurze Einführung
Die Entwicklung von Wasserzeichen ist eine häufige Funktion in der Webentwicklung. Ich werde auch die spezifischen Implementierungsschritte befolgen. Detaillierte Beschreibung basierend auf Code. Basierend auf meinem persönlichen Verständnis teile ich die Arten und Entwicklungsprozesse von Wasserzeichen tatsächlich in die folgenden Kategorien ein.
Arten von Wasserzeichen:
Einzeltext-Wasserzeichen
Einzelbild-Wasserzeichen
Mehrere Text-Wasserzeichen
Mehrere Bild-Wasserzeichen
Wasserzeichen-Entwicklungsprozess:
Bild-Cache-Objekt erstellen
-
Erstellen Sie ein Java-Zeichenwerkzeugobjekt
Verwenden Sie das Zeichenwerkzeugobjekt, um das Originalbild in das zwischengespeicherte Bildobjekt zu zeichnen
Verwenden Sie die Zeichnung Werkzeugobjekt zum Zeichnen des Originalbilds in das Cache-Bildobjekt. Zeichnen Sie Wasserzeichen (Text/Bilder) in zwischengespeicherte Bilder
Bildkodierungs-Werkzeugklasse erstellen
Verwenden Sie die Bildkodierungs-Toolklasse, um das zwischengespeicherte Bild in die Zieldatei auszugeben
Rendering:
Seite hochladen:
Originalbild:
Einzeltext-Wasserzeichen:
Wasserzeichen für ein einzelnes Bild:
Wasserzeichen für mehrere Texte:
Wasserzeichen für mehrere Bilder:
Einzeltext-Wasserzeichenentwicklung
Mit dem sogenannten Textwasserzeichen wird einem Bild ein Textwasserzeichen hinzugefügt. Unser Hauptprozess besteht darin, das entsprechende Bild über die Toolklasse ImageIO zu dekodieren, dann ein BufferImage-Objekt zu erstellen und über BufferImage ein Graphics2D-Objekt zu erstellen -Objekt und zeichnen Sie dann das Originalbild über das Graphics2D-Objekt in das BufferImage-Objekt. Anschließend können wir das Graphics2D-Objekt auch verwenden, um wasserzeichenbezogene Informationen festzulegen, z. B. Wasserzeicheninhalt, Schriftgröße, Schriftstil usw.
Was hier erklärt werden muss, ist, dass wir die Breite des Wasserzeichentextes berechnen müssen. Die chinesische Länge ist die Textbreite und die englische Länge ist die Hälfte der Textbreite. Einzelheiten entnehmen Sie bitte dem entsprechenden Inhalt in meinem Quellcode.
//计算水印文本长度 //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); //创建图片缓存对象 BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); //创建java绘图工具对象 Graphics2D graphics2d = bufferedImage.createGraphics(); //参数主要是,原图,坐标,宽高 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; //水印坐标设置 if (X > widthDiff) { X = widthDiff; } if (Y > heightDiff) { Y = heightDiff; } //水印透明设置 graphics2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, ALPHA)); //纵坐标在下方,不增加字体高度会靠上 graphics2d.drawString(MARK_TEXT, X, Y+FONT_SIZE); graphics2d.dispose(); os = new FileOutputStream(UPLOAD_PATH+"/"+imageFileName); //创建图像编码工具类 JPEGImageEncoder en = JPEGCodec.createJPEGEncoder(os); //使用图像编码工具类,输出缓存图像到目标文件 en.encode(bufferedImage); if(is!=null){ is.close(); } if(os!=null){ os.close(); } } catch (IOException e) { e.printStackTrace(); } return "success"; }
Einzelbild-Wasserzeichenentwicklung
Einzelbild-Wasserzeichen und Der Codefluss des obigen Einzeltextes ist ungefähr gleich, nur die Unterschiede werden hier erläutert.
Zuerst müssen wir den Pfad des Wasserzeichenbilds ermitteln und dann ein Wasserzeichendateiobjekt erstellen. In der Zwischenzeit müssen wir die Länge und Breite nicht berechnen des Textes, denn die Länge und Breite eines einzelnen Textes ist die Länge und Breite unseres Wasserzeichens.
//水印图片路径 //水印坐标设置 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; //水印坐标设置 if (X > widthDiff) { X = widthDiff; } if (Y > heightDiff) { Y = heightDiff; } //水印透明设置 graphics2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, ALPHA)); graphics2d.drawImage(imageLogo, X, Y, null);
Multitext-Wasserzeichenentwicklung
Tatsächlich ähnelt die Multitext-Wasserzeichenentwicklung der Einzeltextentwicklung Der Hauptunterschied besteht darin, dass wir das BufferImage-Objekt drehen müssen. Da das Zeichnen von Wasserzeichen keine rotierenden Wasserzeichen unterstützt, müssen wir das Originalbild drehen und dann durch Schleifen mehrmals ein Textwasserzeichen auf das Originalbild zeichnen.
//旋转原图,注意旋转角度为弧度制。后面两个参数为旋转的坐标中心 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; }
Entwicklung von Mehrbild-Wasserzeichen
Wie oben muss bei der Mehrbild-Wasserzeichenerkennung zuerst das Wasserzeichenbild gelesen werden , und dann Stellen Sie die Transparenz des Wasserzeichens ein, drehen Sie das Originalbild und dann können wir durch Schleifen mehrmals ein Bildwasserzeichen auf das Originalbild zeichnen.
//水印图片路径 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); //水印透明设置 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; }
Vollständiger Geschäftscode:
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); //创建图片缓存对象 BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); //创建java绘图工具对象 Graphics2D graphics2d = bufferedImage.createGraphics(); //参数主要是,原图,坐标,宽高 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; //水印坐标设置 if (X > widthDiff) { X = widthDiff; } if (Y > heightDiff) { Y = heightDiff; } //水印透明设置 graphics2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, ALPHA)); graphics2d.drawString(MARK_TEXT, X, Y+FONT_SIZE); graphics2d.dispose(); os = new FileOutputStream(UPLOAD_PATH+"/"+imageFileName); //创建图像编码工具类 JPEGImageEncoder en = JPEGCodec.createJPEGEncoder(os); //使用图像编码工具类,输出缓存图像到目标文件 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); //创建图片缓存对象 BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); //创建java绘图工具对象 Graphics2D graphics2d = bufferedImage.createGraphics(); //参数主要是,原图,坐标,宽高 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; //水印坐标设置 if (X > widthDiff) { X = widthDiff; } if (Y > heightDiff) { Y = heightDiff; } //水印透明设置 graphics2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, ALPHA)); graphics2d.drawImage(imageLogo, X, Y, null); graphics2d.dispose(); os = new FileOutputStream(UPLOAD_PATH+"/"+imageFileName); //创建图像编码工具类 JPEGImageEncoder en = JPEGCodec.createJPEGEncoder(os); //使用图像编码工具类,输出缓存图像到目标文件 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); //创建图片缓存对象 BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); //创建java绘图工具对象 Graphics2D graphics2d = bufferedImage.createGraphics(); //参数主要是,原图,坐标,宽高 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; //水印透明设置 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); //创建图像编码工具类 JPEGImageEncoder en = JPEGCodec.createJPEGEncoder(os); //使用图像编码工具类,输出缓存图像到目标文件 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); //创建图片缓存对象 BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); //创建java绘图工具对象 Graphics2D graphics2d = bufferedImage.createGraphics(); //参数主要是,原图,坐标,宽高 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); //水印透明设置 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); //创建图像编码工具类 JPEGImageEncoder en = JPEGCodec.createJPEGEncoder(os); //使用图像编码工具类,输出缓存图像到目标文件 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; } }
Endlich wurde diese Demo geschrieben Basierend auf dem letzten Dateiimport- und -export-Framework. Es gibt einige andere Demo-Codes im Quellcode. Die wichtigsten verwendeten Klassen sind WaterMarkController.java, WaterMarkServiceImpl.java, da ich E im Code fest codiert habe. Speichern Sie den Ordner. Wenn Sie ihn ausführen möchten, erstellen Sie bitte zuerst einen neuen Ordner oder ändern Sie ihn in einen anderen Ordner.
Das obige ist der detaillierte Inhalt vonBeispielanalyse zum Hinzufügen von Wasserzeichen zu Bildern in Java. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

JVM arbeitet mit dem Konvertieren von Java -Code in Maschinencode und Verwaltung von Ressourcen. 1) Ladeklasse: Laden Sie die .class -Datei in den Speicher. 2) Laufzeitdatenbereich: Speicherbereich verwalten. 3) Ausführungs Engine: Ausführungsbytecode interpretieren oder kompilieren. 4) Lokale Methodenschnittstelle: Interagieren Sie mit dem Betriebssystem über JNI.

Mit JVM kann Java auf Plattformen rennen. 1) JVM lädt, validiert und führt Bytecode aus. 2) Die Arbeit von JVM umfasst Klassenbelastung, Bytecode -Überprüfung, Interpretationsausführung und Speicherverwaltung. 3) JVM unterstützt erweiterte Funktionen wie dynamisches Klassenbelastung und Reflexion.

Java -Anwendungen können in verschiedenen Betriebssystemen in den folgenden Schritten ausgeführt werden: 1) Verwenden Sie die Datei- oder Pfadeklasse, um Dateipfade zu verarbeiten; 2) Umgebungsvariablen durch system.getenv () einstellen und erhalten; 3) Verwenden Sie Maven oder Gradle, um Abhängigkeiten zu verwalten und zu testen. Die plattformübergreifenden Funktionen von Java beruhen auf der Abstraktionsschicht der JVM, erfordern jedoch eine manuelle Handhabung bestimmter Betriebssystem-spezifischer Funktionen.

Java benötigt eine spezifische Konfiguration und das Tuning auf verschiedenen Plattformen. 1) Passen Sie die JVM -Parameter an, z. B. -xms und -xmx, um die Haufengröße festzulegen. 2) Wählen Sie die entsprechende Strategie für die Müllsammlung, wie z. B. ParallelgC oder G1GC. 3) Konfigurieren Sie die native Bibliothek, um sich an verschiedene Plattformen anzupassen. Diese Maßnahmen können es Java -Anwendungen ermöglichen, in verschiedenen Umgebungen am besten zu funktionieren.

Osgi, Apachecommonslang, JNA und JVMOPTIONSAREEFECTIVEFORHANDLATTLATFORM-Spezifikaldesinjava.1) OsgimanagesDependenciesandisolatesComponents.2) apachecommonslangprovidilityfunctions.3) jnaAllowscallingnativeStivingnativeCallingnativeCode

JvmmanagesGecollectionAcrossplattformseffektivyusingagenerationalApproachandaDaptoosandhardwaredFerces

Java -Code kann auf verschiedenen Betriebssystemen ohne Änderung ausgeführt werden, da Javas "einmal schreiben, überall rennen" von Java Virtual Machine (JVM) implementiert wird. Als Vermittler zwischen dem kompilierten Java -Bytecode und dem Betriebssystem übersetzt das JVM die Bytecode in bestimmte Maschinenanweisungen, um sicherzustellen, dass das Programm mit installiertem JVM unabhängig auf jeder Plattform ausführen kann.

Die Zusammenstellung und Ausführung von Java -Programmen erreicht die Unabhängigkeit der Plattform über Bytecode und JVM. 1) Schreiben Sie Java -Quellcode und kompilieren Sie ihn in Bytecode. 2) Verwenden Sie JVM, um Bytecode auf einer beliebigen Plattform auszuführen, um sicherzustellen, dass der Code über Plattformen hinweg ausgeführt wird.


Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

Video Face Swap
Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heißer Artikel

Heiße Werkzeuge

MinGW – Minimalistisches GNU für Windows
Dieses Projekt wird derzeit auf osdn.net/projects/mingw migriert. Sie können uns dort weiterhin folgen. MinGW: Eine native Windows-Portierung der GNU Compiler Collection (GCC), frei verteilbare Importbibliotheken und Header-Dateien zum Erstellen nativer Windows-Anwendungen, einschließlich Erweiterungen der MSVC-Laufzeit zur Unterstützung der C99-Funktionalität. Die gesamte MinGW-Software kann auf 64-Bit-Windows-Plattformen ausgeführt werden.

SublimeText3 Englische Version
Empfohlen: Win-Version, unterstützt Code-Eingabeaufforderungen!

SublimeText3 Linux neue Version
SublimeText3 Linux neueste Version

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Herunterladen der Mac-Version des Atom-Editors
Der beliebteste Open-Source-Editor
