OSDN Git Service

Version 5.91
[vbslib/main.git] / _src / Test / tools / T_GPL_Tools / Files / src_for_NaturalDocs / BmpFile2.c
1 /* Character Code Encoding: "WHITE SQUARE" is □ */\r
2 #include  "include_c.h" \r
3 #pragma hdrstop\r
4 \r
5  \r
6 /************************************************************************\r
7 * Function: BmpFile2Class_loadBMP\r
8 *    BMP 形式のファイルを読み込みます。\r
9 *\r
10 * 引数:\r
11 *    Path - BMP file path\r
12 *\r
13 * 返り値:\r
14 *    エラーコード、0=エラーなし\r
15 ************************************************************************/\r
16 /*[BmpFile2Class_loadBMP]*/\r
17 errnum_t  BmpFile2Class_loadBMP( BmpFile2Class* self, const TCHAR* Path )\r
18 {\r
19         BITMAPFILEHEADER  bmp_header;\r
20         errnum_t  e;\r
21         errno_t   en;\r
22         FILE*     file = NULL;\r
23         int       height_abs;\r
24 \r
25 \r
26         en= _tfopen_s( &file, Path, _T("rb") ); IF(en){e=E_ERRNO;goto fin;}\r
27 \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
30 \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
34         } else {\r
35                 self->Stride = ( self->Info.biWidth * self->Info.biBitCount + 7 ) / 8;\r
36         }\r
37         self->Stride = ceil_4( self->Stride );\r
38 \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
44         }\r
45         else if ( self->Info.biBitCount <= 8 ) {\r
46                 int  color_count = 1 << self->Info.biBitCount;\r
47 \r
48                 if ( self->Info.biClrUsed != 0 )\r
49                         { color_count = self->Info.biClrUsed; }\r
50 \r
51                 e= MallocMemory( &self->Palette, color_count * sizeof(RGBQUAD) ); IF(e){goto fin;}\r
52 \r
53                 fread( self->Palette, 1,  color_count * sizeof(RGBQUAD), file );\r
54                         IF(ferror(file)){e=E_ERRNO;goto fin;}\r
55 \r
56                 self->PaletteColorCount = color_count;\r
57         }\r
58 \r
59         height_abs = self->Info.biHeight;\r
60         if ( height_abs < 0 ) { height_abs = -height_abs; }\r
61 \r
62         ASSERT_R( self->Info.biSizeImage == 0  ||\r
63                 self->Info.biSizeImage == self->Stride * height_abs, goto err_og );\r
64 \r
65         if ( self->Info.biSizeImage == 0 )\r
66                 { self->Info.biSizeImage = self->Stride * height_abs; }\r
67 \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
70 \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
73 \r
74         e=0;\r
75 fin:\r
76         e= FileT_closeAndNULL( &file, e );\r
77         if ( e ) {\r
78                 e= FreeMemory( &self->Pixels, e );\r
79         }\r
80         return  e;\r
81 \r
82 err_og:\r
83         Error4_printf( _T("<ERROR msg=\"BITMAPINFOHEADER::biSizeImage is invalid\"/>") );\r
84         e = E_ORIGINAL;\r
85         goto fin;\r
86 }\r
87 \r
88 \r
89  \r
90 /************************************************************************\r
91 * Function: BmpFile2Class_saveBMP\r
92 *    BMP 形式のファイルを書き込みます。\r
93 *\r
94 * 引数:\r
95 *    Path - BMP file path\r
96 *\r
97 * 返り値:\r
98 *    エラーコード、0=エラーなし\r
99 ************************************************************************/\r
100 /*[BmpFile2Class_saveBMP]*/\r
101 errnum_t  BmpFile2Class_saveBMP( BmpFile2Class* self, const TCHAR* Path )\r
102 {\r
103         BITMAPFILEHEADER  bmp_header;\r
104         errnum_t  e;\r
105         errno_t   en;\r
106         FILE*     file = NULL;\r
107         int       mod;\r
108         int       plus;\r
109         int       height_abs;\r
110         int       palette_index;\r
111         int       offset;\r
112         uint32_t  palette[16];  // RGBQUAD type\r
113 \r
114 \r
115         height_abs = self->Info.biHeight;\r
116         if ( height_abs < 0 ) { height_abs = -height_abs; }\r
117 \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
122 \r
123         bmp_header.bfOffBits = 0x36;\r
124         switch ( self->Info.biBitCount ) {\r
125                 case 1:\r
126                         bmp_header.bfSize    +=  2 * sizeof(RGBQUAD);\r
127                         bmp_header.bfOffBits +=  2 * sizeof(RGBQUAD);\r
128                         break;\r
129 \r
130                 case 4:\r
131                         bmp_header.bfSize    += 16 * sizeof(RGBQUAD);\r
132                         bmp_header.bfOffBits += 16 * sizeof(RGBQUAD);\r
133                         break;\r
134 \r
135                 case 8:\r
136                         bmp_header.bfSize    += 256 * sizeof(RGBQUAD);\r
137                         bmp_header.bfOffBits += 256 * sizeof(RGBQUAD);\r
138                         break;\r
139 \r
140                 case 16:\r
141                         bmp_header.bfSize    += 4 * sizeof(RGBQUAD);\r
142                         bmp_header.bfOffBits += 4 * sizeof(RGBQUAD);\r
143                         break;\r
144 \r
145                 case 24:  break;\r
146                 case 32:  break;\r
147 \r
148                 default: ASSERT_R( false,  e=E_OTHERS; goto fin );  break;\r
149         }\r
150         mod = bmp_header.bfOffBits % self->Alignment_bfOffBits;\r
151         if ( mod != 0 ) {\r
152                 plus = - mod + self->Alignment_bfOffBits;\r
153                 bmp_header.bfSize    += plus;\r
154                 bmp_header.bfOffBits += plus;\r
155         }\r
156 \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
161 \r
162         switch ( self->Info.biBitCount ) {\r
163          case 1:\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
166                 break;\r
167          case 4:\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
173                 break;\r
174          case 8:\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
179                         }\r
180                         fwrite( palette, 16, sizeof(*palette), file ); IF(ferror(file)){e=E_ERRNO;goto fin;}\r
181                 }\r
182                 break;\r
183          case 16:\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
187                 break;\r
188         }\r
189 \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
193 \r
194         e=0;\r
195 fin:\r
196         if ( file != NULL )  fclose( file );\r
197         return  e;\r
198 }\r
199 \r
200 \r
201  \r
202 /***********************************************************************\r
203   <<< [BmpFile2Class_finish] >>> \r
204 ************************************************************************/\r
205 errnum_t  BmpFile2Class_finish( BmpFile2Class* self, errnum_t e )\r
206 {\r
207         e= FreeMemory( &self->Pixels, e );\r
208         e= FreeMemory( &self->Palette, e );\r
209         return  e;\r
210 }\r
211 \r
212  \r
213 /***********************************************************************\r
214   <<< [BmpFile2Class_loadRaw16bit_Sub] >>> \r
215 ************************************************************************/\r
216 errnum_t  BmpFile2Class_loadRaw16bit_Sub( BmpFile2Class* self, TCHAR* Path, int Stride )\r
217 {\r
218         FILE*     file = NULL;\r
219         errno_t   en;\r
220         errnum_t  e;\r
221         size_t    raw_size;\r
222 \r
223         ASSERT_R( Stride % 4 == 0,  e=E_OTHERS; goto fin );\r
224 \r
225         en= _tfopen_s( &file, Path, _T("rb") ); IF(en){ e=E_ERRNO; goto fin; }\r
226 \r
227         fseek( file, 0, SEEK_END );\r
228         raw_size = ftell( file );\r
229         fseek( file, 0, SEEK_SET );\r
230 \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
234 \r
235         fread( self->Pixels, 1, raw_size, file );\r
236 \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
253 \r
254         e=0;\r
255 fin:\r
256         if ( file != NULL )  fclose( file );\r
257         if ( e ) {\r
258                 if ( self->Pixels != NULL )  free( self->Pixels );\r
259                 self->Pixels = NULL;\r
260         }\r
261         return  e;\r
262 }\r
263 \r
264 \r
265  \r
266 /***********************************************************************\r
267   <<< [BmpFile2Class_loadRawRGB565] >>> \r
268 ************************************************************************/\r
269 errnum_t  BmpFile2Class_loadRawRGB565( BmpFile2Class* self, TCHAR* Path, int Stride )\r
270 {\r
271         errnum_t  e;\r
272 \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
278 \r
279         return  e;\r
280 }\r
281 \r
282 \r
283  \r
284 /***********************************************************************\r
285   <<< [BmpFile2Class_loadRawARGB8888] >>> \r
286 ************************************************************************/\r
287 errnum_t  BmpFile2Class_loadRawARGB8888( BmpFile2Class* self, TCHAR* Path, int Stride )\r
288 {\r
289         FILE*     file = NULL;\r
290         errno_t   en;\r
291         errnum_t  e;\r
292         size_t    raw_size;\r
293 \r
294         ASSERT_R( Stride % 4 == 0,  e=E_OTHERS; goto fin );\r
295 \r
296         en= _tfopen_s( &file, Path, _T("rb") ); IF(en){ e=E_ERRNO; goto fin; }\r
297 \r
298         fseek( file, 0, SEEK_END );\r
299         raw_size = ftell( file );\r
300         fseek( file, 0, SEEK_SET );\r
301 \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
305 \r
306         fread( self->Pixels, 1, raw_size, file );\r
307 \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
319         self->RedMask   = 0;\r
320         self->GreenMask = 0;\r
321         self->BlueMask  = 0;\r
322         self->AlphaMask = 0;\r
323         self->Stride = Stride;\r
324 \r
325         e=0;\r
326 fin:\r
327         if ( file != NULL )  fclose( file );\r
328         if ( e ) {\r
329                 if ( self->Pixels != NULL )  free( self->Pixels );\r
330                 self->Pixels = NULL;\r
331         }\r
332         return  e;\r
333 }\r
334 \r
335 \r
336  \r
337 /***********************************************************************\r
338   <<< [BmpFile2Class_loadRawARGB1555] >>> \r
339 ************************************************************************/\r
340 errnum_t  BmpFile2Class_loadRawARGB1555( BmpFile2Class* self, TCHAR* Path, int Stride )\r
341 {\r
342         errnum_t  e;\r
343 \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
349 \r
350         return  e;\r
351 }\r
352 \r
353 \r
354  \r
355 /***********************************************************************\r
356   <<< [BmpFile2Class_loadRawARGB4444] >>> \r
357 ************************************************************************/\r
358 errnum_t  BmpFile2Class_loadRawARGB4444( BmpFile2Class* self, TCHAR* Path, int Stride )\r
359 {\r
360         errnum_t  e;\r
361 \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
367 \r
368         return  e;\r
369 }\r
370 \r
371 \r
372  \r
373 /***********************************************************************\r
374   <<< [BmpFile2Class_loadPNG] >>> \r
375 ************************************************************************/\r
376 errnum_t  BmpFile2Class_loadPNG( BmpFile2Class* self, const TCHAR* Path )\r
377 {\r
378         FILE*        f = NULL;\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
383         int          ret = 0;\r
384         errno_t      en;\r
385         errnum_t     e;\r
386 \r
387 \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
391 \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
396 \r
397         png_init_io( png, f );\r
398 \r
399 \r
400         /* Read Information */\r
401         {\r
402                 png_read_info( png, info );\r
403 \r
404                 self->Stride = png_get_rowbytes( png, info );\r
405                 self->Stride = ceil_4( self->Stride );\r
406 \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
411 \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
420                 }\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
427         }\r
428 \r
429         /* Read Pixels */\r
430         {\r
431                 int  i;\r
432                 uint8_t*       left_of_line;\r
433                 uint_fast32_t  stride = self->Stride;\r
434 \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
438 \r
439                 left_of_line = self->Pixels;\r
440 \r
441                 for ( i = self->Info.biHeight - 1;  i >= 0;  i -= 1 ) {\r
442                         lines[ i ] = left_of_line;\r
443 \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
447 \r
448                         left_of_line += stride;\r
449                 }\r
450 \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
454         }\r
455 \r
456 fin:\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
462 \r
463         if ( e ) {\r
464                 self->Info.biWidth  = 0;\r
465                 self->Info.biHeight = 0;\r
466                 e= HeapMemory_free( &self->Pixels, e );\r
467         }\r
468 \r
469         return  ret;\r
470 \r
471 err:     e = E_OTHERS;  goto fin;\r
472 err_no:  e = E_ERRNO;   goto fin;\r
473 }\r
474 \r
475 \r
476  \r
477 /***********************************************************************\r
478   <<< [BmpFile2Class_loadJPEG] >>> \r
479 ************************************************************************/\r
480 #ifndef  LibJPEG_is\r
481 #define  LibJPEG_is  LibJPEG_is_DLL\r
482 #endif\r
483 #define  LibJPEG_is_Lib  1\r
484 #define  LibJPEG_is_DLL  2\r
485 \r
486 errnum_t  BmpFile2Class_loadJPEG( BmpFile2Class* self, const TCHAR* Path )\r
487 {\r
488         struct jpeg_decompress_struct  jpeg_decompress;\r
489         struct jpeg_error_mgr          jpeg_error;\r
490         errnum_t  e;\r
491         FILE*     file = NULL;\r
492         errno_t   en;\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
501         int       jpeg_size;\r
502         int       read_size;\r
503 #endif\r
504 \r
505         en = _tfopen_s( &file, Path, _T("rb") ); IF(en){ e=E_ERRNO; goto fin; }\r
506 \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
519         #else\r
520                 jpeg_stdio_src( &jpeg_decompress, file );\r
521         #endif\r
522         jpeg_read_header( &jpeg_decompress, TRUE );\r
523 \r
524         ASSERT_R( jpeg_decompress.num_components == 3, e=E_OTHERS; goto fin );\r
525 \r
526         width_byte = jpeg_decompress.image_width * jpeg_decompress.num_components;\r
527         width_stride = ceil_4( width_byte );\r
528 \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
532 \r
533 \r
534         // set pixel_line_pointers\r
535         {\r
536                 char*   p;\r
537                 char**  pp;\r
538                 char**  pp_over;\r
539 \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
543 \r
544                 p = pixels;\r
545                 pp_over = pixel_line_pointers + jpeg_decompress.image_height;\r
546 \r
547                 for ( pp = pp_over - 1;  pp >= pixel_line_pointers;  pp -- ) {\r
548                         *pp = p;\r
549                         p += width_stride;\r
550                         *(int*)( p - 4 ) = 0;  // fill zero to padding area at right of line\r
551                 }\r
552         }\r
553 \r
554 \r
555         // read pixels\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
560                 char**  pp_over;\r
561 \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
565 \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
569                         char*   p = *pp;\r
570                         char*   p_over = p + width_byte;\r
571 \r
572                         for ( ;  p < p_over;  p += jpeg_decompress.num_components ) {\r
573                                 char  value;\r
574 \r
575                                 value = *( p + 0 );\r
576                                 *( p + 0 ) = *( p + 2 );\r
577                                 *( p + 2 ) = value;\r
578                         }\r
579                 }\r
580         }\r
581 \r
582 \r
583         /* set self attributes */\r
584         {\r
585                 self->Stride = width_stride;\r
586 \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
599         }\r
600 \r
601         e=0;\r
602 fin:\r
603         if ( e ) {\r
604                 if ( pixels != NULL )  free( pixels );\r
605         }\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
612         #endif\r
613         return  e;\r
614 }\r
615 \r
616 \r
617  \r
618 /***********************************************************************\r
619   <<< [BmpFile2Class_addAlphaChannel] >>> \r
620 ************************************************************************/\r
621 errnum_t  BmpFile2Class_addAlphaChannel( BmpFile2Class* self, uint8_t AlphaValue )\r
622 {\r
623         errnum_t  e;\r
624         uint32_t  image_size;\r
625         uint8_t*  new_pixels;\r
626         unsigned  stride24;\r
627         unsigned  stride32;\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
634 \r
635         if ( self->Info.biBitCount == 32 )  return  0;\r
636 \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
639 \r
640         stride24 = self->Stride;\r
641         stride32 = self->Info.biWidth * 4;\r
642 \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
646 \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
651 \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
656         do {\r
657                 src = src_line_head + src_line_tail_offset;\r
658                 dst = dst_line_head + dst_line_tail_offset;\r
659                 do {\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
664                         src -= (24/8);\r
665                         dst -= (32/8);\r
666                 } while ( src >= src_line_head );\r
667 \r
668                 src_line_head -= stride24;\r
669                 dst_line_head -= stride32;\r
670         } while ( src_line_head >= new_pixels );\r
671 \r
672         e=0;\r
673 fin:\r
674         return  e;\r
675 \r
676 err:     e = E_OTHERS;     goto fin;\r
677 err_fm:  e = E_FEW_MEMORY;  goto fin;\r
678 }\r
679 \r
680 \r
681  \r
682 /***********************************************************************\r
683   <<< [BmpFile2Class_convertToRGB565Format] >>> \r
684 ************************************************************************/\r
685 errnum_t  BmpFile2Class_convertToRGB565Format( BmpFile2Class* self )\r
686 {\r
687         errnum_t  e;\r
688         uint32_t  image_size;\r
689         uint8_t*  new_pixels = NULL;\r
690         unsigned  src_stride;\r
691         unsigned  stride16;\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
700 \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
703 \r
704         src_stride = self->Stride;\r
705         stride16 = self->Info.biWidth * 2;\r
706         stride16 = ( stride16 + 3 ) & ~0x3;  // 4byte alignment\r
707 \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
710 \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
716         do {\r
717                 src = src_line_head + src_line_tail_offset;\r
718                 dst = dst_line_head + dst_line_tail_offset;\r
719 \r
720                 *(uint32_t*)( dst_line_head + stride16 - sizeof(uint32_t) ) = 0;  // padding\r
721 \r
722                 while ( src >= src_line_head ) {\r
723                         red   = *( src + 2 );\r
724                         green = *( src + 1 );\r
725                         blue  = *( src );\r
726 \r
727                         *(uint16_t*) dst =\r
728                                 ( ( red   & 0xF8 ) << 8 ) |\r
729                                 ( ( green & 0xFC ) << 3 ) |\r
730                                 ( ( blue  & 0xF8 ) >> 3 );\r
731 \r
732                         src -= src_byte_per_pixel;\r
733                         dst -= 2;\r
734                 }\r
735                 src_line_head -= src_stride;\r
736                 dst_line_head -= stride16;\r
737         } while ( dst_line_head >= new_pixels );\r
738 \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
749 \r
750         new_pixels = NULL;\r
751 \r
752         e=0;\r
753 fin:\r
754         if ( new_pixels != NULL )  free( new_pixels );\r
755         return  e;\r
756 \r
757 err:     e = E_OTHERS;     goto fin;\r
758 err_fm:  e = E_FEW_MEMORY;  goto fin;\r
759 }\r
760 \r
761 \r
762  \r
763 /***********************************************************************\r
764   <<< [BmpFile2Class_convertToARGB1555Format] >>> \r
765 ************************************************************************/\r
766 errnum_t  BmpFile2Class_convertTo16bitARGBFormat( BmpFile2Class* self, uint16_t AlphaMask );\r
767 \r
768 errnum_t  BmpFile2Class_convertToARGB1555Format( BmpFile2Class* self )\r
769 {\r
770         return  BmpFile2Class_convertTo16bitARGBFormat( self, 0x8000 );\r
771 }\r
772 \r
773 errnum_t  BmpFile2Class_convertTo16bitARGBFormat( BmpFile2Class* self, uint16_t AlphaMask )\r
774 {\r
775         errnum_t  e;\r
776         uint32_t  image_size;\r
777         uint8_t*  new_pixels = NULL;\r
778         unsigned  stride32;\r
779         unsigned  stride16;\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
787 \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
792 \r
793         stride32 = self->Stride;\r
794         stride16 = self->Info.biWidth * 2;\r
795         stride16 = ( stride16 + 3 ) & ~0x3;  // 4byte alignment\r
796 \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
799 \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
804         do {\r
805                 src = src_line_head + src_line_tail_offset;\r
806                 dst = dst_line_head + dst_line_tail_offset;\r
807 \r
808                 *(uint32_t*)( dst_line_head + stride16 - sizeof(uint32_t) ) = 0;  // padding\r
809 \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
815                                 blue  = *( src );\r
816 \r
817                                 *(uint16_t*) dst =\r
818                                         ( ( alpha & 0x80 ) << 8 ) |\r
819                                         ( ( red   & 0xF8 ) << 7 ) |\r
820                                         ( ( green & 0xF8 ) << 2 ) |\r
821                                         ( ( blue  & 0xF8 ) >> 3 );\r
822 \r
823                                 src -= 4;\r
824                                 dst -= 2;\r
825                         }\r
826                 }\r
827                 else {  // ARGB4444\r
828                         while ( src >= src_line_head ) {\r
829                                 alpha = *( src + 3 );\r
830                                 red   = *( src + 2 );\r
831                                 green = *( src + 1 );\r
832                                 blue  = *( src );\r
833 \r
834                                 *(uint16_t*) dst =\r
835                                         ( ( alpha & 0xF0 ) << 8 ) |\r
836                                         ( ( red   & 0xF0 ) << 4 ) |\r
837                                         ( ( green & 0xF0 ) ) |\r
838                                         ( ( blue  & 0xF0 ) >> 4 );\r
839 \r
840                                 src -= 4;\r
841                                 dst -= 2;\r
842                         }\r
843                 }\r
844                 src_line_head -= stride32;\r
845                 dst_line_head -= stride16;\r
846         } while ( dst_line_head >= new_pixels );\r
847 \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
859         }\r
860         else {\r
861                 self->RedMask   = 0x0F00;\r
862                 self->GreenMask = 0x00F0;\r
863                 self->BlueMask  = 0x000F;\r
864                 self->AlphaMask = 0xF000;\r
865         }\r
866 \r
867         new_pixels = NULL;\r
868 \r
869         e=0;\r
870 fin:\r
871         if ( new_pixels != NULL )  free( new_pixels );\r
872         return  e;\r
873 \r
874 err:     e = E_OTHERS;     goto fin;\r
875 err_fm:  e = E_FEW_MEMORY;  goto fin;\r
876 }\r
877 \r
878 \r
879  \r
880 /***********************************************************************\r
881   <<< [BmpFile2Class_convertToARGB4444Format] >>> \r
882 ************************************************************************/\r
883 errnum_t  BmpFile2Class_convertToARGB4444Format( BmpFile2Class* self )\r
884 {\r
885         return  BmpFile2Class_convertTo16bitARGBFormat( self, 0xF000 );\r
886 }\r
887 \r
888 \r
889  \r
890 /***********************************************************************\r
891   <<< [BmpFile2Class_convertToA4Format] >>> \r
892 ************************************************************************/\r
893 errnum_t  BmpFile2Class_convertToA4Format( BmpFile2Class* self )\r
894 {\r
895         errnum_t  e;\r
896         uint32_t  image_size;\r
897         uint8_t*  new_pixels = NULL;\r
898         unsigned  stride24;\r
899         unsigned  stride4;\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
907 \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
910 \r
911         stride24 = self->Stride;\r
912         stride4  = ( self->Info.biWidth + 1 ) / 2;\r
913         stride4  = ( stride4 + 3 ) & ~0x3;  // 4byte alignment\r
914 \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
917 \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
922         do {\r
923                 src = src_line_head + src_line_tail_offset;\r
924                 dst = dst_line_head + dst_line_tail_offset;\r
925 \r
926                 *(uint32_t*)( dst_line_head + stride4 - sizeof(uint32_t) ) = 0;  // padding\r
927 \r
928                 if ( is_width_odd ) {\r
929                         *dst = *( src + 1 ) & 0xF0;  // Green\r
930                         src -= (24/8);\r
931                         dst -= 1;\r
932                 }\r
933                 while ( src >= src_line_head ) {\r
934                         *dst = ( *( src - 2 ) & 0xF0 ) | ( *( src + 1 ) >> 4 );  // Green\r
935                         src -= 2*(24/8);\r
936                         dst -= 1;\r
937                 }\r
938 \r
939                 src_line_head -= stride24;\r
940                 dst_line_head -= stride4;\r
941         } while ( dst_line_head >= new_pixels );\r
942 \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
947         new_pixels = NULL;\r
948 \r
949         e=0;\r
950 fin:\r
951         if ( new_pixels != NULL )  free( new_pixels );\r
952         return  e;\r
953 \r
954 err:     e = E_OTHERS;     goto fin;\r
955 err_fm:  e = E_FEW_MEMORY;  goto fin;\r
956 }\r
957 \r
958 \r
959  \r
960 /***********************************************************************\r
961   <<< [BmpFile2Class_convertToA1Format] >>> \r
962 ************************************************************************/\r
963 errnum_t  BmpFile2Class_convertToA1Format( BmpFile2Class* self )\r
964 {\r
965         errnum_t  e;\r
966         uint32_t  image_size;\r
967         uint8_t*  new_pixels = NULL;\r
968         unsigned  stride24;\r
969         unsigned  stride1;\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
977         int       x_mod;\r
978         uint8_t   bits;\r
979 \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
982 \r
983         stride24 = self->Stride;\r
984         stride1  = ( self->Info.biWidth + 7 ) / 8;\r
985         stride1  = ( stride1 + 3 ) & ~0x3;  // 4byte alignment\r
986 \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
989 \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
994         do {\r
995                 src = src_line_head + src_line_tail_offset;\r
996                 dst = dst_line_head + dst_line_tail_offset;\r
997 \r
998                 *(uint32_t*)( dst_line_head + stride1 - sizeof(uint32_t) ) = 0;  // padding\r
999 \r
1000                 if ( width_mod > 0 ) {\r
1001                         bits = 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
1004                                 src -= (24/8);\r
1005                         }\r
1006                         *dst = bits;\r
1007                         dst -= 1;\r
1008                 }\r
1009                 while ( src >= src_line_head ) {\r
1010                         *dst =\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
1019 \r
1020                         src -= 8*(24/8);\r
1021                         dst -= 1;\r
1022                 }\r
1023                 src_line_head -= stride24;\r
1024                 dst_line_head -= stride1;\r
1025         } while ( dst_line_head >= new_pixels );\r
1026 \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
1032 \r
1033         e=0;\r
1034 fin:\r
1035         if ( new_pixels != NULL )  free( new_pixels );\r
1036         return  e;\r
1037 \r
1038 err:     e = E_OTHERS;     goto fin;\r
1039 err_fm:  e = E_FEW_MEMORY;  goto fin;\r
1040 }\r
1041 \r
1042 \r
1043  \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
1048 {\r
1049         errnum_t  e;\r
1050         uint8_t*  source_left;\r
1051         uint8_t*  source_left_over;\r
1052         uint8_t*  destination_left;\r
1053         int       new_stride;\r
1054         int       padding_size;\r
1055         int       height_abs;\r
1056 \r
1057 \r
1058         if ( self->Info.biHeight > 0 ) {\r
1059                 TopY = self->Info.biHeight - ( TopY + Height );\r
1060                 height_abs = self->Info.biHeight;\r
1061         } else {\r
1062                 height_abs = - self->Info.biHeight;\r
1063         }\r
1064 \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
1068 \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
1072 \r
1073         if ( self->Info.biBitCount == 16 ) {\r
1074                 new_stride = ceil_4( Width * 2 );\r
1075                 padding_size = mod_2( Width ) * 2;\r
1076         } else {\r
1077                 IF ( self->Info.biBitCount != 32 ) { e=E_OTHERS; goto fin; }\r
1078                 new_stride = Width * 4;\r
1079                 padding_size = 0;\r
1080         }\r
1081 \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
1087         }\r
1088 \r
1089         self->Info.biWidth = Width;\r
1090         if ( self->Info.biHeight >= 0 )\r
1091                 { self->Info.biHeight = Height; }\r
1092         else\r
1093                 { self->Info.biHeight = - Height; }\r
1094         self->Stride = new_stride;\r
1095 \r
1096         e=0;\r
1097 fin:\r
1098         return  e;\r
1099 }\r
1100 \r
1101 \r
1102  \r