@@ -919,27 +919,45 @@ static inline LineContribType *_gdContributionsCalc(unsigned int line_size, unsi
919919 return res ;
920920}
921921
922+ static inline unsigned char
923+ uchar_clamp (double clr ) {
924+ unsigned short result ;
925+ assert (fabs (clr ) <= SHRT_MAX );
926+ /* Casting a negative float to an unsigned short is undefined.
927+ * However, casting a float to a signed truncates toward zero and
928+ * casting a negative signed value to an unsigned of the same size
929+ * results in a bit-identical value (assuming twos-complement
930+ * arithmetic). This is what we want: all legal negative values
931+ * for clr will be greater than 255. */
932+ /* Convert and clamp. */
933+ result = (unsigned short )(short )(clr + 0.5 );
934+ if (result > 255 ) {
935+ result = (clr < 0 ) ? 0 : 255 ;
936+ }/* if */
937+ return result ;
938+ }/* uchar_clamp*/
939+
922940static inline void _gdScaleRow (gdImagePtr pSrc , unsigned int src_width , gdImagePtr dst , unsigned int dst_width , unsigned int row , LineContribType * contrib )
923941{
924942 int * p_src_row = pSrc -> tpixels [row ];
925943 int * p_dst_row = dst -> tpixels [row ];
926944 unsigned int x ;
927945
928946 for (x = 0 ; x < dst_width ; x ++ ) {
929- register unsigned char r = 0 , g = 0 , b = 0 , a = 0 ;
947+ double r = 0 , g = 0 , b = 0 , a = 0 ;
930948 const int left = contrib -> ContribRow [x ].Left ;
931949 const int right = contrib -> ContribRow [x ].Right ;
932- int i ;
950+ int i ;
933951
934- /* Accumulate each channel */
935- for (i = left ; i <= right ; i ++ ) {
936- const int left_channel = i - left ;
937- r += ( unsigned char )( contrib -> ContribRow [x ].Weights [left_channel ] * (double )(gdTrueColorGetRed (p_src_row [i ]) ));
938- g += ( unsigned char )( contrib -> ContribRow [x ].Weights [left_channel ] * (double )(gdTrueColorGetGreen (p_src_row [i ]) ));
939- b += ( unsigned char )( contrib -> ContribRow [x ].Weights [left_channel ] * (double )(gdTrueColorGetBlue (p_src_row [i ]) ));
940- a += ( unsigned char )( contrib -> ContribRow [x ].Weights [left_channel ] * (double )(gdTrueColorGetAlpha (p_src_row [i ]) ));
941- }
942- p_dst_row [x ] = gdTrueColorAlpha (r , g , b , a );
952+ /* Accumulate each channel */
953+ for (i = left ; i <= right ; i ++ ) {
954+ const int left_channel = i - left ;
955+ r += contrib -> ContribRow [x ].Weights [left_channel ] * (double )(gdTrueColorGetRed (p_src_row [i ]));
956+ g += contrib -> ContribRow [x ].Weights [left_channel ] * (double )(gdTrueColorGetGreen (p_src_row [i ]));
957+ b += contrib -> ContribRow [x ].Weights [left_channel ] * (double )(gdTrueColorGetBlue (p_src_row [i ]));
958+ a += contrib -> ContribRow [x ].Weights [left_channel ] * (double )(gdTrueColorGetAlpha (p_src_row [i ]));
959+ }
960+ p_dst_row [x ] = gdTrueColorAlpha (uchar_clamp ( r ), uchar_clamp ( g ), uchar_clamp ( b ), uchar_clamp ( a ) );
943961 }
944962}
945963
@@ -972,7 +990,7 @@ static inline void _gdScaleCol (gdImagePtr pSrc, unsigned int src_width, gdImag
972990{
973991 unsigned int y ;
974992 for (y = 0 ; y < dst_height ; y ++ ) {
975- register unsigned char r = 0 , g = 0 , b = 0 , a = 0 ;
993+ double r = 0 , g = 0 , b = 0 , a = 0 ;
976994 const int iLeft = contrib -> ContribRow [y ].Left ;
977995 const int iRight = contrib -> ContribRow [y ].Right ;
978996 int i ;
@@ -981,12 +999,12 @@ static inline void _gdScaleCol (gdImagePtr pSrc, unsigned int src_width, gdImag
981999 for (i = iLeft ; i <= iRight ; i ++ ) {
9821000 const int pCurSrc = pSrc -> tpixels [i ][uCol ];
9831001 const int i_iLeft = i - iLeft ;
984- r += ( unsigned char )( contrib -> ContribRow [y ].Weights [i_iLeft ] * (double )(gdTrueColorGetRed (pCurSrc ) ));
985- g += ( unsigned char )( contrib -> ContribRow [y ].Weights [i_iLeft ] * (double )(gdTrueColorGetGreen (pCurSrc ) ));
986- b += ( unsigned char )( contrib -> ContribRow [y ].Weights [i_iLeft ] * (double )(gdTrueColorGetBlue (pCurSrc ) ));
987- a += ( unsigned char )( contrib -> ContribRow [y ].Weights [i_iLeft ] * (double )(gdTrueColorGetAlpha (pCurSrc ) ));
1002+ r += contrib -> ContribRow [y ].Weights [i_iLeft ] * (double )(gdTrueColorGetRed (pCurSrc ));
1003+ g += contrib -> ContribRow [y ].Weights [i_iLeft ] * (double )(gdTrueColorGetGreen (pCurSrc ));
1004+ b += contrib -> ContribRow [y ].Weights [i_iLeft ] * (double )(gdTrueColorGetBlue (pCurSrc ));
1005+ a += contrib -> ContribRow [y ].Weights [i_iLeft ] * (double )(gdTrueColorGetAlpha (pCurSrc ));
9881006 }
989- pRes -> tpixels [y ][uCol ] = gdTrueColorAlpha (r , g , b , a );
1007+ pRes -> tpixels [y ][uCol ] = gdTrueColorAlpha (uchar_clamp ( r ), uchar_clamp ( g ), uchar_clamp ( b ), uchar_clamp ( a ) );
9901008 }
9911009}
9921010
0 commit comments