29
29
30
30
using namespace dsr ;
31
31
32
+ // Preconditions:
33
+ // 0 <= a <= 255
34
+ // 0 <= b <= 255
35
+ // Postconditions:
36
+ // Returns the normalized multiplication of a and b, where the 0..255 range represents decimal values from 0.0 to 1.0.
37
+ // The result may not be less than zero or larger than any of the inputs.
38
+ // Examples:
39
+ // normalizedByteMultiplication(0, 0) = 0
40
+ // normalizedByteMultiplication(x, 0) = 0
41
+ // normalizedByteMultiplication(0, x) = 0
42
+ // normalizedByteMultiplication(x, 255) = x
43
+ // normalizedByteMultiplication(255, x) = x
44
+ // normalizedByteMultiplication(255, 255) = 255
45
+ static inline uint32_t normalizedByteMultiplication (uint32_t a, uint32_t b) {
46
+ // Approximate the reciprocal of an unsigned byte's maximum value 255 for normalization
47
+ // 256³ / 255 ≈ 65793
48
+ // Truncation goes down, so add half a unit before rounding to get the closest value
49
+ // 2^24 / 2 = 8388608
50
+ // No overflow for unsigned 32-bit integers
51
+ // 255² * 65793 + 8388608 = 4286578433 < 2^32
52
+ return (a * b * 65793 + 8388608 ) >> 24 ;
53
+ }
54
+
55
+ // True iff high and low bytes are equal
56
+ // Equivalent to value % 257 == 0 because A + B * 256 = A * 257 when A = B.
57
+ inline bool isUniformByteU16 (uint16_t value) {
58
+ return (value & 0x00FF ) == ((value & 0xFF00 ) >> 8 );
59
+ }
60
+
32
61
// -------------------------------- Drawing shapes --------------------------------
33
62
34
63
template <typename COLOR_TYPE>
@@ -568,10 +597,10 @@ void dsr::imageImpl_drawAlphaFilter(ImageRgbaU8Impl& target, const ImageRgbaU8Im
568
597
targetPixel[target.packOrder .alphaIndex ] = 255 ;
569
598
} else {
570
599
uint32_t targetRatio = 255 - sourceRatio;
571
- targetPixel[target.packOrder .redIndex ] = mulByte_8 (targetPixel[target.packOrder .redIndex ], targetRatio) + mulByte_8 (sourcePixel[source.packOrder .redIndex ], sourceRatio);
572
- targetPixel[target.packOrder .greenIndex ] = mulByte_8 (targetPixel[target.packOrder .greenIndex ], targetRatio) + mulByte_8 (sourcePixel[source.packOrder .greenIndex ], sourceRatio);
573
- targetPixel[target.packOrder .blueIndex ] = mulByte_8 (targetPixel[target.packOrder .blueIndex ], targetRatio) + mulByte_8 (sourcePixel[source.packOrder .blueIndex ], sourceRatio);
574
- targetPixel[target.packOrder .alphaIndex ] = mulByte_8 (targetPixel[target.packOrder .alphaIndex ], targetRatio) + sourceRatio;
600
+ targetPixel[target.packOrder .redIndex ] = normalizedByteMultiplication (targetPixel[target.packOrder .redIndex ], targetRatio) + normalizedByteMultiplication (sourcePixel[source.packOrder .redIndex ], sourceRatio);
601
+ targetPixel[target.packOrder .greenIndex ] = normalizedByteMultiplication (targetPixel[target.packOrder .greenIndex ], targetRatio) + normalizedByteMultiplication (sourcePixel[source.packOrder .greenIndex ], sourceRatio);
602
+ targetPixel[target.packOrder .blueIndex ] = normalizedByteMultiplication (targetPixel[target.packOrder .blueIndex ], targetRatio) + normalizedByteMultiplication (sourcePixel[source.packOrder .blueIndex ], sourceRatio);
603
+ targetPixel[target.packOrder .alphaIndex ] = normalizedByteMultiplication (targetPixel[target.packOrder .alphaIndex ], targetRatio) + sourceRatio;
575
604
}
576
605
}
577
606
);
@@ -636,7 +665,7 @@ static void drawSilhouette_template(ImageRgbaU8Impl& target, const ImageU8Impl&
636
665
if (FULL_ALPHA) {
637
666
sourceRatio = *sourcePixel;
638
667
} else {
639
- sourceRatio = mulByte_8 (*sourcePixel, color.alpha );
668
+ sourceRatio = normalizedByteMultiplication (*sourcePixel, color.alpha );
640
669
}
641
670
if (sourceRatio > 0 ) {
642
671
if (sourceRatio == 255 ) {
@@ -646,10 +675,10 @@ static void drawSilhouette_template(ImageRgbaU8Impl& target, const ImageU8Impl&
646
675
targetPixel[target.packOrder .alphaIndex ] = 255 ;
647
676
} else {
648
677
uint32_t targetRatio = 255 - sourceRatio;
649
- targetPixel[target.packOrder .redIndex ] = mulByte_8 (targetPixel[target.packOrder .redIndex ], targetRatio) + mulByte_8 (color.red , sourceRatio);
650
- targetPixel[target.packOrder .greenIndex ] = mulByte_8 (targetPixel[target.packOrder .greenIndex ], targetRatio) + mulByte_8 (color.green , sourceRatio);
651
- targetPixel[target.packOrder .blueIndex ] = mulByte_8 (targetPixel[target.packOrder .blueIndex ], targetRatio) + mulByte_8 (color.blue , sourceRatio);
652
- targetPixel[target.packOrder .alphaIndex ] = mulByte_8 (targetPixel[target.packOrder .alphaIndex ], targetRatio) + sourceRatio;
678
+ targetPixel[target.packOrder .redIndex ] = normalizedByteMultiplication (targetPixel[target.packOrder .redIndex ], targetRatio) + normalizedByteMultiplication (color.red , sourceRatio);
679
+ targetPixel[target.packOrder .greenIndex ] = normalizedByteMultiplication (targetPixel[target.packOrder .greenIndex ], targetRatio) + normalizedByteMultiplication (color.green , sourceRatio);
680
+ targetPixel[target.packOrder .blueIndex ] = normalizedByteMultiplication (targetPixel[target.packOrder .blueIndex ], targetRatio) + normalizedByteMultiplication (color.blue , sourceRatio);
681
+ targetPixel[target.packOrder .alphaIndex ] = normalizedByteMultiplication (targetPixel[target.packOrder .alphaIndex ], targetRatio) + sourceRatio;
653
682
}
654
683
}
655
684
);
0 commit comments