ImageProcessingTest.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. 
  2. #include "../testTools.h"
  3. AlignedImageU8 addImages_generate(ImageU8 imageA, ImageU8 imageB) {
  4. int width = image_getWidth(imageA);
  5. int height = image_getHeight(imageA);
  6. // Call your lambda for width times height pixels
  7. return filter_generateU8(width, height,
  8. [imageA, imageB](int x, int y) {
  9. int lumaA = image_readPixel_clamp(imageA, x, y);
  10. int lumaB = image_readPixel_clamp(imageB, x, y);
  11. return lumaA + lumaB;
  12. }
  13. );
  14. }
  15. void addImages_map(ImageU8 targetImage, ImageU8 imageA, ImageU8 imageB) {
  16. // Call your lambda for each pixel in targetImage
  17. filter_mapU8(targetImage,
  18. [imageA, imageB](int x, int y) {
  19. int lumaA = image_readPixel_clamp(imageA, x, y);
  20. int lumaB = image_readPixel_clamp(imageB, x, y);
  21. return lumaA + lumaB;
  22. }
  23. );
  24. }
  25. void addImages_loop(ImageU8 targetImage, ImageU8 imageA, ImageU8 imageB) {
  26. int width = image_getWidth(targetImage);
  27. int height = image_getHeight(targetImage);
  28. // Loop over all x, y coordinates yourself
  29. for (int y = 0; y < height; y++) {
  30. for (int x = 0; x < width; x++) {
  31. int lumaA = image_readPixel_clamp(imageA, x, y);
  32. int lumaB = image_readPixel_clamp(imageB, x, y);
  33. image_writePixel(targetImage, x, y, lumaA + lumaB);
  34. }
  35. }
  36. }
  37. void addImages_pointer(ImageU8 targetImage, ImageU8 imageA, ImageU8 imageB) {
  38. int width = image_getWidth(targetImage);
  39. int height = image_getHeight(targetImage);
  40. SafePointer<uint8_t> targetRow = image_getSafePointer(targetImage);
  41. SafePointer<uint8_t> rowA = image_getSafePointer(imageA);
  42. SafePointer<uint8_t> rowB = image_getSafePointer(imageB);
  43. int targetStride = image_getStride(targetImage);
  44. int strideA = image_getStride(imageA);
  45. int strideB = image_getStride(imageB);
  46. for (int y = 0; y < height; y++) {
  47. SafePointer<uint8_t> targetPixel = targetRow;
  48. SafePointer<uint8_t> pixelA = rowA;
  49. SafePointer<uint8_t> pixelB = rowB;
  50. for (int x = 0; x < width; x++) {
  51. // Read both source pixels and add them
  52. int result = *pixelA + *pixelB;
  53. // Clamp overflow
  54. if (result > 255) result = 255;
  55. // Can skip underflow check
  56. //if (result < 0) result = 0;
  57. // Write the result
  58. *targetPixel = result;
  59. // Move pixel pointers to the next pixel
  60. targetPixel += 1;
  61. pixelA += 1;
  62. pixelB += 1;
  63. }
  64. // Move row pointers to the next row
  65. targetRow.increaseBytes(targetStride);
  66. rowA.increaseBytes(strideA);
  67. rowB.increaseBytes(strideB);
  68. }
  69. }
  70. void addImages_simd(AlignedImageU8 targetImage, AlignedImageU8 imageA, AlignedImageU8 imageB) {
  71. int width = image_getWidth(targetImage);
  72. int height = image_getHeight(targetImage);
  73. SafePointer<uint8_t> targetRow = image_getSafePointer(targetImage);
  74. SafePointer<uint8_t> rowA = image_getSafePointer(imageA);
  75. SafePointer<uint8_t> rowB = image_getSafePointer(imageB);
  76. int targetStride = image_getStride(targetImage);
  77. int strideA = image_getStride(imageA);
  78. int strideB = image_getStride(imageB);
  79. for (int y = 0; y < height; y++) {
  80. SafePointer<uint8_t> targetPixel = targetRow;
  81. SafePointer<uint8_t> pixelA = rowA;
  82. SafePointer<uint8_t> pixelB = rowB;
  83. // Assuming that we have ownership of any padding pixels
  84. for (int x = 0; x < width; x += 16) {
  85. // Read 16 source pixels at a time
  86. U8x16 a = U8x16::readAligned(pixelA, "addImages: reading pixelA");
  87. U8x16 b = U8x16::readAligned(pixelB, "addImages: reading pixelB");
  88. // Saturated operations replace conditional move
  89. U8x16 result = saturatedAddition(a, b);
  90. // Write the result 16 pixels at a time
  91. result.writeAligned(targetPixel, "addImages: writing result");
  92. // Move pixel pointers to the next pixel
  93. targetPixel += 16;
  94. pixelA += 16;
  95. pixelB += 16;
  96. }
  97. // Move row pointers to the next row
  98. targetRow.increaseBytes(targetStride);
  99. rowA.increaseBytes(strideA);
  100. rowB.increaseBytes(strideB);
  101. }
  102. }
  103. // Making sure that all code examples from the image processing guide actually works
  104. START_TEST(Image)
  105. {
  106. AlignedImageU8 imageA = image_fromAscii(
  107. "< .x>"
  108. "< ... >"
  109. "< .xx. >"
  110. "< ..... >"
  111. "< .xx.. >"
  112. "< ..x.. >"
  113. "< ...... >"
  114. "< ..xx.. >"
  115. "< ..x. >"
  116. "< ..x.. >"
  117. "< ..x. >"
  118. "< ... >"
  119. "< ... >"
  120. "< ... >"
  121. "< .x.. >"
  122. );
  123. AlignedImageU8 imageB = image_fromAscii(
  124. "< .x>"
  125. "< >"
  126. "< >"
  127. "< >"
  128. "<.. >"
  129. "<.xx... >"
  130. "<...xxxx.... >"
  131. "< ...xxxxxx...>"
  132. "< ....xxxxx>"
  133. "< ...x>"
  134. "< .>"
  135. "<.. >"
  136. "<x.... >"
  137. "<xxx... >"
  138. "<xx.. >"
  139. );
  140. // Using the generate method as a reference implementation.
  141. AlignedImageU8 imageExpected = addImages_generate(imageA, imageB);
  142. //printText("\nGenerate result:\n", image_toAscii(imageExpected));
  143. AlignedImageU8 imageResult = image_create_U8(15, 14);
  144. addImages_map(imageResult, imageA, imageB);
  145. //printText("\nMap result:\n", image_toAscii(imageResult));
  146. ASSERT_EQUAL(image_maxDifference(imageResult, imageExpected), 0);
  147. addImages_loop(imageResult, imageA, imageB);
  148. //printText("\nLoop result:\n", image_toAscii(imageResult));
  149. ASSERT_EQUAL(image_maxDifference(imageResult, imageExpected), 0);
  150. addImages_pointer(imageResult, imageA, imageB);
  151. //printText("\nPointer result:\n", image_toAscii(imageResult));
  152. ASSERT_EQUAL(image_maxDifference(imageResult, imageExpected), 0);
  153. addImages_simd(imageResult, imageA, imageB);
  154. //printText("\nSIMD result:\n", image_toAscii(imageResult));
  155. ASSERT_EQUAL(image_maxDifference(imageResult, imageExpected), 0);
  156. }
  157. END_TEST