1 /*
2 * SmartSprites Project
3 *
4 * Copyright (C) 2007-2009, Stanisław Osiński.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without modification,
8 * are permitted provided that the following conditions are met:
9 *
10 * - Redistributions of source code must retain the above copyright notice, this
11 * list of conditions and the following disclaimer.
12 *
13 * - Redistributions in binary form must reproduce the above copyright notice, this
14 * list of conditions and the following disclaimer in the documentation and/or
15 * other materials provided with the distribution.
16 *
17 * - Neither the name of the SmartSprites Project nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * - We kindly request that you include in the end-user documentation provided with
22 * the redistribution and/or in the software itself an acknowledgement equivalent
23 * to the following: "This product includes software developed by the SmartSprites
24 * Project."
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
30 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
33 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37 package org.carrot2.util;
38
39 import static org.junit.jupiter.api.Assertions.assertEquals;
40 import static org.junit.jupiter.api.Assertions.assertThrows;
41
42 import java.awt.image.BufferedImage;
43 import java.io.IOException;
44
45 import org.junit.jupiter.api.Test;
46
47 import amd.Quantize;
48
49 /**
50 * Test cases for {@link Quantize}.
51 */
52 class ColorQuantizerTest extends BufferedImageTestBase {
53
54 /**
55 * Test one color.
56 *
57 * @throws IOException
58 * Signals that an I/O exception has occurred.
59 */
60 @Test
61 void testOneColor() throws IOException {
62 final String fileName = "one-color.png";
63 final BufferedImage quantized = ColorQuantizer.quantize(image(fileName));
64 org.carrot2.labs.test.Assertions.assertThat(quantized).doesNotHaveAlpha().hasNumberOfColorsEqualTo(1)
65 .isIndexedColor();
66 }
67
68 /**
69 * Test no alpha.
70 *
71 * @throws IOException
72 * Signals that an I/O exception has occurred.
73 */
74 @Test
75 void testNoAlpha() throws IOException {
76 final String fileName = "no-alpha.png";
77 final BufferedImage quantized = ColorQuantizer.quantize(image(fileName));
78 org.carrot2.labs.test.Assertions.assertThat(quantized).doesNotHaveAlpha().hasNumberOfColorsEqualTo(4)
79 .isIndexedColor();
80 }
81
82 /**
83 * Test bit alpha.
84 *
85 * @throws IOException
86 * Signals that an I/O exception has occurred.
87 */
88 @Test
89 void testBitAlpha() throws IOException {
90 final String fileName = "bit-alpha.png";
91 final BufferedImage quantized = ColorQuantizer.quantize(image(fileName));
92 org.carrot2.labs.test.Assertions.assertThat(quantized).hasBitAlpha().hasNumberOfColorsEqualTo(1)
93 .isIndexedColor();
94 }
95
96 /**
97 * Test full alpha.
98 *
99 * @throws IOException
100 * Signals that an I/O exception has occurred.
101 */
102 @Test
103 void testFullAlpha() throws IOException {
104 final String fileName = "full-alpha.png";
105 final BufferedImage quantized = ColorQuantizer.quantize(image(fileName));
106 org.carrot2.labs.test.Assertions.assertThat(quantized).hasBitAlpha().hasNumberOfColorsEqualTo(3)
107 .isIndexedColor();
108 }
109
110 /**
111 * Test exact colors quantize.
112 *
113 * @throws IOException
114 * Signals that an I/O exception has occurred.
115 */
116 @Test
117 void testExactColorsQuantize() throws IOException {
118 final String fileName = "exact-colors.png";
119 final BufferedImage quantized = ColorQuantizer.quantize(image(fileName));
120 org.carrot2.labs.test.Assertions.assertThat(quantized).hasBitAlpha().hasNumberOfColorsEqualTo(16)
121 .isIndexedColor();
122 }
123
124 /**
125 * Test exact colors reduce.
126 *
127 * @throws IOException
128 * Signals that an I/O exception has occurred.
129 */
130 @Test
131 void testExactColorsReduce() throws IOException {
132 final String fileName = "exact-colors.png";
133 final BufferedImage quantized = ColorQuantizer.reduce(image(fileName));
134 org.carrot2.labs.test.Assertions.assertThat(quantized).hasBitAlpha().hasNumberOfColorsEqualTo(255)
135 .isIndexedColor();
136 }
137
138 /**
139 * Test many colors quantize.
140 *
141 * @throws IOException
142 * Signals that an I/O exception has occurred.
143 */
144 @Test
145 void testManyColorsQuantize() throws IOException {
146 final String fileName = "many-colors.png";
147 final BufferedImage quantized = ColorQuantizer.quantize(image(fileName));
148 org.carrot2.labs.test.Assertions.assertThat(quantized).doesNotHaveAlpha().hasNumberOfColorsEqualTo(61)
149 .isIndexedColor();
150 // Current quantizer is far from perfect
151 }
152
153 /**
154 * Test many colors reduce.
155 *
156 * @throws IOException
157 * Signals that an I/O exception has occurred.
158 */
159 @Test
160 void testManyColorsReduce() throws IOException {
161 final String fileName = "many-colors.png";
162 assertThrows(IllegalArgumentException.class, () -> {
163 ColorQuantizer.reduce(image(fileName));
164 });
165 }
166
167 /**
168 * Test can reduce without data loss.
169 *
170 * @throws IOException
171 * Signals that an I/O exception has occurred.
172 */
173 @Test
174 void testCanReduceWithoutDataLoss() throws IOException {
175 checkDataLoss("bit-alpha.png", true);
176 checkDataLoss("exact-colors.png", true);
177 checkDataLoss("full-alpha.png", false);
178 checkDataLoss("many-colors.png", false);
179 checkDataLoss("no-alpha.png", true);
180 checkDataLoss("one-color.png", true);
181 }
182
183 /**
184 * Check data loss.
185 *
186 * @param path
187 * the path
188 * @param expectedCanReduce
189 * the expected can reduce
190 *
191 * @throws IOException
192 * Signals that an I/O exception has occurred.
193 */
194 private void checkDataLoss(String path, boolean expectedCanReduce) throws IOException {
195 assertEquals(expectedCanReduce,
196 ColorQuantizer.getColorReductionInfo(image(path)).canReduceWithoutQualityLoss());
197 }
198 }