ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
bitmap_test.cc
Go to the documentation of this file.
1 // Copyright (c) 2018, ETH Zurich and UNC Chapel Hill.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 //
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 //
14 // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of
15 // its contributors may be used to endorse or promote products derived
16 // from this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
22 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 // POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Author: Johannes L. Schoenberger (jsch-at-demuc-dot-de)
31 
32 #define TEST_NAME "util/bitmap"
33 #include "util/testing.h"
34 
35 #include "util/bitmap.h"
36 
37 using namespace colmap;
38 
39 BOOST_AUTO_TEST_CASE(TestBitmapColorEmpty) {
41  BOOST_CHECK_EQUAL(color.r, 0);
42  BOOST_CHECK_EQUAL(color.g, 0);
43  BOOST_CHECK_EQUAL(color.b, 0);
44  BOOST_CHECK_EQUAL(color, BitmapColor<uint8_t>(0));
45  BOOST_CHECK_EQUAL(color, BitmapColor<uint8_t>(0, 0, 0));
46 }
47 
48 BOOST_AUTO_TEST_CASE(TestBitmapGrayColor) {
50  BOOST_CHECK_EQUAL(color.r, 5);
51  BOOST_CHECK_EQUAL(color.g, 5);
52  BOOST_CHECK_EQUAL(color.b, 5);
53 }
54 
55 BOOST_AUTO_TEST_CASE(TestBitmapColorCast) {
56  BitmapColor<float> color1(1.1, 2.9, -3.0);
57  BitmapColor<uint8_t> color2 = color1.Cast<uint8_t>();
58  BOOST_CHECK_EQUAL(color2.r, 1);
59  BOOST_CHECK_EQUAL(color2.g, 3);
60  BOOST_CHECK_EQUAL(color2.b, 0);
61 }
62 
64  Bitmap bitmap;
65  BOOST_CHECK_EQUAL(bitmap.Width(), 0);
66  BOOST_CHECK_EQUAL(bitmap.Height(), 0);
67  BOOST_CHECK_EQUAL(bitmap.Channels(), 0);
68  BOOST_CHECK_EQUAL(bitmap.IsRGB(), false);
69  BOOST_CHECK_EQUAL(bitmap.IsGrey(), false);
70 }
71 
72 BOOST_AUTO_TEST_CASE(TestAllocateRGB) {
73  Bitmap bitmap;
74  bitmap.Allocate(100, 100, true);
75  BOOST_CHECK_EQUAL(bitmap.Width(), 100);
76  BOOST_CHECK_EQUAL(bitmap.Height(), 100);
77  BOOST_CHECK_EQUAL(bitmap.Channels(), 3);
78  BOOST_CHECK_EQUAL(bitmap.IsRGB(), true);
79  BOOST_CHECK_EQUAL(bitmap.IsGrey(), false);
80 }
81 
82 BOOST_AUTO_TEST_CASE(TestAllocateGrey) {
83  Bitmap bitmap;
84  bitmap.Allocate(100, 100, false);
85  BOOST_CHECK_EQUAL(bitmap.Width(), 100);
86  BOOST_CHECK_EQUAL(bitmap.Height(), 100);
87  BOOST_CHECK_EQUAL(bitmap.Channels(), 1);
88  BOOST_CHECK_EQUAL(bitmap.IsRGB(), false);
89  BOOST_CHECK_EQUAL(bitmap.IsGrey(), true);
90 }
91 
92 BOOST_AUTO_TEST_CASE(TestDeallocate) {
93  Bitmap bitmap;
94  bitmap.Allocate(100, 100, false);
95  bitmap.Deallocate();
96  BOOST_CHECK_EQUAL(bitmap.Width(), 0);
97  BOOST_CHECK_EQUAL(bitmap.Height(), 0);
98  BOOST_CHECK_EQUAL(bitmap.Channels(), 0);
99  BOOST_CHECK_EQUAL(bitmap.NumBytes(), 0);
100  BOOST_CHECK_EQUAL(bitmap.IsRGB(), false);
101  BOOST_CHECK_EQUAL(bitmap.IsGrey(), false);
102 }
103 
104 BOOST_AUTO_TEST_CASE(TestBitsPerPixel) {
105  Bitmap bitmap;
106  bitmap.Allocate(100, 100, true);
107  BOOST_CHECK_EQUAL(bitmap.BitsPerPixel(), 24);
108  bitmap.Allocate(100, 100, false);
109  BOOST_CHECK_EQUAL(bitmap.BitsPerPixel(), 8);
110 }
111 
112 BOOST_AUTO_TEST_CASE(TestNumBytes) {
113  Bitmap bitmap;
114  BOOST_CHECK_EQUAL(bitmap.NumBytes(), 0);
115  bitmap.Allocate(100, 100, true);
116  BOOST_CHECK_EQUAL(bitmap.NumBytes(), 3 * 100 * 100);
117  bitmap.Allocate(100, 100, false);
118  BOOST_CHECK_EQUAL(bitmap.NumBytes(), 100 * 100);
119 }
120 
121 BOOST_AUTO_TEST_CASE(TestConvertToRowMajorArrayRGB) {
122  Bitmap bitmap;
123  bitmap.Allocate(2, 2, true);
124  bitmap.SetPixel(0, 0, BitmapColor<uint8_t>(0, 0, 0));
125  bitmap.SetPixel(0, 1, BitmapColor<uint8_t>(1, 0, 0));
126  bitmap.SetPixel(1, 0, BitmapColor<uint8_t>(2, 0, 0));
127  bitmap.SetPixel(1, 1, BitmapColor<uint8_t>(3, 0, 0));
128  const std::vector<uint8_t> array = bitmap.ConvertToRowMajorArray();
129  BOOST_CHECK_EQUAL(array.size(), 12);
130  BOOST_CHECK_EQUAL(array[0], 0);
131  BOOST_CHECK_EQUAL(array[1], 0);
132  BOOST_CHECK_EQUAL(array[2], 0);
133  BOOST_CHECK_EQUAL(array[3], 0);
134  BOOST_CHECK_EQUAL(array[4], 0);
135  BOOST_CHECK_EQUAL(array[5], 2);
136  BOOST_CHECK_EQUAL(array[6], 0);
137  BOOST_CHECK_EQUAL(array[7], 0);
138  BOOST_CHECK_EQUAL(array[8], 1);
139  BOOST_CHECK_EQUAL(array[9], 0);
140  BOOST_CHECK_EQUAL(array[10], 0);
141  BOOST_CHECK_EQUAL(array[11], 3);
142 }
143 
144 BOOST_AUTO_TEST_CASE(TestConvertToRowMajorArrayGrey) {
145  Bitmap bitmap;
146  bitmap.Allocate(2, 2, false);
147  bitmap.SetPixel(0, 0, BitmapColor<uint8_t>(0, 0, 0));
148  bitmap.SetPixel(0, 1, BitmapColor<uint8_t>(1, 0, 0));
149  bitmap.SetPixel(1, 0, BitmapColor<uint8_t>(2, 0, 0));
150  bitmap.SetPixel(1, 1, BitmapColor<uint8_t>(3, 0, 0));
151  const std::vector<uint8_t> array = bitmap.ConvertToRowMajorArray();
152  BOOST_CHECK_EQUAL(array.size(), 4);
153  BOOST_CHECK_EQUAL(array[0], 0);
154  BOOST_CHECK_EQUAL(array[1], 2);
155  BOOST_CHECK_EQUAL(array[2], 1);
156  BOOST_CHECK_EQUAL(array[3], 3);
157 }
158 
159 BOOST_AUTO_TEST_CASE(TestConvertToColMajorArrayRGB) {
160  Bitmap bitmap;
161  bitmap.Allocate(2, 2, true);
162  bitmap.SetPixel(0, 0, BitmapColor<uint8_t>(0, 0, 0));
163  bitmap.SetPixel(0, 1, BitmapColor<uint8_t>(1, 0, 0));
164  bitmap.SetPixel(1, 0, BitmapColor<uint8_t>(2, 0, 0));
165  bitmap.SetPixel(1, 1, BitmapColor<uint8_t>(3, 0, 0));
166  const std::vector<uint8_t> array = bitmap.ConvertToColMajorArray();
167  BOOST_CHECK_EQUAL(array.size(), 12);
168  BOOST_CHECK_EQUAL(array[0], 0);
169  BOOST_CHECK_EQUAL(array[1], 0);
170  BOOST_CHECK_EQUAL(array[2], 0);
171  BOOST_CHECK_EQUAL(array[3], 0);
172  BOOST_CHECK_EQUAL(array[4], 0);
173  BOOST_CHECK_EQUAL(array[5], 0);
174  BOOST_CHECK_EQUAL(array[6], 0);
175  BOOST_CHECK_EQUAL(array[7], 0);
176  BOOST_CHECK_EQUAL(array[8], 0);
177  BOOST_CHECK_EQUAL(array[9], 1);
178  BOOST_CHECK_EQUAL(array[10], 2);
179  BOOST_CHECK_EQUAL(array[11], 3);
180 }
181 
182 BOOST_AUTO_TEST_CASE(TestConvertToColMajorArrayGrey) {
183  Bitmap bitmap;
184  bitmap.Allocate(2, 2, false);
185  bitmap.SetPixel(0, 0, BitmapColor<uint8_t>(0, 0, 0));
186  bitmap.SetPixel(0, 1, BitmapColor<uint8_t>(1, 0, 0));
187  bitmap.SetPixel(1, 0, BitmapColor<uint8_t>(2, 0, 0));
188  bitmap.SetPixel(1, 1, BitmapColor<uint8_t>(3, 0, 0));
189  const std::vector<uint8_t> array = bitmap.ConvertToColMajorArray();
190  BOOST_CHECK_EQUAL(array.size(), 4);
191  BOOST_CHECK_EQUAL(array[0], 0);
192  BOOST_CHECK_EQUAL(array[1], 1);
193  BOOST_CHECK_EQUAL(array[2], 2);
194  BOOST_CHECK_EQUAL(array[3], 3);
195 }
196 
197 BOOST_AUTO_TEST_CASE(TestGetAndSetPixelRGB) {
198  Bitmap bitmap;
199  bitmap.Allocate(1, 1, true);
200  bitmap.SetPixel(0, 0, BitmapColor<uint8_t>(1, 2, 3));
202  BOOST_CHECK(bitmap.GetPixel(0, 0, &color));
203  BOOST_CHECK_EQUAL(color, BitmapColor<uint8_t>(1, 2, 3));
204 }
205 
206 BOOST_AUTO_TEST_CASE(TestGetAndSetPixelGrey) {
207  Bitmap bitmap;
208  bitmap.Allocate(1, 1, false);
209  bitmap.SetPixel(0, 0, BitmapColor<uint8_t>(0, 2, 3));
211  BOOST_CHECK(bitmap.GetPixel(0, 0, &color));
212  BOOST_CHECK_EQUAL(color, BitmapColor<uint8_t>(0, 0, 0));
213  bitmap.SetPixel(0, 0, BitmapColor<uint8_t>(1, 2, 3));
214  BOOST_CHECK(bitmap.GetPixel(0, 0, &color));
215  BOOST_CHECK_EQUAL(color, BitmapColor<uint8_t>(1, 0, 0));
216 }
217 
218 BOOST_AUTO_TEST_CASE(TestGetScanlineRGB) {
219  Bitmap bitmap;
220  bitmap.Allocate(3, 3, true);
221  bitmap.Fill(BitmapColor<uint8_t>(1, 2, 3));
222  for (size_t r = 0; r < 3; ++r) {
223  const uint8_t* scanline = bitmap.GetScanline(r);
224  for (size_t c = 0; c < 3; ++c) {
226  BOOST_CHECK(bitmap.GetPixel(r, c, &color));
227  BOOST_CHECK_EQUAL(scanline[c * 3 + FI_RGBA_RED], color.r);
228  BOOST_CHECK_EQUAL(scanline[c * 3 + FI_RGBA_GREEN], color.g);
229  BOOST_CHECK_EQUAL(scanline[c * 3 + FI_RGBA_BLUE], color.b);
230  }
231  }
232 }
233 
234 BOOST_AUTO_TEST_CASE(TestGetScanlineGrey) {
235  Bitmap bitmap;
236  bitmap.Allocate(3, 3, false);
237  bitmap.Fill(BitmapColor<uint8_t>(1, 2, 3));
238  for (size_t r = 0; r < 3; ++r) {
239  const uint8_t* scanline = bitmap.GetScanline(r);
240  for (size_t c = 0; c < 3; ++c) {
242  BOOST_CHECK(bitmap.GetPixel(r, c, &color));
243  BOOST_CHECK_EQUAL(scanline[c], color.r);
244  }
245  }
246 }
247 
249  Bitmap bitmap;
250  bitmap.Allocate(100, 100, true);
251  bitmap.Fill(BitmapColor<uint8_t>(1, 2, 3));
252  for (int y = 0; y < bitmap.Height(); ++y) {
253  for (int x = 0; x < bitmap.Width(); ++x) {
255  BOOST_CHECK(bitmap.GetPixel(x, y, &color));
256  BOOST_CHECK_EQUAL(color, BitmapColor<uint8_t>(1, 2, 3));
257  }
258  }
259 }
260 
261 BOOST_AUTO_TEST_CASE(TestInterpolateNearestNeighbor) {
262  Bitmap bitmap;
263  bitmap.Allocate(11, 11, true);
264  bitmap.Fill(BitmapColor<uint8_t>(0, 0, 0));
265  bitmap.SetPixel(5, 5, BitmapColor<uint8_t>(1, 2, 3));
267  BOOST_CHECK(bitmap.InterpolateNearestNeighbor(5, 5, &color));
268  BOOST_CHECK_EQUAL(color, BitmapColor<uint8_t>(1, 2, 3));
269  BOOST_CHECK(bitmap.InterpolateNearestNeighbor(5.4999, 5.4999, &color));
270  BOOST_CHECK_EQUAL(color, BitmapColor<uint8_t>(1, 2, 3));
271  BOOST_CHECK(bitmap.InterpolateNearestNeighbor(5.5, 5.5, &color));
272  BOOST_CHECK_EQUAL(color, BitmapColor<uint8_t>(0, 0, 0));
273  BOOST_CHECK(bitmap.InterpolateNearestNeighbor(4.5, 5.4999, &color));
274  BOOST_CHECK_EQUAL(color, BitmapColor<uint8_t>(1, 2, 3));
275 }
276 
277 BOOST_AUTO_TEST_CASE(TestInterpolateBilinear) {
278  Bitmap bitmap;
279  bitmap.Allocate(11, 11, true);
280  bitmap.Fill(BitmapColor<uint8_t>(0, 0, 0));
281  bitmap.SetPixel(5, 5, BitmapColor<uint8_t>(1, 2, 3));
283  BOOST_CHECK(bitmap.InterpolateBilinear(5, 5, &color));
284  BOOST_CHECK_EQUAL(color, BitmapColor<float>(1, 2, 3));
285  BOOST_CHECK(bitmap.InterpolateBilinear(5.5, 5, &color));
286  BOOST_CHECK_EQUAL(color, BitmapColor<float>(0.5, 1, 1.5));
287  BOOST_CHECK(bitmap.InterpolateBilinear(5.5, 5.5, &color));
288  BOOST_CHECK_EQUAL(color, BitmapColor<float>(0.25, 0.5, 0.75));
289 }
290 
291 BOOST_AUTO_TEST_CASE(TestSmoothRGB) {
292  Bitmap bitmap;
293  bitmap.Allocate(50, 50, true);
294  for (int x = 0; x < 50; ++x) {
295  for (int y = 0; y < 50; ++y) {
296  bitmap.SetPixel(x, y,
297  BitmapColor<uint8_t>(y * 50 + x, y * 50 + x, y * 50 + x));
298  }
299  }
300  bitmap.Smooth(1, 1);
301  BOOST_CHECK_EQUAL(bitmap.Width(), 50);
302  BOOST_CHECK_EQUAL(bitmap.Height(), 50);
303  BOOST_CHECK_EQUAL(bitmap.Channels(), 3);
304  for (int x = 0; x < 50; ++x) {
305  for (int y = 0; y < 50; ++y) {
307  BOOST_CHECK(bitmap.GetPixel(x, y, &color));
308  BOOST_CHECK_EQUAL(color.r, color.g);
309  BOOST_CHECK_EQUAL(color.r, color.b);
310  }
311  }
312 }
313 
314 BOOST_AUTO_TEST_CASE(TestSmoothGrey) {
315  Bitmap bitmap;
316  bitmap.Allocate(50, 50, false);
317  for (int x = 0; x < 50; ++x) {
318  for (int y = 0; y < 50; ++y) {
319  bitmap.SetPixel(x, y,
320  BitmapColor<uint8_t>(y * 50 + x, y * 50 + x, y * 50 + x));
321  }
322  }
323  bitmap.Smooth(1, 1);
324  BOOST_CHECK_EQUAL(bitmap.Width(), 50);
325  BOOST_CHECK_EQUAL(bitmap.Height(), 50);
326  BOOST_CHECK_EQUAL(bitmap.Channels(), 1);
327 }
328 
329 BOOST_AUTO_TEST_CASE(TestRescaleRGB) {
330  Bitmap bitmap;
331  bitmap.Allocate(100, 100, true);
332  Bitmap bitmap1 = bitmap.Clone();
333  bitmap1.Rescale(50, 25);
334  BOOST_CHECK_EQUAL(bitmap1.Width(), 50);
335  BOOST_CHECK_EQUAL(bitmap1.Height(), 25);
336  BOOST_CHECK_EQUAL(bitmap1.Channels(), 3);
337  Bitmap bitmap2 = bitmap.Clone();
338  bitmap2.Rescale(150, 20);
339  BOOST_CHECK_EQUAL(bitmap2.Width(), 150);
340  BOOST_CHECK_EQUAL(bitmap2.Height(), 20);
341  BOOST_CHECK_EQUAL(bitmap2.Channels(), 3);
342 }
343 
344 BOOST_AUTO_TEST_CASE(TestRescaleGrey) {
345  Bitmap bitmap;
346  bitmap.Allocate(100, 100, false);
347  Bitmap bitmap1 = bitmap.Clone();
348  bitmap1.Rescale(50, 25);
349  BOOST_CHECK_EQUAL(bitmap1.Width(), 50);
350  BOOST_CHECK_EQUAL(bitmap1.Height(), 25);
351  BOOST_CHECK_EQUAL(bitmap1.Channels(), 1);
352  Bitmap bitmap2 = bitmap.Clone();
353  bitmap2.Rescale(150, 20);
354  BOOST_CHECK_EQUAL(bitmap2.Width(), 150);
355  BOOST_CHECK_EQUAL(bitmap2.Height(), 20);
356  BOOST_CHECK_EQUAL(bitmap2.Channels(), 1);
357 }
358 
360  Bitmap bitmap;
361  bitmap.Allocate(100, 100, true);
362  const Bitmap cloned_bitmap = bitmap.Clone();
363  BOOST_CHECK_EQUAL(cloned_bitmap.Width(), 100);
364  BOOST_CHECK_EQUAL(cloned_bitmap.Height(), 100);
365  BOOST_CHECK_EQUAL(cloned_bitmap.Channels(), 3);
366  BOOST_CHECK_NE(bitmap.Data(), cloned_bitmap.Data());
367 }
368 
369 BOOST_AUTO_TEST_CASE(TestCloneAsRGB) {
370  Bitmap bitmap;
371  bitmap.Allocate(100, 100, false);
372  const Bitmap cloned_bitmap = bitmap.CloneAsRGB();
373  BOOST_CHECK_EQUAL(cloned_bitmap.Width(), 100);
374  BOOST_CHECK_EQUAL(cloned_bitmap.Height(), 100);
375  BOOST_CHECK_EQUAL(cloned_bitmap.Channels(), 3);
376  BOOST_CHECK_NE(bitmap.Data(), cloned_bitmap.Data());
377 }
378 
379 BOOST_AUTO_TEST_CASE(TestCloneAsGrey) {
380  Bitmap bitmap;
381  bitmap.Allocate(100, 100, true);
382  const Bitmap cloned_bitmap = bitmap.CloneAsGrey();
383  BOOST_CHECK_EQUAL(cloned_bitmap.Width(), 100);
384  BOOST_CHECK_EQUAL(cloned_bitmap.Height(), 100);
385  BOOST_CHECK_EQUAL(cloned_bitmap.Channels(), 1);
386  BOOST_CHECK_NE(bitmap.Data(), cloned_bitmap.Data());
387 }
math::float4 color
BOOST_AUTO_TEST_CASE(TestBitmapColorEmpty)
Definition: bitmap_test.cc:39
bool SetPixel(const int x, const int y, const BitmapColor< uint8_t > &color)
Definition: bitmap.cc:199
std::vector< uint8_t > ConvertToRowMajorArray() const
Definition: bitmap.cc:147
bool GetPixel(const int x, const int y, BitmapColor< uint8_t > *color) const
Definition: bitmap.cc:178
bool IsRGB() const
Definition: bitmap.h:261
void Fill(const BitmapColor< uint8_t > &color)
Definition: bitmap.cc:226
Bitmap Clone() const
Definition: bitmap.cc:586
const uint8_t * GetScanline(const int y) const
Definition: bitmap.cc:220
bool Allocate(const int width, const int height, const bool as_rgb)
Definition: bitmap.cc:104
void Rescale(const int new_width, const int new_height, const FREE_IMAGE_FILTER filter=FILTER_BILINEAR)
Definition: bitmap.cc:581
void Smooth(const float sigma_x, const float sigma_y)
Definition: bitmap.cc:553
bool InterpolateBilinear(const double x, const double y, BitmapColor< float > *color) const
Definition: bitmap.cc:248
std::vector< uint8_t > ConvertToColMajorArray() const
Definition: bitmap.cc:162
int Width() const
Definition: bitmap.h:249
bool InterpolateNearestNeighbor(const double x, const double y, BitmapColor< uint8_t > *color) const
Definition: bitmap.cc:241
bool IsGrey() const
Definition: bitmap.h:263
void Deallocate()
Definition: bitmap.cc:121
const FIBITMAP * Data() const
Definition: bitmap.h:247
int Channels() const
Definition: bitmap.h:251
int Height() const
Definition: bitmap.h:250
size_t NumBytes() const
Definition: bitmap.cc:128
Bitmap CloneAsGrey() const
Definition: bitmap.cc:588
Bitmap CloneAsRGB() const
Definition: bitmap.cc:596
unsigned int BitsPerPixel() const
Definition: bitmap.h:253
normal_z y
normal_z x
BitmapColor< D > Cast() const
Definition: bitmap.h:220