/**
   * Tests the {@link ImageWorker#makeColorTransparent} methods. Some trivial tests are performed
   * before.
   *
   * @throws IOException
   * @throws FileNotFoundException
   * @throws IllegalStateException
   */
  @Test
  public void testMakeColorTransparent()
      throws IllegalStateException, FileNotFoundException, IOException {
    assertTrue("Assertions should be enabled.", ImageWorker.class.desiredAssertionStatus());
    ImageWorker worker = new ImageWorker(sstImage);

    assertSame(sstImage, worker.getRenderedImage());
    assertEquals(1, worker.getNumBands());
    assertEquals(-1, worker.getTransparentPixel());
    assertTrue(worker.isBytes());
    assertFalse(worker.isBinary());
    assertTrue(worker.isIndexed());
    assertTrue(worker.isColorSpaceRGB());
    assertFalse(worker.isColorSpaceGRAYScale());
    assertFalse(worker.isTranslucent());

    assertSame(
        "Expected no operation.", sstImage, worker.forceIndexColorModel(false).getRenderedImage());
    assertSame(
        "Expected no operation.", sstImage, worker.forceIndexColorModel(true).getRenderedImage());
    assertSame("Expected no operation.", sstImage, worker.forceColorSpaceRGB().getRenderedImage());
    assertSame("Expected no operation.", sstImage, worker.retainFirstBand().getRenderedImage());
    assertSame("Expected no operation.", sstImage, worker.retainLastBand().getRenderedImage());

    // Following will change image, so we need to test after the above assertions.
    assertEquals(0, worker.getMinimums()[0], 0);
    assertEquals(255, worker.getMaximums()[0], 0);
    assertNotSame(sstImage, worker.getRenderedImage());
    assertSame(
        "Expected same databuffer, i.e. pixels should not be duplicated.",
        sstImage.getTile(0, 0).getDataBuffer(),
        worker.getRenderedImage().getTile(0, 0).getDataBuffer());

    assertSame(worker, worker.makeColorTransparent(Color.WHITE));
    assertEquals(255, worker.getTransparentPixel());
    assertFalse(worker.isTranslucent());
    assertSame(
        "Expected same databuffer, i.e. pixels should not be duplicated.",
        sstImage.getTile(0, 0).getDataBuffer(),
        worker.getRenderedImage().getTile(0, 0).getDataBuffer());

    // INDEX TO INDEX-ALPHA
    worker = new ImageWorker(chlImage).makeColorTransparent(Color.black);
    show(worker, "CHL01195.png");
    assertEquals(1, worker.getNumBands());
    assertEquals(0, worker.getTransparentPixel());
    assertTrue(worker.isBytes());
    assertTrue(worker.isIndexed());
    assertTrue(worker.isColorSpaceRGB());
    assertFalse(worker.isColorSpaceGRAYScale());
    assertFalse(worker.isTranslucent());
    RenderedImage image = worker.getRenderedImage();
    assertTrue(image.getColorModel() instanceof IndexColorModel);
    IndexColorModel iColorModel = (IndexColorModel) image.getColorModel();
    int transparentColor = iColorModel.getRGB(worker.getTransparentPixel()) & 0x00ffffff;
    assertTrue(transparentColor == 0);

    // INDEX TO INDEX-ALPHA
    worker = new ImageWorker(bathy).makeColorTransparent(Color.WHITE);
    show(worker, "BATHY.png");
    assertEquals(1, worker.getNumBands());
    assertEquals(206, worker.getTransparentPixel());
    assertTrue(worker.isBytes());
    assertTrue(worker.isIndexed());
    assertTrue(worker.isColorSpaceRGB());
    assertFalse(worker.isColorSpaceGRAYScale());
    assertFalse(worker.isTranslucent());
    image = worker.getRenderedImage();
    assertTrue(image.getColorModel() instanceof IndexColorModel);
    iColorModel = (IndexColorModel) image.getColorModel();
    transparentColor = iColorModel.getRGB(worker.getTransparentPixel()) & 0x00ffffff;
    assertTrue(transparentColor == (Color.WHITE.getRGB() & 0x00ffffff));

    // RGB TO RGBA
    worker = new ImageWorker(smallWorld).makeColorTransparent(new Color(11, 10, 50));
    show(worker, "small_world.png");
    assertEquals(4, worker.getNumBands());
    assertEquals(-1, worker.getTransparentPixel());
    assertTrue(worker.isBytes());
    assertFalse(worker.isIndexed());
    assertTrue(worker.isColorSpaceRGB());
    assertFalse(worker.isColorSpaceGRAYScale());
    assertTrue(worker.isTranslucent());
    image = worker.getRenderedImage();
    assertTrue(image.getColorModel() instanceof ComponentColorModel);

    // RGBA to RGBA
    worker = new ImageWorker(worldImage).makeColorTransparent(Color.white);
    show(worker, "world.png");
    assertEquals(4, worker.getNumBands());
    assertEquals(-1, worker.getTransparentPixel());
    assertTrue(worker.isBytes());
    assertFalse(worker.isIndexed());
    assertTrue(worker.isColorSpaceRGB());
    assertFalse(worker.isColorSpaceGRAYScale());
    assertTrue(worker.isTranslucent());
    image = worker.getRenderedImage();
    assertTrue(image.getColorModel() instanceof ComponentColorModel);

    // GRAY TO GRAY-ALPHA
    worker = new ImageWorker(gray).makeColorTransparent(Color.black);
    show(worker, "gray.png");
    assertEquals(2, worker.getNumBands());
    assertEquals(-1, worker.getTransparentPixel());
    assertTrue(worker.isBytes());
    assertFalse(worker.isIndexed());
    assertFalse(worker.isColorSpaceRGB());
    assertTrue(worker.isColorSpaceGRAYScale());
    assertTrue(worker.isTranslucent());
    image = worker.getRenderedImage();
    assertTrue(image.getColorModel() instanceof ComponentColorModel);

    // GRAY-ALPHA TO GRAY-ALPHA.
    worker = new ImageWorker(grayAlpha).makeColorTransparent(Color.black);
    show(worker, "gray-alpha.png");
    assertEquals(2, worker.getNumBands());
    assertEquals(-1, worker.getTransparentPixel());
    assertTrue(worker.isBytes());
    assertFalse(worker.isIndexed());
    assertFalse(worker.isColorSpaceRGB());
    assertTrue(worker.isColorSpaceGRAYScale());
    assertTrue(worker.isTranslucent());
    image = worker.getRenderedImage();
    assertTrue(image.getColorModel() instanceof ComponentColorModel);
  }
  /** Tests the {@link #rescaleToBytes()} operation. */
  @Test
  public void rescaleToBytes() {

    assertTrue("Assertions should be enabled.", ImageWorker.class.desiredAssertionStatus());

    // set up synthetic images for testing
    final RenderedImage test1 =
        ConstantDescriptor.create(128.0f, 128.0f, new Double[] {20000.0}, null);
    final RenderedImage test2 =
        ConstantDescriptor.create(128.0f, 128.0f, new Double[] {255.0}, null);
    final RenderedImage test3 = getSynthetic(20000);
    final RenderedImage test4 = getSynthetic(255);

    // starting to check the results

    // single band value exceed the byte upper bound and is constant
    final ImageWorker test1I = new ImageWorker(test1).rescaleToBytes();
    Assert.assertEquals("Format", test1I.getRenderedOperation().getOperationName());
    final double[] maximums1 = test1I.getMaximums();
    Assert.assertTrue(maximums1.length == 1);
    Assert.assertEquals(255.0, maximums1[0], 1E-10);
    final double[] minimums1 = test1I.getMinimums();
    Assert.assertTrue(minimums1.length == 1);
    Assert.assertEquals(255.0, minimums1[0], 1E-10);

    // single band value does not exceed the byte upper bound and is constant
    final ImageWorker test2I = new ImageWorker(test2).rescaleToBytes();
    Assert.assertEquals("Format", test2I.getRenderedOperation().getOperationName());
    final double[] maximums2 = test1I.getMaximums();
    Assert.assertTrue(maximums2.length == 1);
    Assert.assertEquals(255.0, maximums2[0], 1E-10);
    final double[] minimums2 = test1I.getMinimums();
    Assert.assertTrue(minimums2.length == 1);
    Assert.assertEquals(255.0, minimums2[0], 1E-10);

    // single band value exceed the byte upper bound
    ImageWorker test3I = new ImageWorker(test3);
    final double[] maximums3a = test3I.getMaximums();
    final double[] minimums3a = test3I.getMinimums();
    test3I.rescaleToBytes();
    Assert.assertEquals("Rescale", test3I.getRenderedOperation().getOperationName());
    final double[] maximums3b = test3I.getMaximums();
    final double[] minimums3b = test3I.getMinimums();

    if (maximums3a[0] > 255) {
      Assert.assertTrue(Math.abs(maximums3a[0] - maximums3b[0]) > 1E-10);
      Assert.assertTrue(Math.abs(255.0 - maximums3b[0]) >= 0);
    }

    if (minimums3a[0] < 0) {
      Assert.assertTrue(minimums3b[0] >= 0);
    }

    // single band value does not exceed the byte upper bound
    ImageWorker test4I = new ImageWorker(test4);
    final double[] maximums4a = test4I.getMaximums();
    final double[] minimums4a = test4I.getMinimums();
    test4I.rescaleToBytes();
    Assert.assertEquals("Format", test4I.getRenderedOperation().getOperationName());
    final double[] maximums4b = test4I.getMaximums();
    final double[] minimums4b = test4I.getMinimums();
    Assert.assertEquals(maximums4a[0], maximums4b[0], 1E-10);
    Assert.assertEquals(minimums4a[0], minimums4b[0], 1E-10);

    // now test multibands case
    final RenderedImage multiband = BandMergeDescriptor.create(test2, test3, null);
    ImageWorker testmultibandI = new ImageWorker(multiband);
    final double[] maximums5a = testmultibandI.getMaximums();
    final double[] minimums5a = testmultibandI.getMinimums();
    testmultibandI.rescaleToBytes();
    final double[] maximums5b = testmultibandI.getMaximums();
    final double[] minimums5b = testmultibandI.getMinimums();
    Assert.assertEquals(maximums5a[0], maximums5b[0], 1E-10);
    Assert.assertEquals(minimums5a[0], minimums5b[0], 1E-10);

    Assert.assertTrue(Math.abs(maximums5a[1] - maximums5b[1]) > 1E-10);
    Assert.assertTrue(Math.abs(minimums5a[1] - minimums5b[1]) > 1E-10);
  }