watermarkArr) {
77 | this.watermarkArr.addAll(watermarkArr);
78 | return this;
79 | }
80 |
81 | /**
82 | * 指定源文件图片
83 | *
84 | * @param srcImage
85 | * {@link File}
86 | * @return {@link ImageUtils}
87 | */
88 | public static ImageUtils fromFile(File srcImage) {
89 | ImageUtils image = new ImageUtils(srcImage);
90 | image.init();
91 | return image;
92 | }
93 |
94 | /**
95 | * 定义伸缩比例
96 | *
97 | * @param scale
98 | * 伸缩比例
99 | * @return {@link ImageUtils}
100 | */
101 | public ImageUtils scale(double scale) {
102 | if (scale <= 0) {
103 | throw new IllegalStateException("scale value error!");
104 | }
105 | this.scale = scale;
106 | return this;
107 | }
108 |
109 | /**
110 | * 生成的图片是否以给定的大小不变
111 | *
112 | * @param fixedGivenSize
113 | * {@link Boolean}
114 | * @return {@link ImageUtils}
115 | */
116 | public ImageUtils fixedGivenSize(boolean fixedGivenSize) {
117 | this.fixedGivenSize = fixedGivenSize;
118 | return this;
119 | }
120 |
121 | /**
122 | * 指定生成图片的宽度
123 | *
124 | * @param width
125 | * {@link Integer} 宽度
126 | * @return {@link ImageUtils}
127 | */
128 | public ImageUtils width(int width) {
129 | if (width <= 1) {
130 | throw new IllegalStateException("width value error!");
131 | }
132 | this.width = width;
133 | return this;
134 | }
135 |
136 | /**
137 | * 指定生成图片的高度
138 | *
139 | * @param height
140 | * {@link Integer} 高度
141 | * @return {@link ImageUtils}
142 | */
143 | public ImageUtils height(int height) {
144 | if (height <= 1) {
145 | throw new IllegalStateException("height value error!");
146 | }
147 | this.height = height;
148 | return this;
149 | }
150 |
151 | /**
152 | * 指定生成图片的宽度和高度
153 | *
154 | * @param width
155 | * {@link Integer} 宽度
156 | * @param height
157 | * {@link Integer} 高度
158 | * @return {@link ImageUtils}
159 | */
160 | public ImageUtils size(int width, int height) {
161 | if (width <= 1 || height <= 1) {
162 | throw new IllegalStateException("width or height value error!");
163 | }
164 | this.width = width;
165 | this.height = height;
166 | return this;
167 | }
168 |
169 | /**
170 | * 指定旋转图片角度
171 | *
172 | * @param angle
173 | * {@link Double} 旋转图片的角度
174 | * @return {@link ImageUtils}
175 | */
176 | public ImageUtils rotate(double angle) {
177 | this.angle = angle;
178 | return this;
179 | }
180 |
181 | /**
182 | * 压缩图片的质量
183 | *
184 | * @param quality
185 | * {@link Float}
186 | * @return
187 | */
188 | public ImageUtils quality(float quality) {
189 | this.quality = quality;
190 | return this;
191 | }
192 |
193 | /**
194 | * 设置背景颜色
195 | *
196 | * @param bgcolor
197 | * @return
198 | */
199 | public ImageUtils bgcolor(Color bgcolor) {
200 | this.bgcolor = bgcolor;
201 | return this;
202 | }
203 |
204 | /**
205 | * 指定生成图片的文件
206 | *
207 | * @param destFile
208 | * {@link File}
209 | */
210 | public void toFile(File destFile) {
211 | this.destFile = destFile;
212 | BufferedImage srcImage = null;
213 | try {
214 | srcImage = ImageIO.read(this.srcFile);
215 | if (this.scale > 0 && this.width == 0 && this.height == 0) {
216 | this.width = (int) (srcImage.getWidth() * this.scale);
217 | this.height = (int) (srcImage.getHeight() * this.scale);
218 | }
219 | if (this.angle != 0) {
220 | try {
221 | srcImage = this.rotateImage(srcImage);
222 | } catch (IOException e) {
223 | e.printStackTrace();
224 | System.out.println("rotate error!");
225 | return;
226 | }
227 | }
228 | } catch (IOException e1) {
229 | e1.printStackTrace();
230 | System.out.println("read image error!");
231 | return;
232 | }
233 | BufferedImage destImage = this.resize(srcImage);
234 | if (this.keepRatio) {
235 | destImage = this.keepImageRatio(destImage, this.givenWidth, this.givenHeight);
236 | }
237 | if (this.watermarkArr != null) {
238 | for (Watermark watermark : watermarkArr) {
239 | destImage = watermark.apply(destImage);
240 | }
241 | }
242 | try {
243 | this.makeImage(destImage);
244 | } catch (IOException e) {
245 | e.printStackTrace();
246 | System.out.println("create image error!");
247 | }
248 | }
249 |
250 | /**
251 | * 保存图片的原比例,并计算原图片
252 | *
253 | * @param img
254 | * {@link BufferedImage} 原图片
255 | * @param targetWidth
256 | * {@link Integer} 目标宽度
257 | * @param targetHeight
258 | * {@link Integer} 目标高度
259 | * @return 返回计算结果数组
260 | */
261 | private BufferedImage keepImageRatio(BufferedImage img, int targetWidth, int targetHeight) {
262 | int sourceWidth = img.getWidth();
263 | int sourceHeight = img.getHeight();
264 | int x = 0;
265 | int y = 0;
266 | int drawWidth = targetWidth;
267 | int drawHeight = targetHeight;
268 |
269 | double sourceRatio = (double) sourceWidth / (double) sourceHeight;
270 | double targetRatio = (double) targetWidth / (double) targetHeight;
271 |
272 | /*
273 | * If the ratios are not the same, then the appropriate width and height
274 | * must be picked.
275 | */
276 | if (Double.compare(sourceRatio, targetRatio) != 0) {
277 | if (sourceRatio > targetRatio) {
278 | drawHeight = (int) Math.round(targetWidth / sourceRatio);
279 | } else {
280 | drawWidth = (int) Math.round(targetHeight * sourceRatio);
281 | }
282 | }
283 | x = (targetWidth - drawWidth) / 2;
284 | y = (targetHeight - drawHeight) / 2;
285 | targetWidth = (targetWidth == 0) ? 1 : targetWidth;
286 | targetHeight = (targetHeight == 0) ? 1 : targetHeight;
287 | /*
288 | * BufferedImage resizedImage = Utils.createImage(img, targetWidth,
289 | * targetHeight, this.bgcolor);
290 | */
291 | int type = BufferedImage.TYPE_INT_ARGB;
292 | BufferedImage resizedImage = new BufferedImage(targetWidth, targetHeight, type);
293 | Graphics2D g = resizedImage.createGraphics();
294 | Utils.setRenderingHint(g);
295 | if (this.bgcolor != null) {
296 | g.setPaint(this.bgcolor);
297 | g.fillRect(0, 0, targetWidth, targetHeight);
298 | }
299 | g.drawImage(img, x, y, drawWidth, drawHeight, null);
300 | g.dispose();
301 |
302 | return resizedImage;
303 | }
304 |
305 | /**
306 | * 重新设置图片大小
307 | *
308 | * @param srcImage
309 | * @return
310 | */
311 | private BufferedImage resize(BufferedImage srcImage) {
312 | int width = srcImage.getWidth();
313 | int height = srcImage.getHeight();
314 | if (this.width > 0 && this.height > 0) {
315 | if (this.fixedGivenSize) {
316 | this.givenWidth = this.width;
317 | this.givenHeight = this.height;
318 | if (!this.keepRatio) {
319 | width = this.width;
320 | height = this.height;
321 | }
322 | }
323 | if (this.keepRatio) {
324 | int drawWidth = this.width;
325 | int drawHeight = this.height;
326 | double sourceRatio = (double) width / (double) height;
327 | double targetRatio = (double) this.width / (double) this.height;
328 |
329 | if (Double.compare(sourceRatio, targetRatio) != 0) {
330 | if (sourceRatio > targetRatio) {
331 | drawHeight = (int) Math.round(this.width / sourceRatio);
332 | } else {
333 | drawWidth = (int) Math.round(this.height * sourceRatio);
334 | }
335 | }
336 | if (!this.fixedGivenSize) {
337 | this.givenWidth = drawWidth;
338 | this.givenHeight = drawHeight;
339 | }
340 | width = drawWidth;
341 | height = drawHeight;
342 | }
343 | } else if (this.scale > 0) {
344 | width = (int) (width * this.scale);
345 | height = (int) (height * this.scale);
346 | } else if (this.width > 0 && this.height == 0) {
347 | height = this.width * height / width;
348 | width = this.width;
349 | } else if (this.width == 0 && this.height > 0) {
350 | width = this.height * width / height;
351 | height = this.height;
352 | }
353 | if (width <= 1 || height <= 1) {
354 | throw new IllegalStateException("width or height value error!");
355 | }
356 | this.width = width;
357 | this.height = height;
358 |
359 | this.givenWidth = (this.givenWidth == 0 ? width : this.givenWidth);
360 | this.givenHeight = (this.givenHeight == 0 ? height : this.givenHeight);
361 |
362 | return Utils.createImage(srcImage, width, height, this.bgcolor);
363 | }
364 |
365 | /**
366 | * Returns a {@link BufferedImage} with the specified image type, where the
367 | * graphical content is a copy of the specified image.
368 | *
369 | * @param img
370 | * The image to copy.
371 | * @param imageType
372 | * The image type for the image to return.
373 | * @return A copy of the specified image.
374 | */
375 | public BufferedImage copy(BufferedImage img, int imageType) {
376 | int width = img.getWidth();
377 | int height = img.getHeight();
378 | BufferedImage newImage = new BufferedImage(width, height, imageType);
379 | Graphics g = newImage.createGraphics();
380 | g.drawImage(img, 0, 0, null);
381 | g.dispose();
382 | return newImage;
383 | }
384 |
385 | public void makeImage(BufferedImage newImage) throws IOException {
386 | String fileExtension = getExtension(destFile);
387 | if (fileExtension.equalsIgnoreCase("jpg") || fileExtension.equalsIgnoreCase("jpeg")
388 | || fileExtension.equalsIgnoreCase("bmp")) {
389 | newImage = this.copy(newImage, BufferedImage.TYPE_INT_RGB);
390 | }
391 |
392 | ImageWriter imgWriter = ImageIO.getImageWritersByFormatName(fileExtension).next();
393 | ImageWriteParam imgWriteParam = imgWriter.getDefaultWriteParam();
394 | if (imgWriteParam.canWriteCompressed()) {
395 | if (fileExtension.equalsIgnoreCase("bmp")) {
396 | imgWriteParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
397 | imgWriteParam.setCompressionType("BI_RGB");
398 | } else if (fileExtension.equalsIgnoreCase("gif")) {
399 | imgWriteParam.setCompressionMode(ImageWriteParam.MODE_COPY_FROM_METADATA);
400 | } else {
401 | imgWriteParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
402 | imgWriteParam.setCompressionQuality(this.quality);
403 | }
404 | }
405 | ImageOutputStream outputStream = ImageIO.createImageOutputStream(destFile);
406 | imgWriter.setOutput(outputStream);
407 | IIOImage outputImage = new IIOImage(newImage, null, null);
408 | imgWriter.write(null, outputImage, imgWriteParam);
409 | imgWriter.dispose();
410 | outputStream.close();
411 | }
412 |
413 | private BufferedImage rotateImage(BufferedImage img) throws IOException {
414 | int width = img.getWidth();
415 | int height = img.getHeight();
416 |
417 | BufferedImage newImage;
418 |
419 | double[][] newPositions = new double[4][];
420 | newPositions[0] = this.calculatePosition(0, 0);
421 | newPositions[1] = this.calculatePosition(width, 0);
422 | newPositions[2] = this.calculatePosition(0, height);
423 | newPositions[3] = this.calculatePosition(width, height);
424 |
425 | double minX = Math.min(Math.min(newPositions[0][0], newPositions[1][0]),
426 | Math.min(newPositions[2][0], newPositions[3][0]));
427 | double maxX = Math.max(Math.max(newPositions[0][0], newPositions[1][0]),
428 | Math.max(newPositions[2][0], newPositions[3][0]));
429 | double minY = Math.min(Math.min(newPositions[0][1], newPositions[1][1]),
430 | Math.min(newPositions[2][1], newPositions[3][1]));
431 | double maxY = Math.max(Math.max(newPositions[0][1], newPositions[1][1]),
432 | Math.max(newPositions[2][1], newPositions[3][1]));
433 |
434 | int newWidth = (int) Math.round(maxX - minX);
435 | int newHeight = (int) Math.round(maxY - minY);
436 |
437 | // newImage = new BufferedImageBuilder(newWidth, newHeight).build();
438 | newImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB);
439 |
440 | Graphics2D g = newImage.createGraphics();
441 | Utils.setRenderingHint(g);
442 | if (this.bgcolor != null) {
443 | g.setPaint(this.bgcolor);
444 | g.fillRect(0, 0, newWidth, newHeight);
445 | }
446 | /*
447 | * TODO consider RenderingHints to use. The following are hints which
448 | * have been chosen to give decent image quality. In the future, there
449 | * may be a need to have a way to change these settings.
450 | */
451 | double w = newWidth / 2.0;
452 | double h = newHeight / 2.0;
453 |
454 | int centerX = (int) Math.round((newWidth - width) / 2.0);
455 | int centerY = (int) Math.round((newHeight - height) / 2.0);
456 | g.rotate(Math.toRadians(angle), w, h);
457 | g.drawImage(img, centerX, centerY, null);
458 | g.dispose();
459 | return newImage;
460 | }
461 |
462 | private double[] calculatePosition(double x, double y) {
463 | double angle = this.angle;
464 | angle = Math.toRadians(angle);
465 |
466 | double nx = (Math.cos(angle) * x) - (Math.sin(angle) * y);
467 | double ny = (Math.sin(angle) * x) + (Math.cos(angle) * y);
468 |
469 | return new double[] { nx, ny };
470 | }
471 |
472 | /**
473 | * 返回文件格式
474 | *
475 | * @param f
476 | * {@link File} 文件
477 | * @return 返回文件格式
478 | */
479 | private static String getExtension(File f) {
480 | String fileName = f.getName();
481 | if (fileName.indexOf('.') != -1 && fileName.lastIndexOf('.') != fileName.length() - 1) {
482 | int lastIndex = fileName.lastIndexOf('.');
483 | return fileName.substring(lastIndex + 1);
484 | }
485 | return null;
486 | }
487 |
488 | }
--------------------------------------------------------------------------------
/src/main/java/com/jdk5/blog/image/Position.java:
--------------------------------------------------------------------------------
1 | package com.jdk5.blog.image;
2 |
3 | import java.awt.Point;
4 |
5 | /**
6 | * This interface is implemented by classes which calculate how to position an
7 | * object inside of an enclosing object.
8 | *
9 | */
10 | public interface Position {
11 | /**
12 | * Calculates the position of an object enclosed by an enclosing object.
13 | *
14 | * @param enclosingWidth
15 | * The width of the enclosing object that is to contain the
16 | * enclosed object.
17 | * @param enclosingHeight
18 | * The height of the enclosing object that is to contain the
19 | * enclosed object.
20 | * @param width
21 | * The width of the object that is to be placed inside an
22 | * enclosing object.
23 | * @param height
24 | * The height of the object that is to be placed inside an
25 | * enclosing object.
26 | * @param insetLeft
27 | * The inset on the left-hand side of the object to be enclosed.
28 | * @param insetRight
29 | * The inset on the right-hand side of the object to be enclosed.
30 | * @param insetTop
31 | * The inset on the top side of the object to be enclosed.
32 | * @param insetBottom
33 | * The inset on the bottom side of the object to be enclosed.
34 | * @return The position to place the object.
35 | */
36 | public Point calculate(int enclosingWidth, int enclosingHeight, int width,
37 | int height, int insetLeft, int insetRight, int insetTop,
38 | int insetBottom);
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/com/jdk5/blog/image/Positions.java:
--------------------------------------------------------------------------------
1 | package com.jdk5.blog.image;
2 |
3 | import java.awt.Point;
4 | import java.awt.image.ImageFilter;
5 |
6 | /**
7 | * An enum of predefined {@link Position}s.
8 | *
9 | * Primary use of this enum is for selecting a position to place watermarks
10 | * (using the {@link Watermark} class), captions (using the {@link Caption}
11 | * class) and other {@link ImageFilter}s.
12 | *
13 | */
14 | public enum Positions implements Position
15 | {
16 | /**
17 | * Calculates the {@link Point} at which an enclosed image should be placed
18 | * if it is to be placed at the top left-hand corner of the enclosing
19 | * image.
20 | */
21 | TOP_LEFT()
22 | {
23 | public Point calculate(int enclosingWidth, int enclosingHeight,
24 | int width, int height, int insetLeft, int insetRight,
25 | int insetTop, int insetBottom)
26 | {
27 | int x = insetLeft;
28 | int y = insetTop;
29 | return new Point(x, y);
30 | }
31 | },
32 |
33 | /**
34 | * Calculates the {@link Point} at which an enclosed image should be placed
35 | * if it is to be horizontally centered at the top of the enclosing image.
36 | */
37 | TOP_CENTER()
38 | {
39 | public Point calculate(int enclosingWidth, int enclosingHeight,
40 | int width, int height, int insetLeft, int insetRight,
41 | int insetTop, int insetBottom)
42 | {
43 | int x = (enclosingWidth / 2) - (width / 2);
44 | int y = insetTop;
45 | return new Point(x, y);
46 | }
47 | },
48 |
49 | /**
50 | * Calculates the {@link Point} at which an enclosed image should be placed
51 | * if it is to be placed at the top right-hand corner of the enclosing
52 | * image.
53 | */
54 | TOP_RIGHT()
55 | {
56 | public Point calculate(int enclosingWidth, int enclosingHeight,
57 | int width, int height, int insetLeft, int insetRight,
58 | int insetTop, int insetBottom)
59 | {
60 | int x = enclosingWidth - width - insetRight;
61 | int y = insetTop;
62 | return new Point(x, y);
63 | }
64 | },
65 |
66 | /**
67 | * Calculates the {@link Point} at which an enclosed image should be placed
68 | * if it is to be placed vertically centered at the left-hand corner of
69 | * the enclosing image.
70 | */
71 | CENTER_LEFT()
72 | {
73 | public Point calculate(int enclosingWidth, int enclosingHeight,
74 | int width, int height, int insetLeft, int insetRight,
75 | int insetTop, int insetBottom)
76 | {
77 | int x = insetLeft;
78 | int y = (enclosingHeight / 2) - (height / 2);
79 | return new Point(x, y);
80 | }
81 | },
82 |
83 | /**
84 | * Calculates the {@link Point} at which an enclosed image should be placed
85 | * horizontally and vertically centered in the enclosing image.
86 | */
87 | CENTER()
88 | {
89 | public Point calculate(int enclosingWidth, int enclosingHeight,
90 | int width, int height, int insetLeft, int insetRight,
91 | int insetTop, int insetBottom)
92 | {
93 | int x = (enclosingWidth / 2) - (width / 2);
94 | int y = (enclosingHeight / 2) - (height / 2);
95 | return new Point(x, y);
96 | }
97 | },
98 |
99 | /**
100 | * Calculates the {@link Point} at which an enclosed image should be placed
101 | * if it is to be placed vertically centered at the right-hand corner of
102 | * the enclosing image.
103 | */
104 | CENTER_RIGHT()
105 | {
106 | public Point calculate(int enclosingWidth, int enclosingHeight,
107 | int width, int height, int insetLeft, int insetRight,
108 | int insetTop, int insetBottom)
109 | {
110 | int x = enclosingWidth - width - insetRight;
111 | int y = (enclosingHeight / 2) - (height / 2);
112 | return new Point(x, y);
113 | }
114 | },
115 |
116 | /**
117 | * Calculates the {@link Point} at which an enclosed image should be placed
118 | * if it is to be placed at the bottom left-hand corner of the enclosing
119 | * image.
120 | */
121 | BOTTOM_LEFT()
122 | {
123 | public Point calculate(int enclosingWidth, int enclosingHeight,
124 | int width, int height, int insetLeft, int insetRight,
125 | int insetTop, int insetBottom)
126 | {
127 | int x = insetLeft;
128 | int y = enclosingHeight - height - insetBottom;
129 | return new Point(x, y);
130 | }
131 | },
132 |
133 | /**
134 | * Calculates the {@link Point} at which an enclosed image should be placed
135 | * if it is to be horizontally centered at the bottom of the enclosing
136 | * image.
137 | */
138 | BOTTOM_CENTER()
139 | {
140 | public Point calculate(int enclosingWidth, int enclosingHeight,
141 | int width, int height, int insetLeft, int insetRight,
142 | int insetTop, int insetBottom)
143 | {
144 | int x = (enclosingWidth / 2) - (width / 2);
145 | int y = enclosingHeight - height - insetBottom;
146 | return new Point(x, y);
147 | }
148 | },
149 |
150 | /**
151 | * Calculates the {@link Point} at which an enclosed image should be placed
152 | * if it is to be placed at the bottom right-hand corner of the enclosing
153 | * image.
154 | */
155 | BOTTOM_RIGHT()
156 | {
157 | public Point calculate(int enclosingWidth, int enclosingHeight,
158 | int width, int height, int insetLeft, int insetRight,
159 | int insetTop, int insetBottom)
160 | {
161 | int x = enclosingWidth - width - insetRight;
162 | int y = enclosingHeight - height - insetBottom;
163 | return new Point(x, y);
164 | }
165 | },
166 | ;
167 | }
168 |
--------------------------------------------------------------------------------
/src/main/java/com/jdk5/blog/image/Utils.java:
--------------------------------------------------------------------------------
1 | package com.jdk5.blog.image;
2 |
3 | import java.awt.Color;
4 | import java.awt.Graphics2D;
5 | import java.awt.RenderingHints;
6 | import java.awt.image.BufferedImage;
7 | import java.util.HashMap;
8 | import java.util.Map;
9 |
10 | public class Utils {
11 | public static BufferedImage createImage(BufferedImage img, int width,
12 | int height, Color bgcolor) {
13 | int type = BufferedImage.TYPE_INT_ARGB;
14 | BufferedImage newImage = new BufferedImage(width, height, type);
15 |
16 | Graphics2D g = newImage.createGraphics();
17 | setRenderingHint(g);
18 | if (bgcolor != null) {
19 | g.setPaint(bgcolor);
20 | g.fillRect(0, 0, width, width);
21 | }
22 | g.drawImage(img, 0, 0, width, height, null);
23 | g.dispose();
24 | return newImage;
25 | }
26 |
27 | public static void setRenderingHint(Graphics2D g){
28 | Map m = new HashMap();
29 | m.put(RenderingHints.KEY_INTERPOLATION,
30 | RenderingHints.VALUE_INTERPOLATION_BILINEAR);
31 | m.put(RenderingHints.KEY_ALPHA_INTERPOLATION ,
32 | RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
33 | m.put(RenderingHints.KEY_COLOR_RENDERING , RenderingHints.VALUE_COLOR_RENDER_QUALITY);
34 | m.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
35 | m.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
36 | m.put(RenderingHints.KEY_DITHERING , RenderingHints.VALUE_DITHER_ENABLE);
37 | /*
38 | m.put(RenderingHints. , RenderingHints.);
39 | */
40 | g.setRenderingHints(m);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/com/jdk5/blog/image/Watermark.java:
--------------------------------------------------------------------------------
1 | package com.jdk5.blog.image;
2 |
3 | import java.awt.AlphaComposite;
4 | import java.awt.Graphics2D;
5 | import java.awt.Point;
6 | import java.awt.image.BufferedImage;
7 |
8 | /**
9 | * This class applies a watermark to an image.
10 | *
11 | */
12 | public class Watermark {
13 | /**
14 | * The position of the watermark.
15 | */
16 | private final Position position;
17 |
18 | /**
19 | * The watermark image.
20 | */
21 | private BufferedImage watermarkImg;
22 |
23 | /**
24 | * The opacity of the watermark.
25 | */
26 | private final float opacity;
27 |
28 | /**
29 | * Instantiates a filter which applies a watermark to an image.
30 | *
31 | * @param position
32 | * The position of the watermark.
33 | * @param watermarkImg
34 | * The watermark image.
35 | * @param opacity
36 | * The opacity of the watermark.
37 | *
38 | * The value should be between {@code 0.0f} and {@code 1.0f},
39 | * where {@code 0.0f} is completely transparent, and {@code 1.0f}
40 | * is completely opaque.
41 | */
42 | public Watermark(Position position, BufferedImage watermarkImg, float opacity) {
43 | if (position == null) {
44 | throw new NullPointerException("Position is null.");
45 | }
46 | if (watermarkImg == null) {
47 | throw new NullPointerException("Watermark image is null.");
48 | }
49 | if (opacity > 1.0f || opacity < 0.0f) {
50 | throw new IllegalArgumentException("Opacity is out of range of " + "between 0.0f and 1.0f.");
51 | }
52 |
53 | this.position = position;
54 | this.watermarkImg = watermarkImg;
55 | this.opacity = opacity;
56 | }
57 |
58 | public BufferedImage apply(BufferedImage img) {
59 | int width = img.getWidth();
60 | int height = img.getHeight();
61 |
62 | this.resize(width, height);
63 |
64 | BufferedImage imgWithWatermark = Utils.createImage(img, width, height, null);
65 |
66 | int watermarkWidth = watermarkImg.getWidth();
67 | int watermarkHeight = watermarkImg.getHeight();
68 |
69 | Point p = position.calculate(width, height, watermarkWidth, watermarkHeight, 0, 0, 0, 0);
70 |
71 | Graphics2D g = imgWithWatermark.createGraphics();
72 |
73 | // Draw the actual image.
74 | g.drawImage(img, 0, 0, null);
75 |
76 | // Draw the watermark on top.
77 | g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, opacity));
78 |
79 | g.drawImage(watermarkImg, p.x, p.y, null);
80 |
81 | g.dispose();
82 |
83 | return imgWithWatermark;
84 | }
85 |
86 | private int[] resize(int width, int height) {
87 | int wmwidth = this.watermarkImg.getWidth();
88 | int wmheight = this.watermarkImg.getHeight();
89 |
90 | int drawWidth = width;
91 | int drawHeight = height;
92 | double sourceRatio = (double) wmwidth / (double) wmheight;
93 | double targetRatio = (double) width / (double) height;
94 |
95 | if (wmwidth <= drawWidth && wmheight <= drawHeight) {
96 | drawWidth = wmwidth;
97 | drawHeight = wmheight;
98 | } else if (Double.compare(sourceRatio, targetRatio) != 0) {
99 | if (sourceRatio > targetRatio) {
100 | // drawHeight = (int) Math.round(wmwidth / sourceRatio);
101 | drawHeight = (int) (drawWidth * wmheight / wmwidth);
102 | } else {
103 | // drawWidth = (int) Math.round(wmheight * sourceRatio);
104 | drawWidth = wmwidth * drawHeight / wmheight;
105 | }
106 | }
107 | this.watermarkImg = Utils.createImage(this.watermarkImg, drawWidth, drawHeight, null);
108 | int[] size = { drawWidth, drawHeight };
109 | return size;
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/src/main/resources/images/org.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/caipeiming/java-myutils/dc9719101805d9629b4fc4039ea06c1d0725eb66/src/main/resources/images/org.jpg
--------------------------------------------------------------------------------
/src/main/resources/images/org.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/caipeiming/java-myutils/dc9719101805d9629b4fc4039ea06c1d0725eb66/src/main/resources/images/org.png
--------------------------------------------------------------------------------
/src/main/resources/images/watermarkater.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/caipeiming/java-myutils/dc9719101805d9629b4fc4039ea06c1d0725eb66/src/main/resources/images/watermarkater.png
--------------------------------------------------------------------------------
/src/test/java/com/jdk5/blog/IDValidator/IDValidatorTest.java:
--------------------------------------------------------------------------------
1 | package com.jdk5.blog.IDValidator;
2 |
3 | import junit.framework.TestCase;
4 |
5 | /**
6 | * Unit test for simple App.
7 | */
8 | public class IDValidatorTest extends TestCase {
9 | IDValidator validator = new IDValidator();
10 |
11 | /**
12 | * Rigourous Test :-)
13 | */
14 | public void test() {
15 | assertEquals(false, validator.isValid("152103198909218022"));
16 |
17 | String id15 = validator.makeID(true);
18 | System.out.println(id15);
19 | System.out.println(validator.getInfo(id15));
20 | assertTrue(validator.isValid(id15));
21 | String id18 = validator.makeID(false);
22 | System.out.println(id18);
23 | System.out.println(validator.getInfo(id18));
24 | assertTrue(validator.isValid(id18));
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/test/java/com/jdk5/blog/image/ImageUtilsTest.java:
--------------------------------------------------------------------------------
1 | package com.jdk5.blog.image;
2 |
3 | import java.awt.Color;
4 | import java.awt.image.BufferedImage;
5 | import java.io.File;
6 | import java.util.ArrayList;
7 |
8 | import javax.imageio.ImageIO;
9 |
10 | import junit.framework.TestCase;
11 |
12 |
13 | public class ImageUtilsTest extends TestCase {
14 |
15 | public void test() {
16 | try {
17 | String str = ImageUtilsTest.class.getResource("/images/org.jpg").getPath();
18 | File orgJpg = new File(str);
19 | str = ImageUtilsTest.class.getResource("/images/org.png").getPath();
20 | File orgPng = new File(str);
21 | /*
22 | ImageUtils.fromFile(orgJpg)
23 | .quality(0.7f)
24 | .fixedGivenSize(true)
25 | .keepRatio(true)
26 | .size(400, 100)
27 | .toFile(new File("d:\\image\\400_100_not_ratio.jpg"));
28 |
29 | ImageUtils.fromFile(orgJpg)
30 | .quality(0.7f)
31 | .fixedGivenSize(true)
32 | .keepRatio(true)
33 | .size(200, 200)
34 | .toFile(new File("d:\\image\\200_200_not_ratio.jpg"));
35 |
36 | ImageUtils.fromFile(orgJpg)
37 | .quality(0.7f)
38 | .keepRatio(true)
39 | .size(400, 100)
40 | .toFile(new File("d:\\image\\400_100_ratio.jpg"));
41 |
42 | ImageUtils.fromFile(orgJpg)
43 | .quality(0.7f)
44 | .keepRatio(true)
45 | .size(200, 200)
46 | .toFile(new File("d:\\image\\200_200_ratio.jpg"));
47 |
48 | ImageUtils.fromFile(orgJpg)
49 | .quality(0.7f)
50 | .width(700)
51 | .toFile(new File("d:\\image\\test.jpg"));
52 |
53 | ImageUtils.fromFile(orgJpg)
54 | .scale(1)
55 | .rotate(150)
56 | .quality(0.6f)
57 | .bgcolor(Color.BLUE)
58 | .toFile(new File("d:\\image\\test.jpg"));
59 | */
60 | ImageUtils.fromFile(orgPng)
61 | .size(200, 200)
62 | .rotate(34) //旋转角度
63 | .quality(0.6f)
64 | .fixedGivenSize(true)
65 | .keepRatio(true)
66 | .bgcolor(Color.blue) //透明背景
67 | .toFile(new File("d:\\image\\test.png"));
68 | /*
69 | str = ImageUtilsTest.class.getResource("/images/watermarkater.png").getPath();
70 | BufferedImage watermarkImage = ImageIO.read(new File(str));
71 | Watermark watermark = new Watermark(Positions.CENTER,
72 | watermarkImage, 0.6f);
73 | ImageUtils.fromFile(orgPng)
74 | .scale(1)
75 | .watermark(watermark)
76 | .toFile(new File("d:\\image\\test.png"));
77 |
78 | Watermark watermark2 = new Watermark(Positions.BOTTOM_CENTER,
79 | watermarkImage, 0.6f);
80 | ArrayList list = new ArrayList();
81 | list.add(watermark);
82 | list.add(watermark2);
83 | ImageUtils.fromFile(orgPng)
84 | .scale(1)
85 | .watermarkArray(list)
86 | .toFile(new File("d:\\image\\testMul.png"));
87 | */
88 | } catch (Exception e) {
89 | e.printStackTrace();
90 | }
91 | }
92 | }
--------------------------------------------------------------------------------