2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #include <dali-test-suite-utils.h>
19 #include <dali/devel-api/common/ref-counted-dali-vector.h>
20 #include <dali/internal/imaging/common/image-operations.h>
25 using namespace Dali::Internal::Platform;
30 * @brief Generate a random integer between zero and the parameter passed in.
32 uint32_t RandomInRange(uint32_t max)
34 const uint32_t randToMax = lrand48() % (max + 1);
39 * @brief Random number representable in an 8 bit color component.
41 inline uint32_t RandomComponent8()
43 return RandomInRange(255u);
47 * @brief Random number representable in a 5 bit color component.
49 inline uint32_t RandomComponent5()
51 return RandomInRange(31u);
55 * @brief Random number representable in a 6 bit color component.
57 inline uint32_t RandomComponent6()
59 return RandomInRange(63u);
63 * @brief RGBA8888 Pixels from separate color components.
65 inline uint32_t PixelRGBA8888(uint32_t r, uint32_t g, uint32_t b, uint32_t a)
67 return (r << 24) + (g << 16) + (b << 8) + a;
71 * @brief RGB565 Pixels from color components in the low bits of passed-in words.
73 inline uint16_t PixelRGB565(uint32_t r, uint32_t g, uint32_t b)
75 return (r << 11) + (g << 5) + b;
79 * @brief RGBA8888 Pixels with random color components.
81 inline uint32_t RandomPixelRGBA8888()
83 const uint32_t randomPixel = PixelRGBA8888(RandomComponent8(), RandomComponent8(), RandomComponent8(), RandomComponent8());
88 * @brief Return a hash over a set of pixels.
90 * Used to check a buffer of pixels is unmodified by an operation given inputs
91 * that should mean that it is not changed.
93 inline uint32_t HashPixels(const uint32_t* const pixels, unsigned int numPixels)
97 for(unsigned int i = 0; i < numPixels; ++i)
99 hash = hash * 33 + pixels[i];
106 * @brief Build some dummy scanlines to exercise scanline averaging code on.
108 void SetupScanlineForHalvingTestsRGBA8888(size_t scanlineLength, Dali::Vector<uint32_t>& scanline, Dali::Vector<uint32_t>& reference)
110 scanline.Resize(scanlineLength);
111 reference.Resize(scanlineLength / 2 + 32);
113 // Prepare some random pixels:
114 srand(19 * 23 * 47 * 53);
115 for(size_t i = 0; i < scanlineLength / 2; ++i)
117 // Generate random colors:
118 const uint32_t red1 = RandomComponent8();
119 const uint32_t red2 = RandomComponent8();
120 const uint32_t green1 = RandomComponent8();
121 const uint32_t green2 = RandomComponent8();
122 const uint32_t blue1 = RandomComponent8();
123 const uint32_t blue2 = RandomComponent8();
124 const uint32_t alpha1 = RandomComponent8();
125 const uint32_t alpha2 = RandomComponent8();
127 // The average of these pixels should equal the reference:
128 scanline[i * 2] = PixelRGBA8888(red1, green1, blue1, alpha1);
129 scanline[i * 2 + 1] = PixelRGBA8888(red2, green2, blue2, alpha2);
131 // Average the two pixels manually as a reference:
132 reference[i] = (PixelRGBA8888((red1 + red2) >> 1u, (green1 + green2) >> 1u, (blue1 + blue2) >> 1u, (alpha1 + alpha2) >> 1u));
135 for(size_t i = scanlineLength / 2; i < reference.Count(); ++i)
137 reference[i] = 0xEEEEEEEE;
142 * @brief Build some dummy scanlines to exercise scanline averaging code on.
144 void SetupScanlineForHalvingTestsRGB565(size_t scanlineLength, Dali::Vector<uint16_t>& scanline, Dali::Vector<uint16_t>& reference)
146 scanline.Resize(scanlineLength);
147 reference.Resize(scanlineLength / 2 + 32);
149 // Prepare some random pixels:
150 srand48(19 * 23 * 47 * 53);
151 for(size_t i = 0; i < scanlineLength / 2; ++i)
153 // Generate random colors:
154 const uint32_t red1 = RandomComponent5();
155 const uint32_t red2 = RandomComponent5();
156 const uint32_t green1 = RandomComponent6();
157 const uint32_t green2 = RandomComponent6();
158 const uint32_t blue1 = RandomComponent5();
159 const uint32_t blue2 = RandomComponent5();
161 // The average of these pixels should equal the reference:
162 scanline[i * 2] = PixelRGB565(red1, green1, blue1);
163 scanline[i * 2 + 1] = PixelRGB565(red2, green2, blue2);
165 // Average the two pixels manually as a reference:
166 reference[i] = (PixelRGB565((red1 + red2) >> 1u, (green1 + green2) >> 1u, (blue1 + blue2) >> 1u));
169 for(size_t i = scanlineLength / 2; i < reference.Count(); ++i)
171 reference[i] = 0xEEEE;
176 * @brief Build some dummy scanlines to exercise scanline averaging code on.
178 void SetupScanlineForHalvingTests2Bytes(size_t scanlineLength, Dali::Vector<uint8_t>& scanline, Dali::Vector<uint8_t>& reference)
180 scanline.Resize(scanlineLength * 2);
181 reference.Resize(scanlineLength + 32);
183 // Prepare some random pixels:
184 srand48(19 * 23 * 47 * 53 * 59);
185 for(size_t i = 0; i < scanlineLength / 2; ++i)
187 // Generate random colors:
188 const uint32_t c11 = RandomComponent8();
189 const uint32_t c12 = RandomComponent8();
190 const uint32_t c21 = RandomComponent8();
191 const uint32_t c22 = RandomComponent8();
193 // The average of these pixels should equal the reference:
194 scanline[i * 4] = c11;
195 scanline[i * 4 + 1] = c12;
196 scanline[i * 4 + 2] = c21;
197 scanline[i * 4 + 3] = c22;
199 // Average the two pixels manually as a reference:
200 reference[i * 2] = ((c11 + c21) >> 1u);
201 reference[i * 2 + 1] = ((c12 + c22) >> 1u);
204 for(size_t i = scanlineLength; i < reference.Count(); ++i)
211 * @brief Build some dummy 1 byte per pixel scanlines to exercise scanline averaging code on.
213 void SetupScanlineForHalvingTests1Byte(size_t scanlineLength, Dali::Vector<uint8_t>& scanline, Dali::Vector<uint8_t>& reference)
215 scanline.Resize(scanlineLength);
216 reference.Resize(scanlineLength / 2 + 32);
218 // Prepare some random pixels:
219 srand48(19 * 23 * 47 * 53 * 63);
220 for(size_t i = 0; i < scanlineLength / 2; ++i)
222 // Generate random colors:
223 const uint32_t c1 = RandomComponent8();
224 const uint32_t c2 = RandomComponent8();
226 // The average of these pixels should equal the reference:
227 scanline[i * 2] = c1;
228 scanline[i * 2 + 1] = c2;
230 // Average the two pixels manually as a reference:
231 reference[i] = ((c1 + c2) >> 1u);
234 for(size_t i = scanlineLength / 2; i < reference.Count(); ++i)
241 * @brief Build some dummy scanlines to exercise vertical averaging code on.
243 * All tested formats bar RGB565 can share this setup.
245 void SetupScanlinesRGBA8888(size_t scanlineLength, Dali::Vector<uint32_t>& scanline1, Dali::Vector<uint32_t>& scanline2, Dali::Vector<uint32_t>& reference, Dali::Vector<uint32_t>& output)
247 scanline1.Resize(scanlineLength);
248 scanline2.Resize(scanlineLength);
249 reference.Resize(scanlineLength + 32);
250 output.Resize(scanlineLength + 32);
252 for(size_t i = scanlineLength; i < output.Count(); ++i)
254 output[i] = 0xDEADBEEF;
255 reference[i] = 0xDEADBEEF;
258 // Prepare some random pixels:
259 srand48(19 * 23 * 47);
260 for(size_t i = 0; i < scanlineLength; ++i)
262 // Generate random colors:
263 const uint32_t red1 = RandomComponent8();
264 const uint32_t red2 = RandomComponent8();
265 const uint32_t green1 = RandomComponent8();
266 const uint32_t green2 = RandomComponent8();
267 const uint32_t blue1 = RandomComponent8();
268 const uint32_t blue2 = RandomComponent8();
269 const uint32_t alpha1 = RandomComponent8();
270 const uint32_t alpha2 = RandomComponent8();
272 // The average of these pixels should equal the reference:
273 scanline1[i] = (PixelRGBA8888(red1, green1, blue1, alpha1));
274 scanline2[i] = (PixelRGBA8888(red2, green2, blue2, alpha2));
276 // Average the two pixels manually as a reference:
277 reference[i] = (PixelRGBA8888((red1 + red2) >> 1u, (green1 + green2) >> 1u, (blue1 + blue2) >> 1u, (alpha1 + alpha2) >> 1u));
282 * @brief Compares a scanline of interest to a reference, testing each pixel is the same.
284 void MatchScanlinesRGBA8888(Dali::Vector<uint32_t>& reference, Dali::Vector<uint32_t>& output, size_t& numMatches, const char* const location)
287 for(size_t i = 0, length = reference.Count(); i < length; ++i)
289 DALI_TEST_EQUALS(output[i], reference[i], location);
290 numMatches += output[i] == reference[i];
297 * @brief Test component averaging code.
299 int UtcDaliImageOperationsAverageComponent(void)
301 DALI_TEST_EQUALS(Dali::Internal::Platform::AverageComponent(0u, 0u), 0u, TEST_LOCATION);
302 DALI_TEST_EQUALS(Dali::Internal::Platform::AverageComponent(1u, 1u), 1u, TEST_LOCATION);
303 DALI_TEST_EQUALS(Dali::Internal::Platform::AverageComponent(0xffffffffu >> 1u, 0xffffffffu >> 1u), 0xffffffffu >> 1u, TEST_LOCATION);
304 const unsigned int avg3 = Dali::Internal::Platform::AverageComponent(0xfffffffeu, 1u);
305 DALI_TEST_EQUALS(avg3, 0x7fffffffu, TEST_LOCATION);
306 DALI_TEST_EQUALS(Dali::Internal::Platform::AverageComponent(255u, 255u), 255u, TEST_LOCATION);
307 DALI_TEST_EQUALS(Dali::Internal::Platform::AverageComponent(512u, 0u), 256u, TEST_LOCATION);
308 DALI_TEST_EQUALS(Dali::Internal::Platform::AverageComponent(511u, 0u), 255u, TEST_LOCATION);
309 DALI_TEST_EQUALS(Dali::Internal::Platform::AverageComponent(510u, 0u), 255u, TEST_LOCATION);
310 DALI_TEST_EQUALS(Dali::Internal::Platform::AverageComponent(509u, 0u), 254u, TEST_LOCATION);
311 DALI_TEST_EQUALS(Dali::Internal::Platform::AverageComponent(0u, 509u), 254u, TEST_LOCATION);
316 * @brief Test Pixel averaging code.
318 int UtcDaliImageOperationsAveragePixelRGBA8888(void)
320 DALI_TEST_EQUALS(Dali::Internal::Platform::AveragePixelRGBA8888(0u, 0u), 0u, TEST_LOCATION);
321 DALI_TEST_EQUALS(Dali::Internal::Platform::AveragePixelRGBA8888(0x01010101, 0x01010101), 0x01010101u, TEST_LOCATION);
322 DALI_TEST_EQUALS(Dali::Internal::Platform::AveragePixelRGBA8888(0x01010101, 0x03030303), 0x02020202u, TEST_LOCATION);
323 DALI_TEST_EQUALS(Dali::Internal::Platform::AveragePixelRGBA8888(0xffffffff, 0xffffffff), 0xffffffffu, TEST_LOCATION);
324 DALI_TEST_EQUALS(Dali::Internal::Platform::AveragePixelRGBA8888(0xffffffff, 0u), 0x7f7f7f7fu, TEST_LOCATION);
329 * @brief Test RGBA565 pixel averaging function.
331 int UtcDaliImageOperationsAveragePixelRGB565(void)
333 DALI_TEST_EQUALS(Dali::Internal::Platform::AveragePixelRGB565(0u, 0u), 0u, TEST_LOCATION);
334 DALI_TEST_EQUALS(Dali::Internal::Platform::AveragePixelRGB565(0xf800u, 0xf800u), 0xf800u, TEST_LOCATION);
335 DALI_TEST_EQUALS(Dali::Internal::Platform::AveragePixelRGB565(0xf800u, 0x800u), 1u << 15, TEST_LOCATION);
336 DALI_TEST_EQUALS(Dali::Internal::Platform::AveragePixelRGB565(0x7e0u, 0x7e0u), 0x7e0u, TEST_LOCATION);
337 DALI_TEST_EQUALS(Dali::Internal::Platform::AveragePixelRGB565(0x7e0u, 0x20u), 1u << 10, TEST_LOCATION);
338 DALI_TEST_EQUALS(Dali::Internal::Platform::AveragePixelRGB565(0x1f, 0x1f), 0x1fu, TEST_LOCATION);
339 DALI_TEST_EQUALS(Dali::Internal::Platform::AveragePixelRGB565(0x1f, 0x1), 1u << 4, TEST_LOCATION);
340 DALI_TEST_EQUALS(Dali::Internal::Platform::AveragePixelRGB565(0xf800u, 0x7e0u), 0x7800u + 0x3e0u, TEST_LOCATION);
341 DALI_TEST_EQUALS(Dali::Internal::Platform::AveragePixelRGB565(0xffff, 0xffff), 0xffffu, TEST_LOCATION);
346 * @brief Build a square bitmap, downscale it and assert the resulting bitmap has the right dimensions.
348 void TestDownscaledBitmapHasRightDimensionsAndFormat(
349 Pixel::Format format,
350 uint32_t sourceDimension,
351 uint32_t targetDimension,
352 uint32_t expectedDimension,
353 const char* const location)
355 ImageDimensions desired(targetDimension, targetDimension);
356 FittingMode::Type fittingMode(FittingMode::SHRINK_TO_FIT);
357 SamplingMode::Type samplingMode(SamplingMode::BOX);
359 Dali::Devel::PixelBuffer sourceBitmap = Dali::Devel::PixelBuffer::New(sourceDimension, sourceDimension, format);
361 Dali::Devel::PixelBuffer downScaled = DownscaleBitmap(sourceBitmap, desired, fittingMode, samplingMode);
363 DALI_TEST_EQUALS(downScaled.GetWidth(), expectedDimension, location);
364 DALI_TEST_EQUALS(downScaled.GetHeight(), expectedDimension, location);
365 DALI_TEST_EQUALS(downScaled.GetPixelFormat(), format, location);
369 * @brief Test the top-level function for reducing the dimension of a bitmap,
370 * feeding it each of the five pixel formats that are output by image loaders.
371 * Simply assert that the resulting bitmaps have the expected dimensions and
374 int UtcDaliImageOperationsDownscaleBitmap(void)
376 // Do Scalings that are expected to work for all pixels modes and assert the resulting bitmap dimensions:
378 TestDownscaledBitmapHasRightDimensionsAndFormat(Pixel::RGBA8888, 1024, 8, 8, TEST_LOCATION);
379 TestDownscaledBitmapHasRightDimensionsAndFormat(Pixel::RGB888, 1024, 8, 8, TEST_LOCATION);
380 TestDownscaledBitmapHasRightDimensionsAndFormat(Pixel::RGB565, 1024, 8, 8, TEST_LOCATION);
381 TestDownscaledBitmapHasRightDimensionsAndFormat(Pixel::LA88, 1024, 8, 8, TEST_LOCATION);
382 TestDownscaledBitmapHasRightDimensionsAndFormat(Pixel::L8, 1024, 8, 8, TEST_LOCATION);
384 TestDownscaledBitmapHasRightDimensionsAndFormat(Pixel::RGBA8888, 773, 1, 1, TEST_LOCATION);
385 TestDownscaledBitmapHasRightDimensionsAndFormat(Pixel::RGB888, 787, 1, 1, TEST_LOCATION);
386 TestDownscaledBitmapHasRightDimensionsAndFormat(Pixel::RGB565, 797, 1, 1, TEST_LOCATION);
387 TestDownscaledBitmapHasRightDimensionsAndFormat(Pixel::LA88, 809, 1, 1, TEST_LOCATION);
388 TestDownscaledBitmapHasRightDimensionsAndFormat(Pixel::L8, 811, 1, 1, TEST_LOCATION);
390 // Do Scalings that are expected to produce a slightly larger than requested image:
391 TestDownscaledBitmapHasRightDimensionsAndFormat(Pixel::RGBA8888, 47, 7, 11, TEST_LOCATION);
392 TestDownscaledBitmapHasRightDimensionsAndFormat(Pixel::RGB888, 73, 17, 18, TEST_LOCATION);
393 TestDownscaledBitmapHasRightDimensionsAndFormat(Pixel::RGB565, 61, 8, 15, TEST_LOCATION);
394 TestDownscaledBitmapHasRightDimensionsAndFormat(Pixel::LA88, 19, 5, 9, TEST_LOCATION);
395 TestDownscaledBitmapHasRightDimensionsAndFormat(Pixel::L8, 353, 23, 44, TEST_LOCATION);
401 * @brief Test downscaling of RGB888 images as raw pixel arrays.
403 int UtcDaliImageOperationsDownscaleInPlacePow2RGB888(void)
405 unsigned outWidth = -1, outHeight = -1, outStride = -1;
407 // Do downscaling to 1 x 1 so we can easily assert the value of the single pixel produced:
409 // Scale down a black/white checkerboard to mid-grey:
410 unsigned char check_4x4[16 * 3] = {
411 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff};
413 Dali::Internal::Platform::DownscaleInPlacePow2RGB888(check_4x4, 4, 4, 4, 1, 1, BoxDimensionTestBoth, outWidth, outHeight, outStride);
414 DALI_TEST_EQUALS(outWidth, 1u, TEST_LOCATION);
415 DALI_TEST_EQUALS(outHeight, 1u, TEST_LOCATION);
416 DALI_TEST_EQUALS(outStride, 1u, TEST_LOCATION);
417 DALI_TEST_EQUALS(check_4x4[0], (unsigned char)0x7f, TEST_LOCATION);
419 // Scale down a 16 pixel black image with a single white pixel to a 1/16th grey single pixel:
420 unsigned char single_4x4[16 * 3] = {
421 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
422 Dali::Internal::Platform::DownscaleInPlacePow2RGB888(single_4x4, 4, 4, 4, 1, 1, BoxDimensionTestBoth, outWidth, outHeight, outStride);
423 DALI_TEST_EQUALS(outWidth, 1u, TEST_LOCATION);
424 DALI_TEST_EQUALS(outHeight, 1u, TEST_LOCATION);
425 DALI_TEST_EQUALS(outStride, 1u, TEST_LOCATION);
426 DALI_TEST_EQUALS(single_4x4[0], (unsigned char)0xf, TEST_LOCATION);
428 // Scale down a 16 pixel black image with a single white pixel to a 1/16th grey single pixel:
429 // (white pixel at bottom-right of image)
430 unsigned char single_4x4_2[16 * 3] = {
431 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff};
432 Dali::Internal::Platform::DownscaleInPlacePow2RGB888(single_4x4_2, 4, 4, 4, 1, 1, BoxDimensionTestBoth, outWidth, outHeight, outStride);
433 DALI_TEST_EQUALS(outWidth, 1u, TEST_LOCATION);
434 DALI_TEST_EQUALS(outHeight, 1u, TEST_LOCATION);
435 DALI_TEST_EQUALS(outStride, 1u, TEST_LOCATION);
436 DALI_TEST_EQUALS(single_4x4_2[0], (unsigned char)0xf, TEST_LOCATION);
438 // Build a larger ~600 x ~600 uniform magenta image for tests which only test output dimensions:
440 unsigned char magenta_600_x_600[608 * 608 * 3];
441 for(unsigned int i = 0; i < sizeof(magenta_600_x_600); i += 3)
443 magenta_600_x_600[i] = 0xff;
444 magenta_600_x_600[i + 1] = 0;
445 magenta_600_x_600[i + 2] = 0xff;
448 // Scaling to 0 x 0 should stop at 1 x 1:
449 Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 352, 352, 352, 0, 0, BoxDimensionTestBoth, outWidth, outHeight, outStride);
450 DALI_TEST_EQUALS(outWidth, 1u, TEST_LOCATION);
451 DALI_TEST_EQUALS(outHeight, 1u, TEST_LOCATION);
452 DALI_TEST_CHECK(outStride == outWidth);
454 // Scaling to 1 x 1 should hit 1 x 1:
455 Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 608, 608, 608, 1, 1, BoxDimensionTestBoth, outWidth, outHeight, outStride);
456 DALI_TEST_EQUALS(outWidth, 1u, TEST_LOCATION);
457 DALI_TEST_EQUALS(outHeight, 1u, TEST_LOCATION);
458 DALI_TEST_CHECK(outStride == outWidth);
460 // Scaling to original dimensions should NOP:
461 Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 384, 384, 384, 384, 384, BoxDimensionTestBoth, outWidth, outHeight, outStride);
462 DALI_TEST_EQUALS(outWidth, 384u, TEST_LOCATION);
463 DALI_TEST_EQUALS(outHeight, 384u, TEST_LOCATION);
464 DALI_TEST_CHECK(outStride == outWidth);
466 // More dimension tests:
468 Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 352, 352, 352, 44, 11, BoxDimensionTestBoth, outWidth, outHeight, outStride);
469 DALI_TEST_EQUALS(outWidth, 44u, TEST_LOCATION);
470 DALI_TEST_EQUALS(outHeight, 44u, TEST_LOCATION);
471 DALI_TEST_CHECK(outStride == outWidth);
473 Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 384, 384, 384, 3, 48, BoxDimensionTestBoth, outWidth, outHeight, outStride);
474 DALI_TEST_EQUALS(outWidth, 48u, TEST_LOCATION);
475 DALI_TEST_EQUALS(outHeight, 48u, TEST_LOCATION);
476 DALI_TEST_CHECK(outStride == outWidth);
478 Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 384, 384, 384, 3, 3, BoxDimensionTestBoth, outWidth, outHeight, outStride);
479 DALI_TEST_CHECK(outWidth == 3u && outHeight == 3u);
480 DALI_TEST_CHECK(outStride == outWidth);
482 Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 320, 320, 320, 5, 5, BoxDimensionTestBoth, outWidth, outHeight, outStride);
483 DALI_TEST_CHECK(outWidth == 5u && outHeight == 5u);
484 DALI_TEST_CHECK(outStride == outWidth);
486 Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 448, 448, 448, 7, 7, BoxDimensionTestBoth, outWidth, outHeight, outStride);
487 DALI_TEST_CHECK(outWidth == 7u && outHeight == 7u);
488 DALI_TEST_CHECK(outStride == outWidth);
490 Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 352, 352, 352, 11, 11, BoxDimensionTestBoth, outWidth, outHeight, outStride);
491 DALI_TEST_CHECK(outWidth == 11u && outHeight == 11u);
492 DALI_TEST_CHECK(outStride == outWidth);
494 // Check that no pixel values were modified by the repeated averaging of identical pixels in tests above:
495 unsigned int numNonMagenta = 0u;
496 for(unsigned i = 0; i < sizeof(magenta_600_x_600); i += 3)
498 numNonMagenta += magenta_600_x_600[i] == 0xff && magenta_600_x_600[i + 1] == 0x00 && magenta_600_x_600[i + 2] == 0xff ? 0 : 1;
500 DALI_TEST_EQUALS(numNonMagenta, 0u, TEST_LOCATION);
506 * @brief Test that resizing RGBA8888 images as raw pixel arrays produces a result of the correct dimensions.
508 void TestDownscaleOutputsExpectedDimensionsRGBA8888(uint32_t pixels[], unsigned inputWidth, unsigned inputHeight, unsigned int desiredWidth, unsigned int desiredHeight, unsigned int expectedWidth, unsigned int expectedHeight, const char* const location)
510 unsigned int resultingWidth = -1, resultingHeight = -1, resultingStride = -1;
511 Dali::Internal::Platform::DownscaleInPlacePow2RGBA8888(
512 reinterpret_cast<unsigned char*>(pixels),
518 BoxDimensionTestBoth,
523 DALI_TEST_EQUALS(resultingWidth, expectedWidth, location);
524 DALI_TEST_EQUALS(resultingHeight, expectedHeight, location);
525 DALI_TEST_EQUALS(resultingStride, expectedWidth, location);
529 * @brief Test that resizing RGB565 images as raw pixel arrays produces a result of the correct dimensions.
531 void TestDownscaleOutputsExpectedDimensionsRGB565(uint16_t pixels[], unsigned inputWidth, unsigned inputHeight, unsigned int desiredWidth, unsigned int desiredHeight, unsigned int expectedWidth, unsigned int expectedHeight, const char* const location)
533 unsigned int resultingWidth = -1, resultingHeight = -1, resultingStride = -1;
534 Dali::Internal::Platform::DownscaleInPlacePow2RGB565(
535 reinterpret_cast<unsigned char*>(pixels),
541 BoxDimensionTestBoth,
546 DALI_TEST_EQUALS(resultingWidth, expectedWidth, location);
547 DALI_TEST_EQUALS(resultingHeight, expectedHeight, location);
548 DALI_TEST_EQUALS(resultingStride, expectedWidth, location);
552 * @brief Test that resizing 2-byte-per-pixel images as raw pixel arrays produces a result of the correct dimensions.
554 void TestDownscaleOutputsExpectedDimensions2ComponentPair(uint8_t pixels[], unsigned inputWidth, unsigned inputHeight, unsigned int desiredWidth, unsigned int desiredHeight, unsigned int expectedWidth, unsigned int expectedHeight, const char* const location)
556 unsigned int resultingWidth = -1, resultingHeight = -1, resultingStride = -1;
557 Dali::Internal::Platform::DownscaleInPlacePow2ComponentPair(
564 BoxDimensionTestBoth,
569 DALI_TEST_EQUALS(resultingWidth, expectedWidth, location);
570 DALI_TEST_EQUALS(resultingHeight, expectedHeight, location);
571 DALI_TEST_EQUALS(resultingStride, expectedWidth, location);
575 * @brief Test that resizing single-byte-per-pixel images as raw pixel arrays produces a result of the correct dimensions.
577 void TestDownscaleOutputsExpectedDimensionsSingleComponent(uint8_t pixels[], unsigned inputWidth, unsigned inputHeight, unsigned int desiredWidth, unsigned int desiredHeight, unsigned int expectedWidth, unsigned int expectedHeight, const char* const location)
579 unsigned int resultingWidth = -1, resultingHeight = -1, resultingStride = -1;
580 Dali::Internal::Platform::DownscaleInPlacePow2SingleBytePerPixel(
587 BoxDimensionTestBoth,
592 DALI_TEST_EQUALS(resultingWidth, expectedWidth, location);
593 DALI_TEST_EQUALS(resultingHeight, expectedHeight, location);
594 DALI_TEST_EQUALS(resultingStride, expectedWidth, location);
598 * @brief Test downscaling of RGBA8888 images in raw image arrays.
600 int UtcDaliImageOperationsDownscaleInPlacePow2RGBA8888(void)
602 uint32_t image[608 * 608];
603 for(unsigned i = 0; i < sizeof(image) / sizeof(image[0]); ++i)
605 image[i] = 0xffffffff;
607 unsigned char* const pixels = reinterpret_cast<unsigned char*>(image);
608 unsigned int resultingWidth = -1, resultingHeight = -1, resultingStride = -1;
610 // Test downscaling where the input size is an exact multiple of the desired size:
611 // (We expect a perfect result here)
613 DownscaleInPlacePow2RGBA8888(pixels, 600, 600, 600, 75, 75, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
614 DALI_TEST_EQUALS(resultingWidth, 75u, TEST_LOCATION);
615 DALI_TEST_EQUALS(resultingHeight, 75u, TEST_LOCATION);
616 DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
618 DownscaleInPlacePow2RGBA8888(pixels, 512, 512, 512, 16, 16, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
619 DALI_TEST_EQUALS(resultingWidth, 16u, TEST_LOCATION);
620 DALI_TEST_EQUALS(resultingHeight, 16u, TEST_LOCATION);
621 DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
623 DownscaleInPlacePow2RGBA8888(pixels, 512, 64, 512, 16, 2, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
624 DALI_TEST_EQUALS(resultingWidth, 16u, TEST_LOCATION);
625 DALI_TEST_EQUALS(resultingHeight, 2u, TEST_LOCATION);
626 DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
628 DownscaleInPlacePow2RGBA8888(pixels, 64, 1024, 64, 4, 64, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
629 DALI_TEST_EQUALS(resultingWidth, 4u, TEST_LOCATION);
630 DALI_TEST_EQUALS(resultingHeight, 64u, TEST_LOCATION);
631 DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
633 // Test downscaling where the input size is slightly off being an exact multiple of the desired size:
634 // (We expect a perfect match at the end because of rounding-down to an even width and height at each step)
636 DownscaleInPlacePow2RGBA8888(pixels, 601, 603, 601, 75, 75, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
637 DALI_TEST_EQUALS(resultingWidth, 75u, TEST_LOCATION);
638 DALI_TEST_EQUALS(resultingHeight, 75u, TEST_LOCATION);
639 DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
641 DownscaleInPlacePow2RGBA8888(pixels, 736 + 1, 352 + 3, 736 + 1, 23, 11, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
642 DALI_TEST_EQUALS(resultingWidth, 23u, TEST_LOCATION);
643 DALI_TEST_EQUALS(resultingHeight, 11u, TEST_LOCATION);
644 DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
646 DownscaleInPlacePow2RGBA8888(pixels, 384 + 3, 896 + 1, 384 + 3, 3, 7, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
647 DALI_TEST_EQUALS(resultingWidth, 3u, TEST_LOCATION);
648 DALI_TEST_EQUALS(resultingHeight, 7u, TEST_LOCATION);
649 DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
651 // Test downscales with source dimensions which are under a nice power of two by one:
653 // The target is hit exactly due to losing spare columns or rows at each iteration:
654 DownscaleInPlacePow2RGBA8888(pixels, 63, 31, 63, 7, 3, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
655 DALI_TEST_EQUALS(resultingWidth, 7u, TEST_LOCATION);
656 DALI_TEST_EQUALS(resultingHeight, 3u, TEST_LOCATION);
657 DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
659 // Asking to downscale a bit smaller should stop at the dimensions of the last test as one more halving would go down to 3 x 1, which is too small.
660 DownscaleInPlacePow2RGBA8888(pixels, 63, 31, 63, 4, 2, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
661 DALI_TEST_EQUALS(resultingWidth, 7u, TEST_LOCATION);
662 DALI_TEST_EQUALS(resultingHeight, 3u, TEST_LOCATION);
663 DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
665 // Should stop at almost twice the requested dimensions:
666 DownscaleInPlacePow2RGBA8888(pixels, 15, 127, 15, 4, 32, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
667 DALI_TEST_EQUALS(resultingWidth, 7u, TEST_LOCATION);
668 DALI_TEST_EQUALS(resultingHeight, 63u, TEST_LOCATION);
669 DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
671 // Test downscales to 1 in one or both dimensions:
672 // Parameters: input-x input-y, desired-x, desired-y, expected-x, expected-y
673 TestDownscaleOutputsExpectedDimensionsRGBA8888(image, 512, 512, 1, 1, 1, 1, TEST_LOCATION);
674 TestDownscaleOutputsExpectedDimensionsRGBA8888(image, 512, 32, 16, 1, 16, 1, TEST_LOCATION);
675 TestDownscaleOutputsExpectedDimensionsRGBA8888(image, 512, 32, 7, 1, 16, 1, TEST_LOCATION);
676 TestDownscaleOutputsExpectedDimensionsRGBA8888(image, 512, 32, 7, 1, 16, 1, TEST_LOCATION);
677 TestDownscaleOutputsExpectedDimensionsRGBA8888(image, 512, 32, 5, 1, 16, 1, TEST_LOCATION);
678 TestDownscaleOutputsExpectedDimensionsRGBA8888(image, 512, 32, 3, 1, 16, 1, TEST_LOCATION);
679 TestDownscaleOutputsExpectedDimensionsRGBA8888(image, 32, 512, 1, 1, 1, 16, TEST_LOCATION);
680 TestDownscaleOutputsExpectedDimensionsRGBA8888(image, 32, 512, 1, 16, 1, 16, TEST_LOCATION);
681 TestDownscaleOutputsExpectedDimensionsRGBA8888(image, 32, 512, 1, 3, 1, 16, TEST_LOCATION);
682 TestDownscaleOutputsExpectedDimensionsRGBA8888(image, 33, 33, 1, 1, 1, 1, TEST_LOCATION);
683 TestDownscaleOutputsExpectedDimensionsRGBA8888(image, 17 * 19, 17 * 19, 1, 1, 1, 1, TEST_LOCATION);
684 TestDownscaleOutputsExpectedDimensionsRGBA8888(image, 33, 33, 3, 1, 4, 4, TEST_LOCATION);
685 TestDownscaleOutputsExpectedDimensionsRGBA8888(image, 33, 9, 3, 1, 4, 1, TEST_LOCATION);
687 // Test downscales to zero in one or both dimensions:
688 // Scaling should stop when one or both dimensions reach 1.
689 // Parameters: input-x input-y, desired-x, desired-y, expected-x, expected-y
690 TestDownscaleOutputsExpectedDimensionsRGBA8888(image, 512, 512, 0, 0, 1, 1, TEST_LOCATION);
691 TestDownscaleOutputsExpectedDimensionsRGBA8888(image, 512, 256, 0, 0, 2, 1, TEST_LOCATION);
692 TestDownscaleOutputsExpectedDimensionsRGBA8888(image, 512, 128, 0, 0, 4, 1, TEST_LOCATION);
693 TestDownscaleOutputsExpectedDimensionsRGBA8888(image, 512, 16, 0, 0, 32, 1, TEST_LOCATION);
694 TestDownscaleOutputsExpectedDimensionsRGBA8888(image, 128, 512, 0, 0, 1, 4, TEST_LOCATION);
695 TestDownscaleOutputsExpectedDimensionsRGBA8888(image, 32, 512, 0, 0, 1, 16, TEST_LOCATION);
696 TestDownscaleOutputsExpectedDimensionsRGBA8888(image, 8, 512, 0, 0, 1, 64, TEST_LOCATION);
697 TestDownscaleOutputsExpectedDimensionsRGBA8888(image, 2, 512, 0, 0, 1, 256, TEST_LOCATION);
703 * @brief Test downscalings of RGBA8888 images in raw image arrays that should have no effect on the input.
705 int UtcDaliImageOperationsDownscaleInPlacePow2RGBA8888Nops(void)
707 uint32_t image[608 * 608];
708 const uint32_t numPixels = sizeof(image) / sizeof(image[0]);
709 for(unsigned i = 0; i < numPixels; ++i)
711 image[i] = RandomPixelRGBA8888();
713 const uint32_t imageHash = HashPixels(image, numPixels);
714 unsigned char* const pixels = reinterpret_cast<unsigned char*>(image);
715 unsigned int resultingWidth = -1, resultingHeight = -1, resultingStride = -1;
717 // Test downscales to the same size:
718 // The point is just to be sure the downscale is a NOP in this case:
720 DownscaleInPlacePow2RGBA8888(pixels, 600, 600, 600, 600, 600, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
721 DALI_TEST_EQUALS(resultingWidth, 600u, TEST_LOCATION);
722 DALI_TEST_EQUALS(resultingHeight, 600u, TEST_LOCATION);
723 DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
725 DownscaleInPlacePow2RGBA8888(pixels, 512, 128, 512, 512, 128, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
726 DALI_TEST_EQUALS(resultingWidth, 512u, TEST_LOCATION);
727 DALI_TEST_EQUALS(resultingHeight, 128u, TEST_LOCATION);
728 DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
730 DownscaleInPlacePow2RGBA8888(pixels, 17, 1001, 17, 17, 1001, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
731 DALI_TEST_EQUALS(resultingWidth, 17u, TEST_LOCATION);
732 DALI_TEST_EQUALS(resultingHeight, 1001u, TEST_LOCATION);
733 DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
735 // Test downscales that request a larger size (we never upscale so these are NOPs too):
736 // Parameters: input-x input-y, desired-x, desired-y, expected-x, expected-y
737 TestDownscaleOutputsExpectedDimensionsRGBA8888(image, 300, 300, 600, 600, 300, 300, TEST_LOCATION);
738 TestDownscaleOutputsExpectedDimensionsRGBA8888(image, 3, 127, 99, 599, 3, 127, TEST_LOCATION);
739 TestDownscaleOutputsExpectedDimensionsRGBA8888(image, 600, 600, 999, 999, 600, 600, TEST_LOCATION); //< checks no out of bounds mem access in this case
741 // Make sure that none of these NOP downscalings has affected the pixels of the image:
742 DALI_TEST_EQUALS(HashPixels(image, numPixels), imageHash, TEST_LOCATION);
748 * @brief Do additional downscaling testing using RGB565 images in raw image
749 * arrays to shake out differences relating to the pixel format.
751 int UtcDaliImageOperationsDownscaleInPlacePow2RGB565(void)
753 // Test that calling with null and zero parameters doesn't blow up:
754 unsigned int outWidth, outHeight, outStride;
755 DownscaleInPlacePow2RGB565(0, 0, 0, 0, 0, 0, BoxDimensionTestBoth, outWidth, outHeight, outStride);
757 uint16_t image[608 * 608];
758 for(unsigned i = 0; i < sizeof(image) / sizeof(image[0]); ++i)
763 // Do a straightforward test using an exact divisor target size:
764 TestDownscaleOutputsExpectedDimensionsRGB565(image, 600, 600, 75, 75, 75, 75, TEST_LOCATION);
765 // Test that a slightly smaller than possible to achieve target results in the
766 // next-higher exact divisor output image dimensions:
767 TestDownscaleOutputsExpectedDimensionsRGB565(image, 600, 600, 71, 69, 75, 75, TEST_LOCATION);
768 // Test that resizing from a starting size that is slightly larger than an exact
769 // multiple of the desired dimensions still results in the desired ones being
771 // Parameters: input-x input-y, desired-x, desired-y, expected-x, expected-y
772 TestDownscaleOutputsExpectedDimensionsRGB565(image, 600 + 1, 600 + 1, 75, 75, 75, 75, TEST_LOCATION);
773 TestDownscaleOutputsExpectedDimensionsRGB565(image, 256 + 1, 512 + 1, 2, 4, 2, 4, TEST_LOCATION);
774 TestDownscaleOutputsExpectedDimensionsRGB565(image, 512 + 1, 128 + 1, 16, 4, 16, 4, TEST_LOCATION);
775 TestDownscaleOutputsExpectedDimensionsRGB565(image, 512 + 1, 64 + 1, 16, 2, 16, 2, TEST_LOCATION);
776 TestDownscaleOutputsExpectedDimensionsRGB565(image, 512 + 3, 512 + 3, 16, 16, 16, 16, TEST_LOCATION);
777 TestDownscaleOutputsExpectedDimensionsRGB565(image, 512 + 3, 256 + 3, 16, 8, 16, 8, TEST_LOCATION);
778 TestDownscaleOutputsExpectedDimensionsRGB565(image, 256 + 3, 512 + 3, 4, 8, 4, 8, TEST_LOCATION);
779 TestDownscaleOutputsExpectedDimensionsRGB565(image, 256 + 7, 512 + 7, 4, 8, 4, 8, TEST_LOCATION);
780 TestDownscaleOutputsExpectedDimensionsRGB565(image, 256 + 7, 512 + 7, 2, 4, 2, 4, TEST_LOCATION);
781 TestDownscaleOutputsExpectedDimensionsRGB565(image, 512 + 7, 128 + 7, 16, 4, 16, 4, TEST_LOCATION);
782 TestDownscaleOutputsExpectedDimensionsRGB565(image, 512 + 7, 64 + 7, 16, 2, 16, 2, TEST_LOCATION);
788 * @brief Do additional downscaling testing using 2-byte-per-pixel images in
789 * raw image arrays to shake out differences relating to the pixel format.
791 int UtcDaliImageOperationsDownscaleInPlacePow2ComponentPair(void)
793 // Simple test that a null pointer does not get dereferenced in the function:
794 unsigned int outWidth, outHeight, outStride;
795 DownscaleInPlacePow2ComponentPair(0, 0, 0, 0, 0, 0, BoxDimensionTestBoth, outWidth, outHeight, outStride);
797 // Simple tests of dimensions output:
799 uint8_t image[608 * 608 * 2];
800 for(unsigned i = 0; i < sizeof(image) / sizeof(image[0]); ++i)
805 TestDownscaleOutputsExpectedDimensions2ComponentPair(image,
807 600, //< Input dimensions
809 37, //< Requested dimensions
811 37, //< Expected output dimensions
813 TestDownscaleOutputsExpectedDimensions2ComponentPair(image,
815 600, //< Input dimensions
817 35, //< Requested dimensions to scale-down to
819 37, //< Expected output dimensions achieved
821 ///@note: No need to be as comprehensive as with RGB888 and RGBA8888 as the logic is shared.
827 * @brief Do additional downscaling testing using 1-byte-per-pixel images in
828 * raw image arrays to shake out differences relating to the pixel format.
830 int UtcDaliImageOperationsDownscaleInPlacePow2SingleBytePerPixel(void)
832 // Simple test that a null pointer does not get dereferenced in the function:
833 unsigned int outWidth, outHeight, outStride;
834 DownscaleInPlacePow2SingleBytePerPixel(0, 0, 0, 0, 0, 0, BoxDimensionTestBoth, outWidth, outHeight, outStride);
836 // Tests of output dimensions from downscaling:
837 uint8_t image[608 * 608];
838 for(unsigned i = 0; i < sizeof(image) / sizeof(image[0]); ++i)
843 TestDownscaleOutputsExpectedDimensionsSingleComponent(image,
845 300, //< Input dimensions
847 75, //< Requested dimensions to scale-down to
849 75, //< Expected output dimensions achieved
851 TestDownscaleOutputsExpectedDimensionsSingleComponent(image, 577, 411, 142, 99, 144, 102, TEST_LOCATION);
857 * @brief Test the function for averaging pairs of pixels on a scanline.
859 int UtcDaliImageOperationsHalveScanlineInPlaceRGB888(void)
861 // Red and cyan, averaging to grey:
862 unsigned char shortEven[] = {0xff, 0, 0, 0, 0xff, 0xff, 0xff, 0, 0, 0, 0xff, 0xff};
863 unsigned char shortOdd[] = {0xff, 0, 0, 0, 0xff, 0xff, 0xff, 0, 0, 0, 0xff, 0xff, 0xC, 0xC, 0xC};
865 Dali::Internal::Platform::HalveScanlineInPlaceRGB888(shortEven, 4u);
866 Dali::Internal::Platform::HalveScanlineInPlaceRGB888(shortOdd, 4u);
868 for(unsigned i = 0; i < (sizeof(shortEven) >> 1u); ++i)
870 DALI_TEST_EQUALS(unsigned(shortEven[i]), 0x7fu, TEST_LOCATION);
871 DALI_TEST_EQUALS(unsigned(shortOdd[i]), 0x7fu, TEST_LOCATION);
878 * @brief Test the function for averaging pairs of pixels on a scanline.
880 int UtcDaliImageOperationsHalveScanlineInPlaceRGBA8888(void)
882 const size_t scanlineLength = 4096u;
883 Dali::Vector<uint32_t> scanline;
884 Dali::Vector<uint32_t> reference;
885 SetupScanlineForHalvingTestsRGBA8888(scanlineLength, scanline, reference);
887 HalveScanlineInPlaceRGBA8888((uint8_t*)&scanline[0], scanlineLength);
889 // Check that the halving matches the independently calculated reference:
890 size_t numMatches = 0;
891 for(int i = 0, length = scanlineLength / 2; i < length; ++i)
893 DALI_TEST_EQUALS(scanline[i], reference[i], TEST_LOCATION);
894 numMatches += scanline[i] == reference[i];
896 DALI_TEST_EQUALS(numMatches, scanlineLength / 2, TEST_LOCATION);
898 // Test for no beyond-bounds writes:
899 for(size_t i = scanlineLength / 2; i < reference.Count(); ++i)
901 DALI_TEST_EQUALS(reference[i], (uint32_t)0xEEEEEEEE, TEST_LOCATION);
908 * @brief Test the function for averaging pairs of pixels on a scanline.
910 int UtcDaliImageOperationsHalveScanlineInPlaceRGB565(void)
912 const size_t scanlineLength = 4096u;
913 Dali::Vector<uint16_t> scanline;
914 Dali::Vector<uint16_t> reference;
915 SetupScanlineForHalvingTestsRGB565(scanlineLength, scanline, reference);
917 HalveScanlineInPlaceRGB565((unsigned char*)(&scanline[0]), scanlineLength);
919 // Check output against reference:
920 size_t numMatches = 0;
921 for(int i = 0, length = scanlineLength / 2; i < length; ++i)
923 DALI_TEST_EQUALS(scanline[i], reference[i], TEST_LOCATION);
924 numMatches += scanline[i] == reference[i];
926 DALI_TEST_EQUALS(numMatches, scanlineLength / 2, TEST_LOCATION);
928 // Test for no beyond-bounds writes:
929 for(size_t i = scanlineLength / 2; i < reference.Count(); ++i)
931 DALI_TEST_EQUALS(reference[i], (uint16_t)0xEEEE, TEST_LOCATION);
938 * @brief Test the function for averaging pairs of pixels on a scanline.
940 int UtcDaliImageOperationsHalveScanlineInPlace2Bytes(void)
942 const size_t scanlineLength = 4096u;
943 Dali::Vector<uint8_t> scanline;
944 Dali::Vector<uint8_t> reference;
945 SetupScanlineForHalvingTests2Bytes(scanlineLength, scanline, reference);
947 HalveScanlineInPlace2Bytes(&scanline[0], scanlineLength);
949 // Test the output against the reference (no differences):
950 size_t numMatches = 0;
951 for(int i = 0, length = scanlineLength; i < length; ++i)
953 DALI_TEST_EQUALS(1u * scanline[i], 1u * reference[i], TEST_LOCATION);
954 numMatches += scanline[i] == reference[i];
956 // The number of matching bytes should be double the number of pixels, which happens to be the original scanline length in pixels:
957 DALI_TEST_EQUALS(numMatches, scanlineLength, TEST_LOCATION);
963 * @brief Test the function for averaging pairs of pixels on a scanline.
965 int UtcDaliImageOperationsHalveScanlineInPlace1Byte(void)
967 const size_t scanlineLength = 4096u;
968 Dali::Vector<uint8_t> scanline;
969 Dali::Vector<uint8_t> reference;
970 SetupScanlineForHalvingTests1Byte(scanlineLength, scanline, reference);
972 HalveScanlineInPlace1Byte(&scanline[0], scanlineLength);
974 // Test the reference matches the output:
975 size_t numMatches = 0;
976 for(int i = 0, length = scanlineLength / 2; i < length; ++i)
978 DALI_TEST_EQUALS(1u * scanline[i], 1u * reference[i], TEST_LOCATION);
979 numMatches += scanline[i] == reference[i];
981 // Only half will be matched
982 DALI_TEST_EQUALS(numMatches, scanlineLength / 2, TEST_LOCATION);
988 * @brief Test the function for averaging vertically-adjacent pairs of single-byte-per-pixel pixels on a scanline.
990 int UtcDaliImageOperationsAverageScanlines1ExceptTest(void)
992 // Edge cases for averagescanlines1:
993 unsigned char shortEven1[] = {0x00, 0x00, 0xff, 0xff, 0xff, 0xfe, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x02, 0x03, 0x00, 0x01};
994 unsigned char shortEven2[] = {0x00, 0xff, 0x00, 0xff, 0x01, 0x01, 0xff, 0xfe, 0x00, 0x01, 0x01, 0x02, 0x00, 0x00, 0x03, 0x02};
995 unsigned char expectBuffer[] = {0x00, 0x7f, 0x7f, 0xff, 0x80, 0x7f, 0x80, 0x7f, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
996 unsigned char outputBuffer[sizeof(shortEven1)];
998 AverageScanlines1(shortEven1, shortEven2, outputBuffer, sizeof(shortEven1));
999 for(unsigned i = 0; i < sizeof(shortEven1); ++i)
1001 DALI_TEST_EQUALS(unsigned(outputBuffer[i]), unsigned(expectBuffer[i]), TEST_LOCATION);
1008 * @brief Test the function for averaging vertically-adjacent pairs of single-byte-per-pixel pixels on a scanline.
1010 int UtcDaliImageOperationsAverageScanlines1(void)
1012 // Red and cyan, averaging to grey:
1013 unsigned char shortEven1[] = {0xff, 0, 0, 0, 0xff, 0xff, 0xff, 0, 0, 0, 0xff, 0xff};
1014 unsigned char shortEven2[] = {0, 0xff, 0xff, 0xff, 0, 0, 0, 0xff, 0xff, 0xff, 0, 0};
1015 unsigned char outputBuffer[sizeof(shortEven1)];
1017 AverageScanlines1(shortEven1, shortEven2, outputBuffer, sizeof(shortEven1));
1018 for(unsigned i = 0; i < sizeof(shortEven1); ++i)
1020 DALI_TEST_EQUALS(unsigned(outputBuffer[i]), 0x7fu, TEST_LOCATION);
1023 // Longer test reusing RGBA setup/test logic:
1025 const size_t scanlineLength = 4096u;
1026 Dali::Vector<uint32_t> scanline1;
1027 Dali::Vector<uint32_t> scanline2;
1028 Dali::Vector<uint32_t> reference;
1029 Dali::Vector<uint32_t> output;
1030 SetupScanlinesRGBA8888(scanlineLength, scanline1, scanline2, reference, output);
1032 AverageScanlines1((const unsigned char*)&scanline1[0], (const unsigned char*)&scanline2[0], (unsigned char*)&output[0], scanlineLength * 4);
1034 // Check the output matches the independently generated reference:
1035 size_t numMatches = 0;
1036 MatchScanlinesRGBA8888(reference, output, numMatches, TEST_LOCATION);
1037 DALI_TEST_EQUALS(numMatches, reference.Count(), TEST_LOCATION);
1040 // Longer test reusing RGBA setup/test logic with none-8-divisable length
1042 const size_t scanlineLength = 1003u;
1043 Dali::Vector<uint32_t> scanline1;
1044 Dali::Vector<uint32_t> scanline2;
1045 Dali::Vector<uint32_t> reference;
1046 Dali::Vector<uint32_t> output;
1047 SetupScanlinesRGBA8888(scanlineLength, scanline1, scanline2, reference, output);
1049 AverageScanlines1((const unsigned char*)&scanline1[0], (const unsigned char*)&scanline2[0], (unsigned char*)&output[0], scanlineLength * 4);
1051 // Check the output matches the independently generated reference:
1052 size_t numMatches = 0;
1053 MatchScanlinesRGBA8888(reference, output, numMatches, TEST_LOCATION);
1054 DALI_TEST_EQUALS(numMatches, reference.Count(), TEST_LOCATION);
1057 // Very short test reusing RGBA setup/test logic with less-than-8 length
1059 const size_t scanlineLength = 1003u;
1060 Dali::Vector<uint32_t> scanline1;
1061 Dali::Vector<uint32_t> scanline2;
1062 Dali::Vector<uint32_t> reference;
1063 Dali::Vector<uint32_t> output;
1064 SetupScanlinesRGBA8888(scanlineLength, scanline1, scanline2, reference, output);
1066 AverageScanlines1((const unsigned char*)&scanline1[0], (const unsigned char*)&scanline2[0], (unsigned char*)&output[0], scanlineLength * 4);
1068 // Check the output matches the independently generated reference:
1069 size_t numMatches = 0;
1070 MatchScanlinesRGBA8888(reference, output, numMatches, TEST_LOCATION);
1071 DALI_TEST_EQUALS(numMatches, reference.Count(), TEST_LOCATION);
1078 * @brief Test the function for averaging vertically-adjacent pairs of 2-byte-per-pixel pixels on a scanline.
1080 int UtcDaliImageOperationsAverageScanlines2(void)
1082 // Red and cyan, averaging to grey:
1083 unsigned char shortEven1[] = {0xff, 0, 0, 0, 0xff, 0xff, 0xff, 0, 0, 0, 0xff, 0xff};
1084 unsigned char shortEven2[] = {0, 0xff, 0xff, 0xff, 0, 0, 0, 0xff, 0xff, 0xff, 0, 0};
1085 unsigned char outputBuffer[sizeof(shortEven1)];
1087 AverageScanlines2(shortEven1, shortEven2, outputBuffer, sizeof(shortEven1) / 2);
1089 for(unsigned i = 0; i < sizeof(shortEven1); ++i)
1091 DALI_TEST_EQUALS(unsigned(outputBuffer[i]), 0x7fu, TEST_LOCATION);
1094 // Longer test reusing RGBA setup/test logic:
1096 const size_t scanlineLength = 4096u;
1097 Dali::Vector<uint32_t> scanline1;
1098 Dali::Vector<uint32_t> scanline2;
1099 Dali::Vector<uint32_t> reference;
1100 Dali::Vector<uint32_t> output;
1101 SetupScanlinesRGBA8888(scanlineLength, scanline1, scanline2, reference, output);
1103 AverageScanlines2((const unsigned char*)&scanline1[0], (const unsigned char*)&scanline2[0], (unsigned char*)&output[0], scanlineLength * 2);
1105 // Check the output matches the independently generated reference:
1106 size_t numMatches = 0;
1107 MatchScanlinesRGBA8888(reference, output, numMatches, TEST_LOCATION);
1108 DALI_TEST_EQUALS(numMatches, reference.Count(), TEST_LOCATION);
1111 // Longer test reusing RGBA setup/test logic with none-8-divisable length
1113 const size_t scanlineLength = 501u;
1114 Dali::Vector<uint32_t> scanline1;
1115 Dali::Vector<uint32_t> scanline2;
1116 Dali::Vector<uint32_t> reference;
1117 Dali::Vector<uint32_t> output;
1118 SetupScanlinesRGBA8888(scanlineLength, scanline1, scanline2, reference, output);
1120 AverageScanlines2((const unsigned char*)&scanline1[0], (const unsigned char*)&scanline2[0], (unsigned char*)&output[0], scanlineLength * 2);
1122 // Check the output matches the independently generated reference:
1123 size_t numMatches = 0;
1124 MatchScanlinesRGBA8888(reference, output, numMatches, TEST_LOCATION);
1125 DALI_TEST_EQUALS(numMatches, reference.Count(), TEST_LOCATION);
1128 // Very short test reusing RGBA setup/test logic with less-than-8 length
1130 const size_t scanlineLength = 3u;
1131 Dali::Vector<uint32_t> scanline1;
1132 Dali::Vector<uint32_t> scanline2;
1133 Dali::Vector<uint32_t> reference;
1134 Dali::Vector<uint32_t> output;
1135 SetupScanlinesRGBA8888(scanlineLength, scanline1, scanline2, reference, output);
1137 AverageScanlines2((const unsigned char*)&scanline1[0], (const unsigned char*)&scanline2[0], (unsigned char*)&output[0], scanlineLength * 2);
1139 // Check the output matches the independently generated reference:
1140 size_t numMatches = 0;
1141 MatchScanlinesRGBA8888(reference, output, numMatches, TEST_LOCATION);
1142 DALI_TEST_EQUALS(numMatches, reference.Count(), TEST_LOCATION);
1149 * @brief Test the function for averaging vertically-adjacent pairs of RGB888 pixels on a scanline.
1151 int UtcDaliImageOperationsAverageScanlines3(void)
1153 // Red and cyan, averaging to grey:
1154 unsigned char shortEven1[] = {0xff, 0, 0, 0, 0xff, 0xff, 0xff, 0, 0, 0, 0xff, 0xff};
1155 unsigned char shortEven2[] = {0, 0xff, 0xff, 0xff, 0, 0, 0, 0xff, 0xff, 0xff, 0, 0};
1156 unsigned char outputBuffer[sizeof(shortEven1)];
1158 AverageScanlines3(shortEven1, shortEven2, outputBuffer, sizeof(shortEven1) / 3);
1159 for(unsigned i = 0; i < sizeof(shortEven1); ++i)
1161 DALI_TEST_EQUALS(unsigned(outputBuffer[i]), 0x7fu, TEST_LOCATION);
1164 // Longer test reusing RGBA setup/test logic:
1166 const size_t scanlineLength = 3 * 4 * 90u;
1167 Dali::Vector<uint32_t> scanline1;
1168 Dali::Vector<uint32_t> scanline2;
1169 Dali::Vector<uint32_t> reference;
1170 Dali::Vector<uint32_t> output;
1171 SetupScanlinesRGBA8888(scanlineLength, scanline1, scanline2, reference, output);
1173 AverageScanlines3((const unsigned char*)&scanline1[0], (const unsigned char*)&scanline2[0], (unsigned char*)&output[0], scanlineLength * 4 / 3);
1175 // Check the output matches the independently generated reference:
1176 size_t numMatches = 0;
1177 MatchScanlinesRGBA8888(reference, output, numMatches, TEST_LOCATION);
1178 DALI_TEST_EQUALS(numMatches, reference.Count(), TEST_LOCATION);
1181 // Longer test reusing RGBA setup/test logic with none-8-divisable length
1183 const size_t scanlineLength = 3 * 501u;
1184 Dali::Vector<uint32_t> scanline1;
1185 Dali::Vector<uint32_t> scanline2;
1186 Dali::Vector<uint32_t> reference;
1187 Dali::Vector<uint32_t> output;
1188 SetupScanlinesRGBA8888(scanlineLength, scanline1, scanline2, reference, output);
1190 AverageScanlines3((const unsigned char*)&scanline1[0], (const unsigned char*)&scanline2[0], (unsigned char*)&output[0], scanlineLength * 4 / 3);
1192 // Check the output matches the independently generated reference:
1193 size_t numMatches = 0;
1194 MatchScanlinesRGBA8888(reference, output, numMatches, TEST_LOCATION);
1195 DALI_TEST_EQUALS(numMatches, reference.Count(), TEST_LOCATION);
1198 // Very short test reusing RGBA setup/test logic with less-than-8 length
1200 const size_t scanlineLength = 3u;
1201 Dali::Vector<uint32_t> scanline1;
1202 Dali::Vector<uint32_t> scanline2;
1203 Dali::Vector<uint32_t> reference;
1204 Dali::Vector<uint32_t> output;
1205 SetupScanlinesRGBA8888(scanlineLength, scanline1, scanline2, reference, output);
1207 AverageScanlines3((const unsigned char*)&scanline1[0], (const unsigned char*)&scanline2[0], (unsigned char*)&output[0], scanlineLength * 4 / 3);
1209 // Check the output matches the independently generated reference:
1210 size_t numMatches = 0;
1211 MatchScanlinesRGBA8888(reference, output, numMatches, TEST_LOCATION);
1212 DALI_TEST_EQUALS(numMatches, reference.Count(), TEST_LOCATION);
1219 * @brief Test the function for averaging vertically-adjacent pairs of RGBA8888 pixels on a scanline.
1221 int UtcDaliImageOperationsAverageScanlinesRGBA8888(void)
1223 const size_t scanlineLength = 4096u;
1224 Dali::Vector<uint32_t> scanline1;
1225 Dali::Vector<uint32_t> scanline2;
1226 Dali::Vector<uint32_t> reference;
1227 Dali::Vector<uint32_t> output;
1228 SetupScanlinesRGBA8888(scanlineLength, scanline1, scanline2, reference, output);
1230 AverageScanlinesRGBA8888((const unsigned char*)&scanline1[0], (const unsigned char*)&scanline2[0], (unsigned char*)&output[0], scanlineLength);
1232 // Check the output matches the independently generated reference:
1233 size_t numMatches = 0;
1234 MatchScanlinesRGBA8888(reference, output, numMatches, TEST_LOCATION);
1235 DALI_TEST_EQUALS(numMatches, reference.Count(), TEST_LOCATION);
1241 * @brief Test the function for averaging vertically-adjacent pairs of RGB565 pixels on a scanline.
1243 int UtcDaliImageOperationsAverageScanlinesRGB565(void)
1245 // Red and cyan, averaging to grey:
1246 const uint16_t shortEven1[] = {0xf800, 0xf800, 0xf800, 0xf800, 0xf800, 0xf800, 0xBEEF, 0xBEEF};
1247 const uint16_t shortEven2[] = {0x7ff, 0x7ff, 0x7ff, 0x7ff, 0x7ff, 0x7ff, 0xBEEF, 0xBEEF};
1248 const size_t arrayLength = sizeof(shortEven1) / sizeof(shortEven1[0]) - 2;
1249 uint16_t outputBuffer[arrayLength + 2];
1250 outputBuffer[arrayLength] = 0xDEAD;
1251 outputBuffer[arrayLength + 1] = 0xDEAD;
1253 Dali::Internal::Platform::AverageScanlinesRGB565((const unsigned char*)shortEven1, (const unsigned char*)shortEven2, (unsigned char*)outputBuffer, arrayLength);
1254 for(unsigned i = 0; i < arrayLength; ++i)
1256 DALI_TEST_EQUALS(unsigned(outputBuffer[i]), 0xffff - (1u << 15) - (1u << 10) - (1u << 4), TEST_LOCATION);
1259 // Check for buffer overrun:
1260 DALI_TEST_EQUALS(outputBuffer[arrayLength], (uint16_t)0xDEAD, TEST_LOCATION);
1261 DALI_TEST_EQUALS(outputBuffer[arrayLength + 1], (uint16_t)0xDEAD, TEST_LOCATION);
1268 void MakeSingleColorImageRGBA8888(unsigned int width, unsigned int height, uint32_t* inputImage)
1270 const uint32_t inPixel = PixelRGBA8888(255, 192, 128, 64);
1271 for(unsigned int i = 0; i < width * height; ++i)
1273 inputImage[i] = inPixel;
1278 * @brief Make an image with a checkerboard pattern.
1279 * @note This is an easy pattern to scan for correctness after a downscaling test.
1281 Dali::IntrusivePtr<Dali::RefCountedVector<uint32_t> > MakeCheckerboardImageRGBA8888(unsigned int width, unsigned int height, unsigned int checkerSize)
1283 const unsigned int imageWidth = width * checkerSize;
1284 const unsigned int imageHeight = height * checkerSize;
1285 Dali::IntrusivePtr<Dali::RefCountedVector<uint32_t> > image = new Dali::RefCountedVector<uint32_t>;
1286 image->GetVector().Resize(imageWidth * imageHeight);
1288 uint32_t rowColor = 0xffffffff;
1289 for(unsigned int cy = 0; cy < height; ++cy)
1291 rowColor = rowColor == 0xffffffff ? 0xff000000 : 0xffffffff;
1292 uint32_t checkColor = rowColor;
1293 for(unsigned int cx = 0; cx < width; ++cx)
1295 checkColor = checkColor == 0xffffffff ? 0xff000000 : 0xffffffff;
1296 uint32_t paintedColor = checkColor;
1297 // Draw 3 special case checks as r,g,b:
1298 if(cx == 0 && cy == 0)
1300 paintedColor = 0xff0000ff; // Red
1302 else if(cx == 7 && cy == 0)
1304 paintedColor = 0xff00ff00; // Green
1306 else if(cx == 7 && cy == 7)
1308 paintedColor = 0xffff0000; // blue
1310 uint32_t* check = &image->GetVector()[(cy * checkerSize * imageWidth) + (cx * checkerSize)];
1311 for(unsigned int py = 0; py < checkerSize; ++py)
1313 uint32_t* checkLine = check + py * imageWidth;
1314 for(unsigned int px = 0; px < checkerSize; ++px)
1316 checkLine[px] = paintedColor;
1328 * @brief Test the right pixels are generated when downsampling a checkerboard into a small image.
1330 int UtcDaliImageOperationsPointSampleCheckerboardRGBA888(void)
1332 Dali::IntrusivePtr<Dali::RefCountedVector<uint32_t> > image = MakeCheckerboardImageRGBA8888(8, 8, 32);
1333 const unsigned int desiredWidth = 8;
1334 const unsigned int desiredHeight = 8;
1336 uint32_t outputImage[desiredWidth * desiredHeight];
1338 Dali::Internal::Platform::PointSample4BPP((const unsigned char*)&image->GetVector()[0], 256, 256, 256, (unsigned char*)outputImage, desiredWidth, desiredHeight);
1340 DALI_TEST_EQUALS(outputImage[0], (uint32_t)0xff0000ff, TEST_LOCATION); // < Red corner pixel
1341 DALI_TEST_EQUALS(outputImage[7], (uint32_t)0xff00ff00, TEST_LOCATION); // < Green corner pixel
1342 DALI_TEST_EQUALS(outputImage[8 * 8 - 1], (uint32_t)0xffff0000, TEST_LOCATION); // < Blue corner pixel
1344 DALI_TEST_EQUALS(outputImage[1], (uint32_t)0xff000000, TEST_LOCATION); // < black pixel
1345 DALI_TEST_EQUALS(outputImage[2], (uint32_t)0xffffffff, TEST_LOCATION); // < white pixel
1346 DALI_TEST_EQUALS(outputImage[3], (uint32_t)0xff000000, TEST_LOCATION); // < black pixel
1347 DALI_TEST_EQUALS(outputImage[4], (uint32_t)0xffffffff, TEST_LOCATION); // < white pixel
1348 DALI_TEST_EQUALS(outputImage[5], (uint32_t)0xff000000, TEST_LOCATION); // < black pixel
1349 DALI_TEST_EQUALS(outputImage[6], (uint32_t)0xffffffff, TEST_LOCATION); // < white pixel
1352 DALI_TEST_EQUALS(outputImage[8 + 0], (uint32_t)0xff000000, TEST_LOCATION); // < black pixel
1353 DALI_TEST_EQUALS(outputImage[8 + 1], (uint32_t)0xffffffff, TEST_LOCATION); // < white pixel
1354 DALI_TEST_EQUALS(outputImage[8 + 2], (uint32_t)0xff000000, TEST_LOCATION); // < black pixel
1355 DALI_TEST_EQUALS(outputImage[8 + 3], (uint32_t)0xffffffff, TEST_LOCATION); // < white pixel
1356 DALI_TEST_EQUALS(outputImage[8 + 4], (uint32_t)0xff000000, TEST_LOCATION); // < black pixel
1357 DALI_TEST_EQUALS(outputImage[8 + 5], (uint32_t)0xffffffff, TEST_LOCATION); // < white pixel
1358 DALI_TEST_EQUALS(outputImage[8 + 6], (uint32_t)0xff000000, TEST_LOCATION); // < black pixel
1359 DALI_TEST_EQUALS(outputImage[8 + 7], (uint32_t)0xffffffff, TEST_LOCATION); // < white pixel
1362 DALI_TEST_EQUALS(outputImage[16 + 0], (uint32_t)0xffffffff, TEST_LOCATION); // < white pixel
1363 DALI_TEST_EQUALS(outputImage[16 + 1], (uint32_t)0xff000000, TEST_LOCATION); // < black pixel
1364 DALI_TEST_EQUALS(outputImage[16 + 2], (uint32_t)0xffffffff, TEST_LOCATION); // < white pixel
1365 DALI_TEST_EQUALS(outputImage[16 + 3], (uint32_t)0xff000000, TEST_LOCATION); // < black pixel
1366 DALI_TEST_EQUALS(outputImage[16 + 4], (uint32_t)0xffffffff, TEST_LOCATION); // < white pixel
1367 DALI_TEST_EQUALS(outputImage[16 + 5], (uint32_t)0xff000000, TEST_LOCATION); // < black pixel
1368 DALI_TEST_EQUALS(outputImage[16 + 6], (uint32_t)0xffffffff, TEST_LOCATION); // < white pixel
1369 DALI_TEST_EQUALS(outputImage[16 + 7], (uint32_t)0xff000000, TEST_LOCATION); // < black pixel
1371 // ... could do more scanlines (there are 8)
1373 // Sample a few more pixels:
1376 DALI_TEST_EQUALS(outputImage[24 + 3], (uint32_t)0xffffffff, TEST_LOCATION); // < white pixel
1377 DALI_TEST_EQUALS(outputImage[32 + 4], (uint32_t)0xffffffff, TEST_LOCATION); // < white pixel
1378 DALI_TEST_EQUALS(outputImage[40 + 5], (uint32_t)0xffffffff, TEST_LOCATION); // < white pixel
1379 DALI_TEST_EQUALS(outputImage[48 + 6], (uint32_t)0xffffffff, TEST_LOCATION); // < white pixel
1380 DALI_TEST_EQUALS(outputImage[24 + 4], (uint32_t)0xff000000, TEST_LOCATION); // < black pixel
1381 DALI_TEST_EQUALS(outputImage[32 + 3], (uint32_t)0xff000000, TEST_LOCATION); // < black pixel
1382 DALI_TEST_EQUALS(outputImage[40 + 2], (uint32_t)0xff000000, TEST_LOCATION); // < black pixel
1383 DALI_TEST_EQUALS(outputImage[48 + 1], (uint32_t)0xff000000, TEST_LOCATION); // < black pixel
1384 DALI_TEST_EQUALS(outputImage[56 + 0], (uint32_t)0xff000000, TEST_LOCATION); // < black pixel
1390 * @brief Test that a scaling preserves input color in destination image.
1392 int UtcDaliImageOperationsPointSampleRGBA888PixelsCorrectColor(void)
1394 const unsigned int inputWidth = 137;
1395 const unsigned int inputHeight = 571;
1396 const unsigned int desiredWidth = 59;
1397 const unsigned int desiredHeight = 257;
1399 uint32_t inputImage[inputWidth * inputHeight];
1400 MakeSingleColorImageRGBA8888(inputWidth, inputHeight, inputImage);
1402 const size_t outputBufferSize = desiredWidth * desiredHeight;
1403 std::vector<uint32_t> buffer;
1404 buffer.resize(outputBufferSize);
1405 uint32_t* outputImage = &buffer[0];
1407 Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, inputWidth, inputHeight, inputWidth, (unsigned char*)outputImage, desiredWidth, desiredHeight);
1409 // Check that all the output pixels are the right color:
1410 const uint32_t reference = inputImage[inputWidth * inputHeight / 2];
1411 unsigned int differentColorCount = 0;
1412 for(unsigned int i = 0; i < desiredWidth * desiredHeight; ++i)
1414 if(outputImage[i] != reference)
1416 ++differentColorCount;
1420 DALI_TEST_EQUALS(0U, differentColorCount, TEST_LOCATION);
1426 * @brief Test that scaling down to a 1x1 image works.
1428 int UtcDaliImageOperationsPointSampleRGBA888ScaleToSinglePixel(void)
1430 const unsigned int desiredWidth = 1;
1431 const unsigned int desiredHeight = 1;
1433 uint32_t inputImage[1024 * 1024];
1434 MakeSingleColorImageRGBA8888(1024, 1024, inputImage);
1435 uint32_t outputImage = 0;
1437 // Try several different starting image sizes:
1440 Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 1, 1, 1, (unsigned char*)&outputImage, desiredWidth, desiredHeight);
1441 DALI_TEST_EQUALS(outputImage, inputImage[0], TEST_LOCATION);
1444 // Single-pixel wide tall stripe:
1445 Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 1, 1024, 1, (unsigned char*)&outputImage, desiredWidth, desiredHeight);
1446 DALI_TEST_EQUALS(outputImage, inputImage[0], TEST_LOCATION);
1449 // Single-pixel tall, wide strip:
1450 Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 1024, 1, 1024, (unsigned char*)&outputImage, desiredWidth, desiredHeight);
1451 DALI_TEST_EQUALS(outputImage, inputImage[0], TEST_LOCATION);
1454 // Square mid-size image:
1455 Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 103, 103, 103, (unsigned char*)&outputImage, desiredWidth, desiredHeight);
1456 DALI_TEST_EQUALS(outputImage, inputImage[0], TEST_LOCATION);
1459 // Wide mid-size image:
1460 Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 313, 79, 313, (unsigned char*)&outputImage, desiredWidth, desiredHeight);
1461 DALI_TEST_EQUALS(outputImage, inputImage[0], TEST_LOCATION);
1464 // Tall mid-size image:
1465 Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 53, 467, 53, (unsigned char*)&outputImage, desiredWidth, desiredHeight);
1466 DALI_TEST_EQUALS(outputImage, inputImage[0], TEST_LOCATION);
1469 // 0 x 0 input image (make sure output not written to):
1470 outputImage = 0xDEADBEEF;
1471 Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 0, 0, 0, (unsigned char*)&outputImage, desiredWidth, desiredHeight);
1472 DALI_TEST_EQUALS(outputImage, (uint32_t)0xDEADBEEF, TEST_LOCATION);
1479 * @brief Test that downsampling to 0 - area images is a NOP and does not modify the destination.
1482 int UtcDaliImageOperationsPointSampleRGBA888N(void)
1484 uint32_t inputImage[128 * 128];
1485 MakeSingleColorImageRGBA8888(128, 128, inputImage);
1486 uint32_t outputImage[128 * 128];
1487 memset(outputImage, 0xaa, 128 * 128 * sizeof(uint32_t));
1489 // Try several different starting image sizes:
1492 Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 1, 1, 1, (unsigned char*)outputImage, 0, 0);
1493 DALI_TEST_EQUALS(0xaaaaaaaa, outputImage[0], TEST_LOCATION);
1495 // Single-pixel wide tall stripe:
1496 Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 1, 102, 1, (unsigned char*)outputImage, 0, 33);
1497 DALI_TEST_EQUALS(0xaaaaaaaa, outputImage[0], TEST_LOCATION);
1499 // Single-pixel tall, wide strip:
1500 Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 102, 1, 102, (unsigned char*)outputImage, 0, 67);
1501 DALI_TEST_EQUALS(0xaaaaaaaa, outputImage[0], TEST_LOCATION);
1503 // Square mid-size image:
1504 Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 103, 103, 103, (unsigned char*)outputImage, 21, 0);
1505 DALI_TEST_EQUALS(0xaaaaaaaa, outputImage[0], TEST_LOCATION);
1507 // Wide mid-size image to 0 height
1508 Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 313, 79, 313, (unsigned char*)outputImage, 99, 0);
1509 DALI_TEST_EQUALS(0xaaaaaaaa, outputImage[0], TEST_LOCATION);
1511 // Tall mid-size image to 0 height, over width
1512 Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 53, 46, 53, (unsigned char*)outputImage, 9999, 0);
1513 DALI_TEST_EQUALS(0xaaaaaaaa, outputImage[0], TEST_LOCATION);
1515 // 0 x 0 input image:
1516 Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 0, 0, 0, (unsigned char*)outputImage, 200, 99);
1517 DALI_TEST_EQUALS(0xaaaaaaaa, outputImage[0], TEST_LOCATION);
1523 * @brief Test the small int (x,y) tuple.
1525 int UtcDaliImageOperationsUint16Pair(void)
1527 Uint16Pair vec1(2, 3);
1529 DALI_TEST_EQUALS(vec1.GetWidth(), (uint16_t)2, TEST_LOCATION);
1530 DALI_TEST_EQUALS(vec1.GetX(), (uint16_t)2, TEST_LOCATION);
1532 DALI_TEST_EQUALS(vec1.GetHeight(), (uint16_t)3, TEST_LOCATION);
1533 DALI_TEST_EQUALS(vec1.GetY(), (uint16_t)3, TEST_LOCATION);
1535 Uint16Pair vec1Copy = vec1;
1537 DALI_TEST_EQUALS(vec1Copy.GetWidth(), (uint16_t)2, TEST_LOCATION);
1538 DALI_TEST_EQUALS(vec1Copy.GetX(), (uint16_t)2, TEST_LOCATION);
1540 DALI_TEST_EQUALS(vec1Copy.GetHeight(), (uint16_t)3, TEST_LOCATION);
1541 DALI_TEST_EQUALS(vec1Copy.GetY(), (uint16_t)3, TEST_LOCATION);
1543 Uint16Pair vec2(65535u, 65535u);
1545 DALI_TEST_EQUALS(vec2.GetX(), (uint16_t)65535u, TEST_LOCATION);
1546 DALI_TEST_EQUALS(vec2.GetY(), (uint16_t)65535u, TEST_LOCATION);
1552 * @brief Test the four-tap linear blending for single-byte modes.
1554 int UtcDaliImageOperationsBilinearFilter1BPP(void)
1556 // Zeros blend to zero:
1557 DALI_TEST_EQUALS(0u, BilinearFilter1Component(0, 0, 0, 0, 0, 0), TEST_LOCATION);
1558 DALI_TEST_EQUALS(0u, BilinearFilter1Component(0, 0, 0, 0, 32768, 0), TEST_LOCATION);
1559 DALI_TEST_EQUALS(0u, BilinearFilter1Component(0, 0, 0, 0, 65535, 0), TEST_LOCATION);
1560 DALI_TEST_EQUALS(0u, BilinearFilter1Component(0, 0, 0, 0, 0, 32768), TEST_LOCATION);
1561 DALI_TEST_EQUALS(0u, BilinearFilter1Component(0, 0, 0, 0, 0, 65535), TEST_LOCATION);
1563 // Ones and zeros average to 0.5:
1564 DALI_TEST_EQUALS(127u, BilinearFilter1Component(255, 0, 0, 255, 32768, 32768), TEST_LOCATION);
1565 DALI_TEST_EQUALS(127u, BilinearFilter1Component(0, 255, 0, 255, 32768, 32768), TEST_LOCATION);
1567 // Quarters ones average to 0.25:
1568 DALI_TEST_EQUALS(64u, BilinearFilter1Component(255, 0, 0, 0, 32768, 32768), TEST_LOCATION);
1569 DALI_TEST_EQUALS(64u, BilinearFilter1Component(0, 255, 0, 0, 32768, 32768), TEST_LOCATION);
1570 DALI_TEST_EQUALS(64u, BilinearFilter1Component(0, 0, 255, 0, 32768, 32768), TEST_LOCATION);
1571 DALI_TEST_EQUALS(64u, BilinearFilter1Component(0, 0, 0, 255, 32768, 32768), TEST_LOCATION);
1573 // Horizontal blends:
1574 DALI_TEST_EQUALS(0u, BilinearFilter1Component(0, 255, 0, 255, 0, 32768), TEST_LOCATION);
1575 for(unsigned y = 0; y < 65536u; y += 256)
1577 // Vertical blends don't change result in this case as there is no vertical gradient in inputs:
1578 DALI_TEST_EQUALS(0u, BilinearFilter1Component(0, 255, 0, 255, 0, y), TEST_LOCATION);
1580 DALI_TEST_EQUALS(5u, BilinearFilter1Component(0, 255, 0, 255, 1233, 32768), TEST_LOCATION);
1581 DALI_TEST_EQUALS(29u, BilinearFilter1Component(0, 255, 0, 255, 7539, 32768), TEST_LOCATION);
1582 DALI_TEST_EQUALS(29u, BilinearFilter1Component(0, 255, 0, 255, 7539, 32768), TEST_LOCATION);
1583 DALI_TEST_EQUALS(67u, BilinearFilter1Component(0, 255, 0, 255, 17291, 32768), TEST_LOCATION);
1584 DALI_TEST_EQUALS(123u, BilinearFilter1Component(0, 255, 0, 255, 31671, 32768), TEST_LOCATION);
1585 DALI_TEST_EQUALS(184u, BilinearFilter1Component(0, 255, 0, 255, 47231, 32768), TEST_LOCATION);
1586 DALI_TEST_EQUALS(207u, BilinearFilter1Component(0, 255, 0, 255, 53129, 32768), TEST_LOCATION);
1587 DALI_TEST_EQUALS(239u, BilinearFilter1Component(0, 255, 0, 255, 61392, 32768), TEST_LOCATION);
1588 DALI_TEST_EQUALS(255u, BilinearFilter1Component(0, 255, 0, 255, 65535, 32768), TEST_LOCATION);
1591 DALI_TEST_EQUALS(0u, BilinearFilter1Component(0, 0, 255, 255, 32768, 0), TEST_LOCATION);
1592 DALI_TEST_EQUALS(60u, BilinearFilter1Component(0, 0, 255, 255, 32768, 15379), TEST_LOCATION);
1593 DALI_TEST_EQUALS(130u, BilinearFilter1Component(0, 0, 255, 255, 32768, 33451), TEST_LOCATION);
1594 DALI_TEST_EQUALS(186u, BilinearFilter1Component(0, 0, 255, 255, 32768, 47836), TEST_LOCATION);
1595 DALI_TEST_EQUALS(244u, BilinearFilter1Component(0, 0, 255, 255, 32768, 62731), TEST_LOCATION);
1596 DALI_TEST_EQUALS(255u, BilinearFilter1Component(0, 0, 255, 255, 32768, 65535), TEST_LOCATION);