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.jupiter.api.Assertions.assertEquals;
20  
21  import java.awt.image.BufferedImage;
22  
23  import org.apache.commons.imaging.AbstractImagingTest;
24  import org.apache.commons.imaging.ImagingException;
25  import org.junit.jupiter.api.Test;
26  
27  public class PaletteQuantizationTest extends AbstractImagingTest {
28  
29      private void checkPaletteDetails(final BufferedImage image, final int limit, final int expectedSize) throws ImagingException {
30          final PaletteFactory paletteFactory = new PaletteFactory();
31          Palette palette;
32  
33          palette = paletteFactory.makeExactRgbPaletteSimple(image, limit);
34          // too small palettes are null
35          boolean exact = false;
36          if (palette != null) {
37              assertEquals(expectedSize, palette.length());
38              // checkUniqueColors(image, palette);
39              exact = true;
40          }
41          if (exact) {
42              // checkDithering(image, palette);
43          }
44  
45          palette = paletteFactory.makeQuantizedRgbaPalette(image, false, limit);
46          assertEquals(expectedSize, palette.length());
47          checkUniqueColors(image, palette);
48          if (exact) {
49              checkPixelsAreIdentical(image, palette);
50          }
51  
52          palette = paletteFactory.makeQuantizedRgbPalette(image, limit);
53          assertEquals(expectedSize, palette.length());
54          // checkUniqueColors(image, palette);
55          if (exact) {
56              // checkDithering(image, palette);
57          }
58  
59          final MedianCutQuantizer medianCutQuantizer = new MedianCutQuantizer(true);
60          palette = medianCutQuantizer.process(image, limit, new MostPopulatedBoxesMedianCut());
61          assertEquals(expectedSize, palette.length());
62          checkUniqueColors(image, palette);
63          if (exact) {
64              checkPixelsAreIdentical(image, palette);
65          }
66      }
67  
68      private void checkPixelsAreIdentical(final BufferedImage src, final Palette palette) throws ImagingException {
69          final BufferedImage dst = new BufferedImage(src.getWidth(), src.getHeight(), BufferedImage.TYPE_INT_RGB);
70          dst.getGraphics().drawImage(src, 0, 0, src.getWidth(), src.getHeight(), null);
71          Dithering.applyFloydSteinbergDithering(dst, palette);
72          for (int y = 0; y < src.getHeight(); y++) {
73              for (int x = 0; x < src.getWidth(); x++) {
74                  assertEquals(src.getRGB(x, y), dst.getRGB(x, y));
75              }
76          }
77      }
78  
79      private void checkUniqueColors(final BufferedImage src, final Palette palette) throws ImagingException {
80          final BufferedImage dst = new BufferedImage(src.getWidth(), src.getHeight(), BufferedImage.TYPE_INT_RGB);
81          dst.getGraphics().drawImage(src, 0, 0, src.getWidth(), src.getHeight(), null);
82          Dithering.applyFloydSteinbergDithering(dst, palette);
83          final Palette ditheredPalette = new PaletteFactory().makeExactRgbPaletteSimple(dst, palette.length() * 2);
84          assertEquals(palette.length(), ditheredPalette.length());
85      }
86  
87      @Test
88      public void testPaletteQuantization() throws ImagingException {
89          final BufferedImage whiteImage = new BufferedImage(10, 10, BufferedImage.TYPE_INT_RGB);
90          for (int y = 0; y < whiteImage.getHeight(); y++) {
91              for (int x = 0; x < whiteImage.getWidth(); x++) {
92                  whiteImage.setRGB(x, y, 0xFFFFFF);
93              }
94          }
95          checkPaletteDetails(whiteImage, 10, 1);
96  
97          final BufferedImage whiteAndBlackImage = new BufferedImage(10, 10, BufferedImage.TYPE_INT_RGB);
98          for (int y = 0; y < whiteImage.getHeight(); y++) {
99              for (int x = 0; x < 5; x++) {
100                 whiteAndBlackImage.setRGB(x, y, 0xFFFFFF);
101             }
102             for (int x = 5; x < 10; x++) {
103                 whiteAndBlackImage.setRGB(x, y, 0x000000);
104             }
105         }
106         checkPaletteDetails(whiteAndBlackImage, 10, 2);
107 
108         final BufferedImage rainbowImage = new BufferedImage(9, 10, BufferedImage.TYPE_INT_RGB);
109         for (int y = 0; y < whiteImage.getHeight(); y++) {
110             for (int x = 0; x < 3; x++) {
111                 rainbowImage.setRGB(x, y, 0xFF0000);
112             }
113             for (int x = 3; x < 6; x++) {
114                 rainbowImage.setRGB(x, y, 0x00FF00);
115             }
116             for (int x = 6; x < 9; x++) {
117                 rainbowImage.setRGB(x, y, 0x0000FF);
118             }
119         }
120         checkPaletteDetails(rainbowImage, 10, 3);
121         checkPaletteDetails(rainbowImage, 2, 2);
122     }
123 }