Merge remote-tracking branch 'origin/tizen' into new_text
[platform/core/uifw/dali-adaptor.git] / automated-tests / src / dali-adaptor-internal / utc-Dali-ImageOperations.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 #include <dali-test-suite-utils.h>
19
20 #include "platform-abstractions/portable/image-operations.h"
21
22 using namespace Dali::Internal::Platform;
23
24 namespace
25 {
26
27 /**
28  * @brief Generate a random integer between zero and the parameter passed in.
29  **/
30 uint32_t RandomInRange( uint32_t max )
31 {
32   const uint32_t randToMax = lrand48() % (max + 1);
33   return randToMax;
34 }
35
36 /**
37  * @brief Random number representable in an 8 bit color component.
38  */
39 inline uint32_t RandomComponent8()
40 {
41   return RandomInRange( 255u );
42 }
43
44 /**
45  * @brief Random number representable in a 5 bit color component.
46  */
47 inline uint32_t RandomComponent5()
48 {
49   return RandomInRange( 31u );
50 }
51
52 /**
53  * @brief Random number representable in a 6 bit color component.
54  */
55 inline uint32_t RandomComponent6()
56 {
57   return RandomInRange( 63u );
58 }
59
60 /**
61  * @brief RGBA8888 Pixels from separate color components.
62  */
63 inline uint32_t PixelRGBA8888( uint32_t r, uint32_t g, uint32_t b, uint32_t a )
64 {
65   return (r << 24) + (g << 16) + (b << 8) + a;
66 }
67
68 /**
69  * @brief RGB565 Pixels from color components in the low bits of passed-in words.
70  */
71 inline uint16_t PixelRGB565( uint32_t r, uint32_t g, uint32_t b )
72 {
73   return (r << 11) + (g << 5) + b;
74 }
75
76 /**
77  * @brief RGBA8888 Pixels with random color components.
78  */
79 inline uint32_t RandomPixelRGBA8888( )
80 {
81   const uint32_t randomPixel = PixelRGBA8888( RandomComponent8(), RandomComponent8(), RandomComponent8(), RandomComponent8() );
82   return randomPixel;
83 }
84
85 /**
86  * @brief Return a hash over a set of pixels.
87  *
88  * Used to check a buffer of pixels is unmodified by an operation given inputs
89  * that should mean that it is not changed.
90  */
91 inline uint32_t HashPixels( const uint32_t* const pixels, unsigned int numPixels )
92 {
93   uint32_t hash = 5381;
94
95   for( unsigned int i = 0; i < numPixels; ++i )
96   {
97     hash = hash * 33 + pixels[i];
98   }
99
100   return hash;
101 }
102
103 /**
104  * @brief Build some dummy scanlines to exercise scanline averaging code on.
105  */
106 void SetupScanlineForHalvingTestsRGBA8888( size_t scanlineLength, Dali::Vector<uint32_t>& scanline, Dali::Vector<uint32_t>& reference )
107 {
108   scanline.Resize( scanlineLength );
109   reference.Reserve( scanlineLength / 2 + 32 );
110
111   // Prepare some random pixels:
112   srand( 19 * 23 * 47 * 53 );
113   for( size_t i = 0; i < scanlineLength / 2; ++i )
114   {
115     // Generate random colors:
116     const uint32_t red1   = RandomComponent8();
117     const uint32_t red2   = RandomComponent8();
118     const uint32_t green1 = RandomComponent8();
119     const uint32_t green2 = RandomComponent8();
120     const uint32_t blue1  = RandomComponent8();
121     const uint32_t blue2  = RandomComponent8();
122     const uint32_t alpha1 = RandomComponent8();
123     const uint32_t alpha2 = RandomComponent8();
124
125     // The average of these pixels should equal the reference:
126     scanline[i * 2]     = PixelRGBA8888( red1, green1, blue1, alpha1 );
127     scanline[i * 2 + 1] = PixelRGBA8888( red2, green2, blue2, alpha2 );
128
129     // Average the two pixels manually as a reference:
130     reference.PushBack( PixelRGBA8888( (red1 + red2) >> 1u, (green1 + green2) >> 1u, (blue1 + blue2) >> 1u, (alpha1 + alpha2) >> 1u ) );
131   }
132
133   for( size_t i = scanlineLength / 2; i < reference.Capacity(); ++i )
134   {
135     reference[i] = 0xEEEEEEEE;
136   }
137 }
138
139 /**
140  * @brief Build some dummy scanlines to exercise scanline averaging code on.
141  */
142 void SetupScanlineForHalvingTestsRGB565( size_t scanlineLength, Dali::Vector<uint16_t>& scanline, Dali::Vector<uint16_t>& reference )
143 {
144   scanline.Resize( scanlineLength );
145   reference.Reserve( scanlineLength / 2 + 32 );
146
147   // Prepare some random pixels:
148   srand48( 19 * 23 * 47 * 53 );
149   for( size_t i = 0; i < scanlineLength / 2; ++i )
150   {
151     // Generate random colors:
152     const uint32_t red1   = RandomComponent5();
153     const uint32_t red2   = RandomComponent5();
154     const uint32_t green1 = RandomComponent6();
155     const uint32_t green2 = RandomComponent6();
156     const uint32_t blue1  = RandomComponent5();
157     const uint32_t blue2  = RandomComponent5();
158
159     // The average of these pixels should equal the reference:
160     scanline[i * 2]     = PixelRGB565( red1, green1, blue1 );
161     scanline[i * 2 + 1] = PixelRGB565( red2, green2, blue2 );
162
163     // Average the two pixels manually as a reference:
164     reference.PushBack( PixelRGB565( (red1 + red2) >> 1u, (green1 + green2) >> 1u, (blue1 + blue2) >> 1u ) );
165   }
166
167   for( size_t i = scanlineLength / 2; i < reference.Capacity(); ++i )
168   {
169     reference[i] = 0xEEEE;
170   }
171 }
172
173 /**
174  * @brief Build some dummy scanlines to exercise scanline averaging code on.
175  */
176 void SetupScanlineForHalvingTests2Bytes( size_t scanlineLength, Dali::Vector<uint8_t>& scanline, Dali::Vector<uint8_t>& reference )
177 {
178   scanline.Resize( scanlineLength * 2 );
179   reference.Reserve( scanlineLength + 32 );
180
181   // Prepare some random pixels:
182   srand48( 19 * 23 * 47 * 53 * 59 );
183   for( size_t i = 0; i < scanlineLength / 2; ++i )
184   {
185     // Generate random colors:
186     const uint32_t c11   = RandomComponent8();
187     const uint32_t c12   = RandomComponent8();
188     const uint32_t c21   = RandomComponent8();
189     const uint32_t c22   = RandomComponent8();
190
191     // The average of these pixels should equal the reference:
192     scanline[i * 4]     = c11;
193     scanline[i * 4 + 1] = c12;
194     scanline[i * 4 + 2] = c21;
195     scanline[i * 4 + 3] = c22;
196
197     // Average the two pixels manually as a reference:
198     reference.PushBack( (c11 + c21) >> 1u );
199     reference.PushBack( (c12 + c22) >> 1u );
200   }
201
202   for( size_t i = scanlineLength; i < reference.Capacity(); ++i )
203   {
204     reference[i] = 0xEE;
205   }
206 }
207
208 /**
209  * @brief Build some dummy 1 byte per pixel scanlines to exercise scanline averaging code on.
210  */
211 void SetupScanlineForHalvingTests1Byte( size_t scanlineLength, Dali::Vector<uint8_t>& scanline, Dali::Vector<uint8_t>& reference )
212 {
213   scanline.Resize( scanlineLength * 2 );
214   reference.Reserve( scanlineLength + 32 );
215
216   // Prepare some random pixels:
217   srand48( 19 * 23 * 47 * 53 * 63 );
218   for( size_t i = 0; i < scanlineLength / 2; ++i )
219   {
220     // Generate random colors:
221     const uint32_t c1 = RandomComponent8();
222     const uint32_t c2 = RandomComponent8();
223
224     // The average of these pixels should equal the reference:
225     scanline[i * 2]     = c1;
226     scanline[i * 2 + 1] = c2;
227
228     // Average the two pixels manually as a reference:
229     reference.PushBack( (c1 + c2) >> 1u );
230
231   }
232
233   for( size_t i = scanlineLength; i < reference.Capacity(); ++i )
234   {
235     reference[i] = 0xEE;
236   }
237 }
238
239 /**
240  * @brief Build some dummy scanlines to exercise vertical averaging code on.
241  *
242  * All tested formats bar RGB565 can share this setup.
243  */
244 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 )
245 {
246   scanline1.Reserve( scanlineLength );
247   scanline2.Reserve( scanlineLength );
248   reference.Reserve( scanlineLength + 32 );
249   output.Reserve( scanlineLength + 32 );
250
251   for( size_t i = scanlineLength; i < output.Capacity(); ++i )
252   {
253     output[i]    = 0xDEADBEEF;
254     reference[i] = 0xDEADBEEF;
255   }
256
257   // Prepare some random pixels:
258   srand48( 19 * 23 * 47 );
259   for( size_t i = 0; i < scanlineLength; ++i )
260   {
261     // Generate random colors:
262     const uint32_t red1   = RandomComponent8();
263     const uint32_t red2   = RandomComponent8();
264     const uint32_t green1 = RandomComponent8();
265     const uint32_t green2 = RandomComponent8();
266     const uint32_t blue1  = RandomComponent8();
267     const uint32_t blue2  = RandomComponent8();
268     const uint32_t alpha1 = RandomComponent8();
269     const uint32_t alpha2 = RandomComponent8();
270
271     // The average of these pixels should equal the reference:
272     scanline1.PushBack( PixelRGBA8888( red1, green1, blue1, alpha1 ) );
273     scanline2.PushBack( PixelRGBA8888( red2, green2, blue2, alpha2 ) );
274
275     // Average the two pixels manually as a reference:
276     reference.PushBack( PixelRGBA8888( (red1 + red2) >> 1u, (green1 + green2) >> 1u, (blue1 + blue2) >> 1u, (alpha1 + alpha2) >> 1u ) );
277   }
278 }
279
280 /**
281  * @brief Compares a scanline of interest to a reference, testing each pixel is the same.
282  */
283 void MatchScanlinesRGBA8888( Dali::Vector<uint32_t>& reference, Dali::Vector<uint32_t>& output, size_t& numMatches, const char * const location )
284 {
285   numMatches = 0;
286   for( size_t i = 0, length = reference.Capacity(); i < length; ++i )
287   {
288     DALI_TEST_EQUALS( output[i], reference[i], location );
289     numMatches += output[i] == reference[i];
290   }
291 }
292
293 } //< namespace unnamed
294
295 /**
296  * @brief Test component averaging code.
297  */
298 int UtcDaliImageOperationsAverageComponent(void)
299 {
300   DALI_TEST_EQUALS( Dali::Internal::Platform::AverageComponent( 0u, 0u ), 0u, TEST_LOCATION );
301   DALI_TEST_EQUALS( Dali::Internal::Platform::AverageComponent( 1u, 1u ), 1u, TEST_LOCATION );
302   DALI_TEST_EQUALS( Dali::Internal::Platform::AverageComponent( 0xffffffffu >> 1u, 0xffffffffu >> 1u ), 0xffffffffu >> 1u, TEST_LOCATION );
303   const unsigned int avg3 = Dali::Internal::Platform::AverageComponent( 0xfffffffeu, 1u );
304   DALI_TEST_EQUALS( avg3, 0x7fffffffu, TEST_LOCATION );
305   DALI_TEST_EQUALS( Dali::Internal::Platform::AverageComponent( 255u, 255u ), 255u, TEST_LOCATION );
306   DALI_TEST_EQUALS( Dali::Internal::Platform::AverageComponent( 512u, 0u ), 256u, TEST_LOCATION );
307   DALI_TEST_EQUALS( Dali::Internal::Platform::AverageComponent( 511u, 0u ), 255u, TEST_LOCATION );
308   DALI_TEST_EQUALS( Dali::Internal::Platform::AverageComponent( 510u, 0u ), 255u, TEST_LOCATION );
309   DALI_TEST_EQUALS( Dali::Internal::Platform::AverageComponent( 509u, 0u ), 254u, TEST_LOCATION );
310   DALI_TEST_EQUALS( Dali::Internal::Platform::AverageComponent( 0u, 509u ), 254u, TEST_LOCATION );
311   END_TEST;
312 }
313
314 /**
315  * @brief Test Pixel averaging code.
316  */
317 int UtcDaliImageOperationsAveragePixelRGBA8888(void)
318 {
319   DALI_TEST_EQUALS( Dali::Internal::Platform::AveragePixelRGBA8888( 0u, 0u ), 0u, TEST_LOCATION );
320   DALI_TEST_EQUALS( Dali::Internal::Platform::AveragePixelRGBA8888( 0x01010101, 0x01010101 ), 0x01010101u, TEST_LOCATION );
321   DALI_TEST_EQUALS( Dali::Internal::Platform::AveragePixelRGBA8888( 0x01010101, 0x03030303 ), 0x02020202u, TEST_LOCATION );
322   DALI_TEST_EQUALS( Dali::Internal::Platform::AveragePixelRGBA8888( 0xffffffff, 0xffffffff ), 0xffffffffu, TEST_LOCATION );
323   DALI_TEST_EQUALS( Dali::Internal::Platform::AveragePixelRGBA8888( 0xffffffff, 0u ), 0x7f7f7f7fu, TEST_LOCATION );
324   END_TEST;
325 }
326
327 /**
328  * @brief Test RGBA565 pixel averaging function.
329  */
330 int UtcDaliImageOperationsAveragePixelRGB565(void)
331 {
332   DALI_TEST_EQUALS( Dali::Internal::Platform::AveragePixelRGB565( 0u, 0u ), 0u, TEST_LOCATION );
333   DALI_TEST_EQUALS( Dali::Internal::Platform::AveragePixelRGB565( 0xf800u, 0xf800u ), 0xf800u, TEST_LOCATION );
334   DALI_TEST_EQUALS( Dali::Internal::Platform::AveragePixelRGB565( 0xf800u, 0x800u ), 1u << 15, TEST_LOCATION );
335   DALI_TEST_EQUALS( Dali::Internal::Platform::AveragePixelRGB565( 0x7e0u, 0x7e0u ), 0x7e0u, TEST_LOCATION );
336   DALI_TEST_EQUALS( Dali::Internal::Platform::AveragePixelRGB565( 0x7e0u, 0x20u ), 1u << 10, TEST_LOCATION );
337   DALI_TEST_EQUALS( Dali::Internal::Platform::AveragePixelRGB565( 0x1f, 0x1f ), 0x1fu, TEST_LOCATION );
338   DALI_TEST_EQUALS( Dali::Internal::Platform::AveragePixelRGB565( 0x1f, 0x1 ), 1u << 4, TEST_LOCATION );
339   DALI_TEST_EQUALS( Dali::Internal::Platform::AveragePixelRGB565( 0xf800u, 0x7e0u ), 0x7800u + 0x3e0u, TEST_LOCATION );
340   DALI_TEST_EQUALS( Dali::Internal::Platform::AveragePixelRGB565( 0xffff, 0xffff ), 0xffffu, TEST_LOCATION );
341   END_TEST;
342 }
343
344 /**
345  * @brief Build a square bitmap, downscale it and assert the resulting bitmap has the right dimensions.
346  */
347 void TestDownscaledBitmapHasRightDimensionsAndFormat( Pixel::Format format, uint32_t sourceDimension, uint32_t targetDimension, uint32_t expectedDimension, const char * const location )
348 {
349   ImageAttributes attributes;
350   attributes.SetScalingMode( ImageAttributes::ShrinkToFit );
351   attributes.SetSize( targetDimension, targetDimension );
352
353   Integration::BitmapPtr sourceBitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::DISCARD );
354   sourceBitmap->GetPackedPixelsProfile()->ReserveBuffer( format, sourceDimension, sourceDimension, sourceDimension, sourceDimension );
355
356   Integration::BitmapPtr downScaled = DownscaleBitmap( *sourceBitmap, attributes );
357   DALI_TEST_EQUALS( downScaled->GetImageWidth(), expectedDimension, location );
358   DALI_TEST_EQUALS( downScaled->GetImageHeight(), expectedDimension, location );
359   DALI_TEST_EQUALS( downScaled->GetPixelFormat(), format, location );
360 }
361
362 /**
363  * @brief Test the top-level function for reducing the dimension of a bitmap,
364  * feeding it each of the five pixel formats that are output by image loaders.
365  * Simply assert that the resulting bitmaps have the expected dimensions and
366  * formats.
367  */
368 int UtcDaliImageOperationsDownscaleBitmap(void)
369 {
370   // Do Scalings that are expected to work for all pixels modes and assert the resulting bitmap dimensions:
371
372   TestDownscaledBitmapHasRightDimensionsAndFormat( Pixel::RGBA8888, 1024, 8, 8, TEST_LOCATION );
373   TestDownscaledBitmapHasRightDimensionsAndFormat( Pixel::RGB888, 1024, 8, 8, TEST_LOCATION );
374   TestDownscaledBitmapHasRightDimensionsAndFormat( Pixel::RGB565, 1024, 8, 8, TEST_LOCATION );
375   TestDownscaledBitmapHasRightDimensionsAndFormat( Pixel::LA88, 1024, 8, 8, TEST_LOCATION );
376   TestDownscaledBitmapHasRightDimensionsAndFormat( Pixel::L8, 1024, 8, 8, TEST_LOCATION );
377
378   TestDownscaledBitmapHasRightDimensionsAndFormat( Pixel::RGBA8888, 773, 1, 1, TEST_LOCATION );
379   TestDownscaledBitmapHasRightDimensionsAndFormat( Pixel::RGB888, 787, 1, 1, TEST_LOCATION );
380   TestDownscaledBitmapHasRightDimensionsAndFormat( Pixel::RGB565, 797, 1, 1, TEST_LOCATION );
381   TestDownscaledBitmapHasRightDimensionsAndFormat( Pixel::LA88, 809, 1, 1, TEST_LOCATION );
382   TestDownscaledBitmapHasRightDimensionsAndFormat( Pixel::L8, 811, 1, 1, TEST_LOCATION );
383
384   // Do Scalings that are expected to produce a slightly larger than requested image:
385   TestDownscaledBitmapHasRightDimensionsAndFormat( Pixel::RGBA8888, 47, 7, 11, TEST_LOCATION );
386   TestDownscaledBitmapHasRightDimensionsAndFormat( Pixel::RGB888, 73, 17, 18, TEST_LOCATION );
387   TestDownscaledBitmapHasRightDimensionsAndFormat( Pixel::RGB565, 61, 8, 15, TEST_LOCATION );
388   TestDownscaledBitmapHasRightDimensionsAndFormat( Pixel::LA88, 19, 5, 9, TEST_LOCATION );
389   TestDownscaledBitmapHasRightDimensionsAndFormat( Pixel::L8, 353, 23, 44, TEST_LOCATION );
390
391   END_TEST;
392 }
393
394 /**
395  * @brief Test downscaling of RGB888 images as raw pixel arrays.
396  */
397 int UtcDaliImageOperationsDownscaleInPlacePow2RGB888(void)
398 {
399   unsigned outWidth = -1, outHeight = -1;
400
401   // Do downscaling to 1 x 1 so we can easily assert the value of the single pixel produced:
402
403   // Scale down a black/white checkerboard to mid-grey:
404   unsigned char check_4x4 [16 * 3] = {
405       0xff, 0xff, 0xff,  0x00, 0x00, 0x00,  0xff, 0xff, 0xff,  0x00, 0x00, 0x00,
406       0x00, 0x00, 0x00,  0xff, 0xff, 0xff,  0x00, 0x00, 0x00,  0xff, 0xff, 0xff,
407       0xff, 0xff, 0xff,  0x00, 0x00, 0x00,  0xff, 0xff, 0xff,  0x00, 0x00, 0x00,
408       0x00, 0x00, 0x00,  0xff, 0xff, 0xff,  0x00, 0x00, 0x00,  0xff, 0xff, 0xff
409   };
410
411   Dali::Internal::Platform::DownscaleInPlacePow2RGB888(check_4x4, 4, 4, 1, 1, BoxDimensionTestBoth, outWidth, outHeight );
412   DALI_TEST_EQUALS( outWidth, 1u, TEST_LOCATION );
413   DALI_TEST_EQUALS( outHeight, 1u, TEST_LOCATION );
414   DALI_TEST_EQUALS( check_4x4[0], 0x7f, TEST_LOCATION );
415
416   // Scale down a 16 pixel black image with a single white pixel to a 1/16th grey single pixel:
417   unsigned char single_4x4 [16 * 3] = {
418     0xff, 0xff, 0xff,  0x00, 0x00, 0x00,  0x00, 0x00, 0x00,  0x00, 0x00, 0x00,
419     0x00, 0x00, 0x00,  0x00, 0x00, 0x00,  0x00, 0x00, 0x00,  0x00, 0x00, 0x00,
420     0x00, 0x00, 0x00,  0x00, 0x00, 0x00,  0x00, 0x00, 0x00,  0x00, 0x00, 0x00,
421     0x00, 0x00, 0x00,  0x00, 0x00, 0x00,  0x00, 0x00, 0x00,  0x00, 0x00, 0x00
422   };
423   Dali::Internal::Platform::DownscaleInPlacePow2RGB888(single_4x4, 4, 4, 1, 1, BoxDimensionTestBoth, outWidth, outHeight );
424   DALI_TEST_EQUALS( outWidth, 1u, TEST_LOCATION );
425   DALI_TEST_EQUALS( outHeight, 1u, TEST_LOCATION );
426   DALI_TEST_EQUALS( single_4x4[0], 0xf, TEST_LOCATION );
427
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,
432       0x00, 0x00, 0x00,  0x00, 0x00, 0x00,  0x00, 0x00, 0x00,  0x00, 0x00, 0x00,
433       0x00, 0x00, 0x00,  0x00, 0x00, 0x00,  0x00, 0x00, 0x00,  0x00, 0x00, 0x00,
434       0x00, 0x00, 0x00,  0x00, 0x00, 0x00,  0x00, 0x00, 0x00,  0xff, 0xff, 0xff
435     };
436   Dali::Internal::Platform::DownscaleInPlacePow2RGB888(single_4x4_2, 4, 4, 1, 1, BoxDimensionTestBoth, outWidth, outHeight );
437   DALI_TEST_EQUALS( outWidth, 1u, TEST_LOCATION );
438   DALI_TEST_EQUALS( outHeight, 1u, TEST_LOCATION );
439   DALI_TEST_EQUALS( single_4x4_2[0], 0xf, TEST_LOCATION );
440
441   // Build a larger ~600 x ~600 uniform magenta image for tests which only test output dimensions:
442
443   unsigned char magenta_600_x_600[608*608 * 3];
444   for( unsigned int i = 0; i < sizeof(magenta_600_x_600); i += 3 )
445   {
446     magenta_600_x_600[i] = 0xff;
447     magenta_600_x_600[i + 1] = 0;
448     magenta_600_x_600[i + 2] = 0xff;
449   }
450
451   // Scaling to 0 x 0 should stop at 1 x 1:
452   Dali::Internal::Platform::DownscaleInPlacePow2RGB888( magenta_600_x_600, 352, 352, 0, 0, BoxDimensionTestBoth, outWidth, outHeight );
453   DALI_TEST_EQUALS( outWidth, 1u, TEST_LOCATION );
454   DALI_TEST_EQUALS( outHeight, 1u, TEST_LOCATION );
455
456   // Scaling to 1 x 1 should hit 1 x 1:
457   Dali::Internal::Platform::DownscaleInPlacePow2RGB888( magenta_600_x_600, 608, 608, 1, 1, BoxDimensionTestBoth, outWidth, outHeight );
458   DALI_TEST_EQUALS( outWidth, 1u, TEST_LOCATION );
459   DALI_TEST_EQUALS( outHeight, 1u, TEST_LOCATION );
460
461   // Scaling to original dimensions should NOP:
462   Dali::Internal::Platform::DownscaleInPlacePow2RGB888( magenta_600_x_600, 384, 384, 384, 384, BoxDimensionTestBoth, outWidth, outHeight );
463   DALI_TEST_EQUALS( outWidth, 384u, TEST_LOCATION );
464   DALI_TEST_EQUALS( outHeight, 384u, TEST_LOCATION );
465
466   // More dimension tests:
467
468   Dali::Internal::Platform::DownscaleInPlacePow2RGB888( magenta_600_x_600, 352, 352, 44, 11, BoxDimensionTestBoth, outWidth, outHeight );
469   DALI_TEST_EQUALS( outWidth, 44u, TEST_LOCATION );
470   DALI_TEST_EQUALS( outHeight, 44u, TEST_LOCATION );
471
472   Dali::Internal::Platform::DownscaleInPlacePow2RGB888( magenta_600_x_600, 384, 384, 3, 48, BoxDimensionTestBoth, outWidth, outHeight );
473   DALI_TEST_EQUALS( outWidth, 48u, TEST_LOCATION );
474   DALI_TEST_EQUALS( outHeight, 48u, TEST_LOCATION );
475
476   Dali::Internal::Platform::DownscaleInPlacePow2RGB888( magenta_600_x_600, 384, 384, 3, 3, BoxDimensionTestBoth, outWidth, outHeight );
477   DALI_TEST_CHECK( outWidth == 3u && outHeight == 3u );
478
479   Dali::Internal::Platform::DownscaleInPlacePow2RGB888( magenta_600_x_600, 320, 320, 5, 5, BoxDimensionTestBoth, outWidth, outHeight );
480   DALI_TEST_CHECK( outWidth == 5u && outHeight == 5u );
481
482   Dali::Internal::Platform::DownscaleInPlacePow2RGB888( magenta_600_x_600, 448, 448, 7, 7, BoxDimensionTestBoth, outWidth, outHeight );
483   DALI_TEST_CHECK( outWidth == 7u && outHeight == 7u );
484
485   Dali::Internal::Platform::DownscaleInPlacePow2RGB888( magenta_600_x_600, 352, 352, 11, 11, BoxDimensionTestBoth, outWidth, outHeight );
486   DALI_TEST_CHECK( outWidth == 11u && outHeight == 11u );
487
488   // Check that no pixel values were modified by the repeated averaging of identical pixels in tests above:
489   unsigned int numNonMagenta = 0u;
490   for( unsigned i = 0; i < sizeof(magenta_600_x_600); i += 3 )
491   {
492     numNonMagenta += magenta_600_x_600[i] == 0xff && magenta_600_x_600[i + 1] == 0x00 && magenta_600_x_600[i + 2] == 0xff ? 0 : 1;
493   }
494   DALI_TEST_EQUALS( numNonMagenta, 0u, TEST_LOCATION );
495
496   END_TEST;
497 }
498
499 /**
500  * @brief Test that resizing RGBA8888 images as raw pixel arrays produces a result of the correct dimensions.
501  */
502 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 )
503 {
504   unsigned int resultingWidth = -1, resultingHeight = -1;
505   Dali::Internal::Platform::DownscaleInPlacePow2RGBA8888(
506       reinterpret_cast<unsigned char *> (pixels),
507       inputWidth, inputHeight,
508       desiredWidth, desiredHeight, BoxDimensionTestBoth,
509       resultingWidth, resultingHeight );
510
511   DALI_TEST_EQUALS( resultingWidth, expectedWidth, location );
512   DALI_TEST_EQUALS( resultingHeight, expectedHeight, location );
513 }
514
515 /**
516  * @brief Test that resizing RGB565 images as raw pixel arrays produces a result of the correct dimensions.
517  */
518 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 )
519 {
520   unsigned int resultingWidth = -1, resultingHeight = -1;
521   Dali::Internal::Platform::DownscaleInPlacePow2RGB565(
522       reinterpret_cast<unsigned char *> (pixels),
523       inputWidth, inputHeight,
524       desiredWidth, desiredHeight, BoxDimensionTestBoth,
525       resultingWidth, resultingHeight );
526
527   DALI_TEST_EQUALS( resultingWidth, expectedWidth, location );
528   DALI_TEST_EQUALS( resultingHeight, expectedHeight, location );
529 }
530
531 /**
532  * @brief Test that resizing 2-byte-per-pixel images as raw pixel arrays produces a result of the correct dimensions.
533  */
534 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 )
535 {
536   unsigned int resultingWidth = -1, resultingHeight = -1;
537   Dali::Internal::Platform::DownscaleInPlacePow2ComponentPair(
538       pixels,
539       inputWidth, inputHeight,
540       desiredWidth, desiredHeight, BoxDimensionTestBoth,
541       resultingWidth, resultingHeight );
542
543   DALI_TEST_EQUALS( resultingWidth, expectedWidth, location );
544   DALI_TEST_EQUALS( resultingHeight, expectedHeight, location );
545 }
546
547 /**
548  * @brief Test that resizing single-byte-per-pixel images as raw pixel arrays produces a result of the correct dimensions.
549  */
550 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 )
551 {
552   unsigned int resultingWidth = -1, resultingHeight = -1;
553   Dali::Internal::Platform::DownscaleInPlacePow2SingleBytePerPixel(
554       pixels,
555       inputWidth, inputHeight,
556       desiredWidth, desiredHeight, BoxDimensionTestBoth,
557       resultingWidth, resultingHeight );
558
559   DALI_TEST_EQUALS( resultingWidth, expectedWidth, location );
560   DALI_TEST_EQUALS( resultingHeight, expectedHeight, location );
561 }
562
563 /**
564  * @brief Test downscaling of RGBA8888 images in raw image arrays.
565  */
566 int UtcDaliImageOperationsDownscaleInPlacePow2RGBA8888(void)
567 {
568   uint32_t image[608*608];
569   for( unsigned i = 0; i < sizeof(image) / sizeof(image[0]); ++i )
570   {
571     image[i] = 0xffffffff;
572   }
573   unsigned char* const pixels = reinterpret_cast<unsigned char *> (image);
574   unsigned int resultingWidth = -1, resultingHeight = -1;
575
576   // Test downscaling where the input size is an exact multiple of the desired size:
577   // (We expect a perfect result here)
578
579   DownscaleInPlacePow2RGBA8888( pixels, 600, 600, 75, 75, BoxDimensionTestBoth, resultingWidth, resultingHeight );
580   DALI_TEST_EQUALS( resultingWidth, 75u, TEST_LOCATION );
581   DALI_TEST_EQUALS( resultingHeight, 75u, TEST_LOCATION );
582
583   DownscaleInPlacePow2RGBA8888( pixels, 512, 512, 16, 16, BoxDimensionTestBoth, resultingWidth, resultingHeight );
584   DALI_TEST_EQUALS( resultingWidth, 16u, TEST_LOCATION );
585   DALI_TEST_EQUALS( resultingHeight, 16u, TEST_LOCATION );
586
587   DownscaleInPlacePow2RGBA8888( pixels, 512, 64, 16, 2, BoxDimensionTestBoth, resultingWidth, resultingHeight );
588   DALI_TEST_EQUALS( resultingWidth, 16u, TEST_LOCATION  );
589   DALI_TEST_EQUALS( resultingHeight, 2u, TEST_LOCATION );
590
591   DownscaleInPlacePow2RGBA8888( pixels, 64, 1024, 4, 64, BoxDimensionTestBoth, resultingWidth, resultingHeight );
592   DALI_TEST_EQUALS( resultingWidth, 4u, TEST_LOCATION  );
593   DALI_TEST_EQUALS( resultingHeight, 64u, TEST_LOCATION );
594
595   // Test downscaling where the input size is slightly off being an exact multiple of the desired size:
596   // (We expect a perfect match at the end because of rounding-down to an even width and height at each step)
597
598   DownscaleInPlacePow2RGBA8888( pixels, 601, 603, 75, 75, BoxDimensionTestBoth, resultingWidth, resultingHeight );
599   DALI_TEST_EQUALS( resultingWidth, 75u, TEST_LOCATION  );
600   DALI_TEST_EQUALS( resultingHeight, 75u, TEST_LOCATION );
601
602   DownscaleInPlacePow2RGBA8888( pixels, 736 + 1, 352 + 3, 23, 11, BoxDimensionTestBoth, resultingWidth, resultingHeight );
603   DALI_TEST_EQUALS( resultingWidth, 23u, TEST_LOCATION  );
604   DALI_TEST_EQUALS( resultingHeight, 11u, TEST_LOCATION );
605
606   DownscaleInPlacePow2RGBA8888( pixels, 384 + 3, 896 + 1, 3, 7, BoxDimensionTestBoth, resultingWidth, resultingHeight );
607   DALI_TEST_EQUALS( resultingWidth, 3u, TEST_LOCATION  );
608   DALI_TEST_EQUALS( resultingHeight, 7u, TEST_LOCATION );
609
610   // Test downscales with source dimensions which are under a nice power of two by one:
611
612   // The target is hit exactly due to losing spare columns or rows at each iteration:
613   DownscaleInPlacePow2RGBA8888( pixels, 63, 31, 7, 3, BoxDimensionTestBoth, resultingWidth, resultingHeight );
614   DALI_TEST_EQUALS( resultingWidth, 7u, TEST_LOCATION  );
615   DALI_TEST_EQUALS( resultingHeight, 3u, TEST_LOCATION );
616
617   // 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.
618   DownscaleInPlacePow2RGBA8888( pixels, 63, 31, 4, 2, BoxDimensionTestBoth, resultingWidth, resultingHeight );
619   DALI_TEST_EQUALS( resultingWidth, 7u, TEST_LOCATION  );
620   DALI_TEST_EQUALS( resultingHeight, 3u, TEST_LOCATION );
621
622   // Should stop at almost twice the requested dimensions:
623   DownscaleInPlacePow2RGBA8888( pixels, 15, 127, 4, 32, BoxDimensionTestBoth, resultingWidth, resultingHeight );
624   DALI_TEST_EQUALS( resultingWidth, 7u, TEST_LOCATION  );
625   DALI_TEST_EQUALS( resultingHeight, 63u, TEST_LOCATION );
626
627   // Test downscales to 1 in one or both dimensions:
628   // Parameters:                                         input-x  input-y, desired-x, desired-y, expected-x, expected-y
629   TestDownscaleOutputsExpectedDimensionsRGBA8888( image, 512,     512,     1,         1,         1,          1,         TEST_LOCATION );
630   TestDownscaleOutputsExpectedDimensionsRGBA8888( image, 512,     32,      16,        1,         16,         1,         TEST_LOCATION );
631   TestDownscaleOutputsExpectedDimensionsRGBA8888( image, 512,     32,      7,         1,         16,         1,         TEST_LOCATION );
632   TestDownscaleOutputsExpectedDimensionsRGBA8888( image, 512,     32,      7,         1,         16,         1,         TEST_LOCATION );
633   TestDownscaleOutputsExpectedDimensionsRGBA8888( image, 512,     32,      5,         1,         16,         1,         TEST_LOCATION );
634   TestDownscaleOutputsExpectedDimensionsRGBA8888( image, 512,     32,      3,         1,         16,         1,         TEST_LOCATION );
635   TestDownscaleOutputsExpectedDimensionsRGBA8888( image, 32,      512,     1,         1,         1,          16,        TEST_LOCATION );
636   TestDownscaleOutputsExpectedDimensionsRGBA8888( image, 32,      512,     1,         16,        1,          16,        TEST_LOCATION );
637   TestDownscaleOutputsExpectedDimensionsRGBA8888( image, 32,      512,     1,         3,         1,          16,        TEST_LOCATION );
638   TestDownscaleOutputsExpectedDimensionsRGBA8888( image, 33,      33,      1,         1,         1,          1,         TEST_LOCATION );
639   TestDownscaleOutputsExpectedDimensionsRGBA8888( image, 17*19,   17*19,   1,         1,         1,          1,         TEST_LOCATION );
640   TestDownscaleOutputsExpectedDimensionsRGBA8888( image, 33,      33,      3,         1,         4,          4,         TEST_LOCATION );
641   TestDownscaleOutputsExpectedDimensionsRGBA8888( image, 33,      9,       3,         1,         4,          1,         TEST_LOCATION );
642
643
644
645   // Test downscales to zero in one or both dimensions:
646   // Scaling should stop when one or both dimensions reach 1.
647   // Parameters:                                         input-x  input-y, desired-x, desired-y, expected-x, expected-y
648   TestDownscaleOutputsExpectedDimensionsRGBA8888( image, 512,     512,     0,         0,         1,          1,         TEST_LOCATION );
649   TestDownscaleOutputsExpectedDimensionsRGBA8888( image, 512,     256,     0,         0,         2,          1,         TEST_LOCATION );
650   TestDownscaleOutputsExpectedDimensionsRGBA8888( image, 512,     128,     0,         0,         4,          1,         TEST_LOCATION );
651   TestDownscaleOutputsExpectedDimensionsRGBA8888( image, 512,     16,      0,         0,         32,         1,         TEST_LOCATION );
652   TestDownscaleOutputsExpectedDimensionsRGBA8888( image, 128,     512,     0,         0,         1,          4,         TEST_LOCATION );
653   TestDownscaleOutputsExpectedDimensionsRGBA8888( image, 32,      512,     0,         0,         1,          16,        TEST_LOCATION );
654   TestDownscaleOutputsExpectedDimensionsRGBA8888( image, 8,       512,     0,         0,         1,          64,        TEST_LOCATION );
655   TestDownscaleOutputsExpectedDimensionsRGBA8888( image, 2,       512,     0,         0,         1,          256,       TEST_LOCATION );
656
657   END_TEST;
658 }
659
660 /**
661  * @brief Test downscalings of RGBA8888 images in raw image arrays that should have no effect on the input.
662  */
663 int UtcDaliImageOperationsDownscaleInPlacePow2RGBA8888Nops(void)
664 {
665   uint32_t image[608*608];
666   const uint32_t numPixels = sizeof(image) / sizeof(image[0]);
667   for( unsigned i = 0; i < numPixels; ++i )
668   {
669     image[i] = RandomPixelRGBA8888();
670   }
671   const uint32_t imageHash = HashPixels( image, numPixels );
672   unsigned char* const pixels = reinterpret_cast<unsigned char *> (image);
673   unsigned int resultingWidth = -1, resultingHeight = -1;
674
675   // Test downscales to the same size:
676   // The point is just to be sure the downscale is a NOP in this case:
677
678   DownscaleInPlacePow2RGBA8888( pixels, 600, 600, 600, 600, BoxDimensionTestBoth, resultingWidth, resultingHeight );
679   DALI_TEST_EQUALS( resultingWidth, 600u, TEST_LOCATION );
680   DALI_TEST_EQUALS( resultingHeight, 600u, TEST_LOCATION );
681
682   DownscaleInPlacePow2RGBA8888( pixels, 512, 128, 512, 128, BoxDimensionTestBoth, resultingWidth, resultingHeight );
683   DALI_TEST_EQUALS( resultingWidth, 512u, TEST_LOCATION );
684   DALI_TEST_EQUALS( resultingHeight, 128u, TEST_LOCATION );
685
686   DownscaleInPlacePow2RGBA8888( pixels, 17, 1001, 17, 1001, BoxDimensionTestBoth, resultingWidth, resultingHeight );
687   DALI_TEST_EQUALS( resultingWidth, 17u, TEST_LOCATION );
688   DALI_TEST_EQUALS( resultingHeight, 1001u, TEST_LOCATION );
689
690   // Test downscales that request a larger size (we never upscale so these are NOPs too):
691   // Parameters:                                         input-x  input-y, desired-x, desired-y, expected-x, expected-y
692   TestDownscaleOutputsExpectedDimensionsRGBA8888( image, 300,     300,     600,       600,       300,        300,       TEST_LOCATION );
693   TestDownscaleOutputsExpectedDimensionsRGBA8888( image, 3,       127,     99,        599,       3,          127,       TEST_LOCATION );
694   TestDownscaleOutputsExpectedDimensionsRGBA8888( image, 600,     600,     999,       999,       600,        600,       TEST_LOCATION ); //< checks no out of bounds mem access in this case
695
696
697   // Make sure that none of these NOP downscalings has affected the pixels of the image:
698   DALI_TEST_EQUALS( HashPixels( image, numPixels ), imageHash, TEST_LOCATION );
699
700   END_TEST;
701 }
702
703 /**
704  * @brief Do additional downscaling testing using RGB565 images in raw image
705  * arrays to shake out differences relating to the pixel format.
706  */
707 int UtcDaliImageOperationsDownscaleInPlacePow2RGB565(void)
708 {
709   // Test that calling with null and zero parameters doesn't blow up:
710   unsigned int outWidth, outHeight;
711   DownscaleInPlacePow2RGB565( 0, 0, 0, 0, 0, BoxDimensionTestBoth, outWidth, outHeight );
712
713   uint16_t image[608*608];
714   for( unsigned i = 0; i < sizeof(image) / sizeof(image[0]); ++i )
715   {
716     image[i] = 0xffff;
717   }
718
719   // Do a straightforward test using an exact divisor target size:
720   TestDownscaleOutputsExpectedDimensionsRGB565( image, 600, 600, 75, 75, 75, 75, TEST_LOCATION );
721   // Test that a slightly smaller than possible to achieve target results in the
722   // next-higher exact divisor output image dimensions:
723   TestDownscaleOutputsExpectedDimensionsRGB565( image, 600, 600, 71, 69, 75, 75, TEST_LOCATION );
724   // Test that resizing from a starting size that is slightly larger than an exact
725   // multiple of the desired dimensions still results in the desired ones being
726   // reached:
727   // Parameters:                                       input-x  input-y, desired-x, desired-y, expected-x, expected-y
728   TestDownscaleOutputsExpectedDimensionsRGB565( image, 600 + 1, 600 + 1, 75,        75,        75,         75,        TEST_LOCATION );
729   TestDownscaleOutputsExpectedDimensionsRGB565( image, 256 + 1, 512 + 1, 2,         4,         2,          4,         TEST_LOCATION );
730   TestDownscaleOutputsExpectedDimensionsRGB565( image, 512 + 1, 128 + 1, 16,        4,         16,         4,         TEST_LOCATION );
731   TestDownscaleOutputsExpectedDimensionsRGB565( image, 512 + 1, 64  + 1, 16,        2,         16,         2,         TEST_LOCATION );
732   TestDownscaleOutputsExpectedDimensionsRGB565( image, 512 + 3, 512 + 3, 16,        16,        16,         16,        TEST_LOCATION );
733   TestDownscaleOutputsExpectedDimensionsRGB565( image, 512 + 3, 256 + 3, 16,        8,         16,         8,         TEST_LOCATION );
734   TestDownscaleOutputsExpectedDimensionsRGB565( image, 256 + 3, 512 + 3, 4,         8,         4,          8,         TEST_LOCATION );
735   TestDownscaleOutputsExpectedDimensionsRGB565( image, 256 + 7, 512 + 7, 4,         8,         4,          8,         TEST_LOCATION );
736   TestDownscaleOutputsExpectedDimensionsRGB565( image, 256 + 7, 512 + 7, 2,         4,         2,          4,         TEST_LOCATION );
737   TestDownscaleOutputsExpectedDimensionsRGB565( image, 512 + 7, 128 + 7, 16,        4,         16,         4,         TEST_LOCATION );
738   TestDownscaleOutputsExpectedDimensionsRGB565( image, 512 + 7, 64  + 7, 16,        2,         16,         2,         TEST_LOCATION );
739
740
741   END_TEST;
742 }
743
744 /**
745  * @brief Do additional downscaling testing using 2-byte-per-pixel images in
746  * raw image arrays to shake out differences relating to the pixel format.
747  */
748 int UtcDaliImageOperationsDownscaleInPlacePow2ComponentPair(void)
749 {
750   // Simple test that a null pointer does not get dereferenced in the function:
751   unsigned int outWidth, outHeight;
752   DownscaleInPlacePow2ComponentPair( 0, 0, 0, 0, 0, BoxDimensionTestBoth, outWidth, outHeight );
753
754   // Simple tests of dimensions output:
755
756   uint8_t image[608*608*2];
757   for( unsigned i = 0; i < sizeof(image) / sizeof(image[0]); ++i )
758   {
759     image[i] = 0xff;
760   }
761
762   TestDownscaleOutputsExpectedDimensions2ComponentPair( image,
763                                                         600, 600, //< Input dimensions
764                                                         37, 37,   //< Requested dimensions
765                                                         37, 37,   //< Expected output dimensions
766                                                         TEST_LOCATION );
767   TestDownscaleOutputsExpectedDimensions2ComponentPair( image,
768                                                         600, 600, //< Input dimensions
769                                                         34, 35,   //< Requested dimensions to scale-down to
770                                                         37, 37,   //< Expected output dimensions achieved
771                                                         TEST_LOCATION );
772   ///@note: No need to be as comprehensive as with RGB888 and RGBA8888 as the logic is shared.
773
774   END_TEST;
775 }
776
777 /**
778  * @brief Do additional downscaling testing using 1-byte-per-pixel images in
779  * raw image arrays to shake out differences relating to the pixel format.
780  */
781 int UtcDaliImageOperationsDownscaleInPlacePow2SingleBytePerPixel(void)
782 {
783   // Simple test that a null pointer does not get dereferenced in the function:
784   unsigned int outWidth, outHeight;
785   DownscaleInPlacePow2SingleBytePerPixel( 0, 0, 0, 0, 0, BoxDimensionTestBoth, outWidth, outHeight );
786
787   // Tests of output dimensions from downscaling:
788   uint8_t image[608*608];
789   for( unsigned i = 0; i < sizeof(image) / sizeof(image[0]); ++i )
790   {
791     image[i] = 0xff;
792   }
793
794   TestDownscaleOutputsExpectedDimensionsSingleComponent( image,
795                                                          600, 300,  //< Input dimensions
796                                                          150, 75,   //< Requested dimensions to scale-down to
797                                                          150, 75,   //< Expected output dimensions achieved
798                                                          TEST_LOCATION );
799   TestDownscaleOutputsExpectedDimensionsSingleComponent( image, 577, 411, 142, 99, 144, 102, TEST_LOCATION );
800
801   END_TEST;
802 }
803
804 /**
805  * @brief Test the function for averaging pairs of pixels on a scanline.
806  */
807 int UtcDaliImageOperationsHalveScanlineInPlaceRGB888(void)
808 {
809   // Red and cyan, averaging to grey:
810   unsigned char shortEven[] =    { 0xff, 0, 0,   0, 0xff, 0xff,   0xff, 0, 0,   0, 0xff, 0xff };
811   unsigned char shortOdd[] =     { 0xff, 0, 0,  0, 0xff, 0xff,  0xff, 0, 0,  0, 0xff, 0xff,  0xC, 0xC, 0xC };
812
813   Dali::Internal::Platform::HalveScanlineInPlaceRGB888( shortEven, 4u );
814   Dali::Internal::Platform::HalveScanlineInPlaceRGB888( shortOdd, 4u );
815   for( unsigned i = 0; i < sizeof(shortEven) >> 1u ; ++i )
816   {
817     DALI_TEST_EQUALS( unsigned(shortEven[i]), 0x7fu, TEST_LOCATION );
818     DALI_TEST_EQUALS( unsigned(shortOdd[i]), 0x7fu, TEST_LOCATION );
819   }
820
821   END_TEST;
822 }
823
824 /**
825  * @brief Test the function for averaging pairs of pixels on a scanline.
826  */
827 int UtcDaliImageOperationsHalveScanlineInPlaceRGBA8888(void)
828 {
829   const size_t scanlineLength = 4096u;
830   Dali::Vector<uint32_t> scanline;
831   Dali::Vector<uint32_t> reference;
832   SetupScanlineForHalvingTestsRGBA8888( scanlineLength, scanline, reference );
833
834   HalveScanlineInPlaceRGBA8888( (uint8_t *) &scanline[0], scanlineLength );
835
836   // Check that the halving matches the independently calculated reference:
837   size_t numMatches = 0;
838   for( int i = 0, length = reference.Size(); i < length; ++i )
839   {
840     DALI_TEST_EQUALS( scanline[i], reference[i], TEST_LOCATION );
841     numMatches += scanline[i] == reference[i];
842   }
843   DALI_TEST_EQUALS( numMatches, scanlineLength / 2, TEST_LOCATION );
844
845   // Test for no beyond-bounds writes:
846   for( size_t i = scanlineLength / 2; i < reference.Capacity(); ++i )
847   {
848     DALI_TEST_EQUALS( reference[i],  0xEEEEEEEE, TEST_LOCATION );
849   }
850
851   END_TEST;
852 }
853
854 /**
855  * @brief Test the function for averaging pairs of pixels on a scanline.
856  */
857 int UtcDaliImageOperationsHalveScanlineInPlaceRGB565(void)
858 {
859   const size_t scanlineLength = 4096u;
860   Dali::Vector<uint16_t> scanline;
861   Dali::Vector<uint16_t> reference;
862   SetupScanlineForHalvingTestsRGB565( scanlineLength, scanline, reference );
863
864   HalveScanlineInPlaceRGB565( (unsigned char *) (&scanline[0]), scanlineLength );
865
866   // Check output against reference:
867   size_t numMatches = 0;
868   for( int i = 0, length = reference.Size(); i < length; ++i )
869   {
870     DALI_TEST_EQUALS( scanline[i], reference[i], TEST_LOCATION );
871     numMatches += scanline[i] == reference[i];
872   }
873   DALI_TEST_EQUALS( numMatches, scanlineLength / 2, TEST_LOCATION );
874
875   // Test for no beyond-bounds writes:
876   for( size_t i = scanlineLength / 2; i < reference.Capacity(); ++i )
877   {
878     DALI_TEST_EQUALS( reference[i],  0xEEEE, TEST_LOCATION );
879   }
880
881   END_TEST;
882 }
883
884 /**
885  * @brief Test the function for averaging pairs of pixels on a scanline.
886  */
887 int UtcDaliImageOperationsHalveScanlineInPlace2Bytes(void)
888 {
889   const size_t scanlineLength = 4096u;
890   Dali::Vector<uint8_t> scanline;
891   Dali::Vector<uint8_t> reference;
892   SetupScanlineForHalvingTests2Bytes( scanlineLength, scanline, reference );
893
894   HalveScanlineInPlace2Bytes( &scanline[0], scanlineLength );
895
896   // Test the output against the reference (no differences):
897   size_t numMatches = 0;
898   for( int i = 0, length = reference.Size(); i < length; ++i )
899   {
900     DALI_TEST_EQUALS( 1u * scanline[i], 1u * reference[i], TEST_LOCATION );
901     numMatches += scanline[i] == reference[i];
902   }
903   // The number of matching bytes should be double the number of pixels, which happens to be the original scanline length in pixels:
904   DALI_TEST_EQUALS( numMatches, scanlineLength, TEST_LOCATION );
905
906   END_TEST;
907 }
908
909 /**
910  * @brief Test the function for averaging pairs of pixels on a scanline.
911  */
912 int UtcDaliImageOperationsHalveScanlineInPlace1Byte(void)
913 {
914   const size_t scanlineLength = 4096u;
915   Dali::Vector<uint8_t> scanline;
916   Dali::Vector<uint8_t> reference;
917   SetupScanlineForHalvingTests1Byte( scanlineLength, scanline, reference );
918
919   HalveScanlineInPlace1Byte( &scanline[0], scanlineLength );
920
921   // Test the reference matches the output:
922   size_t numMatches = 0;
923   for( int i = 0, length = reference.Size(); i < length; ++i )
924   {
925     DALI_TEST_EQUALS( 1u * scanline[i], 1u * reference[i], TEST_LOCATION );
926     numMatches += scanline[i] == reference[i];
927   }
928   DALI_TEST_EQUALS( numMatches, scanlineLength / 2, TEST_LOCATION );
929
930   END_TEST;
931 }
932
933 /**
934  * @brief Test the function for averaging vertically-adjacent pairs of single-byte-per-pixel pixels on a scanline.
935  */
936 int UtcDaliImageOperationsAverageScanlines1(void)
937 {
938   // Red and cyan, averaging to grey:
939   unsigned char shortEven1[] =    { 0xff, 0, 0,    0, 0xff, 0xff,  0xff, 0, 0,      0, 0xff, 0xff };
940   unsigned char shortEven2[] =    { 0, 0xff, 0xff, 0xff, 0, 0,     0, 0xff,  0xff,  0xff, 0, 0 };
941   unsigned char outputBuffer[sizeof(shortEven1)];
942
943   AverageScanlines1( shortEven1, shortEven2, outputBuffer, sizeof(shortEven1) );
944   for( unsigned i = 0; i < sizeof(shortEven1) ; ++i )
945   {
946     DALI_TEST_EQUALS( unsigned(outputBuffer[i]), 0x7fu, TEST_LOCATION );
947   }
948
949   // Longer test reusing RGBA setup/test logic:
950   const size_t scanlineLength = 4096u;
951   Dali::Vector<uint32_t> scanline1;
952   Dali::Vector<uint32_t> scanline2;
953   Dali::Vector<uint32_t> reference;
954   Dali::Vector<uint32_t> output;
955   SetupScanlinesRGBA8888( scanlineLength, scanline1, scanline2, reference, output );
956
957   AverageScanlines1( (const unsigned char*) &scanline1[0], (const unsigned char*) &scanline2[0], (unsigned char*) &output[0], scanlineLength * 4 );
958
959   // Check the output matches the independently generated reference:
960   size_t numMatches = 0;
961   MatchScanlinesRGBA8888( reference, output, numMatches, TEST_LOCATION );
962   DALI_TEST_EQUALS( numMatches, reference.Capacity(), TEST_LOCATION );
963
964   END_TEST;
965 }
966
967 /**
968  * @brief Test the function for averaging vertically-adjacent pairs of 2-byte-per-pixel pixels on a scanline.
969  */
970 int UtcDaliImageOperationsAverageScanlines2(void)
971 {
972   // Red and cyan, averaging to grey:
973   unsigned char shortEven1[] =    { 0xff, 0, 0,    0, 0xff, 0xff,  0xff, 0, 0,      0, 0xff, 0xff };
974   unsigned char shortEven2[] =    { 0, 0xff, 0xff, 0xff, 0, 0,     0, 0xff,  0xff,  0xff, 0, 0 };
975   unsigned char outputBuffer[sizeof(shortEven1)];
976
977   AverageScanlines2( shortEven1, shortEven2, outputBuffer, sizeof(shortEven1) / 2 );
978
979   for( unsigned i = 0; i < sizeof(shortEven1); ++i )
980   {
981     DALI_TEST_EQUALS( unsigned(outputBuffer[i]), 0x7fu, TEST_LOCATION );
982   }
983
984   // Longer test reusing RGBA setup/test logic:
985   const size_t scanlineLength = 4096u;
986   Dali::Vector<uint32_t> scanline1;
987   Dali::Vector<uint32_t> scanline2;
988   Dali::Vector<uint32_t> reference;
989   Dali::Vector<uint32_t> output;
990   SetupScanlinesRGBA8888( scanlineLength, scanline1, scanline2, reference, output );
991
992   AverageScanlines2( (const unsigned char*) &scanline1[0], (const unsigned char*) &scanline2[0], (unsigned char*) &output[0], scanlineLength * 2 );
993
994   // Check the output matches the independently generated reference:
995   size_t numMatches = 0;
996   MatchScanlinesRGBA8888( reference, output, numMatches, TEST_LOCATION );
997   DALI_TEST_EQUALS( numMatches, reference.Capacity(), TEST_LOCATION );
998
999   END_TEST;
1000 }
1001
1002 /**
1003  * @brief Test the function for averaging vertically-adjacent pairs of RGB888 pixels on a scanline.
1004  */
1005 int UtcDaliImageOperationsAverageScanlines3(void)
1006 {
1007   // Red and cyan, averaging to grey:
1008   unsigned char shortEven1[] =    { 0xff, 0, 0,    0, 0xff, 0xff,  0xff, 0, 0,      0, 0xff, 0xff };
1009   unsigned char shortEven2[] =    { 0, 0xff, 0xff, 0xff, 0, 0,     0, 0xff,  0xff,  0xff, 0, 0 };
1010   unsigned char outputBuffer[sizeof(shortEven1)];
1011
1012   AverageScanlines3( shortEven1, shortEven2, outputBuffer, sizeof(shortEven1) / 3 );
1013   for( unsigned i = 0; i < sizeof(shortEven1) ; ++i )
1014   {
1015     DALI_TEST_EQUALS( unsigned(outputBuffer[i]), 0x7fu, TEST_LOCATION );
1016   }
1017
1018   // Longer test reusing RGBA setup/test logic:
1019   const size_t scanlineLength = 3 * 4 * 90u;
1020   Dali::Vector<uint32_t> scanline1;
1021   Dali::Vector<uint32_t> scanline2;
1022   Dali::Vector<uint32_t> reference;
1023   Dali::Vector<uint32_t> output;
1024   SetupScanlinesRGBA8888( scanlineLength, scanline1, scanline2, reference, output );
1025
1026   AverageScanlines3( (const unsigned char*) &scanline1[0], (const unsigned char*) &scanline2[0], (unsigned char*) &output[0], scanlineLength * 4 / 3 );
1027
1028   // Check the output matches the independently generated reference:
1029   size_t numMatches = 0;
1030   MatchScanlinesRGBA8888( reference, output, numMatches, TEST_LOCATION );
1031   DALI_TEST_EQUALS( numMatches, reference.Capacity(), TEST_LOCATION );
1032
1033   END_TEST;
1034 }
1035
1036 /**
1037  * @brief Test the function for averaging vertically-adjacent pairs of RGBA8888 pixels on a scanline.
1038  */
1039 int UtcDaliImageOperationsAverageScanlinesRGBA8888(void)
1040 {
1041   const size_t scanlineLength = 4096u;
1042   Dali::Vector<uint32_t> scanline1;
1043   Dali::Vector<uint32_t> scanline2;
1044   Dali::Vector<uint32_t> reference;
1045   Dali::Vector<uint32_t> output;
1046   SetupScanlinesRGBA8888( scanlineLength, scanline1, scanline2, reference, output );
1047
1048   AverageScanlinesRGBA8888( (const unsigned char*) &scanline1[0], (const unsigned char*) &scanline2[0], (unsigned char*) &output[0], scanlineLength );
1049
1050   // Check the output matches the independently generated reference:
1051   size_t numMatches = 0;
1052   MatchScanlinesRGBA8888( reference, output, numMatches, TEST_LOCATION );
1053   DALI_TEST_EQUALS( numMatches, reference.Capacity(), TEST_LOCATION );
1054
1055   END_TEST;
1056 }
1057
1058 /**
1059  * @brief Test the function for averaging vertically-adjacent pairs of RGB565 pixels on a scanline.
1060  */
1061 int UtcDaliImageOperationsAverageScanlinesRGB565(void)
1062 {
1063   // Red and cyan, averaging to grey:
1064   const uint16_t shortEven1[] =    { 0xf800, 0xf800, 0xf800, 0xf800, 0xf800, 0xf800, 0xBEEF, 0xBEEF };
1065   const uint16_t shortEven2[] =    { 0x7ff,  0x7ff,  0x7ff,  0x7ff,  0x7ff,  0x7ff, 0xBEEF, 0xBEEF };
1066   const size_t arrayLength = sizeof(shortEven1) / sizeof(shortEven1[0]) - 2;
1067   uint16_t outputBuffer[arrayLength + 2];
1068   outputBuffer[arrayLength] = 0xDEAD;
1069   outputBuffer[arrayLength+1] = 0xDEAD;
1070
1071   Dali::Internal::Platform::AverageScanlinesRGB565( (const unsigned char*) shortEven1, (const unsigned char*) shortEven2, (unsigned char*) outputBuffer,  arrayLength );
1072   for( unsigned i = 0; i <  arrayLength ; ++i )
1073   {
1074     DALI_TEST_EQUALS( unsigned(outputBuffer[i]), 0xffff - (1u << 15) - (1u << 10) - (1u << 4), TEST_LOCATION );
1075   }
1076
1077   // Check for buffer overrun:
1078   DALI_TEST_EQUALS( outputBuffer[arrayLength], 0xDEAD, TEST_LOCATION );
1079   DALI_TEST_EQUALS( outputBuffer[arrayLength+1], 0xDEAD, TEST_LOCATION );
1080
1081   END_TEST;
1082 }