ImageProcessingTest.cpp 5.8 KB

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