[Git][java-team/libthumbnailator-java][upstream] New upstream version 0.4.20

Markus Koschany (@apo) gitlab at salsa.debian.org
Wed Sep 13 14:58:11 BST 2023



Markus Koschany pushed to branch upstream at Debian Java Maintainers / libthumbnailator-java


Commits:
ede1f103 by Markus Koschany at 2023-09-13T15:52:14+02:00
New upstream version 0.4.20
- - - - -


9 changed files:

- LICENSE
- README.md
- pom.xml
- src/main/java/net/coobird/thumbnailator/geometry/Region.java
- src/main/java/net/coobird/thumbnailator/tasks/io/BufferedImageSource.java
- src/main/java/net/coobird/thumbnailator/tasks/io/InputStreamImageSource.java
- src/main/resources/META-INF/LICENSE
- src/test/java/net/coobird/thumbnailator/ThumbnailsBuilderTest.java
- src/test/java/net/coobird/thumbnailator/test/BufferedImageComparer.java


Changes:

=====================================
LICENSE
=====================================
@@ -1,6 +1,6 @@
-The MIT License
+MIT License
 
-Copyright (c) 2008-2021 Chris Kroells
+Copyright (c) 2008-2023 Chris Kroells
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal


=====================================
README.md
=====================================
@@ -1,4 +1,4 @@
-_*December 31, 2022: Thumbnailator 0.4.19 has been released!
+_*June 28, 2023: Thumbnailator 0.4.20 has been released!
 See [Changes](https://github.com/coobird/thumbnailator/wiki/Changes) for details.*_
 
 _*Thumbnailator is now available through
@@ -49,7 +49,7 @@ The following pages have more information on what _Thumbnailator_ can do:
 
 * [Features](https://github.com/coobird/thumbnailator/wiki/Features)
 * [Examples](https://github.com/coobird/thumbnailator/wiki/Examples)
-* [Thumbnailator API Documentation](https://coobird.github.io/thumbnailator/javadoc/0.4.19/)
+* [Thumbnailator API Documentation](https://coobird.github.io/thumbnailator/javadoc/0.4.20/)
 * [Frequently Asked Questions](https://github.com/coobird/thumbnailator/wiki/FAQ)
 
 # Disclaimer


=====================================
pom.xml
=====================================
@@ -2,15 +2,15 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>net.coobird</groupId>
   <artifactId>thumbnailator</artifactId>
-  <version>0.4.19</version>
+  <version>0.4.20</version>
   <packaging>jar</packaging>
   <name>thumbnailator</name>
   <description>Thumbnailator - a thumbnail generation library for Java</description>
   <url>https://github.com/coobird/thumbnailator</url>
   <licenses>
     <license>
-      <name>The MIT License (MIT)</name>
-      <url>http://www.opensource.org/licenses/mit-license.html</url>
+      <name>MIT License</name>
+      <url>https://spdx.org/licenses/MIT.html</url>
       <distribution>repo</distribution>
     </license>
   </licenses>
@@ -23,7 +23,7 @@
     <developer>
       <name>Chris Kroells</name>
       <email>coobirdnet at gmail.com</email>
-      <url>http://coobird.net</url>
+      <url>https://coobird.net</url>
     </developer>
   </developers>
   <distributionManagement>


=====================================
src/main/java/net/coobird/thumbnailator/geometry/Region.java
=====================================
@@ -1,7 +1,7 @@
 /*
  * Thumbnailator - a thumbnail generation library
  *
- * Copyright (c) 2008-2020 Chris Kroells
+ * Copyright (c) 2008-2023 Chris Kroells
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -91,24 +91,51 @@ public final class Region {
 	 * Calculates the position and size of the enclosed region, relative to the
 	 * enclosing region.
 	 * <p>
-	 * The portions of the enclosed region which lies outside of the enclosing
+	 * The portions of the enclosed region which lies outside the enclosing
 	 * region are ignored. Effectively, the {@link Rectangle} returned by this
-	 * method is a intersection of the enclosing and enclose regions.
+	 * method is an intersection of the enclosing and enclose regions.
 	 * 
-	 * @param width		Width of the enclosing region.
-	 * @param height	Height of the enclosing region.
-	 * @return			Position and size of the enclosed region.
+	 * @param outerWidth		Width of the enclosing region.
+	 * @param outerHeight		Height of the enclosing region.
+	 * @param flipHorizontal	Whether enclosed region should flip
+	 * 							horizontally within the enclosing region.
+	 * @param flipVertical		Whether enclosed region should flip
+	 * 							vertically within the enclosing region.
+	 * @param swapDimensions	Whether the components of the point and
+	 * 							dimension of the enclosed region should be
+	 * 							swapped.
+	 * @return					Position and size of the enclosed region.
 	 */
-	public Rectangle calculate(int width, int height) {
-		Dimension d = size.calculate(width, height);
+	public Rectangle calculate(
+			int outerWidth,
+			int outerHeight,
+			boolean flipHorizontal,
+			boolean flipVertical,
+			boolean swapDimensions
+	) {
+		Dimension innerDimension = size.calculate(outerWidth, outerHeight);
 
-		Point p = position.calculate(
-				width, height, d.width, d.height, 0, 0, 0, 0
+		Point innerPoint = position.calculate(
+				outerWidth, outerHeight, innerDimension.width, innerDimension.height, 0, 0, 0, 0
 		);
-		
-		Rectangle outerRectangle = new Rectangle(0, 0, width, height);
-		Rectangle innerRectangle = new Rectangle(p, d);
-		
+
+		if (swapDimensions) {
+			innerDimension = new Dimension(innerDimension.height, innerDimension.width);
+			innerPoint = new Point(innerPoint.y, innerPoint.x);
+		}
+
+		if (flipHorizontal) {
+			int newX = outerWidth - innerPoint.x - innerDimension.width;
+			innerPoint.setLocation(newX, innerPoint.y);
+		}
+		if (flipVertical) {
+			int newY = outerHeight - innerPoint.y - innerDimension.height;
+			innerPoint.setLocation(innerPoint.x, newY);
+		}
+
+		Rectangle outerRectangle = new Rectangle(0, 0, outerWidth, outerHeight);
+		Rectangle innerRectangle = new Rectangle(innerPoint, innerDimension);
+
 		return outerRectangle.intersection(innerRectangle);
 	}
 


=====================================
src/main/java/net/coobird/thumbnailator/tasks/io/BufferedImageSource.java
=====================================
@@ -1,7 +1,7 @@
 /*
  * Thumbnailator - a thumbnail generation library
  *
- * Copyright (c) 2008-2020 Chris Kroells
+ * Copyright (c) 2008-2023 Chris Kroells
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -66,7 +66,9 @@ public class BufferedImageSource extends AbstractImageSource<BufferedImage> {
 		
 		if (param != null && param.getSourceRegion() != null) {
 			Region region = param.getSourceRegion();
-			Rectangle r = region.calculate(img.getWidth(), img.getHeight());
+			Rectangle r = region.calculate(
+					img.getWidth(), img.getHeight(), false, false, false
+			);
 			
 			return finishedReading(img.getSubimage(r.x, r.y, r.width, r.height));
 		} else {


=====================================
src/main/java/net/coobird/thumbnailator/tasks/io/InputStreamImageSource.java
=====================================
@@ -1,7 +1,7 @@
 /*
  * Thumbnailator - a thumbnail generation library
  *
- * Copyright (c) 2008-2022 Chris Kroells
+ * Copyright (c) 2008-2023 Chris Kroells
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -484,10 +484,9 @@ public class InputStreamImageSource extends AbstractImageSource<InputStream> {
 	}
 
 	private BufferedImage readImage(ImageReader reader) throws IOException {
-
+		Orientation orientation = null;
 		try {
 			if (param.useExifOrientation()) {
-				Orientation orientation = null;
 
 				// Attempt to use Exif reader of the ImageReader.
 				// If the ImageReader fails like seen in Issue #108, use the
@@ -531,9 +530,9 @@ public class InputStreamImageSource extends AbstractImageSource<InputStream> {
 
 		if (param != null && param.getSourceRegion() != null) {
 			Region region = param.getSourceRegion();
-			Rectangle sourceRegion = region.calculate(width, height);
-
-			irParam.setSourceRegion(sourceRegion);
+			irParam.setSourceRegion(
+					calculateSourceRegion(width, height, orientation, region)
+			);
 		}
 
 		/*
@@ -594,6 +593,52 @@ public class InputStreamImageSource extends AbstractImageSource<InputStream> {
 		return reader.read(FIRST_IMAGE_INDEX, irParam);
 	}
 
+	private Rectangle calculateSourceRegion(int width, int height, Orientation orientation, Region region) {
+		boolean flipHorizontal = false;
+		boolean flipVertical = false;
+		boolean swapDimensions = false;
+
+		/*
+		 * Fix for Issue 207:
+		 * https://github.com/coobird/thumbnailator/issues/207
+		 *
+		 * Source region should be selected from the image _after_ applying
+		 * the Exif orientation. Therefore, we need to change the source
+		 * region based on the Exif orientation, as source pixels will be
+		 * oriented differently.
+		 */
+		if (orientation == Orientation.TOP_RIGHT) {
+			flipHorizontal = true;
+
+		} else if (orientation == Orientation.BOTTOM_RIGHT) {
+			flipHorizontal = true;
+			flipVertical = true;
+
+		} else if (orientation == Orientation.BOTTOM_LEFT) {
+			flipVertical = true;
+
+		} else if (orientation == Orientation.LEFT_TOP) {
+			swapDimensions = true;
+
+		} else if (orientation == Orientation.RIGHT_TOP) {
+			flipVertical = true;
+			swapDimensions = true;
+
+		} else if (orientation == Orientation.RIGHT_BOTTOM) {
+			flipHorizontal = true;
+			flipVertical = true;
+			swapDimensions = true;
+
+		} else if (orientation == Orientation.LEFT_BOTTOM) {
+			flipHorizontal = true;
+			swapDimensions = true;
+		}
+
+		return region.calculate(
+				width, height, flipHorizontal, flipVertical, swapDimensions
+		);
+	}
+
 	public InputStream getSource() {
 		return is;
 	}


=====================================
src/main/resources/META-INF/LICENSE
=====================================
@@ -1,6 +1,6 @@
-The MIT License
+MIT License
 
-Copyright (c) 2008-2021 Chris Kroells
+Copyright (c) 2008-2023 Chris Kroells
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal


=====================================
src/test/java/net/coobird/thumbnailator/ThumbnailsBuilderTest.java
=====================================
@@ -1,7 +1,7 @@
 /*
  * Thumbnailator - a thumbnail generation library
  *
- * Copyright (c) 2008-2022 Chris Kroells
+ * Copyright (c) 2008-2023 Chris Kroells
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -4405,6 +4405,208 @@ public class ThumbnailsBuilderTest {
 		}
 	}
 
+	@RunWith(Parameterized.class)
+	public static class SourceRegionTests {
+		// Error tolerance to deal with JPEG artifacts.
+		private static final int MAX_ERROR = 3;
+		private static final BufferedImage EXPECTED_GRID_IMAGE;
+		private static final BufferedImage EXPECTED_F_IMAGE;
+		private static final BufferedImage EXPECTED_GRID_TOP_LEFT_SHIFT_IMAGE;
+		private static final BufferedImage EXPECTED_F_TOP_LEFT_SHIFT_IMAGE;
+		private static final BufferedImage EXPECTED_GRID_BOTTOM_LEFT_SHIFT_IMAGE;
+		private static final BufferedImage EXPECTED_F_BOTTOM_LEFT_SHIFT_IMAGE;
+		private static final BufferedImage EXPECTED_GRID_BOTTOM_RIGHT_SHIFT_IMAGE;
+		private static final BufferedImage EXPECTED_F_BOTTOM_RIGHT_SHIFT_IMAGE;
+
+		static {
+			InputStream is;
+			try {
+				is = TestUtils.getResourceStream("Thumbnailator/grid.png");
+				EXPECTED_GRID_IMAGE = ImageIO.read(is).getSubimage(0, 0, 50, 50);
+				is.close();
+
+				is = TestUtils.getResourceStream("Exif/original.png");
+				EXPECTED_F_IMAGE = ImageIO.read(is).getSubimage(0, 0, 80, 80);
+				is.close();
+
+				is = TestUtils.getResourceStream("Thumbnailator/grid.png");
+				EXPECTED_GRID_TOP_LEFT_SHIFT_IMAGE = ImageIO.read(is).getSubimage(10, 20, 50, 30);
+				is.close();
+
+				is = TestUtils.getResourceStream("Exif/original.png");
+				EXPECTED_F_TOP_LEFT_SHIFT_IMAGE = ImageIO.read(is).getSubimage(10, 20, 80, 90);
+				is.close();
+
+				is = TestUtils.getResourceStream("Thumbnailator/grid.png");
+				EXPECTED_GRID_BOTTOM_LEFT_SHIFT_IMAGE = ImageIO.read(is).getSubimage(10, 50, 50, 30);
+				is.close();
+
+				is = TestUtils.getResourceStream("Exif/original.png");
+				EXPECTED_F_BOTTOM_LEFT_SHIFT_IMAGE = ImageIO.read(is).getSubimage(10, 60, 80, 90);
+				is.close();
+
+				is = TestUtils.getResourceStream("Thumbnailator/grid.png");
+				EXPECTED_GRID_BOTTOM_RIGHT_SHIFT_IMAGE = ImageIO.read(is).getSubimage(30, 50, 50, 30);
+				is.close();
+
+				is = TestUtils.getResourceStream("Exif/original.png");
+				EXPECTED_F_BOTTOM_RIGHT_SHIFT_IMAGE = ImageIO.read(is).getSubimage(70, 60, 80, 90);
+				is.close();
+
+			} catch (Exception e) {
+				throw new RuntimeException("Shouldn't happen.", e);
+			}
+		}
+
+		@Parameterized.Parameters(name = "sourceImage={0}, x={2}, y={3}, width={4}, height={5}")
+		public static Object[][] values() {
+			return new Object[][] {
+					new Object[] { "Thumbnailator/grid.png", EXPECTED_GRID_IMAGE, 0, 0, 50, 50 },
+					new Object[] { "Exif/source_1.jpg", EXPECTED_F_IMAGE, 0, 0, 80, 80 },
+					new Object[] { "Exif/source_2.jpg", EXPECTED_F_IMAGE, 0, 0, 80, 80 },
+					new Object[] { "Exif/source_3.jpg", EXPECTED_F_IMAGE, 0, 0, 80, 80 },
+					new Object[] { "Exif/source_4.jpg", EXPECTED_F_IMAGE, 0, 0, 80, 80 },
+					new Object[] { "Exif/source_5.jpg", EXPECTED_F_IMAGE, 0, 0, 80, 80 },
+					new Object[] { "Exif/source_6.jpg", EXPECTED_F_IMAGE, 0, 0, 80, 80 },
+					new Object[] { "Exif/source_7.jpg", EXPECTED_F_IMAGE, 0, 0, 80, 80 },
+					new Object[] { "Exif/source_8.jpg", EXPECTED_F_IMAGE, 0, 0, 80, 80 },
+					new Object[] { "Thumbnailator/grid.png", EXPECTED_GRID_TOP_LEFT_SHIFT_IMAGE, 10, 20, 50, 30 },
+					new Object[] { "Exif/source_1.jpg", EXPECTED_F_TOP_LEFT_SHIFT_IMAGE, 10, 20, 80, 90 },
+					new Object[] { "Exif/source_2.jpg", EXPECTED_F_TOP_LEFT_SHIFT_IMAGE, 10, 20, 80, 90 },
+					new Object[] { "Exif/source_3.jpg", EXPECTED_F_TOP_LEFT_SHIFT_IMAGE, 10, 20, 80, 90 },
+					new Object[] { "Exif/source_4.jpg", EXPECTED_F_TOP_LEFT_SHIFT_IMAGE, 10, 20, 80, 90 },
+					new Object[] { "Exif/source_5.jpg", EXPECTED_F_TOP_LEFT_SHIFT_IMAGE, 10, 20, 80, 90 },
+					new Object[] { "Exif/source_6.jpg", EXPECTED_F_TOP_LEFT_SHIFT_IMAGE, 10, 20, 80, 90 },
+					new Object[] { "Exif/source_7.jpg", EXPECTED_F_TOP_LEFT_SHIFT_IMAGE, 10, 20, 80, 90 },
+					new Object[] { "Exif/source_8.jpg", EXPECTED_F_TOP_LEFT_SHIFT_IMAGE, 10, 20, 80, 90 },
+					new Object[] { "Thumbnailator/grid.png", EXPECTED_GRID_BOTTOM_LEFT_SHIFT_IMAGE, 10, 50, 50, 30 },
+					new Object[] { "Exif/source_1.jpg", EXPECTED_F_BOTTOM_LEFT_SHIFT_IMAGE, 10, 60, 80, 90 },
+					new Object[] { "Exif/source_2.jpg", EXPECTED_F_BOTTOM_LEFT_SHIFT_IMAGE, 10, 60, 80, 90 },
+					new Object[] { "Exif/source_3.jpg", EXPECTED_F_BOTTOM_LEFT_SHIFT_IMAGE, 10, 60, 80, 90 },
+					new Object[] { "Exif/source_4.jpg", EXPECTED_F_BOTTOM_LEFT_SHIFT_IMAGE, 10, 60, 80, 90 },
+					new Object[] { "Exif/source_5.jpg", EXPECTED_F_BOTTOM_LEFT_SHIFT_IMAGE, 10, 60, 80, 90 },
+					new Object[] { "Exif/source_6.jpg", EXPECTED_F_BOTTOM_LEFT_SHIFT_IMAGE, 10, 60, 80, 90 },
+					new Object[] { "Exif/source_7.jpg", EXPECTED_F_BOTTOM_LEFT_SHIFT_IMAGE, 10, 60, 80, 90 },
+					new Object[] { "Exif/source_8.jpg", EXPECTED_F_BOTTOM_LEFT_SHIFT_IMAGE, 10, 60, 80, 90 },
+					new Object[] { "Thumbnailator/grid.png", EXPECTED_GRID_BOTTOM_RIGHT_SHIFT_IMAGE, 30, 50, 50, 30 },
+					new Object[] { "Exif/source_1.jpg", EXPECTED_F_BOTTOM_RIGHT_SHIFT_IMAGE, 70, 60, 80, 90 },
+					new Object[] { "Exif/source_2.jpg", EXPECTED_F_BOTTOM_RIGHT_SHIFT_IMAGE, 70, 60, 80, 90 },
+					new Object[] { "Exif/source_3.jpg", EXPECTED_F_BOTTOM_RIGHT_SHIFT_IMAGE, 70, 60, 80, 90 },
+					new Object[] { "Exif/source_4.jpg", EXPECTED_F_BOTTOM_RIGHT_SHIFT_IMAGE, 70, 60, 80, 90 },
+					new Object[] { "Exif/source_5.jpg", EXPECTED_F_BOTTOM_RIGHT_SHIFT_IMAGE, 70, 60, 80, 90 },
+					new Object[] { "Exif/source_6.jpg", EXPECTED_F_BOTTOM_RIGHT_SHIFT_IMAGE, 70, 60, 80, 90 },
+					new Object[] { "Exif/source_7.jpg", EXPECTED_F_BOTTOM_RIGHT_SHIFT_IMAGE, 70, 60, 80, 90 },
+					new Object[] { "Exif/source_8.jpg", EXPECTED_F_BOTTOM_RIGHT_SHIFT_IMAGE, 70, 60, 80, 90 },
+			};
+		}
+
+		@Parameterized.Parameter
+		public String resourcePath;
+
+		@Parameterized.Parameter(1)
+		public BufferedImage expectedImage;
+
+		@Parameterized.Parameter(2)
+		public int x;
+
+		@Parameterized.Parameter(3)
+		public int y;
+
+		@Parameterized.Parameter(4)
+		public int width;
+
+		@Parameterized.Parameter(5)
+		public int height;
+
+		@Rule
+		public TemporaryFolder temporaryFolder = new TemporaryFolder();
+
+		@Test
+		public void sourceRegion_Region() throws IOException {
+			// given
+			File sourceFile = TestUtils.copyResourceToTemporaryFile(resourcePath, temporaryFolder);
+
+			// when
+			BufferedImage thumbnail = Thumbnails.of(sourceFile)
+					.sourceRegion(new Region(new Coordinate(x, y), new AbsoluteSize(width, height)))
+					.size(width, height)
+					.asBufferedImage();
+
+			// then
+			assertEquals(width, thumbnail.getWidth());
+			assertEquals(height, thumbnail.getHeight());
+			assertTrue(BufferedImageComparer.isRGBSimilar(thumbnail, expectedImage, MAX_ERROR));
+		}
+
+		@Test
+		public void sourceRegion_Rectangle() throws IOException {
+			// given
+			File sourceFile = TestUtils.copyResourceToTemporaryFile(resourcePath, temporaryFolder);
+
+			// when
+			BufferedImage thumbnail = Thumbnails.of(sourceFile)
+					.sourceRegion(new Rectangle(x, y, width, height))
+					.size(width, height)
+					.asBufferedImage();
+
+			// then
+			assertEquals(width, thumbnail.getWidth());
+			assertEquals(height, thumbnail.getHeight());
+			assertTrue(BufferedImageComparer.isRGBSimilar(thumbnail, expectedImage, MAX_ERROR));
+		}
+
+		@Test
+		public void sourceRegion_PositionSize() throws IOException {
+			// given
+			File sourceFile = TestUtils.copyResourceToTemporaryFile(resourcePath, temporaryFolder);
+
+			// when
+			BufferedImage thumbnail = Thumbnails.of(sourceFile)
+					.sourceRegion(new Coordinate(x, y), new AbsoluteSize(width, height))
+					.size(width, height)
+					.asBufferedImage();
+
+			// then
+			assertEquals(width, thumbnail.getWidth());
+			assertEquals(height, thumbnail.getHeight());
+			assertTrue(BufferedImageComparer.isRGBSimilar(thumbnail, expectedImage, MAX_ERROR));
+		}
+
+		@Test
+		public void sourceRegion_PositionIntInt() throws IOException {
+			// given
+			File sourceFile = TestUtils.copyResourceToTemporaryFile(resourcePath, temporaryFolder);
+
+			// when
+			BufferedImage thumbnail = Thumbnails.of(sourceFile)
+					.sourceRegion(new Coordinate(x, y), width, height)
+					.size(width, height)
+					.asBufferedImage();
+
+			// then
+			assertEquals(width, thumbnail.getWidth());
+			assertEquals(height, thumbnail.getHeight());
+			assertTrue(BufferedImageComparer.isRGBSimilar(thumbnail, expectedImage, MAX_ERROR));
+		}
+
+		@Test
+		public void sourceRegion_IntIntIntInt() throws IOException {
+			// given
+			File sourceFile = TestUtils.copyResourceToTemporaryFile(resourcePath, temporaryFolder);
+
+			// when
+			BufferedImage thumbnail = Thumbnails.of(sourceFile)
+					.sourceRegion(x, y, width, height)
+					.size(width, height)
+					.asBufferedImage();
+
+			// then
+			assertEquals(width, thumbnail.getWidth());
+			assertEquals(height, thumbnail.getHeight());
+			assertTrue(BufferedImageComparer.isRGBSimilar(thumbnail, expectedImage, 5));
+		}
+	}
+
 	@RunWith(Parameterized.class)
 	public static class WatermarkPositioningTests {
 		@Parameterized.Parameters(name = "position={0}, x={1}, y={2}")


=====================================
src/test/java/net/coobird/thumbnailator/test/BufferedImageComparer.java
=====================================
@@ -1,7 +1,7 @@
 /*
  * Thumbnailator - a thumbnail generation library
  *
- * Copyright (c) 2008-2020 Chris Kroells
+ * Copyright (c) 2008-2023 Chris Kroells
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -139,4 +139,47 @@ public final class BufferedImageComparer {
 		
 		return true;
 	}
+
+	// Checks if the pixels are similar.
+	public static final boolean isRGBSimilar(BufferedImage img0, BufferedImage img1, int maxError) {
+		int width0 = img0.getWidth();
+		int height0 = img0.getHeight();
+		int width1 = img1.getWidth();
+		int height1 = img1.getHeight();
+
+		if (width0 != width1 || height0 != height1) {
+			throw new AssertionError("Width and/or height do not match.");
+		}
+
+		/*
+		 * Check the RGB data.
+		 */
+		for (int i = 0; i < width0; i++) {
+			for (int j = 0; j < height0; j++) {
+				int v0 = img0.getRGB(i, j);
+				int v1 = img1.getRGB(i, j);
+
+				int r0 = (v0 << 8) >>> 24;
+				int r1 = (v1 << 8) >>> 24;
+				int g0 = (v0 << 16) >>> 24;
+				int g1 = (v1 << 16) >>> 24;
+				int b0 = (v0 << 24) >>> 24;
+				int b1 = (v1 << 24) >>> 24;
+
+				int rError = Math.abs(r1 - r0);
+				int gError = Math.abs(g1 - g0);
+				int bError = Math.abs(b1 - b0);
+
+				if (rError > maxError || gError > maxError || bError > maxError) {
+					String message = String.format(
+							"Pixels errors too large. location: (%d, %d), rgb: ([%d, %d, %d], [%d, %d, %d])",
+							i, j, r0, g0, b0, r1, g1, b1
+					);
+					throw new AssertionError(message);
+				}
+			}
+		}
+
+		return true;
+	}
 }



View it on GitLab: https://salsa.debian.org/java-team/libthumbnailator-java/-/commit/ede1f1030d27d94dc1ecc7986d39a01c0f0be4e7

-- 
View it on GitLab: https://salsa.debian.org/java-team/libthumbnailator-java/-/commit/ede1f1030d27d94dc1ecc7986d39a01c0f0be4e7
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-java-commits/attachments/20230913/0a9687e8/attachment.htm>


More information about the pkg-java-commits mailing list