1 /* Character Code Encoding: "WHITE SQUARE" is □ */
\r
2 #include "include_c.h"
\r
6 /************************************************************************
\r
7 * Function: BmpFile2Class_loadBMP
\r
8 * BMP 形式のファイルを読み込みます。
\r
11 * Path - BMP file path
\r
15 ************************************************************************/
\r
16 /*[BmpFile2Class_loadBMP]*/
\r
17 errnum_t BmpFile2Class_loadBMP( BmpFile2Class* self, const TCHAR* Path )
\r
19 BITMAPFILEHEADER bmp_header;
\r
26 en= _tfopen_s( &file, Path, _T("rb") ); IF(en){e=E_ERRNO;goto fin;}
\r
28 fread( &bmp_header, 1, sizeof(bmp_header), file ); IF(ferror(file)){e=E_ERRNO;goto fin;}
\r
29 ASSERT_R( bmp_header.bfType == ('B' | ( 'M' << 8 )), e=E_OTHERS; goto fin );
\r
31 fread( &self->Info, 1, sizeof(self->Info), file ); IF(ferror(file)){e=E_ERRNO;goto fin;}
\r
32 if ( self->Info.biBitCount >= 8 ) {
\r
33 self->Stride = self->Info.biWidth * ( ( self->Info.biBitCount + 7 ) / 8 );
\r
35 self->Stride = ( self->Info.biWidth * self->Info.biBitCount + 7 ) / 8;
\r
37 self->Stride = ceil_4( self->Stride );
\r
39 if ( self->Info.biBitCount == 16 ) {
\r
40 fread( &self->RedMask, 1, sizeof(self->RedMask), file ); IF(ferror(file)){e=E_ERRNO;goto fin;}
\r
41 fread( &self->GreenMask, 1, sizeof(self->GreenMask), file ); IF(ferror(file)){e=E_ERRNO;goto fin;}
\r
42 fread( &self->BlueMask, 1, sizeof(self->BlueMask), file ); IF(ferror(file)){e=E_ERRNO;goto fin;}
\r
43 fread( &self->AlphaMask, 1, sizeof(self->AlphaMask), file ); IF(ferror(file)){e=E_ERRNO;goto fin;}
\r
45 else if ( self->Info.biBitCount <= 8 ) {
\r
46 int color_count = 1 << self->Info.biBitCount;
\r
48 if ( self->Info.biClrUsed != 0 )
\r
49 { color_count = self->Info.biClrUsed; }
\r
51 e= MallocMemory( &self->Palette, color_count * sizeof(RGBQUAD) ); IF(e){goto fin;}
\r
53 fread( self->Palette, 1, color_count * sizeof(RGBQUAD), file );
\r
54 IF(ferror(file)){e=E_ERRNO;goto fin;}
\r
56 self->PaletteColorCount = color_count;
\r
59 height_abs = self->Info.biHeight;
\r
60 if ( height_abs < 0 ) { height_abs = -height_abs; }
\r
62 ASSERT_R( self->Info.biSizeImage == 0 ||
\r
63 self->Info.biSizeImage == self->Stride * height_abs, goto err_og );
\r
65 if ( self->Info.biSizeImage == 0 )
\r
66 { self->Info.biSizeImage = self->Stride * height_abs; }
\r
68 e= FreeMemory( &self->Pixels, 0 ); IF(e){goto fin;}
\r
69 e= MallocMemory( &self->Pixels, self->Info.biSizeImage ); IF(e){goto fin;}
\r
71 fseek( file, bmp_header.bfOffBits, SEEK_SET ); IF(ferror(file)){e=E_ERRNO;goto fin;}
\r
72 fread( self->Pixels, self->Info.biSizeImage, 1, file ); IF(ferror(file)){e=E_ERRNO;goto fin;}
\r
76 e= FileT_closeAndNULL( &file, e );
\r
78 e= FreeMemory( &self->Pixels, e );
\r
83 Error4_printf( _T("<ERROR msg=\"BITMAPINFOHEADER::biSizeImage is invalid\"/>") );
\r
90 /************************************************************************
\r
91 * Function: BmpFile2Class_saveBMP
\r
92 * BMP 形式のファイルを書き込みます。
\r
95 * Path - BMP file path
\r
99 ************************************************************************/
\r
100 /*[BmpFile2Class_saveBMP]*/
\r
101 errnum_t BmpFile2Class_saveBMP( BmpFile2Class* self, const TCHAR* Path )
\r
103 BITMAPFILEHEADER bmp_header;
\r
112 uint32_t palette[16]; // RGBQUAD type
\r
115 height_abs = self->Info.biHeight;
\r
116 if ( height_abs < 0 ) { height_abs = -height_abs; }
\r
118 memset( &bmp_header, 0, sizeof(bmp_header) );
\r
119 bmp_header.bfType = 'B' | ( 'M' << 8 );
\r
120 bmp_header.bfSize = sizeof(bmp_header) + sizeof(self->Info) +
\r
121 height_abs * self->Stride;
\r
123 bmp_header.bfOffBits = 0x36;
\r
124 switch ( self->Info.biBitCount ) {
\r
126 bmp_header.bfSize += 2 * sizeof(RGBQUAD);
\r
127 bmp_header.bfOffBits += 2 * sizeof(RGBQUAD);
\r
131 bmp_header.bfSize += 16 * sizeof(RGBQUAD);
\r
132 bmp_header.bfOffBits += 16 * sizeof(RGBQUAD);
\r
136 bmp_header.bfSize += 256 * sizeof(RGBQUAD);
\r
137 bmp_header.bfOffBits += 256 * sizeof(RGBQUAD);
\r
141 bmp_header.bfSize += 4 * sizeof(RGBQUAD);
\r
142 bmp_header.bfOffBits += 4 * sizeof(RGBQUAD);
\r
148 default: ASSERT_R( false, e=E_OTHERS; goto fin ); break;
\r
150 mod = bmp_header.bfOffBits % self->Alignment_bfOffBits;
\r
152 plus = - mod + self->Alignment_bfOffBits;
\r
153 bmp_header.bfSize += plus;
\r
154 bmp_header.bfOffBits += plus;
\r
157 en= _tfopen_s( &file, Path, _T("wb") ); IF(en){e=E_ERRNO;goto fin;}
\r
158 ASSERT_R( file != NULL, e=E_OTHERS; goto fin );
\r
159 fwrite( &bmp_header, 1, sizeof(bmp_header), file ); IF(ferror(file)){e=E_ERRNO;goto fin;}
\r
160 fwrite( &self->Info, 1, sizeof(self->Info), file ); IF(ferror(file)){e=E_ERRNO;goto fin;}
\r
162 switch ( self->Info.biBitCount ) {
\r
164 palette[0] = 0x00000000; palette[1] = 0x00FFFFFF;
\r
165 fwrite( palette, 2, sizeof(*palette), file ); IF(ferror(file)){e=E_ERRNO;goto fin;}
\r
168 palette[0] = 0x00000000; palette[1] = 0x00111111; palette[2] = 0x00222222; palette[3] = 0x00333333;
\r
169 palette[4] = 0x00444444; palette[5] = 0x00555555; palette[6] = 0x00666666; palette[7] = 0x00777777;
\r
170 palette[8] = 0x00888888; palette[9] = 0x00999999; palette[10]= 0x00AAAAAA; palette[11]= 0x00BBBBBB;
\r
171 palette[12]= 0x00CCCCCC; palette[13]= 0x00DDDDDD; palette[14]= 0x00EEEEEE; palette[15]= 0x00FFFFFF;
\r
172 fwrite( palette, 16, sizeof(*palette), file ); IF(ferror(file)){e=E_ERRNO;goto fin;}
\r
175 for ( palette_index = 0; palette_index < 256; palette_index += 0x10 ) {
\r
176 palette[ 0 ] = 0x00010101 * palette_index;
\r
177 for ( offset = 1; offset < 0x10; offset += 1 ) {
\r
178 palette[ offset ] = palette[ 0 ] + 0x00010101 * offset;
\r
180 fwrite( palette, 16, sizeof(*palette), file ); IF(ferror(file)){e=E_ERRNO;goto fin;}
\r
184 palette[0] = self->RedMask; palette[1] = self->GreenMask;
\r
185 palette[2] = self->BlueMask; palette[3] = self->AlphaMask;
\r
186 fwrite( palette, 4, sizeof(*palette), file ); IF(ferror(file)){e=E_ERRNO;goto fin;}
\r
190 fseek( file, bmp_header.bfOffBits, SEEK_SET ); IF(ferror(file)){e=E_ERRNO;goto fin;}
\r
191 fwrite( self->Pixels, 1, height_abs * self->Stride, file );
\r
192 IF(ferror(file)){e=E_ERRNO;goto fin;}
\r
196 if ( file != NULL ) fclose( file );
\r
202 /***********************************************************************
\r
203 <<< [BmpFile2Class_finish] >>>
\r
204 ************************************************************************/
\r
205 errnum_t BmpFile2Class_finish( BmpFile2Class* self, errnum_t e )
\r
207 e= FreeMemory( &self->Pixels, e );
\r
208 e= FreeMemory( &self->Palette, e );
\r
213 /***********************************************************************
\r
214 <<< [BmpFile2Class_loadRaw16bit_Sub] >>>
\r
215 ************************************************************************/
\r
216 errnum_t BmpFile2Class_loadRaw16bit_Sub( BmpFile2Class* self, TCHAR* Path, int Stride )
\r
223 ASSERT_R( Stride % 4 == 0, e=E_OTHERS; goto fin );
\r
225 en= _tfopen_s( &file, Path, _T("rb") ); IF(en){ e=E_ERRNO; goto fin; }
\r
227 fseek( file, 0, SEEK_END );
\r
228 raw_size = ftell( file );
\r
229 fseek( file, 0, SEEK_SET );
\r
231 if ( self->Pixels != NULL ) free( self->Pixels );
\r
232 self->Pixels = (uint8_t*) malloc( raw_size );
\r
233 ASSERT_R( self->Pixels != NULL, e=E_OTHERS; goto fin );
\r
235 fread( self->Pixels, 1, raw_size, file );
\r
237 self->Info.biSize = sizeof(BITMAPINFOHEADER) + 4 * sizeof(uint32_t);
\r
238 self->Info.biWidth = Stride / 2;
\r
239 self->Info.biHeight = - (LONG)( raw_size / Stride );
\r
240 self->Info.biPlanes = 1;
\r
241 self->Info.biBitCount = 16;
\r
242 self->Info.biCompression = BI_BITFIELDS;
\r
243 self->Info.biSizeImage = raw_size;
\r
244 self->Info.biXPelsPerMeter = 0;
\r
245 self->Info.biYPelsPerMeter = 0;
\r
246 self->Info.biClrUsed = 0;
\r
247 self->Info.biClrImportant = 0;
\r
248 self->RedMask = 0xF800;
\r
249 self->GreenMask = 0x07E0;
\r
250 self->BlueMask = 0x001F;
\r
251 self->AlphaMask = 0x0000;
\r
252 self->Stride = Stride;
\r
256 if ( file != NULL ) fclose( file );
\r
258 if ( self->Pixels != NULL ) free( self->Pixels );
\r
259 self->Pixels = NULL;
\r
266 /***********************************************************************
\r
267 <<< [BmpFile2Class_loadRawRGB565] >>>
\r
268 ************************************************************************/
\r
269 errnum_t BmpFile2Class_loadRawRGB565( BmpFile2Class* self, TCHAR* Path, int Stride )
\r
273 e= BmpFile2Class_loadRaw16bit_Sub( self, Path, Stride );
\r
274 self->RedMask = 0xF800;
\r
275 self->GreenMask = 0x07E0;
\r
276 self->BlueMask = 0x001F;
\r
277 self->AlphaMask = 0x0000;
\r
284 /***********************************************************************
\r
285 <<< [BmpFile2Class_loadRawARGB8888] >>>
\r
286 ************************************************************************/
\r
287 errnum_t BmpFile2Class_loadRawARGB8888( BmpFile2Class* self, TCHAR* Path, int Stride )
\r
294 ASSERT_R( Stride % 4 == 0, e=E_OTHERS; goto fin );
\r
296 en= _tfopen_s( &file, Path, _T("rb") ); IF(en){ e=E_ERRNO; goto fin; }
\r
298 fseek( file, 0, SEEK_END );
\r
299 raw_size = ftell( file );
\r
300 fseek( file, 0, SEEK_SET );
\r
302 if ( self->Pixels != NULL ) free( self->Pixels );
\r
303 self->Pixels = (uint8_t*) malloc( raw_size );
\r
304 ASSERT_R( self->Pixels != NULL, e=E_OTHERS; goto fin );
\r
306 fread( self->Pixels, 1, raw_size, file );
\r
308 self->Info.biSize = sizeof(BITMAPINFOHEADER);
\r
309 self->Info.biWidth = Stride / 4;
\r
310 self->Info.biHeight = - (LONG)( raw_size / Stride );
\r
311 self->Info.biPlanes = 1;
\r
312 self->Info.biBitCount = 32;
\r
313 self->Info.biCompression = 0;
\r
314 self->Info.biSizeImage = raw_size;
\r
315 self->Info.biXPelsPerMeter = 0;
\r
316 self->Info.biYPelsPerMeter = 0;
\r
317 self->Info.biClrUsed = 0;
\r
318 self->Info.biClrImportant = 0;
\r
320 self->GreenMask = 0;
\r
321 self->BlueMask = 0;
\r
322 self->AlphaMask = 0;
\r
323 self->Stride = Stride;
\r
327 if ( file != NULL ) fclose( file );
\r
329 if ( self->Pixels != NULL ) free( self->Pixels );
\r
330 self->Pixels = NULL;
\r
337 /***********************************************************************
\r
338 <<< [BmpFile2Class_loadRawARGB1555] >>>
\r
339 ************************************************************************/
\r
340 errnum_t BmpFile2Class_loadRawARGB1555( BmpFile2Class* self, TCHAR* Path, int Stride )
\r
344 e= BmpFile2Class_loadRaw16bit_Sub( self, Path, Stride );
\r
345 self->RedMask = 0x7C00;
\r
346 self->GreenMask = 0x03E0;
\r
347 self->BlueMask = 0x001F;
\r
348 self->AlphaMask = 0x8000;
\r
355 /***********************************************************************
\r
356 <<< [BmpFile2Class_loadRawARGB4444] >>>
\r
357 ************************************************************************/
\r
358 errnum_t BmpFile2Class_loadRawARGB4444( BmpFile2Class* self, TCHAR* Path, int Stride )
\r
362 e= BmpFile2Class_loadRaw16bit_Sub( self, Path, Stride );
\r
363 self->RedMask = 0x0F00;
\r
364 self->GreenMask = 0x00F0;
\r
365 self->BlueMask = 0x000F;
\r
366 self->AlphaMask = 0xF000;
\r
373 /***********************************************************************
\r
374 <<< [BmpFile2Class_loadPNG] >>>
\r
375 ************************************************************************/
\r
376 errnum_t BmpFile2Class_loadPNG( BmpFile2Class* self, const TCHAR* Path )
\r
379 png_struct* png = NULL;
\r
380 png_info* info = NULL;
\r
381 png_info* end_info = NULL;
\r
382 uint8_t** lines = NULL;
\r
388 /* Open file and Create work */
\r
389 en= _tfopen_s( &f, Path, _T("rb") ); IF(en)goto err_no;
\r
390 IF( f == NULL ){goto err;}
\r
392 png = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL );
\r
393 IF( png == NULL ){goto err;}
\r
394 info = png_create_info_struct( png ); IF( info == NULL ){goto err;}
\r
395 end_info = png_create_info_struct( png ); IF( end_info == NULL ){goto err;}
\r
397 png_init_io( png, f );
\r
400 /* Read Information */
\r
402 png_read_info( png, info );
\r
404 self->Stride = png_get_rowbytes( png, info );
\r
405 self->Stride = ceil_4( self->Stride );
\r
407 ASSERT_R( info->num_palette == 0, goto err );
\r
408 ASSERT_R( info->bit_depth == 8, goto err );
\r
409 ASSERT_R( info->color_type == PNG_COLOR_TYPE_RGB ||
\r
410 info->color_type == PNG_COLOR_TYPE_RGB_ALPHA, goto err );
\r
412 self->Info.biSize = sizeof(BITMAPINFOHEADER);
\r
413 self->Info.biWidth = info->width;
\r
414 self->Info.biHeight = info->height;
\r
415 self->Info.biPlanes = 1;
\r
416 switch ( info->color_type ) {
\r
417 case PNG_COLOR_TYPE_RGB: self->Info.biBitCount = 24; break;
\r
418 case PNG_COLOR_TYPE_RGB_ALPHA: self->Info.biBitCount = 32; break;
\r
419 default: ASSERT_R( false, goto err );
\r
421 self->Info.biCompression = BI_RGB;
\r
422 self->Info.biSizeImage = self->Info.biHeight * self->Stride;
\r
423 self->Info.biXPelsPerMeter = 0;
\r
424 self->Info.biYPelsPerMeter = 0;
\r
425 self->Info.biClrUsed = 0;
\r
426 self->Info.biClrImportant = 0;
\r
432 uint8_t* left_of_line;
\r
433 uint_fast32_t stride = self->Stride;
\r
435 e= HeapMemory_free( &self->Pixels, 0 ); IF(e){goto fin;}
\r
436 e= HeapMemory_allocateArray( &lines, self->Info.biHeight ); IF(e){goto fin;}
\r
437 e= HeapMemory_allocateArray( &self->Pixels, stride * self->Info.biHeight ); IF(e){goto fin;}
\r
439 left_of_line = self->Pixels;
\r
441 for ( i = self->Info.biHeight - 1; i >= 0; i -= 1 ) {
\r
442 lines[ i ] = left_of_line;
\r
444 left_of_line[ stride - 3 ] = 0x00; /* Padding */
\r
445 left_of_line[ stride - 2 ] = 0x00;
\r
446 left_of_line[ stride - 1 ] = 0x00;
\r
448 left_of_line += stride;
\r
451 png_set_bgr( png );
\r
452 png_read_image( png, lines ); /* Set to "self->Pixels" */
\r
453 png_read_end( png, end_info );
\r
457 e= HeapMemory_free( &lines, e );
\r
458 if ( info != NULL ) { png_destroy_info_struct( png, &info ); }
\r
459 if ( end_info != NULL ) { png_destroy_info_struct( png, &end_info ); }
\r
460 if ( png != NULL ) { png_destroy_read_struct( &png, NULL, NULL ); }
\r
461 if ( f != NULL ) { fclose( f ); }
\r
464 self->Info.biWidth = 0;
\r
465 self->Info.biHeight = 0;
\r
466 e= HeapMemory_free( &self->Pixels, e );
\r
471 err: e = E_OTHERS; goto fin;
\r
472 err_no: e = E_ERRNO; goto fin;
\r
477 /***********************************************************************
\r
478 <<< [BmpFile2Class_loadJPEG] >>>
\r
479 ************************************************************************/
\r
481 #define LibJPEG_is LibJPEG_is_DLL
\r
483 #define LibJPEG_is_Lib 1
\r
484 #define LibJPEG_is_DLL 2
\r
486 errnum_t BmpFile2Class_loadJPEG( BmpFile2Class* self, const TCHAR* Path )
\r
488 struct jpeg_decompress_struct jpeg_decompress;
\r
489 struct jpeg_error_mgr jpeg_error;
\r
493 char* pixels = NULL;
\r
494 char** pixel_line_pointers = NULL;
\r
495 unsigned width_stride;
\r
496 unsigned width_byte;
\r
497 bool is_jpeg_decompress = false;
\r
498 bool is_started_jpeg_decompress = false;
\r
499 #if LibJPEG_is == LibJPEG_is_DLL
\r
500 void* data_of_JPEG = NULL;
\r
505 en = _tfopen_s( &file, Path, _T("rb") ); IF(en){ e=E_ERRNO; goto fin; }
\r
507 // set up JPEG library and read JPEG header in the file
\r
508 jpeg_decompress.err = jpeg_std_error( &jpeg_error );
\r
509 jpeg_create_decompress( &jpeg_decompress ); is_jpeg_decompress = true;
\r
510 #if LibJPEG_is == LibJPEG_is_DLL
\r
511 fseek( file, 0, SEEK_END );
\r
512 jpeg_size = ftell( file );
\r
513 fseek( file, 0, SEEK_SET );
\r
514 data_of_JPEG = (char*) malloc( jpeg_size );
\r
515 IF( data_of_JPEG == NULL ){ e=E_FEW_MEMORY; goto fin; }
\r
516 read_size = fread( data_of_JPEG, 1, jpeg_size, file );
\r
517 ASSERT_R( read_size == jpeg_size, e=E_OTHERS; goto fin );
\r
518 jpeg_mem_src( &jpeg_decompress, (unsigned char*) data_of_JPEG, jpeg_size );
\r
520 jpeg_stdio_src( &jpeg_decompress, file );
\r
522 jpeg_read_header( &jpeg_decompress, TRUE );
\r
524 ASSERT_R( jpeg_decompress.num_components == 3, e=E_OTHERS; goto fin );
\r
526 width_byte = jpeg_decompress.image_width * jpeg_decompress.num_components;
\r
527 width_stride = ceil_4( width_byte );
\r
529 pixels = (char*) malloc(
\r
530 width_stride * jpeg_decompress.image_height * sizeof(char) );
\r
531 IF(pixels == NULL){ e=E_FEW_MEMORY; goto fin; }
\r
534 // set pixel_line_pointers
\r
540 pixel_line_pointers = (char**) malloc(
\r
541 jpeg_decompress.image_height * sizeof(char*) );
\r
542 IF(pixel_line_pointers == NULL){ e=E_FEW_MEMORY; goto fin; };
\r
545 pp_over = pixel_line_pointers + jpeg_decompress.image_height;
\r
547 for ( pp = pp_over - 1; pp >= pixel_line_pointers; pp -- ) {
\r
550 *(int*)( p - 4 ) = 0; // fill zero to padding area at right of line
\r
556 jpeg_start_decompress( &jpeg_decompress );
\r
557 is_started_jpeg_decompress = true;
\r
558 while ( jpeg_decompress.output_scanline < jpeg_decompress.output_height ) {
\r
559 char** pp = pixel_line_pointers + jpeg_decompress.output_scanline;
\r
562 jpeg_read_scanlines( &jpeg_decompress,
\r
563 (JSAMPARRAY)( pixel_line_pointers + jpeg_decompress.output_scanline ),
\r
564 jpeg_decompress.output_height - jpeg_decompress.output_scanline );
\r
566 // change from RGB to BGR
\r
567 pp_over = pixel_line_pointers + jpeg_decompress.output_scanline;
\r
568 for ( ; pp < pp_over; pp ++ ) {
\r
570 char* p_over = p + width_byte;
\r
572 for ( ; p < p_over; p += jpeg_decompress.num_components ) {
\r
575 value = *( p + 0 );
\r
576 *( p + 0 ) = *( p + 2 );
\r
577 *( p + 2 ) = value;
\r
583 /* set self attributes */
\r
585 self->Stride = width_stride;
\r
587 self->Info.biSize = sizeof(BITMAPINFOHEADER);
\r
588 self->Info.biWidth = jpeg_decompress.image_width;
\r
589 self->Info.biHeight = jpeg_decompress.image_height;
\r
590 self->Info.biPlanes = 1;
\r
591 self->Info.biBitCount = 24;
\r
592 self->Info.biCompression = BI_RGB;
\r
593 self->Info.biSizeImage = self->Info.biHeight * self->Stride;
\r
594 self->Info.biXPelsPerMeter = 0;
\r
595 self->Info.biYPelsPerMeter = 0;
\r
596 self->Info.biClrUsed = 0;
\r
597 self->Info.biClrImportant = 0;
\r
598 self->Pixels = (uint8_t*) pixels;
\r
604 if ( pixels != NULL ) free( pixels );
\r
606 if ( is_started_jpeg_decompress ) jpeg_finish_decompress( &jpeg_decompress );
\r
607 if ( is_jpeg_decompress ) jpeg_destroy_decompress( &jpeg_decompress );
\r
608 if ( pixel_line_pointers != NULL ) free( pixel_line_pointers );
\r
609 if ( file != NULL ) fclose( file );
\r
610 #if LibJPEG_is == LibJPEG_is_DLL
\r
611 if ( data_of_JPEG != NULL ) { free( data_of_JPEG ); }
\r
618 /***********************************************************************
\r
619 <<< [BmpFile2Class_addAlphaChannel] >>>
\r
620 ************************************************************************/
\r
621 errnum_t BmpFile2Class_addAlphaChannel( BmpFile2Class* self, uint8_t AlphaValue )
\r
624 uint32_t image_size;
\r
625 uint8_t* new_pixels;
\r
628 uint8_t* src; // source
\r
629 uint8_t* dst; // destination
\r
630 uint8_t* src_line_head;
\r
631 uint8_t* dst_line_head;
\r
632 int src_line_tail_offset;
\r
633 int dst_line_tail_offset;
\r
635 if ( self->Info.biBitCount == 32 ) return 0;
\r
637 ASSERT_R( self->Info.biBitCount == 24, goto err );
\r
638 ASSERT_R( self->Stride * self->Info.biHeight == self->Info.biSizeImage, goto err );
\r
640 stride24 = self->Stride;
\r
641 stride32 = self->Info.biWidth * 4;
\r
643 image_size = stride32 * self->Info.biHeight;
\r
644 new_pixels = (uint8_t*) realloc( self->Pixels, image_size );
\r
645 ASSERT_R( new_pixels != NULL, goto err_fm );
\r
647 self->Pixels = new_pixels;
\r
648 self->Info.biBitCount = 32;
\r
649 self->Stride = stride32;
\r
650 self->Info.biSizeImage = image_size;
\r
652 src_line_head = new_pixels + stride24 * (self->Info.biHeight - 1);
\r
653 dst_line_head = new_pixels + stride32 * (self->Info.biHeight - 1);
\r
654 src_line_tail_offset = (self->Info.biWidth - 1) * (24/8);
\r
655 dst_line_tail_offset = (self->Info.biWidth - 1) * (32/8);
\r
657 src = src_line_head + src_line_tail_offset;
\r
658 dst = dst_line_head + dst_line_tail_offset;
\r
660 *( dst + 3 ) = AlphaValue;
\r
661 *( dst + 2 ) = *( src + 2 ); // Red
\r
662 *( dst + 1 ) = *( src + 1 ); // Green
\r
663 *( dst ) = *( src ); // Blue
\r
666 } while ( src >= src_line_head );
\r
668 src_line_head -= stride24;
\r
669 dst_line_head -= stride32;
\r
670 } while ( src_line_head >= new_pixels );
\r
676 err: e = E_OTHERS; goto fin;
\r
677 err_fm: e = E_FEW_MEMORY; goto fin;
\r
682 /***********************************************************************
\r
683 <<< [BmpFile2Class_convertToRGB565Format] >>>
\r
684 ************************************************************************/
\r
685 errnum_t BmpFile2Class_convertToRGB565Format( BmpFile2Class* self )
\r
688 uint32_t image_size;
\r
689 uint8_t* new_pixels = NULL;
\r
690 unsigned src_stride;
\r
692 uint16_t red, green, blue;
\r
693 uint8_t* src; // source
\r
694 uint8_t* dst; // destination
\r
695 uint8_t* src_line_head;
\r
696 uint8_t* dst_line_head;
\r
697 int src_line_tail_offset;
\r
698 int dst_line_tail_offset;
\r
699 int src_byte_per_pixel;
\r
701 ASSERT_R( self->Info.biBitCount == 24 || self->Info.biBitCount == 32, goto err );
\r
702 ASSERT_R( self->Stride * self->Info.biHeight == self->Info.biSizeImage, goto err );
\r
704 src_stride = self->Stride;
\r
705 stride16 = self->Info.biWidth * 2;
\r
706 stride16 = ( stride16 + 3 ) & ~0x3; // 4byte alignment
\r
708 image_size = stride16 * self->Info.biHeight;
\r
709 new_pixels = (uint8_t*) malloc( image_size ); IF(new_pixels==NULL)goto err_fm;
\r
711 src_line_head = self->Pixels + src_stride * (self->Info.biHeight - 1);
\r
712 dst_line_head = new_pixels + stride16 * (self->Info.biHeight - 1);
\r
713 src_line_tail_offset = (self->Info.biWidth - 1) * ( self->Info.biBitCount / 8 );
\r
714 dst_line_tail_offset = (self->Info.biWidth - 1) * (16/8);
\r
715 src_byte_per_pixel = self->Info.biBitCount / 8;
\r
717 src = src_line_head + src_line_tail_offset;
\r
718 dst = dst_line_head + dst_line_tail_offset;
\r
720 *(uint32_t*)( dst_line_head + stride16 - sizeof(uint32_t) ) = 0; // padding
\r
722 while ( src >= src_line_head ) {
\r
723 red = *( src + 2 );
\r
724 green = *( src + 1 );
\r
728 ( ( red & 0xF8 ) << 8 ) |
\r
729 ( ( green & 0xFC ) << 3 ) |
\r
730 ( ( blue & 0xF8 ) >> 3 );
\r
732 src -= src_byte_per_pixel;
\r
735 src_line_head -= src_stride;
\r
736 dst_line_head -= stride16;
\r
737 } while ( dst_line_head >= new_pixels );
\r
739 self->Pixels = new_pixels;
\r
740 self->Info.biBitCount = 16;
\r
741 self->Stride = stride16;
\r
742 self->Info.biSizeImage = image_size;
\r
743 self->Info.biCompression = BI_BITFIELDS;
\r
744 self->Info.biSize = sizeof(BITMAPINFOHEADER) + 4 * sizeof(uint32_t);
\r
745 self->RedMask = 0xF800;
\r
746 self->GreenMask = 0x07E0;
\r
747 self->BlueMask = 0x001F;
\r
748 self->AlphaMask = 0x0000;
\r
754 if ( new_pixels != NULL ) free( new_pixels );
\r
757 err: e = E_OTHERS; goto fin;
\r
758 err_fm: e = E_FEW_MEMORY; goto fin;
\r
763 /***********************************************************************
\r
764 <<< [BmpFile2Class_convertToARGB1555Format] >>>
\r
765 ************************************************************************/
\r
766 errnum_t BmpFile2Class_convertTo16bitARGBFormat( BmpFile2Class* self, uint16_t AlphaMask );
\r
768 errnum_t BmpFile2Class_convertToARGB1555Format( BmpFile2Class* self )
\r
770 return BmpFile2Class_convertTo16bitARGBFormat( self, 0x8000 );
\r
773 errnum_t BmpFile2Class_convertTo16bitARGBFormat( BmpFile2Class* self, uint16_t AlphaMask )
\r
776 uint32_t image_size;
\r
777 uint8_t* new_pixels = NULL;
\r
780 uint16_t red, green, blue, alpha;
\r
781 uint8_t* src; // source
\r
782 uint8_t* dst; // destination
\r
783 uint8_t* src_line_head;
\r
784 uint8_t* dst_line_head;
\r
785 int src_line_tail_offset;
\r
786 int dst_line_tail_offset;
\r
788 ASSERT_R( self->Info.biBitCount == 32, goto err ); // need alpha channel
\r
789 ASSERT_R( self->Stride * self->Info.biHeight == self->Info.biSizeImage, goto err );
\r
790 ASSERT_R( AlphaMask == 0x8000 || AlphaMask == 0xF000, goto err );
\r
791 // 0x8000 = ARGB1555, 0xF000 = ARGB4444
\r
793 stride32 = self->Stride;
\r
794 stride16 = self->Info.biWidth * 2;
\r
795 stride16 = ( stride16 + 3 ) & ~0x3; // 4byte alignment
\r
797 image_size = stride16 * self->Info.biHeight;
\r
798 new_pixels = (uint8_t*) malloc( image_size ); IF(new_pixels==NULL)goto err_fm;
\r
800 src_line_head = self->Pixels + stride32 * (self->Info.biHeight - 1);
\r
801 dst_line_head = new_pixels + stride16 * (self->Info.biHeight - 1);
\r
802 src_line_tail_offset = (self->Info.biWidth - 1) * (32/8);
\r
803 dst_line_tail_offset = (self->Info.biWidth - 1) * (16/8);
\r
805 src = src_line_head + src_line_tail_offset;
\r
806 dst = dst_line_head + dst_line_tail_offset;
\r
808 *(uint32_t*)( dst_line_head + stride16 - sizeof(uint32_t) ) = 0; // padding
\r
810 if ( AlphaMask == 0x8000 ) { // ARGB1555
\r
811 while ( src >= src_line_head ) {
\r
812 alpha = *( src + 3 );
\r
813 red = *( src + 2 );
\r
814 green = *( src + 1 );
\r
818 ( ( alpha & 0x80 ) << 8 ) |
\r
819 ( ( red & 0xF8 ) << 7 ) |
\r
820 ( ( green & 0xF8 ) << 2 ) |
\r
821 ( ( blue & 0xF8 ) >> 3 );
\r
828 while ( src >= src_line_head ) {
\r
829 alpha = *( src + 3 );
\r
830 red = *( src + 2 );
\r
831 green = *( src + 1 );
\r
835 ( ( alpha & 0xF0 ) << 8 ) |
\r
836 ( ( red & 0xF0 ) << 4 ) |
\r
837 ( ( green & 0xF0 ) ) |
\r
838 ( ( blue & 0xF0 ) >> 4 );
\r
844 src_line_head -= stride32;
\r
845 dst_line_head -= stride16;
\r
846 } while ( dst_line_head >= new_pixels );
\r
848 self->Pixels = new_pixels;
\r
849 self->Info.biBitCount = 16;
\r
850 self->Stride = stride16;
\r
851 self->Info.biSizeImage = image_size;
\r
852 self->Info.biCompression = BI_BITFIELDS;
\r
853 self->Info.biSize = sizeof(BITMAPINFOHEADER) + 4 * sizeof(uint32_t);
\r
854 if ( AlphaMask == 0x8000 ) {
\r
855 self->RedMask = 0x7C00;
\r
856 self->GreenMask = 0x03E0;
\r
857 self->BlueMask = 0x001F;
\r
858 self->AlphaMask = 0x8000;
\r
861 self->RedMask = 0x0F00;
\r
862 self->GreenMask = 0x00F0;
\r
863 self->BlueMask = 0x000F;
\r
864 self->AlphaMask = 0xF000;
\r
871 if ( new_pixels != NULL ) free( new_pixels );
\r
874 err: e = E_OTHERS; goto fin;
\r
875 err_fm: e = E_FEW_MEMORY; goto fin;
\r
880 /***********************************************************************
\r
881 <<< [BmpFile2Class_convertToARGB4444Format] >>>
\r
882 ************************************************************************/
\r
883 errnum_t BmpFile2Class_convertToARGB4444Format( BmpFile2Class* self )
\r
885 return BmpFile2Class_convertTo16bitARGBFormat( self, 0xF000 );
\r
890 /***********************************************************************
\r
891 <<< [BmpFile2Class_convertToA4Format] >>>
\r
892 ************************************************************************/
\r
893 errnum_t BmpFile2Class_convertToA4Format( BmpFile2Class* self )
\r
896 uint32_t image_size;
\r
897 uint8_t* new_pixels = NULL;
\r
900 uint8_t* src; // source
\r
901 uint8_t* dst; // destination
\r
902 uint8_t* src_line_head;
\r
903 uint8_t* dst_line_head;
\r
904 int src_line_tail_offset;
\r
905 int dst_line_tail_offset;
\r
906 const bool is_width_odd = ( self->Info.biWidth % 2 == 1 );
\r
908 ASSERT_R( self->Info.biBitCount == 24, goto err );
\r
909 ASSERT_R( self->Stride * self->Info.biHeight == self->Info.biSizeImage, goto err );
\r
911 stride24 = self->Stride;
\r
912 stride4 = ( self->Info.biWidth + 1 ) / 2;
\r
913 stride4 = ( stride4 + 3 ) & ~0x3; // 4byte alignment
\r
915 image_size = stride4 * self->Info.biHeight;
\r
916 new_pixels = (uint8_t*) malloc( image_size ); IF(new_pixels==NULL)goto err_fm;
\r
918 src_line_head = self->Pixels + stride24 * (self->Info.biHeight - 1);
\r
919 dst_line_head = new_pixels + stride4 * (self->Info.biHeight - 1);
\r
920 src_line_tail_offset = (self->Info.biWidth - 1) * (24/8);
\r
921 dst_line_tail_offset = (self->Info.biWidth - 1) * 4 / 8;
\r
923 src = src_line_head + src_line_tail_offset;
\r
924 dst = dst_line_head + dst_line_tail_offset;
\r
926 *(uint32_t*)( dst_line_head + stride4 - sizeof(uint32_t) ) = 0; // padding
\r
928 if ( is_width_odd ) {
\r
929 *dst = *( src + 1 ) & 0xF0; // Green
\r
933 while ( src >= src_line_head ) {
\r
934 *dst = ( *( src - 2 ) & 0xF0 ) | ( *( src + 1 ) >> 4 ); // Green
\r
939 src_line_head -= stride24;
\r
940 dst_line_head -= stride4;
\r
941 } while ( dst_line_head >= new_pixels );
\r
943 self->Pixels = new_pixels;
\r
944 self->Info.biBitCount = 4;
\r
945 self->Stride = stride4;
\r
946 self->Info.biSizeImage = image_size;
\r
951 if ( new_pixels != NULL ) free( new_pixels );
\r
954 err: e = E_OTHERS; goto fin;
\r
955 err_fm: e = E_FEW_MEMORY; goto fin;
\r
960 /***********************************************************************
\r
961 <<< [BmpFile2Class_convertToA1Format] >>>
\r
962 ************************************************************************/
\r
963 errnum_t BmpFile2Class_convertToA1Format( BmpFile2Class* self )
\r
966 uint32_t image_size;
\r
967 uint8_t* new_pixels = NULL;
\r
970 uint8_t* src; // source
\r
971 uint8_t* dst; // destination
\r
972 uint8_t* src_line_head;
\r
973 uint8_t* dst_line_head;
\r
974 int src_line_tail_offset;
\r
975 int dst_line_tail_offset;
\r
976 const int width_mod = self->Info.biWidth % 8;
\r
980 ASSERT_R( self->Info.biBitCount == 24, goto err );
\r
981 ASSERT_R( self->Stride * self->Info.biHeight == self->Info.biSizeImage, goto err );
\r
983 stride24 = self->Stride;
\r
984 stride1 = ( self->Info.biWidth + 7 ) / 8;
\r
985 stride1 = ( stride1 + 3 ) & ~0x3; // 4byte alignment
\r
987 image_size = stride1 * self->Info.biHeight;
\r
988 new_pixels = (uint8_t*) malloc( image_size ); IF(new_pixels==NULL)goto err_fm;
\r
990 src_line_head = self->Pixels + stride24 * (self->Info.biHeight - 1);
\r
991 dst_line_head = new_pixels + stride1 * (self->Info.biHeight - 1);
\r
992 src_line_tail_offset = (self->Info.biWidth - 1) * (24/8);
\r
993 dst_line_tail_offset = (self->Info.biWidth - 1) / 8;
\r
995 src = src_line_head + src_line_tail_offset;
\r
996 dst = dst_line_head + dst_line_tail_offset;
\r
998 *(uint32_t*)( dst_line_head + stride1 - sizeof(uint32_t) ) = 0; // padding
\r
1000 if ( width_mod > 0 ) {
\r
1002 for ( x_mod = width_mod - 1; x_mod >= 0; x_mod -= 1 ) {
\r
1003 bits |= ( *( src + 1 ) & 0x80 ) >> x_mod; // Green
\r
1009 while ( src >= src_line_head ) {
\r
1011 ( *( src + 1 ) & 0x80 ) >> 7 | // Green
\r
1012 ( *( src - 2 ) & 0x80 ) >> 6 |
\r
1013 ( *( src - 5 ) & 0x80 ) >> 5 |
\r
1014 ( *( src - 8 ) & 0x80 ) >> 4 |
\r
1015 ( *( src -11 ) & 0x80 ) >> 3 |
\r
1016 ( *( src -14 ) & 0x80 ) >> 2 |
\r
1017 ( *( src -17 ) & 0x80 ) >> 1 |
\r
1018 ( *( src -20 ) & 0x80 );
\r
1023 src_line_head -= stride24;
\r
1024 dst_line_head -= stride1;
\r
1025 } while ( dst_line_head >= new_pixels );
\r
1027 self->Pixels = new_pixels;
\r
1028 self->Info.biBitCount = 1;
\r
1029 self->Stride = stride1;
\r
1030 self->Info.biSizeImage = image_size;
\r
1031 new_pixels = NULL;
\r
1035 if ( new_pixels != NULL ) free( new_pixels );
\r
1038 err: e = E_OTHERS; goto fin;
\r
1039 err_fm: e = E_FEW_MEMORY; goto fin;
\r
1044 /***********************************************************************
\r
1045 <<< [BmpFile2Class_trimming] >>>
\r
1046 ************************************************************************/
\r
1047 errnum_t BmpFile2Class_trimming( BmpFile2Class* self, int LeftX, int TopY, int Width, int Height )
\r
1050 uint8_t* source_left;
\r
1051 uint8_t* source_left_over;
\r
1052 uint8_t* destination_left;
\r
1058 if ( self->Info.biHeight > 0 ) {
\r
1059 TopY = self->Info.biHeight - ( TopY + Height );
\r
1060 height_abs = self->Info.biHeight;
\r
1062 height_abs = - self->Info.biHeight;
\r
1065 ASSERT_R( Width >= 0 && Height >= 0, e=E_OTHERS; goto fin );
\r
1066 ASSERT_R( LeftX >= 0 && LeftX + Width <= self->Info.biWidth, e=E_OTHERS; goto fin );
\r
1067 ASSERT_R( TopY >= 0 && TopY + Height <= height_abs, e=E_OTHERS; goto fin );
\r
1069 source_left = self->Pixels + self->Stride * TopY + LeftX * self->Info.biBitCount / 8;
\r
1070 source_left_over = source_left + self->Stride * height_abs;
\r
1071 destination_left = self->Pixels;
\r
1073 if ( self->Info.biBitCount == 16 ) {
\r
1074 new_stride = ceil_4( Width * 2 );
\r
1075 padding_size = mod_2( Width ) * 2;
\r
1077 IF ( self->Info.biBitCount != 32 ) { e=E_OTHERS; goto fin; }
\r
1078 new_stride = Width * 4;
\r
1082 while ( source_left < source_left_over ) {
\r
1083 memcpy( destination_left, source_left, new_stride );
\r
1084 source_left += self->Stride;
\r
1085 destination_left += new_stride;
\r
1086 memset( destination_left - padding_size, 0x00, padding_size );
\r
1089 self->Info.biWidth = Width;
\r
1090 if ( self->Info.biHeight >= 0 )
\r
1091 { self->Info.biHeight = Height; }
\r
1093 { self->Info.biHeight = - Height; }
\r
1094 self->Stride = new_stride;
\r