| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
-
- #include "../testTools.h"
- AlignedImageU8 addImages_generate(ImageU8 imageA, ImageU8 imageB) {
- int width = image_getWidth(imageA);
- int height = image_getHeight(imageA);
- // Call your lambda for width times height pixels
- return filter_generateU8(width, height,
- [imageA, imageB](int x, int y) {
- int lumaA = image_readPixel_clamp(imageA, x, y);
- int lumaB = image_readPixel_clamp(imageB, x, y);
- return lumaA + lumaB;
- }
- );
- }
- void addImages_map(ImageU8 targetImage, ImageU8 imageA, ImageU8 imageB) {
- // Call your lambda for each pixel in targetImage
- filter_mapU8(targetImage,
- [imageA, imageB](int x, int y) {
- int lumaA = image_readPixel_clamp(imageA, x, y);
- int lumaB = image_readPixel_clamp(imageB, x, y);
- return lumaA + lumaB;
- }
- );
- }
- void addImages_loop(ImageU8 targetImage, ImageU8 imageA, ImageU8 imageB) {
- int width = image_getWidth(targetImage);
- int height = image_getHeight(targetImage);
- // Loop over all x, y coordinates yourself
- for (int y = 0; y < height; y++) {
- for (int x = 0; x < width; x++) {
- int lumaA = image_readPixel_clamp(imageA, x, y);
- int lumaB = image_readPixel_clamp(imageB, x, y);
- image_writePixel(targetImage, x, y, lumaA + lumaB);
- }
- }
- }
- void addImages_pointer(ImageU8 targetImage, ImageU8 imageA, ImageU8 imageB) {
- int width = image_getWidth(targetImage);
- int height = image_getHeight(targetImage);
- SafePointer<uint8_t> targetRow = image_getSafePointer(targetImage);
- SafePointer<uint8_t> rowA = image_getSafePointer(imageA);
- SafePointer<uint8_t> rowB = image_getSafePointer(imageB);
- int targetStride = image_getStride(targetImage);
- int strideA = image_getStride(imageA);
- int strideB = image_getStride(imageB);
- for (int y = 0; y < height; y++) {
- SafePointer<uint8_t> targetPixel = targetRow;
- SafePointer<uint8_t> pixelA = rowA;
- SafePointer<uint8_t> pixelB = rowB;
- for (int x = 0; x < width; x++) {
- // Read both source pixels and add them
- int result = *pixelA + *pixelB;
- // Clamp overflow
- if (result > 255) result = 255;
- // Can skip underflow check
- //if (result < 0) result = 0;
- // Write the result
- *targetPixel = result;
- // Move pixel pointers to the next pixel
- targetPixel += 1;
- pixelA += 1;
- pixelB += 1;
- }
- // Move row pointers to the next row
- targetRow.increaseBytes(targetStride);
- rowA.increaseBytes(strideA);
- rowB.increaseBytes(strideB);
- }
- }
- void addImages_simd(AlignedImageU8 targetImage, AlignedImageU8 imageA, AlignedImageU8 imageB) {
- int width = image_getWidth(targetImage);
- int height = image_getHeight(targetImage);
- SafePointer<uint8_t> targetRow = image_getSafePointer(targetImage);
- SafePointer<uint8_t> rowA = image_getSafePointer(imageA);
- SafePointer<uint8_t> rowB = image_getSafePointer(imageB);
- int targetStride = image_getStride(targetImage);
- int strideA = image_getStride(imageA);
- int strideB = image_getStride(imageB);
- for (int y = 0; y < height; y++) {
- SafePointer<uint8_t> targetPixel = targetRow;
- SafePointer<uint8_t> pixelA = rowA;
- SafePointer<uint8_t> pixelB = rowB;
- // Assuming that we have ownership of any padding pixels
- for (int x = 0; x < width; x += 16) {
- // Read 16 source pixels at a time
- U8x16 a = U8x16::readAligned(pixelA, "addImages: reading pixelA");
- U8x16 b = U8x16::readAligned(pixelB, "addImages: reading pixelB");
- // Saturated operations replace conditional move
- U8x16 result = saturatedAddition(a, b);
- // Write the result 16 pixels at a time
- result.writeAligned(targetPixel, "addImages: writing result");
- // Move pixel pointers to the next pixel
- targetPixel += 16;
- pixelA += 16;
- pixelB += 16;
- }
- // Move row pointers to the next row
- targetRow.increaseBytes(targetStride);
- rowA.increaseBytes(strideA);
- rowB.increaseBytes(strideB);
- }
- }
- // Making sure that all code examples from the image processing guide actually works
- START_TEST(Image)
- {
- AlignedImageU8 imageA = image_fromAscii(
- "< .x>"
- "< ... >"
- "< .xx. >"
- "< ..... >"
- "< .xx.. >"
- "< ..x.. >"
- "< ...... >"
- "< ..xx.. >"
- "< ..x. >"
- "< ..x.. >"
- "< ..x. >"
- "< ... >"
- "< ... >"
- "< ... >"
- "< .x.. >"
- );
- AlignedImageU8 imageB = image_fromAscii(
- "< .x>"
- "< >"
- "< >"
- "< >"
- "<.. >"
- "<.xx... >"
- "<...xxxx.... >"
- "< ...xxxxxx...>"
- "< ....xxxxx>"
- "< ...x>"
- "< .>"
- "<.. >"
- "<x.... >"
- "<xxx... >"
- "<xx.. >"
- );
- // Using the generate method as a reference implementation.
- AlignedImageU8 imageExpected = addImages_generate(imageA, imageB);
- //printText("\nGenerate result:\n", image_toAscii(imageExpected));
-
- AlignedImageU8 imageResult = image_create_U8(15, 14);
- addImages_map(imageResult, imageA, imageB);
- //printText("\nMap result:\n", image_toAscii(imageResult));
- ASSERT_EQUAL(image_maxDifference(imageResult, imageExpected), 0);
- addImages_loop(imageResult, imageA, imageB);
- //printText("\nLoop result:\n", image_toAscii(imageResult));
- ASSERT_EQUAL(image_maxDifference(imageResult, imageExpected), 0);
- addImages_pointer(imageResult, imageA, imageB);
- //printText("\nPointer result:\n", image_toAscii(imageResult));
- ASSERT_EQUAL(image_maxDifference(imageResult, imageExpected), 0);
- addImages_simd(imageResult, imageA, imageB);
- //printText("\nSIMD result:\n", image_toAscii(imageResult));
- ASSERT_EQUAL(image_maxDifference(imageResult, imageExpected), 0);
- }
- END_TEST
|