View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.imaging.palette;
18  
19  import static org.junit.Assert.assertEquals;
20  
21  import java.awt.image.BufferedImage;
22  
23  import org.apache.commons.imaging.ImageWriteException;
24  import org.apache.commons.imaging.ImagingTest;
25  import org.junit.Test;
26  
27  public class PaletteQuantizationTest extends ImagingTest {
28  
29      @Test
30      public void testPaletteQuantization() throws ImageWriteException {
31          final BufferedImage whiteImage = new BufferedImage(10, 10, BufferedImage.TYPE_INT_RGB);
32          for (int y = 0; y < whiteImage.getHeight(); y++) {
33              for (int x = 0; x < whiteImage.getWidth(); x++) {
34                  whiteImage.setRGB(x, y, 0xFFFFFF);
35              }
36          }
37          checkPaletteDetails(whiteImage, 10, 1);
38          
39          final BufferedImage whiteAndBlackImage = new BufferedImage(10, 10, BufferedImage.TYPE_INT_RGB);
40          for (int y = 0; y < whiteImage.getHeight(); y++) {
41              for (int x = 0; x < 5; x++) {
42                  whiteAndBlackImage.setRGB(x, y, 0xFFFFFF);
43              }
44              for (int x = 5; x < 10; x++) {
45                  whiteAndBlackImage.setRGB(x, y, 0x000000);
46              }
47          }
48          checkPaletteDetails(whiteAndBlackImage, 10, 2);
49          
50          final BufferedImage rainbowImage = new BufferedImage(9, 10, BufferedImage.TYPE_INT_RGB);
51          for (int y = 0; y < whiteImage.getHeight(); y++) {
52              for (int x = 0; x < 3; x++) {
53                  rainbowImage.setRGB(x, y, 0xFF0000);
54              }
55              for (int x = 3; x < 6; x++) {
56                  rainbowImage.setRGB(x, y, 0x00FF00);
57              }
58              for (int x = 6; x < 9; x++) {
59                  rainbowImage.setRGB(x, y, 0x0000FF);
60              }
61          }
62          checkPaletteDetails(rainbowImage, 10, 3);
63          checkPaletteDetails(rainbowImage, 2, 2);
64      }
65      
66      private void checkPaletteDetails(final BufferedImage image, final int limit, final int expectedSize) throws ImageWriteException {
67          final PaletteFactory paletteFactory = new PaletteFactory();
68          Palette palette;
69  
70          palette = paletteFactory.makeExactRgbPaletteSimple(image, limit);
71          // too small palettes are null
72          boolean exact = false;
73          if (palette != null) {
74              assertEquals(expectedSize, palette.length());
75              //checkUniqueColors(image, palette);
76              exact = true;
77          }
78          if (exact) {
79              //checkDithering(image, palette);
80          }
81  
82          palette = paletteFactory.makeQuantizedRgbaPalette(image, false, limit);
83          assertEquals(expectedSize, palette.length());
84          checkUniqueColors(image, palette);
85          if (exact) {
86              checkPixelsAreIdentical(image, palette);
87          }
88          
89          palette = paletteFactory.makeQuantizedRgbPalette(image, limit);
90          assertEquals(expectedSize, palette.length());
91          //checkUniqueColors(image, palette);
92          if (exact) {
93              //checkDithering(image, palette);
94          }
95          
96          final MedianCutQuantizer medianCutQuantizer = new MedianCutQuantizer(true);
97          palette = medianCutQuantizer.process(
98                  image, limit, new MostPopulatedBoxesMedianCut(), false);
99          assertEquals(expectedSize, palette.length());
100         checkUniqueColors(image, palette);
101         if (exact) {
102             checkPixelsAreIdentical(image, palette);
103         }
104     }
105     
106     private void checkUniqueColors(final BufferedImage src, final Palette palette) throws ImageWriteException {
107         final BufferedImage dst = new BufferedImage(src.getWidth(), src.getHeight(), BufferedImage.TYPE_INT_RGB);
108         dst.getGraphics().drawImage(src, 0, 0, src.getWidth(), src.getHeight(), null);
109         Dithering.applyFloydSteinbergDithering(dst, palette);
110         final Palette ditheredPalette = new PaletteFactory().makeExactRgbPaletteSimple(dst, palette.length() * 2);
111         assertEquals(palette.length(), ditheredPalette.length());
112     }
113     
114     private void checkPixelsAreIdentical(final BufferedImage src, final Palette palette) throws ImageWriteException {
115         final BufferedImage dst = new BufferedImage(src.getWidth(), src.getHeight(), BufferedImage.TYPE_INT_RGB);
116         dst.getGraphics().drawImage(src, 0, 0, src.getWidth(), src.getHeight(), null);
117         Dithering.applyFloydSteinbergDithering(dst, palette);
118         for (int y = 0; y < src.getHeight(); y++) {
119             for (int x = 0; x < src.getWidth(); x++) {
120                 assertEquals(src.getRGB(x, y), dst.getRGB(x, y));
121             }
122         }
123     }
124 }