mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-10-30 23:47:27 +03:00 
			
		
		
		
	Remove pointer casts as they may lead to UB and refactor code to not use union rgb565 structs
This commit is contained in:
		
							parent
							
								
									a05be82920
								
							
						
					
					
						commit
						c6c0749a16
					
				|  | @ -28,3 +28,15 @@ typedef struct { | |||
|     INT8 a0, a1; | ||||
|     UINT8 lut[6]; | ||||
| } bc5s_alpha; | ||||
| 
 | ||||
| #define BIT_MASK(bit_count) ((1 << (bit_count)) - 1) | ||||
| #define SET_BITS(target, bit_offset, bit_count, value) \ | ||||
|     target |= (((value)&BIT_MASK(bit_count)) << (bit_offset)) | ||||
| #define GET_BITS(source, bit_offset, bit_count) \ | ||||
|     ((source) & (BIT_MASK(bit_count) << (bit_offset))) >> (bit_offset) | ||||
| #define SWAP(TYPE, A, B) \ | ||||
|     do {                 \ | ||||
|         TYPE TMP = A;    \ | ||||
|         (A) = B;           \ | ||||
|         (B) = TMP;         \ | ||||
|     } while (0) | ||||
|  |  | |||
|  | @ -16,54 +16,44 @@ | |||
| #include "Bcn.h" | ||||
| #include "math.h" | ||||
| 
 | ||||
| #define BIT_MASK(bit_count) ((1 << (bit_count)) - 1) | ||||
| #define SET_BITS(target, bit_offset, bit_count, value) \ | ||||
|     target |= (((value)&BIT_MASK(bit_count)) << (bit_offset)) | ||||
| #define SWAP(TYPE, A, B) \ | ||||
|     do {                 \ | ||||
|         TYPE TMP = A;    \ | ||||
|         A = B;           \ | ||||
|         B = TMP;         \ | ||||
|     } while (0) | ||||
| #define PACK_SHORT_565(r, g, b) \ | ||||
|     ((((b) << 8) & 0xF800) | (((g) << 3) & 0x7E0) | ((r) >> 3)) | ||||
| 
 | ||||
| typedef union { | ||||
|     struct { | ||||
|         UINT16 r : 5; | ||||
|         UINT16 g : 6; | ||||
|         UINT16 b : 5; | ||||
|     } color; | ||||
|     UINT16 value; | ||||
| } rgb565; | ||||
| #define UNPACK_SHORT_565(source, r, g, b) \ | ||||
|     (r) = GET_BITS((source), 0, 5);       \ | ||||
|     (g) = GET_BITS((source), 5, 6);       \ | ||||
|     (b) = GET_BITS((source), 11, 5); | ||||
| 
 | ||||
| static UINT16 | ||||
| pack_565(UINT8 r, UINT8 g, UINT8 b) { | ||||
|     rgb565 color; | ||||
|     color.color.r = r / (255 / 31); | ||||
|     color.color.g = g / (255 / 63); | ||||
|     color.color.b = b / (255 / 31); | ||||
|     return color.value; | ||||
| } | ||||
| #define WRITE_SHORT(buf, value) \ | ||||
|     *(buf++) = value & 0xFF;    \ | ||||
|     *(buf++) = value >> 8; | ||||
| 
 | ||||
| static UINT16 | ||||
| rgb565_diff(UINT16 a, UINT16 b) { | ||||
|     rgb565 c0; | ||||
|     c0.value = a; | ||||
|     rgb565 c1; | ||||
|     c1.value = b; | ||||
|     return ((UINT16)abs(c0.color.r - c1.color.r)) + abs(c0.color.g - c1.color.g) + | ||||
|            abs(c0.color.b - c1.color.b); | ||||
| #define WRITE_INT(buf, value)        \ | ||||
|     WRITE_SHORT(buf, value & 0xFFFF) \ | ||||
|     WRITE_SHORT(buf, value >> 16) | ||||
| 
 | ||||
| #define WRITE_BC1_BLOCK(buf, block) \ | ||||
|     WRITE_SHORT(buf, block.c0)      \ | ||||
|     WRITE_SHORT(buf, block.c1)      \ | ||||
|     WRITE_INT(buf, block.lut) | ||||
| 
 | ||||
| static inline UINT16 | ||||
| rgb565_diff(UINT16 c0, UINT16 c1) { | ||||
|     UINT8 r0, g0, b0, r1, g1, b1; | ||||
|     UNPACK_SHORT_565(c0, r0, g0, b0) | ||||
|     UNPACK_SHORT_565(c1, r1, g1, b1) | ||||
|     return ((UINT16)abs(r0 - r1)) + abs(g0 - g1) + abs(b0 - b1); | ||||
| } | ||||
| 
 | ||||
| static inline UINT16 | ||||
| rgb565_lerp(UINT16 a, UINT16 b, UINT8 a_fac, UINT8 b_fac) { | ||||
|     rgb565 c0; | ||||
|     c0.value = a; | ||||
|     rgb565 c1; | ||||
|     c1.value = b; | ||||
|     return pack_565( | ||||
|         (c0.color.r * a_fac + c1.color.r * b_fac) / (a_fac + b_fac), | ||||
|         (c0.color.g * a_fac + c1.color.g * b_fac) / (a_fac + b_fac), | ||||
|         (c0.color.b * a_fac + c1.color.b * b_fac) / (a_fac + b_fac)); | ||||
| rgb565_lerp(UINT16 c0, UINT16 c1, UINT8 a_fac, UINT8 b_fac) { | ||||
|     UINT8 r0, g0, b0, r1, g1, b1; | ||||
|     UNPACK_SHORT_565(c0, r0, g0, b0) | ||||
|     UNPACK_SHORT_565(c1, r1, g1, b1) | ||||
|     return PACK_SHORT_565( | ||||
|         (r0 * a_fac + r1 * b_fac) / (a_fac + b_fac), | ||||
|         (g0 * a_fac + g1 * b_fac) / (a_fac + b_fac), | ||||
|         (b0 * a_fac + b1 * b_fac) / (a_fac + b_fac)); | ||||
| } | ||||
| 
 | ||||
| typedef struct { | ||||
|  | @ -131,13 +121,13 @@ get_closest_color_index(const UINT16 *colors, UINT16 color) { | |||
| 
 | ||||
| int | ||||
| encode_bc1(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) { | ||||
|     bc1_color *blocks = (bc1_color *)buf; | ||||
|     UINT8* dst = buf; | ||||
|     UINT8 no_alpha = 0; | ||||
|     INT32 block_index; | ||||
|     if (strchr(im->mode, 'A') == NULL) { | ||||
|         no_alpha = 1; | ||||
|     } | ||||
|     UINT32 block_count = (im->xsize * im->ysize) / 16; | ||||
|     INT32 block_count = (im->xsize * im->ysize) / 16; | ||||
|     if (block_count * sizeof(bc1_color) > bytes) { | ||||
|         state->errcode = IMAGING_CODEC_MEMORY; | ||||
|         return 0; | ||||
|  | @ -166,7 +156,7 @@ encode_bc1(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) { | |||
|                 UINT8 g = im->image[y][x * im->pixelsize + 1]; | ||||
|                 UINT8 b = im->image[y][x * im->pixelsize + 0]; | ||||
|                 UINT8 a = im->image[y][x * im->pixelsize + 3]; | ||||
|                 UINT16 color = pack_565(r, g, b); | ||||
|                 UINT16 color = PACK_SHORT_565(r, g, b); | ||||
|                 opaque[bx + by * 4] = a >= 127; | ||||
|                 all_colors[bx + by * 4] = color; | ||||
| 
 | ||||
|  | @ -201,10 +191,9 @@ encode_bc1(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) { | |||
|             palette[2] = rgb565_lerp(c0, c1, 1, 1); | ||||
|             palette[3] = 0; | ||||
|         } | ||||
|         bc1_color *block = &blocks[block_index]; | ||||
| 
 | ||||
|         block->c0 = c0; | ||||
|         block->c1 = c1; | ||||
|         bc1_color block = {0}; | ||||
|         block.c0 = c0; | ||||
|         block.c1 = c1; | ||||
|         UINT32 color_id; | ||||
|         for (color_id = 0; color_id < 16; ++color_id) { | ||||
|             UINT8 bc_color_id; | ||||
|  | @ -213,11 +202,12 @@ encode_bc1(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) { | |||
|             } else { | ||||
|                 bc_color_id = 3; | ||||
|             } | ||||
|             SET_BITS(block->lut, color_id * 2, 2, bc_color_id); | ||||
|             SET_BITS(block.lut, color_id * 2, 2, bc_color_id); | ||||
|         } | ||||
|         WRITE_BC1_BLOCK(dst, block) | ||||
|     } | ||||
|     state->errcode = IMAGING_CODEC_END; | ||||
|     return block_count * sizeof(bc1_color); | ||||
|     return dst - buf; | ||||
| } | ||||
| 
 | ||||
| int | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user