| 1 | // Jomic - a viewer for comic book archives. |
| 2 | // Copyright (C) 2004-2011 Thomas Aglassinger |
| 3 | // |
| 4 | // This program is free software: you can redistribute it and/or modify |
| 5 | // it under the terms of the GNU General Public License as published by |
| 6 | // the Free Software Foundation, either version 3 of the License, or |
| 7 | // (at your option) any later version. |
| 8 | // |
| 9 | // This program is distributed in the hope that it will be useful, |
| 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 | // GNU General Public License for more details. |
| 13 | // |
| 14 | // You should have received a copy of the GNU General Public License |
| 15 | // along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 16 | package net.sf.jomic.tools; |
| 17 | |
| 18 | import java.awt.Color; |
| 19 | import java.awt.Dimension; |
| 20 | import java.awt.Transparency; |
| 21 | import java.awt.color.ColorSpace; |
| 22 | import java.awt.image.BufferedImage; |
| 23 | import java.awt.image.ColorModel; |
| 24 | import java.awt.image.ComponentColorModel; |
| 25 | import java.awt.image.DataBuffer; |
| 26 | import java.awt.image.RenderedImage; |
| 27 | import java.io.File; |
| 28 | import java.io.IOException; |
| 29 | import java.util.NoSuchElementException; |
| 30 | |
| 31 | import javax.imageio.ImageReader; |
| 32 | import javax.imageio.stream.ImageInputStream; |
| 33 | import javax.media.jai.BorderExtenderConstant; |
| 34 | import javax.media.jai.JAI; |
| 35 | import javax.media.jai.ParameterBlockJAI; |
| 36 | import javax.media.jai.PlanarImage; |
| 37 | import javax.media.jai.util.ImagingException; |
| 38 | import javax.swing.JFrame; |
| 39 | |
| 40 | import junit.framework.TestCase; |
| 41 | import net.sf.jomic.jaiunit.Tools; |
| 42 | import org.apache.commons.logging.Log; |
| 43 | import org.apache.commons.logging.LogFactory; |
| 44 | |
| 45 | import com.sun.media.jai.widget.DisplayJAI; |
| 46 | |
| 47 | /** |
| 48 | * Test case for ImageTools. |
| 49 | * |
| 50 | * @author Thomas Aglassinger |
| 51 | */ |
| 52 | public class ImageToolsTest extends TestCase |
| 53 | { |
| 54 | /** |
| 55 | * Number of bits to use per pixel. |
| 56 | */ |
| 57 | private static final int BITS_PER_COMPONENT = 8; |
| 58 | private static final int STANDARD_IMAGE_HEIGHT = 640; |
| 59 | private static final int STANDARD_IMAGE_WIDTH = 480; |
| 60 | |
| 61 | private static Log logger = LogFactory.getLog(ImageToolsTest.class); |
| 62 | |
| 63 | private FileTools fileTools; |
| 64 | private ImageTools imageTools; |
| 65 | private RenderedImage source; |
| 66 | private int sourceHeight; |
| 67 | private int sourceWidth; |
| 68 | private StringTools stringTools; |
| 69 | private TestTools testTools; |
| 70 | |
| 71 | public ImageToolsTest(String arg0) |
| 72 | throws IOException { |
| 73 | super(arg0); |
| 74 | testTools = TestTools.instance(); |
| 75 | source = testTools.getTestImage(); |
| 76 | sourceWidth = source.getWidth(); |
| 77 | sourceHeight = source.getHeight(); |
| 78 | fileTools = FileTools.instance(); |
| 79 | imageTools = ImageTools.instance(); |
| 80 | stringTools = StringTools.instance(); |
| 81 | } |
| 82 | |
| 83 | public void testBrokenEmptyImage() |
| 84 | throws IOException { |
| 85 | try { |
| 86 | imageTools.readImage(testTools.getTestFile(TestTools.TEST_IMAGE_BROKEN_EMPTY_NAME)); |
| 87 | } catch (ImagingException expectedError) { |
| 88 | if (logger.isDebugEnabled()) { |
| 89 | logger.debug("ignoring expected error", expectedError); |
| 90 | } |
| 91 | } |
| 92 | } |
| 93 | |
| 94 | public void testColorFillBorder() { |
| 95 | testColorFillBorder("#000000"); |
| 96 | testColorFillBorder("#ff0000"); |
| 97 | testColorFillBorder("#00ff00"); |
| 98 | testColorFillBorder("#0000ff"); |
| 99 | testColorFillBorder("#ffffff"); |
| 100 | testColorFillBorder("#123456"); |
| 101 | } |
| 102 | |
| 103 | public void testCreateColorBox() { |
| 104 | testCreateColorBox("#123456"); |
| 105 | testCreateColorBox("#808080"); |
| 106 | testCreateColorBox("#ffffff"); |
| 107 | testCreateColorBox("#000000"); |
| 108 | } |
| 109 | |
| 110 | public void testCreateImageInputStream() |
| 111 | throws IOException { |
| 112 | ImageInputStream in; |
| 113 | |
| 114 | File imageFile = testTools.getTestImageFile(); |
| 115 | |
| 116 | in = imageTools.createImageInputStream(imageFile); |
| 117 | assertNotNull(in); |
| 118 | in.close(); |
| 119 | |
| 120 | File textFile = testTools.getTestTextFile(); |
| 121 | |
| 122 | in = imageTools.createImageInputStream(textFile); |
| 123 | assertNotNull(in); |
| 124 | in.close(); |
| 125 | } |
| 126 | |
| 127 | public void testFillColorValues() |
| 128 | throws IOException { |
| 129 | testFillColorValues("#123456", ColorSpace.CS_sRGB); |
| 130 | testFillColorValues("#808080", ColorSpace.CS_sRGB); |
| 131 | testFillColorValues("#ffffff", ColorSpace.CS_sRGB); |
| 132 | testFillColorValues("#000000", ColorSpace.CS_sRGB); |
| 133 | } |
| 134 | |
| 135 | public void testGetDeltaRotation() { |
| 136 | assertEquals(-1, imageTools.getDeltaRotation(0, -1)); |
| 137 | assertEquals(2, imageTools.getDeltaRotation(0, 2)); |
| 138 | assertEquals(0, imageTools.getDeltaRotation(0, 0)); |
| 139 | assertEquals(-1, imageTools.getDeltaRotation(2, 1)); |
| 140 | assertEquals(1, imageTools.getDeltaRotation(2, -1)); |
| 141 | assertEquals(0, imageTools.getDeltaRotation(-1, -1)); |
| 142 | assertEquals(2, imageTools.getDeltaRotation(-1, 1)); |
| 143 | assertEquals(0, imageTools.getDeltaRotation(1, 1)); |
| 144 | } |
| 145 | |
| 146 | public void testGetFixedRotation() { |
| 147 | assertEquals(-1, imageTools.getFixedRotation(-1)); |
| 148 | assertEquals(0, imageTools.getFixedRotation(0)); |
| 149 | assertEquals(1, imageTools.getFixedRotation(1)); |
| 150 | assertEquals(2, imageTools.getFixedRotation(2)); |
| 151 | assertEquals(-1, imageTools.getFixedRotation(3)); |
| 152 | assertEquals(2, imageTools.getFixedRotation(-2)); |
| 153 | assertEquals(1, imageTools.getFixedRotation(-3)); |
| 154 | assertEquals(0, imageTools.getFixedRotation(-4)); |
| 155 | } |
| 156 | |
| 157 | public void testGetGIF89Size() |
| 158 | throws IOException { |
| 159 | testGetSize(TestTools.TEST_IMAGE_GIF89A); |
| 160 | } |
| 161 | |
| 162 | public void testGetGif87aSize() |
| 163 | throws IOException { |
| 164 | testGetSize(TestTools.TEST_IMAGE_GIF87A); |
| 165 | } |
| 166 | |
| 167 | public void testGetIbmTiffSize() |
| 168 | throws IOException { |
| 169 | testGetSize(TestTools.TEST_IMAGE_IBM_TIFF); |
| 170 | } |
| 171 | |
| 172 | public void testGetImageFormat() |
| 173 | throws IOException { |
| 174 | testGetImageFormat("jpeg", TestTools.TEST_IMAGE_JPG_NAME); |
| 175 | testGetImageFormat("png", TestTools.TEST_IMAGE_PNG_NAME); |
| 176 | testGetImageFormat("jpeg", TestTools.TEST_IMAGE_DISGUISED_JPG); |
| 177 | testGetImageFormat("png", TestTools.TEST_IMAGE_DISGUISED_PNG); |
| 178 | testGetImageFormat(null, TestTools.TEST_TEXT_NAME); |
| 179 | } |
| 180 | |
| 181 | public void testGetImageFormat(String expectedFormat, String fileName) |
| 182 | throws IOException { |
| 183 | File imageFile = testTools.getTestFile(fileName); |
| 184 | String actualFormat = imageTools.getImageFormat(imageFile); |
| 185 | |
| 186 | assertEquals("image format must match: " + imageFile, expectedFormat, actualFormat); |
| 187 | } |
| 188 | |
| 189 | public void testGetImageReader() |
| 190 | throws IOException { |
| 191 | ImageInputStream imageStream; |
| 192 | ImageReader reader; |
| 193 | |
| 194 | // Get a reader for an actual image. |
| 195 | imageStream = imageTools.createImageInputStream(testTools.getTestImageFile()); |
| 196 | try { |
| 197 | reader = imageTools.getImageReader(imageStream); |
| 198 | assertNotNull(reader); |
| 199 | reader.dispose(); |
| 200 | } finally { |
| 201 | imageStream.close(); |
| 202 | } |
| 203 | |
| 204 | // Attempt to get a reader for a text file, which won't work. |
| 205 | File testTextFile = testTools.getTestTextFile(); |
| 206 | |
| 207 | imageStream = imageTools.createImageInputStream(testTextFile); |
| 208 | try { |
| 209 | imageTools.getImageReader(imageStream); |
| 210 | fail("must not find reader for text file: " + testTextFile); |
| 211 | } catch (NoSuchElementException expectedError) { |
| 212 | // Ignore expected error. |
| 213 | } finally { |
| 214 | imageStream.close(); |
| 215 | } |
| 216 | } |
| 217 | |
| 218 | public void testGetJpeg2000Size() |
| 219 | throws IOException { |
| 220 | testGetSize(TestTools.TEST_IMAGE_JP2_NAME); |
| 221 | } |
| 222 | |
| 223 | public void testGetJpegSize() |
| 224 | throws IOException { |
| 225 | testGetSize(TestTools.TEST_IMAGE_JPG_NAME); |
| 226 | } |
| 227 | |
| 228 | public void testGetLeftRotation() { |
| 229 | assertEquals(2, imageTools.getLeftRotation(-1)); |
| 230 | assertEquals(-1, imageTools.getLeftRotation(0)); |
| 231 | assertEquals(0, imageTools.getLeftRotation(1)); |
| 232 | assertEquals(1, imageTools.getLeftRotation(2)); |
| 233 | } |
| 234 | |
| 235 | public void testGetMacTiffSize() |
| 236 | throws IOException { |
| 237 | testGetSize(TestTools.TEST_IMAGE_MAC_TIFF); |
| 238 | } |
| 239 | |
| 240 | public void testGetNoSize() |
| 241 | throws IOException { |
| 242 | Dimension noSize = imageTools.getImageDimension(testTools.getTestTextFile()); |
| 243 | |
| 244 | assertNull(noSize); |
| 245 | } |
| 246 | |
| 247 | public void testGetPngSize() |
| 248 | throws IOException { |
| 249 | testGetSize(TestTools.TEST_IMAGE_PNG_NAME); |
| 250 | } |
| 251 | |
| 252 | public void testGetRightRotation() { |
| 253 | assertEquals(0, imageTools.getRightRotation(-1)); |
| 254 | assertEquals(1, imageTools.getRightRotation(0)); |
| 255 | assertEquals(2, imageTools.getRightRotation(1)); |
| 256 | assertEquals(-1, imageTools.getRightRotation(2)); |
| 257 | } |
| 258 | |
| 259 | public void testGrayFillColorValues() |
| 260 | throws IOException { |
| 261 | testFillColorValues("#808080", ColorSpace.CS_GRAY); |
| 262 | testFillColorValues("#ffffff", ColorSpace.CS_GRAY); |
| 263 | testFillColorValues("#000000", ColorSpace.CS_GRAY); |
| 264 | } |
| 265 | |
| 266 | public void testIsCompressedFormat() |
| 267 | throws IOException { |
| 268 | testIsCompressedFormat(TestTools.TEST_IMAGE_JPG_NAME, true); |
| 269 | testIsCompressedFormat(TestTools.TEST_IMAGE_PNG_NAME, true); |
| 270 | testIsCompressedFormat(TestTools.TEST_IMAGE_GIF87A, true); |
| 271 | testIsCompressedFormat(TestTools.TEST_IMAGE_GIF89A, true); |
| 272 | testIsCompressedFormat(TestTools.TEST_IMAGE_MAC_TIFF, false); |
| 273 | } |
| 274 | |
| 275 | public void testRotated() |
| 276 | throws IOException { |
| 277 | RenderedImage image = testTools.getTestImage(); |
| 278 | |
| 279 | for (int rotation = -1; rotation < 3; rotation += 1) { |
| 280 | RenderedImage rotatedImage = imageTools.getRotatedImage(image, rotation); |
| 281 | |
| 282 | if (false) { |
| 283 | showImage(rotatedImage); |
| 284 | } |
| 285 | } |
| 286 | } |
| 287 | |
| 288 | public void testScaleActual() { |
| 289 | RenderedImage target; |
| 290 | |
| 291 | target = imageTools.getSqueezed(source, sourceHeight, sourceWidth, |
| 292 | ImageTools.SCALE_ACTUAL); |
| 293 | assertActualSize(target); |
| 294 | |
| 295 | target = imageTools.getSqueezed(source, sourceHeight, sourceWidth, |
| 296 | ImageTools.SCALE_ACTUAL); |
| 297 | assertActualSize(target); |
| 298 | |
| 299 | target = imageTools.getSqueezed(source, sourceHeight / 3, sourceWidth / 2, |
| 300 | ImageTools.SCALE_ACTUAL); |
| 301 | assertActualSize(target); |
| 302 | } |
| 303 | |
| 304 | public void testScaleFit() { |
| 305 | RenderedImage scaled; |
| 306 | |
| 307 | scaled = imageTools.getSqueezed(source, sourceWidth, sourceHeight, ImageTools.SCALE_FIT); |
| 308 | assertFit(scaled, scaled.getWidth() == sourceWidth); |
| 309 | assertFit(scaled, scaled.getHeight() == sourceHeight); |
| 310 | |
| 311 | scaled = imageTools.getSqueezed(source, 2 * sourceWidth, sourceHeight, |
| 312 | ImageTools.SCALE_FIT); |
| 313 | assertFit(scaled, scaled.getWidth() == sourceWidth); |
| 314 | assertFit(scaled, scaled.getHeight() == sourceHeight); |
| 315 | |
| 316 | scaled = imageTools.getSqueezed(source, sourceWidth, 2 * sourceHeight, |
| 317 | ImageTools.SCALE_FIT); |
| 318 | assertFit(scaled, scaled.getWidth() == sourceWidth); |
| 319 | assertFit(scaled, scaled.getHeight() == sourceHeight); |
| 320 | |
| 321 | scaled = imageTools.getSqueezed(source, sourceWidth / 2, 2 * sourceHeight, |
| 322 | ImageTools.SCALE_FIT); |
| 323 | assertFit(scaled, scaled.getWidth() == sourceWidth / 2); |
| 324 | assertFit(scaled, scaled.getHeight() == sourceHeight / 2); |
| 325 | } |
| 326 | |
| 327 | public void testScaleFitHeight() { |
| 328 | RenderedImage scaled; |
| 329 | |
| 330 | scaled = imageTools.getSqueezed(source, sourceWidth / 10, sourceHeight, |
| 331 | ImageTools.SCALE_HEIGHT); |
| 332 | assertFit(scaled, scaled.getHeight() == sourceHeight); |
| 333 | |
| 334 | scaled = imageTools.getSqueezed(source, sourceWidth * 10, sourceHeight, |
| 335 | ImageTools.SCALE_HEIGHT); |
| 336 | assertFit(scaled, scaled.getHeight() == sourceHeight); |
| 337 | |
| 338 | for (int i = -5; i <= 5; i += 1) { |
| 339 | int width = sourceWidth + i; |
| 340 | |
| 341 | assert width > 0; |
| 342 | scaled = imageTools.getSqueezed(source, width, sourceHeight, |
| 343 | ImageTools.SCALE_HEIGHT); |
| 344 | assertFit(scaled, scaled.getHeight() == sourceHeight); |
| 345 | } |
| 346 | |
| 347 | scaled = imageTools.getSqueezed(source, 1, sourceHeight, |
| 348 | ImageTools.SCALE_HEIGHT); |
| 349 | assertFit(scaled, scaled.getHeight() == sourceHeight); |
| 350 | |
| 351 | scaled = imageTools.getSqueezed(source, Integer.MAX_VALUE, sourceHeight, |
| 352 | ImageTools.SCALE_HEIGHT); |
| 353 | assertFit(scaled, scaled.getHeight() == sourceHeight); |
| 354 | } |
| 355 | |
| 356 | public void testScaleFitWidth() { |
| 357 | RenderedImage scaled; |
| 358 | |
| 359 | scaled = imageTools.getSqueezed(source, sourceWidth, sourceHeight / 10, |
| 360 | ImageTools.SCALE_WIDTH); |
| 361 | assertFit(scaled, scaled.getWidth() == sourceWidth); |
| 362 | |
| 363 | scaled = imageTools.getSqueezed(source, sourceWidth, sourceHeight * 10, |
| 364 | ImageTools.SCALE_WIDTH); |
| 365 | assertFit(scaled, scaled.getWidth() == sourceWidth); |
| 366 | |
| 367 | for (int i = -5; i <= 5; i += 1) { |
| 368 | int height = sourceHeight + i; |
| 369 | |
| 370 | assert height > 0; |
| 371 | scaled = imageTools.getSqueezed(source, sourceWidth, height, |
| 372 | ImageTools.SCALE_WIDTH); |
| 373 | assertFit(scaled, scaled.getWidth() == sourceWidth); |
| 374 | } |
| 375 | |
| 376 | scaled = imageTools.getSqueezed(source, sourceWidth, 1, |
| 377 | ImageTools.SCALE_WIDTH); |
| 378 | assertFit(scaled, scaled.getWidth() == sourceWidth); |
| 379 | |
| 380 | scaled = imageTools.getSqueezed(source, sourceWidth, Integer.MAX_VALUE, |
| 381 | ImageTools.SCALE_WIDTH); |
| 382 | assertFit(scaled, scaled.getWidth() == sourceWidth); |
| 383 | } |
| 384 | |
| 385 | /** |
| 386 | * Test that getSqueezed is reasonably fast compared to reading an image, even if the render |
| 387 | * settings are high quality. |
| 388 | */ |
| 389 | public void testSqueezePerformance() |
| 390 | throws IOException { |
| 391 | long startTimeMillis = System.currentTimeMillis(); |
| 392 | RenderedImage image = imageTools.readImage(testTools.getTestFile("scaled_slowly.jpg")); |
| 393 | long durationForRead = System.currentTimeMillis() - startTimeMillis; |
| 394 | |
| 395 | logger.info("reading lasted " + durationForRead + " ms"); |
| 396 | |
| 397 | startTimeMillis = System.currentTimeMillis(); |
| 398 | imageTools.getSqueezed(image, (int) Math.round(0.23 * image.getWidth()), |
| 399 | 2 * image.getHeight(), ImageTools.SCALE_FIT); |
| 400 | |
| 401 | long durationForSqueeze = System.currentTimeMillis() - startTimeMillis; |
| 402 | |
| 403 | logger.info("squeeze lasted " + durationForSqueeze + " ms"); |
| 404 | testTools.assertLessThan(durationForSqueeze, durationForRead); |
| 405 | } |
| 406 | |
| 407 | private void assertActualSize(RenderedImage target) { |
| 408 | assertFit(target, target.getWidth() == sourceWidth); |
| 409 | assertFit(target, target.getHeight() == sourceHeight); |
| 410 | } |
| 411 | |
| 412 | private void assertFit(RenderedImage image, boolean condition) { |
| 413 | String message = "source = " + sourceWidth + "x" + sourceHeight + " -> scaled=" |
| 414 | + image.getWidth() + "x" + image.getHeight(); |
| 415 | |
| 416 | if (logger.isInfoEnabled()) { |
| 417 | logger.info(message); |
| 418 | } |
| 419 | assertTrue(message, condition); |
| 420 | } |
| 421 | |
| 422 | private void assertPixelEquals(RenderedImage image, int x, int y, String expectedColorText) { |
| 423 | assert image != null; |
| 424 | assert (x >= 0) && (x < image.getWidth()) : "x=" + x; |
| 425 | assert (y >= 0) && (y < image.getHeight()) : "y=" + y; |
| 426 | assert expectedColorText != null; |
| 427 | assert image instanceof BufferedImage : "image must be a BufferedImage (for now)"; |
| 428 | int rgba = ((BufferedImage) image).getRGB(x, y); |
| 429 | String actualColorText = stringTools.colorString(rgba); |
| 430 | |
| 431 | assertEquals(expectedColorText, actualColorText); |
| 432 | } |
| 433 | |
| 434 | private void showImage(RenderedImage both) { |
| 435 | JFrame frame = new JFrame(getClass().getName()); |
| 436 | DisplayJAI imageView = new DisplayJAI(); |
| 437 | |
| 438 | frame.getContentPane().add(imageView); |
| 439 | imageView.set(both); |
| 440 | frame.pack(); |
| 441 | frame.setVisible(true); |
| 442 | testTools.waitSomeTime(); |
| 443 | try { |
| 444 | Thread.sleep(5000); |
| 445 | } catch (InterruptedException error) { |
| 446 | logger.warn("interrupted", error); |
| 447 | } |
| 448 | frame.dispose(); |
| 449 | } |
| 450 | |
| 451 | private void testColorFillBorder(String expectedColorText) { |
| 452 | assert expectedColorText != null; |
| 453 | Tools jaiUnitTools = Tools.instance(); |
| 454 | RenderedImage image = jaiUnitTools.createTestImage( |
| 455 | STANDARD_IMAGE_WIDTH, STANDARD_IMAGE_HEIGHT, BufferedImage.TYPE_INT_RGB, "test", "border at bottom"); |
| 456 | Color color = Color.decode(expectedColorText); |
| 457 | int bottomPad = 10; |
| 458 | double[] fillValues = imageTools.fillColorValues(color, image.getColorModel()); |
| 459 | ParameterBlockJAI pbBorder = new ParameterBlockJAI("border"); |
| 460 | |
| 461 | pbBorder.addSource(image); |
| 462 | pbBorder.setParameter("leftPad", 0); |
| 463 | pbBorder.setParameter("rightPad", 0); |
| 464 | pbBorder.setParameter("topPad", 0); |
| 465 | pbBorder.setParameter("bottomPad", bottomPad); |
| 466 | pbBorder.setParameter("type", new BorderExtenderConstant(fillValues)); |
| 467 | |
| 468 | RenderedImage imageWithBorder = JAI.create("border", pbBorder); |
| 469 | BufferedImage bufferedImageWithBorder = PlanarImage.wrapRenderedImage(imageWithBorder).getAsBufferedImage(); |
| 470 | |
| 471 | if (logger.isDebugEnabled()) { |
| 472 | logger.debug("image=" + image); |
| 473 | } |
| 474 | int argbBorder = bufferedImageWithBorder.getRGB(2, image.getHeight() + 2); |
| 475 | String actualColorText = stringTools.colorString(argbBorder); |
| 476 | |
| 477 | jaiUnitTools.showImage(imageWithBorder, ImageToolsTest.class, "testColorFillBorder"); |
| 478 | assertEquals("actualColorText", expectedColorText, actualColorText); |
| 479 | } |
| 480 | |
| 481 | private void testCreateColorBox(String colorText) { |
| 482 | assert colorText != null; |
| 483 | Color color = Color.decode(colorText); |
| 484 | RenderedImage image = imageTools.createColorBox(STANDARD_IMAGE_WIDTH, STANDARD_IMAGE_HEIGHT, color); |
| 485 | |
| 486 | assertEquals(STANDARD_IMAGE_WIDTH, image.getWidth()); |
| 487 | assertEquals(STANDARD_IMAGE_HEIGHT, image.getHeight()); |
| 488 | assertPixelEquals(image, 1, 1, colorText); |
| 489 | assertPixelEquals(image, STANDARD_IMAGE_WIDTH - 2, 1, colorText); |
| 490 | assertPixelEquals(image, 1, STANDARD_IMAGE_HEIGHT - 2, colorText); |
| 491 | assertPixelEquals(image, STANDARD_IMAGE_WIDTH - 2, STANDARD_IMAGE_HEIGHT - 2, colorText); |
| 492 | } |
| 493 | |
| 494 | private void testFillColorValues(String colorText, int colorSpaceType) |
| 495 | throws IOException { |
| 496 | assert colorText != null; |
| 497 | RenderedImage image = null; |
| 498 | |
| 499 | image = imageTools.readImage(testTools.getTestImageFile()); |
| 500 | if (logger.isDebugEnabled()) { |
| 501 | logger.debug("color image: " + image + ", type=" + image.getColorModel().getTransferType()); |
| 502 | } |
| 503 | Color color = Color.decode(colorText); |
| 504 | ColorSpace colorSpace = ColorSpace.getInstance(colorSpaceType); |
| 505 | int componentCount = colorSpace.getNumComponents(); |
| 506 | int[] bits = new int[componentCount]; |
| 507 | |
| 508 | for (int i = 0; i < componentCount; i += 1) { |
| 509 | bits[i] = BITS_PER_COMPONENT; |
| 510 | } |
| 511 | |
| 512 | ColorModel colorModel = new ComponentColorModel(colorSpace, |
| 513 | false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE); |
| 514 | double[] fillColorValues = imageTools.fillColorValues(color, colorModel); |
| 515 | |
| 516 | assertEquals("fillColorValues.length", componentCount, fillColorValues.length); |
| 517 | |
| 518 | int rgb = 0; |
| 519 | |
| 520 | for (int i = 0; i < componentCount; i += 1) { |
| 521 | double fillColorValue = fillColorValues[i]; |
| 522 | float minValue = colorSpace.getMinValue(i); |
| 523 | float maxValue = colorSpace.getMaxValue(i); |
| 524 | double range = maxValue - minValue; |
| 525 | |
| 526 | if (logger.isInfoEnabled()) { |
| 527 | logger.info("fillColorValues[" + i + "]: " + minValue + " <= " + fillColorValue + " <= " + maxValue); |
| 528 | } |
| 529 | assert fillColorValue <= maxValue |
| 530 | : "fillColorValues[" + i + "]=" + fillColorValue + " but must be <= " + maxValue; |
| 531 | assert fillColorValue >= minValue |
| 532 | : "fillColorValues[" + i + "]=" + fillColorValue + " but must be >= " + minValue; |
| 533 | int component = (int) (fillColorValue * 255.0 / range); |
| 534 | |
| 535 | if (logger.isInfoEnabled()) { |
| 536 | logger.info("rgb=" + rgb + ", c=" + component); |
| 537 | logger.info("rgb*256=" + (rgb * 256)); |
| 538 | logger.info("rgb*256+c=" + (rgb * 256 + component)); |
| 539 | } |
| 540 | rgb = rgb * 256 + component; |
| 541 | } |
| 542 | if (componentCount == 1) { |
| 543 | rgb = rgb * 0x10000 + rgb * 0x100 + rgb; |
| 544 | } |
| 545 | String resultColorText = stringTools.colorString(rgb); |
| 546 | |
| 547 | if (logger.isInfoEnabled()) { |
| 548 | logger.info(colorText + " -> " + resultColorText); |
| 549 | } |
| 550 | assertEquals("resultColorText", colorText, resultColorText); |
| 551 | } |
| 552 | |
| 553 | private void testGetSize(String imageName) |
| 554 | throws IOException { |
| 555 | assert imageName != null; |
| 556 | assert imageName.indexOf('.') >= 0; |
| 557 | |
| 558 | File file = testTools.getTestFile(imageName); |
| 559 | |
| 560 | try { |
| 561 | Dimension dimension = imageTools.getImageDimension(file); |
| 562 | |
| 563 | assertNotNull("dimension", dimension); |
| 564 | assertEquals(STANDARD_IMAGE_WIDTH, dimension.width); |
| 565 | assertEquals(STANDARD_IMAGE_HEIGHT, dimension.height); |
| 566 | } catch (NoSuchElementException error) { |
| 567 | String lastSuffix = fileTools.getSuffix(file); |
| 568 | |
| 569 | logger.warn("cannot get image dimension of \"" |
| 570 | + file + "\": ImageIO plug-in for suffix \"." |
| 571 | + lastSuffix + "\" should be installed."); |
| 572 | } |
| 573 | } |
| 574 | |
| 575 | private void testIsCompressedFormat(String imageName, boolean expectedIsCompressed) |
| 576 | throws IOException { |
| 577 | File imageFile = testTools.getTestFile(imageName); |
| 578 | String imageFormat = imageTools.getImageFormat(imageFile); |
| 579 | boolean actualIsCompressed = imageTools.isCompressedImageFormat(imageFormat); |
| 580 | |
| 581 | assertEquals("compression of image format \"" + imageFormat + "\" from image file " |
| 582 | + stringTools.sourced(imageFile) + " must match", expectedIsCompressed, actualIsCompressed); |
| 583 | } |
| 584 | } |