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.comic; |
17 | |
18 | import java.awt.Graphics2D; |
19 | import java.awt.geom.AffineTransform; |
20 | import java.awt.image.BufferedImage; |
21 | import java.awt.image.RenderedImage; |
22 | import java.io.File; |
23 | import java.io.IOException; |
24 | import java.text.DecimalFormat; |
25 | |
26 | import junit.framework.TestCase; |
27 | import net.sf.jomic.common.ComicSheetRenderSettings; |
28 | import net.sf.jomic.tools.ImageTools; |
29 | import net.sf.jomic.tools.TestTools; |
30 | import org.apache.commons.logging.Log; |
31 | import org.apache.commons.logging.LogFactory; |
32 | |
33 | /** |
34 | * TestCase for ComicSheetLayout. |
35 | * |
36 | * @author Thomas Aglassinger |
37 | */ |
38 | public class ComicSheetLayoutTest extends TestCase |
39 | { |
40 | private static final double SCALE_COMPARISON_EPSILON = 0.0001; |
41 | |
42 | private Log logger; |
43 | private TestTools testTools; |
44 | |
45 | protected void setUp() |
46 | throws Exception { |
47 | super.setUp(); |
48 | logger = LogFactory.getLog(ComicSheetLayoutTest.class); |
49 | testTools = TestTools.instance(); |
50 | } |
51 | |
52 | public void testGetTargetScales() |
53 | throws IOException { |
54 | RenderedImage leftImage = testTools.getTestImage("01.png"); |
55 | RenderedImage rightImage = testTools.getTestImage("02.png"); |
56 | ComicSheetRenderSettings renderSettings = new ComicSheetRenderSettings(); |
57 | ComicSheetLayout renderer = new ComicSheetLayout(); |
58 | |
59 | renderer.prepare(leftImage, rightImage, renderSettings); |
60 | |
61 | double[] scalesWithLeft = renderer.getTargetScales(300, 200, ComicSheetLayout.RENDER_LEFT); |
62 | |
63 | assertNotNull(scalesWithLeft); |
64 | assertEquals(2, scalesWithLeft.length); |
65 | testTools.assertGreaterThan(scalesWithLeft[0], 0.0); |
66 | assertEquals(ComicSheetLayout.NO_SCALE, scalesWithLeft[1], SCALE_COMPARISON_EPSILON); |
67 | |
68 | double[] scalesWithRight = renderer.getTargetScales(300, 200, ComicSheetLayout.RENDER_RIGHT); |
69 | |
70 | assertNotNull(scalesWithRight); |
71 | assertEquals(2, scalesWithRight.length); |
72 | assertEquals(ComicSheetLayout.NO_SCALE, scalesWithRight[0], 0.0001); |
73 | testTools.assertGreaterThan(scalesWithRight[1], 0.0); |
74 | } |
75 | |
76 | public void testRenderBothActual() |
77 | throws IOException { |
78 | RenderedImage leftImage = testTools.getTestImage("01.png"); |
79 | RenderedImage rightImage = testTools.getTestImage("02.png"); |
80 | int totalWidth = leftImage.getWidth() + rightImage.getWidth(); |
81 | int totalHeight = Math.max(leftImage.getHeight(), rightImage.getHeight()); |
82 | |
83 | testRenderBoth("actual-center", leftImage, rightImage, totalWidth + 50, totalHeight + 75, |
84 | ImageTools.SCALE_ACTUAL); |
85 | testRenderBoth("actual-fit-x", leftImage, rightImage, totalWidth, totalHeight + 75, ImageTools.SCALE_ACTUAL); |
86 | testRenderBoth("actual-fit-y", leftImage, rightImage, totalWidth + 50, totalHeight, ImageTools.SCALE_ACTUAL); |
87 | testRenderBoth("actual-fit", leftImage, rightImage, totalWidth, totalHeight, ImageTools.SCALE_ACTUAL); |
88 | } |
89 | |
90 | public void testRenderBothActualFitWithDifferentFormats() |
91 | throws IOException { |
92 | testRenderBothActualFit("8-bit", TestTools.TEST_IMAGE_8_BIT, TestTools.TEST_IMAGE_FILE_NAME); |
93 | testRenderBothActualFit("8-bit-gray", TestTools.TEST_IMAGE_8_BIT_GRAY, TestTools.TEST_IMAGE_FILE_NAME); |
94 | testRenderBothActualFit("4-bit", TestTools.TEST_IMAGE_4_BIT, TestTools.TEST_IMAGE_FILE_NAME); |
95 | testRenderBothActualFit("1-bit", TestTools.TEST_IMAGE_1_BIT, TestTools.TEST_IMAGE_FILE_NAME); |
96 | } |
97 | |
98 | public void testRenderBothFitl() |
99 | throws IOException { |
100 | RenderedImage leftImage = testTools.getTestImage("01.png"); |
101 | RenderedImage rightImage = testTools.getTestImage("02.png"); |
102 | int totalWidth = leftImage.getWidth() + rightImage.getWidth(); |
103 | int totalHeight = Math.max(leftImage.getHeight(), rightImage.getHeight()); |
104 | |
105 | testRenderBoth("fit-x", leftImage, rightImage, totalWidth, totalHeight + 75, ImageTools.SCALE_FIT); |
106 | testRenderBoth("fit-perfectly", leftImage, rightImage, totalWidth, totalHeight, ImageTools.SCALE_FIT); |
107 | testRenderBoth("fit-y", leftImage, rightImage, totalWidth + 50, totalHeight, ImageTools.SCALE_FIT); |
108 | testRenderBoth("fit-grow", leftImage, rightImage, 2 * totalWidth, 2 * totalHeight, ImageTools.SCALE_FIT); |
109 | testRenderBoth("fit-shrink", leftImage, rightImage, totalWidth / 2, totalHeight / 2, ImageTools.SCALE_FIT); |
110 | } |
111 | |
112 | public void testRenderLeftActual() |
113 | throws IOException { |
114 | RenderedImage leftImage = testTools.getTestImage("01.png"); |
115 | |
116 | testRenderLeft("actual-center", leftImage, 1.3, 1.7, ImageTools.SCALE_ACTUAL); |
117 | testRenderLeft("actual-fit-x", leftImage, 1.0, 1.7, ImageTools.SCALE_ACTUAL); |
118 | testRenderLeft("actual-fit-y", leftImage, 1.3, 1.0, ImageTools.SCALE_ACTUAL); |
119 | } |
120 | |
121 | public void testRenderLeftFitX() |
122 | throws IOException { |
123 | RenderedImage leftImage = testTools.getTestImage("01.png"); |
124 | |
125 | testRenderLeft("fit-x", leftImage, 1.3, 1.7, ImageTools.SCALE_FIT); |
126 | testRenderLeft("fit-y", leftImage, 1.7, 1.3, ImageTools.SCALE_FIT); |
127 | testRenderLeft("fit-perfectly", leftImage, 1.0, 1.0, ImageTools.SCALE_FIT); |
128 | } |
129 | |
130 | public void testRenderRightActual() |
131 | throws IOException { |
132 | RenderedImage rightImage = testTools.getTestImage("02.png"); |
133 | |
134 | testRenderRight("actual-center", rightImage, 1.3, 1.7, ImageTools.SCALE_ACTUAL); |
135 | testRenderRight("actual-fit-x", rightImage, 1.0, 1.7, ImageTools.SCALE_ACTUAL); |
136 | testRenderRight("actual-fit-y", rightImage, 1.3, 1.0, ImageTools.SCALE_ACTUAL); |
137 | } |
138 | |
139 | public void testRenderRightFitX() |
140 | throws IOException { |
141 | RenderedImage rightImage = testTools.getTestImage("02.png"); |
142 | |
143 | testRenderRight("fit-x", rightImage, 1.3, 1.7, ImageTools.SCALE_FIT); |
144 | testRenderRight("fit-y", rightImage, 1.7, 1.3, ImageTools.SCALE_FIT); |
145 | testRenderRight("fit-perfectly", rightImage, 1.0, 1.0, ImageTools.SCALE_FIT); |
146 | } |
147 | |
148 | protected void tearDown() |
149 | throws Exception { |
150 | testTools = null; |
151 | super.tearDown(); |
152 | } |
153 | |
154 | private BufferedImage createTargetImage(int sourceWidth, int sourceHeight) { |
155 | assert sourceWidth > 0; |
156 | assert sourceHeight > 0; |
157 | |
158 | BufferedImage result = new BufferedImage(sourceWidth, sourceHeight, BufferedImage.TYPE_INT_RGB); |
159 | |
160 | return result; |
161 | } |
162 | |
163 | private BufferedImage createTargetImageFor(RenderedImage sourceImage, double xScale, double yScale) { |
164 | assert sourceImage != null; |
165 | assert xScale > 0; |
166 | assert yScale > 0; |
167 | |
168 | return createTargetImageFor(sourceImage.getWidth(), sourceImage.getHeight(), xScale, yScale); |
169 | } |
170 | |
171 | private BufferedImage createTargetImageFor(int sourceWidth, int sourceHeight, double xScale, double yScale) { |
172 | assert sourceWidth > 0; |
173 | assert sourceHeight > 0; |
174 | assert xScale > 0; |
175 | assert yScale > 0; |
176 | |
177 | return createTargetImage((int) Math.ceil(xScale * sourceWidth), (int) Math.ceil(yScale * sourceHeight)); |
178 | } |
179 | |
180 | private void testRenderBoth(String nameDetails, RenderedImage leftImage, RenderedImage rightImage, |
181 | int targetImageWidth, int targetImageHeight, String scaleMode) |
182 | throws IOException { |
183 | ComicSheetRenderSettings renderSettings = new ComicSheetRenderSettings(); |
184 | ComicSheetLayout renderer = new ComicSheetLayout(); |
185 | BufferedImage targetImage = createTargetImage(targetImageWidth, targetImageHeight); |
186 | |
187 | renderSettings.setScaleMode(scaleMode); |
188 | renderer.prepare(leftImage, rightImage, renderSettings); |
189 | |
190 | double[] scales = renderer.getTargetScales(targetImageWidth, targetImageHeight, ComicSheetLayout.RENDER_BOTH); |
191 | int[] topLeftCorner = renderer.getTargetTopLeft(targetImageWidth, targetImageHeight, |
192 | ComicSheetLayout.RENDER_BOTH, scales); |
193 | AffineTransform rotationTransformation = renderer.getTargetRotationTransformation( |
194 | targetImageWidth, targetImageHeight); |
195 | |
196 | if (logger.isInfoEnabled()) { |
197 | logger.info("scales[0] = " + (new DecimalFormat("#.00").format(scales[0]))); |
198 | logger.info("scales[1] = " + (new DecimalFormat("#.00").format(scales[1]))); |
199 | } |
200 | renderer.render((Graphics2D) targetImage.getGraphics(), ComicSheetLayout.RENDER_BOTH, scales, topLeftCorner, |
201 | rotationTransformation); |
202 | writeTestTargetTopLeftImage("both-" + nameDetails, targetImage); |
203 | } |
204 | |
205 | private void testRenderBothActualFit(String nameDetails, String leftName, String rightName) |
206 | throws IOException { |
207 | RenderedImage leftImage = testTools.getTestImage(leftName); |
208 | RenderedImage rightImage = testTools.getTestImage(rightName); |
209 | ComicSheetRenderSettings renderSettings = new ComicSheetRenderSettings(); |
210 | ComicSheetLayout renderer = new ComicSheetLayout(); |
211 | int targetImageWidth = leftImage.getWidth() + rightImage.getWidth(); |
212 | int targetImageHeight = Math.max(leftImage.getHeight(), rightImage.getHeight()); |
213 | BufferedImage targetImage = createTargetImage(targetImageWidth, targetImageHeight); |
214 | |
215 | renderSettings.setScaleMode(ImageTools.SCALE_ACTUAL); |
216 | renderer.prepare(leftImage, rightImage, renderSettings); |
217 | |
218 | double[] scales = renderer.getTargetScales(targetImageWidth, targetImageHeight, ComicSheetLayout.RENDER_BOTH); |
219 | int[] topLeftCorner = renderer.getTargetTopLeft(targetImageWidth, targetImageHeight, |
220 | ComicSheetLayout.RENDER_BOTH, scales); |
221 | AffineTransform rotationTransformation = renderer.getTargetRotationTransformation( |
222 | targetImageWidth, targetImageHeight); |
223 | |
224 | assertEquals(1.0, scales[0], SCALE_COMPARISON_EPSILON); |
225 | assertEquals(1.0, scales[1], SCALE_COMPARISON_EPSILON); |
226 | renderer.render((Graphics2D) targetImage.getGraphics(), ComicSheetLayout.RENDER_BOTH, scales, topLeftCorner, |
227 | rotationTransformation); |
228 | writeTestTargetTopLeftImage("both-actual-fit-" + nameDetails, targetImage); |
229 | } |
230 | |
231 | private void testRenderLeft(String nameDetails, RenderedImage leftImage, |
232 | double targetXScale, double targetYScale, String scaleMode) |
233 | throws IOException { |
234 | ComicSheetRenderSettings renderSettings = new ComicSheetRenderSettings(); |
235 | ComicSheetLayout renderer = new ComicSheetLayout(); |
236 | BufferedImage targetImage = createTargetImageFor(leftImage, targetXScale, targetYScale); |
237 | int targetImageWidth = targetImage.getWidth(); |
238 | int targetImageHeight = targetImage.getHeight(); |
239 | |
240 | renderSettings.setScaleMode(scaleMode); |
241 | renderer.prepare(leftImage, null, renderSettings); |
242 | |
243 | double[] scales = renderer.getTargetScales(targetImageWidth, targetImageHeight, ComicSheetLayout.RENDER_LEFT); |
244 | int[] topLeftCorner = renderer.getTargetTopLeft(targetImageWidth, targetImageHeight, |
245 | ComicSheetLayout.RENDER_LEFT, scales); |
246 | AffineTransform rotationTransformation = renderer.getTargetRotationTransformation( |
247 | targetImageWidth, targetImageHeight); |
248 | |
249 | renderer.render((Graphics2D) targetImage.getGraphics(), ComicSheetLayout.RENDER_LEFT, scales, topLeftCorner, |
250 | rotationTransformation); |
251 | writeTestTargetTopLeftImage("left-" + nameDetails, targetImage); |
252 | } |
253 | |
254 | private void testRenderRight(String nameDetails, RenderedImage rightImage, |
255 | double targetXScale, double targetYScale, String scaleMode) |
256 | throws IOException { |
257 | RenderedImage dummyLeftImage = testTools.getTestImage("01.png"); |
258 | ComicSheetRenderSettings renderSettings = new ComicSheetRenderSettings(); |
259 | ComicSheetLayout renderer = new ComicSheetLayout(); |
260 | BufferedImage targetImage = createTargetImageFor(rightImage, targetXScale, targetYScale); |
261 | int targetImageWidth = targetImage.getWidth(); |
262 | int targetImageHeight = targetImage.getHeight(); |
263 | |
264 | renderSettings.setScaleMode(scaleMode); |
265 | renderer.prepare(dummyLeftImage, rightImage, renderSettings); |
266 | |
267 | double[] scales = renderer.getTargetScales(targetImageWidth, targetImageHeight, ComicSheetLayout.RENDER_RIGHT); |
268 | int[] topLeftCorner = renderer.getTargetTopLeft(targetImageWidth, targetImageHeight, |
269 | ComicSheetLayout.RENDER_RIGHT, scales); |
270 | AffineTransform rotationTransformation = renderer.getTargetRotationTransformation( |
271 | targetImageWidth, targetImageHeight); |
272 | |
273 | renderer.render((Graphics2D) targetImage.getGraphics(), ComicSheetLayout.RENDER_RIGHT, scales, topLeftCorner, |
274 | rotationTransformation); |
275 | writeTestTargetTopLeftImage("right-" + nameDetails, targetImage); |
276 | } |
277 | |
278 | private void writeTestTargetTopLeftImage(String name, RenderedImage imageToWrite) |
279 | throws IOException { |
280 | assert name != null; |
281 | |
282 | String targetImageName = testTools.getTestFileName(ComicSheetLayoutTest.class, "testRender", name, "png"); |
283 | File targetImageFile = testTools.getTestOutputFile(targetImageName); |
284 | |
285 | testTools.writeImageFile(targetImageFile, imageToWrite); |
286 | } |
287 | } |