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  
18  package org.apache.commons.imaging.formats.bmp;
19  
20  import static org.junit.jupiter.api.Assertions.assertEquals;
21  import static org.junit.jupiter.api.Assertions.assertNotNull;
22  
23  import java.awt.image.BufferedImage;
24  import java.io.IOException;
25  import java.util.Random;
26  
27  import org.apache.commons.imaging.ImageFormats;
28  import org.apache.commons.imaging.Imaging;
29  import org.apache.commons.imaging.ImagingException;
30  import org.apache.commons.imaging.internal.Debug;
31  import org.junit.jupiter.api.Test;
32  
33  public class BmpRoundtripTest extends AbstractBmpTest {
34  
35      private int[][] bufferedImageToImageData(final BufferedImage image) {
36          final int width = image.getWidth();
37          final int height = image.getHeight();
38          final int[][] result = new int[height][width];
39  
40          for (int y = 0; y < height; y++) {
41              for (int x = 0; x < width; x++) {
42                  result[y][x] = image.getRGB(x, y);
43              }
44          }
45          return result;
46      }
47  
48      private void compare(final int[][] a, final int[][] b) {
49          assertNotNull(a);
50          assertNotNull(b);
51          assertEquals(a.length, b.length);
52  
53          for (int y = 0; y < a.length; y++) {
54              assertEquals(a[y].length, b[y].length);
55              // make sure row lengths consistent.
56              assertEquals(a[0].length, b[y].length);
57              for (int x = 0; x < a[y].length; x++) {
58                  // ignore alpha channel - BMP has no transparency.
59                  final int rgbA = 0xffffff & a[y][x];
60                  final int rgbB = 0xffffff & b[y][x];
61  
62                  if (rgbA != rgbB) {
63                      Debug.debug("x: " + x + ", y: " + y + ", rgbA: " + rgbA + " (0x" + Integer.toHexString(rgbA) + ")" + ", rgbB: " + rgbB + " (0x"
64                              + Integer.toHexString(rgbB) + ")");
65                  }
66                  assertEquals(rgbA, rgbB);
67              }
68          }
69      }
70  
71      private int[][] getAscendingRawData(final int width, final int height) {
72          final int[][] result = new int[height][width];
73          for (int y = 0; y < height; y++) {
74              for (int x = 0; x < width; x++) {
75                  final int alpha = (x + y) % 256;
76                  final int value = (x + y) % 256;
77                  final int argb = (0xff & alpha) << 24 | (0xff & value) << 16 | (0xff & value) << 8 | (0xff & value) << 0;
78  
79                  result[y][x] = argb;
80              }
81          }
82          return result;
83      }
84  
85      private int[][] getSimpleRawData(final int width, final int height, final int value) {
86          final int[][] result = new int[height][width];
87          for (int y = 0; y < height; y++) {
88              for (int x = 0; x < width; x++) {
89                  result[y][x] = value;
90              }
91          }
92          return result;
93      }
94  
95      private BufferedImage imageDataToBufferedImage(final int[][] rawData) {
96          final int width = rawData[0].length;
97          final int height = rawData.length;
98          final BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
99          for (int y = 0; y < height; y++) {
100             for (int x = 0; x < width; x++) {
101                 image.setRGB(x, y, rawData[y][x]);
102             }
103         }
104         return image;
105     }
106 
107     private int[][] randomRawData(final int width, final int height) {
108         final Random random = new Random();
109         final int[][] result = new int[height][width];
110         for (int y = 0; y < height; y++) {
111             for (int x = 0; x < width; x++) {
112                 final int argb = random.nextInt();
113                 result[y][x] = argb;
114             }
115         }
116         return result;
117     }
118 
119     @Test
120     public void testSingleBlackPixel() throws Exception {
121         final int[][] singleBlackPixel = getSimpleRawData(1, 1, 0);
122         writeAndReadImageData(singleBlackPixel);
123     }
124 
125     @Test
126     public void testSingleRedPixel() throws Exception {
127         final int[][] singleRedPixel = getSimpleRawData(1, 1, 0xffff0000);
128         writeAndReadImageData(singleRedPixel);
129     }
130 
131     @Test
132     public void testSmallAscendingPixels() throws Exception {
133         final int[][] smallAscendingPixels = getAscendingRawData(256, 256);
134         writeAndReadImageData(smallAscendingPixels);
135     }
136 
137     @Test
138     public void testSmallBlackPixels() throws Exception {
139         final int[][] smallBlackPixels = getSimpleRawData(256, 256, 0);
140         writeAndReadImageData(smallBlackPixels);
141     }
142 
143     @Test
144     public void testSmallRandomPixels() throws Exception {
145         final int[][] smallRandomPixels = randomRawData(256, 256);
146         writeAndReadImageData(smallRandomPixels);
147     }
148 
149     @Test
150     public void testSmallRedPixels() throws Exception {
151         final int[][] smallRedPixels = getSimpleRawData(256, 256, 0xffff0000);
152         writeAndReadImageData(smallRedPixels);
153     }
154 
155     private void writeAndReadImageData(final int[][] rawData) throws IOException, ImagingException, ImagingException {
156         final BufferedImage srcImage = imageDataToBufferedImage(rawData);
157 
158         final byte[] bytes = Imaging.writeImageToBytes(srcImage, ImageFormats.BMP);
159 
160         final BufferedImage dstImage = Imaging.getBufferedImage(bytes);
161 
162         assertNotNull(dstImage);
163         assertEquals(srcImage.getWidth(), dstImage.getWidth());
164         assertEquals(srcImage.getHeight(), dstImage.getHeight());
165 
166         final int[][] dstData = bufferedImageToImageData(dstImage);
167         compare(rawData, dstData);
168     }
169 
170 }