1 /*$
2 Copyright (C) 2013-2020 Azel.
3
4 This file is part of AzPainter.
5
6 AzPainter is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 AzPainter is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 $*/
19
20 /*****************************************
21 * BMP 読み込み関数
22 *****************************************/
23
24 #include <string.h>
25
26 #include "mDef.h"
27 #include "mLoadImage.h"
28
29 #include "mIOFileBuf.h"
30 #include "mUtil.h"
31
32
33 //--------------------
34
35 typedef struct
36 {
37 mLoadImage *param;
38
39 mIOFileBuf *io;
40 uint8_t *rawbuf, //Y1行分の生バッファ
41 *convbuf, //変換後のバッファ
42 *palbuf, //パレットバッファ [R-G-B-A]
43 *rlebuf, //RLE 用バッファ
44 *rlebuf_end, //RLE バッファ終端位置
45 *rlebuf_cur; //RLE バッファ現在位置
46
47 int bits, //BMP ビット数 (1,4,8,16,24,32)
48 palnum, //パレット数
49 compression, //BMP圧縮タイプ
50 maxR,maxG,maxB,maxA, //16bit 各色の最大値
51 convtype; //イメージ変換タイプ
52
53 uint32_t maskR,maskG,maskB,maskA; //各色のビットマスク (0 で常に 0。A の場合は 0 なら不透明)
54 uint8_t shiftR,shiftG,shiftB,shiftA,
55 morethan_ver4, //ver4 以降か
56 end_of_bmp, //RLE で EOB が出現したか
57 rle_eof; //RLE ファイルの最後まで読み込んだか
58 }_LOADBMP;
59
60 //--------------------
61
62 #define BI_RGB 0
63 #define BI_RLE8 1
64 #define BI_RLE4 2
65 #define BI_BITFIELDS 3
66
67 #define RET_OK 0
68 #define RET_ERR_NOMES -1 //メッセージはセット済み
69
70 #define RLE_BUFSIZE 1024
71
72 enum
73 {
74 CONVTYPE_PALETTE,
75 CONVTYPE_24BIT,
76 CONVTYPE_32BIT_BGRA,
77 CONVTYPE_BITFIELDS
78 };
79
80 //--------------------
81
82
83 //=======================
84 // 読み込み
85 //=======================
86
87
88 /** ファイルヘッダ読み込み */
89
_read_fileheader(_LOADBMP * p)90 static int _read_fileheader(_LOADBMP *p)
91 {
92 uint8_t d[14];
93 int size;
94
95 size = mIOFileBuf_read(p->io, d, 14);
96
97 //BMP ではない
98
99 if(size < 2 || d[0] != 'B' || d[1] != 'M')
100 {
101 mLoadImage_setMessage(p->param, "This is not BMP");
102 return RET_ERR_NOMES;
103 }
104
105 //データが足りない
106
107 if(size != 14)
108 return MLOADIMAGE_ERR_CORRUPT;
109
110 return RET_OK;
111 }
112
113 /** マスク値からシフト値と値の最大値取得 */
114
_get_maskvalue(uint32_t mask,uint8_t * shift,int * max)115 static void _get_maskvalue(uint32_t mask,uint8_t *shift,int *max)
116 {
117 if(mask == 0)
118 {
119 *shift = 0;
120 *max = 0;
121 }
122 else
123 {
124 *shift = mGetBitOnPos(mask);
125 *max = (1 << mGetBitOffPos(mask >> *shift)) - 1;
126 }
127 }
128
129 /** ビットフィールド読み込み/セット */
130
_read_bitfield(_LOADBMP * p,int * readbytes)131 static int _read_bitfield(_LOADBMP *p,int *readbytes)
132 {
133 uint8_t d[16];
134 int size;
135
136 //RGBA マスク値
137
138 if(p->compression == BI_BITFIELDS)
139 {
140 //指定あり (V4 以降ならアルファ値のマスクもある)
141
142 size = (p->morethan_ver4)? 16: 12;
143
144 if(!mIOFileBuf_readSize(p->io, d, size))
145 return MLOADIMAGE_ERR_CORRUPT;
146
147 p->maskR = mGetBuf32LE(d);
148 p->maskG = mGetBuf32LE(d + 4);
149 p->maskB = mGetBuf32LE(d + 8);
150
151 if(size == 16)
152 {
153 p->maskA = mGetBuf32LE(d + 12);
154
155 _get_maskvalue(p->maskA, &p->shiftA, &p->maxA);
156 }
157
158 *readbytes = size;
159 }
160 else
161 {
162 //指定なし = デフォルト値 (アルファマスクなし)
163
164 if(p->bits == 16)
165 {
166 p->maskR = 0x7c00;
167 p->maskG = 0x03e0;
168 p->maskB = 0x001f;
169 }
170 else
171 {
172 p->maskR = 0xff0000;
173 p->maskG = 0x00ff00;
174 p->maskB = 0x0000ff;
175 }
176 }
177
178 //RGB 各パラメータ
179
180 _get_maskvalue(p->maskR, &p->shiftR, &p->maxR);
181 _get_maskvalue(p->maskG, &p->shiftG, &p->maxG);
182 _get_maskvalue(p->maskB, &p->shiftB, &p->maxB);
183
184 return RET_OK;
185 }
186
187 /** 情報ヘッダ読み込み */
188
_read_infoheader(_LOADBMP * p,mLoadImageInfo * info)189 static int _read_infoheader(_LOADBMP *p,mLoadImageInfo *info)
190 {
191 uint8_t d[40];
192 int width,height,n,readbytes;
193 uint32_t headersize,clrused;
194
195 //読み込み
196
197 if(!mIOFileBuf_readSize(p->io, d, 40))
198 return MLOADIMAGE_ERR_CORRUPT;
199
200 mConvertEndianBuf(d, -1, "44422444444");
201
202 //------ 基本情報
203
204 //ヘッダサイズ
205
206 headersize = M_BUF_UINT32(d);
207 if(headersize < 40) return MLOADIMAGE_ERR_UNSUPPORTED; //OS/2 は非対応
208
209 p->morethan_ver4 = (headersize >= 108);
210
211 //圧縮形式
212
213 n = p->compression = M_BUF_UINT32(d + 16);
214
215 if(n < 0 || n > BI_BITFIELDS)
216 return MLOADIMAGE_ERR_UNSUPPORTED;
217
218 //幅・高さ
219
220 width = M_BUF_UINT32(d + 4);
221 height = M_BUF_UINT32(d + 8);
222
223 if(width <= 0 || height == 0)
224 return MLOADIMAGE_ERR_INVALID_VALUE;
225
226 if(height < 0)
227 {
228 //トップダウン
229 height = -height;
230 info->bottomup = FALSE;
231 }
232 else
233 info->bottomup = TRUE;
234
235 if((p->param->max_width > 0 && width > p->param->max_width)
236 || (p->param->max_height > 0 && height > p->param->max_height))
237 return MLOADIMAGE_ERR_LARGE_SIZE;
238
239 info->width = width;
240 info->height = height;
241
242 //ビット数
243
244 n = M_BUF_UINT16(d + 14);
245
246 if(n != 1 && n != 4 && n != 8 && n != 16 && n != 24 && n != 32)
247 return MLOADIMAGE_ERR_INVALID_VALUE;
248
249 p->bits = n;
250
251 //解像度
252
253 info->resolution_unit = MLOADIMAGE_RESOLITION_UNIT_DPM;
254 info->resolution_horz = M_BUF_UINT32(d + 24);
255 info->resolution_vert = M_BUF_UINT32(d + 28);
256
257 //パレット数
258
259 n = clrused = M_BUF_UINT32(d + 32);
260
261 if(p->bits >= 24)
262 n = 0;
263 else if(n == 0)
264 n = 1 << p->bits;
265 else if(n > (1 << p->bits))
266 return MLOADIMAGE_ERR_INVALID_VALUE;
267
268 p->palnum = n;
269
270 //------- 他データ
271
272 //ビットフィールド
273
274 if(p->bits == 16 || p->bits == 32)
275 {
276 if((n = _read_bitfield(p, &readbytes)))
277 return n;
278 }
279
280 //次の位置へ (パレット or イメージ)
281
282 n = headersize - 40;
283 if(p->compression == BI_BITFIELDS) n -= readbytes;
284
285 mIOFileBuf_readEmpty(p->io, n);
286
287 //16bit 以上の場合、カラーテーブルをスキップ
288
289 if(p->bits >= 16 && clrused)
290 {
291 if(!mIOFileBuf_readEmpty(p->io, clrused << 2))
292 return MLOADIMAGE_ERR_CORRUPT;
293 }
294
295 //------- 情報セット
296
297 info->sample_bits = 8;
298 info->raw_sample_bits = 8;
299 info->raw_bits = p->bits;
300 info->raw_pitch = (((info->width * p->bits + 7) >> 3) + 3) & (~3);
301
302 //カラータイプ
303
304 if(p->bits <= 8)
305 info->raw_coltype = MLOADIMAGE_COLTYPE_PALETTE;
306 else if(p->maskA)
307 info->raw_coltype = MLOADIMAGE_COLTYPE_RGBA;
308 else
309 info->raw_coltype = MLOADIMAGE_COLTYPE_RGB;
310
311 //イメージ変換タイプ
312
313 if(p->bits <= 8)
314 p->convtype = CONVTYPE_PALETTE;
315 else if(p->bits == 24)
316 p->convtype = CONVTYPE_24BIT;
317 else if(p->bits == 32
318 && p->maskR == 0xff0000 && p->maskG == 0x00ff00 && p->maskB == 0x0000ff)
319 p->convtype = CONVTYPE_32BIT_BGRA;
320 else
321 p->convtype = CONVTYPE_BITFIELDS;
322
323 return RET_OK;
324 }
325
326 /** パレット読み込み */
327
_read_palette(_LOADBMP * p)328 static int _read_palette(_LOADBMP *p)
329 {
330 int i,size;
331 uint8_t *ppal,tmp;
332
333 size = p->palnum << 2;
334
335 //確保
336
337 p->palbuf = (uint8_t *)mMalloc(size, FALSE);
338 if(!p->palbuf) return MLOADIMAGE_ERR_ALLOC;
339
340 //読み込み
341
342 if(!mIOFileBuf_readSize(p->io, p->palbuf, size))
343 return MLOADIMAGE_ERR_CORRUPT;
344
345 //RGB 順入れ替え (BGRA => RGBA)
346
347 ppal = p->palbuf;
348
349 for(i = p->palnum; i > 0; i--, ppal += 4)
350 {
351 tmp = ppal[0];
352 ppal[0] = ppal[2];
353 ppal[2] = tmp;
354 ppal[3] = 255;
355 }
356
357 return RET_OK;
358 }
359
360
361 //===========================
362 // RLE 展開
363 //===========================
364
365
366 /** RLE バッファに読み込み */
367
_read_to_rlebuf(_LOADBMP * p)368 static int _read_to_rlebuf(_LOADBMP *p)
369 {
370 int remain,read;
371
372 remain = p->rlebuf_end - p->rlebuf_cur;
373
374 if(p->rle_eof)
375 {
376 //ファイルの最後まで読み込んだ
377
378 return (remain < 2)? MLOADIMAGE_ERR_CORRUPT: RET_OK;
379 }
380 else
381 {
382 //残りが 258byte 未満なら読み込み
383 /* 非連続データの最大が 258byte なので、最大サイズ分を読み込んでおく */
384
385 if(remain < 258)
386 {
387 memmove(p->rlebuf, p->rlebuf_cur, remain);
388
389 read = mIOFileBuf_read(p->io, p->rlebuf + remain, RLE_BUFSIZE - remain);
390
391 if(read < RLE_BUFSIZE - remain)
392 p->rle_eof = TRUE;
393
394 remain += read;
395 if(remain < 2) return MLOADIMAGE_ERR_CORRUPT;
396
397 p->rlebuf_end = p->rlebuf + remain;
398 p->rlebuf_cur = p->rlebuf;
399 }
400
401 return RET_OK;
402 }
403 }
404
405 /** RLE 展開 (4bit) */
406
_decompress_rle4(_LOADBMP * p)407 static int _decompress_rle4(_LOADBMP *p)
408 {
409 uint8_t *pd,*ps,b1,b2,val;
410 int ret,width,x = 0,len,bytes,bytes_wd;
411
412 pd = p->rawbuf;
413 width = (p->param->info.width + 1) & (~1); //奇数幅での +1px は許容
414
415 while(1)
416 {
417 //読み込み
418
419 ret = _read_to_rlebuf(p);
420 if(ret) return ret;
421
422 //2byte データ
423
424 b1 = p->rlebuf_cur[0];
425 b2 = p->rlebuf_cur[1];
426 p->rlebuf_cur += 2;
427
428 //
429
430 if(b1 != 0)
431 {
432 //---- 連続データ ([1-255] + データ)
433
434 len = b1;
435 if(x + len > width) return MLOADIMAGE_ERR_DECODE;
436
437 //出力位置が下位4bitの場合
438
439 if(x & 1)
440 {
441 *(pd++) |= b2 >> 4;
442 b2 = (b2 >> 4) | ((b2 & 15) << 4);
443 len--;
444 }
445
446 //2px単位で出力
447
448 for(; len > 0; len -= 2)
449 *(pd++) = b2;
450
451 //余分に出力した場合は 1px 戻る
452
453 if(len == -1)
454 *(--pd) &= 0xf0;
455
456 x += b1;
457 }
458 else if(b2 == 0 || b2 == 1)
459 {
460 //行終わり (0 + 0) or イメージ終わり (0 + 1)
461
462 memset(pd, 0, p->param->info.raw_pitch - (x + 1) / 2);
463 if(b2 == 1) p->end_of_bmp = TRUE;
464
465 break;
466 }
467 else if(b2 == 2)
468 //位置移動 (0 + 2) は非対応
469 return MLOADIMAGE_ERR_UNSUPPORTED;
470 else
471 {
472 //----- 非連続データ (0 + [3-255] + データxlen)
473
474 len = b2;
475 bytes = (len + 1) >> 1;
476 bytes_wd = (bytes + 1) & (~1); //データは2byte境界
477
478 if(x + len > width) return MLOADIMAGE_ERR_DECODE;
479
480 if(p->rlebuf_end - p->rlebuf_cur < bytes_wd)
481 return MLOADIMAGE_ERR_CORRUPT;
482
483 ps = p->rlebuf_cur;
484
485 if(x & 1)
486 {
487 //出力先の先頭が下位4bit
488
489 for(; len > 0; len -= 2)
490 {
491 val = *(ps++);
492
493 *(pd++) |= val >> 4;
494 if(len != 1) *pd = (val & 15) << 4;
495 }
496 }
497 else
498 {
499 //先頭が上位4bit
500
501 memcpy(pd, ps, bytes);
502
503 pd += bytes;
504
505 if(len & 1)
506 *(--pd) &= 0xf0;
507 }
508
509 x += b2;
510 p->rlebuf_cur += bytes_wd;
511 }
512 }
513
514 return RET_OK;
515 }
516
517 /** RLE 展開 (8bit) */
518
_decompress_rle8(_LOADBMP * p)519 static int _decompress_rle8(_LOADBMP *p)
520 {
521 uint8_t *pd,b1,b2;
522 int ret,width,x = 0,bytes_wd;
523
524 pd = p->rawbuf;
525 width = p->param->info.width;
526
527 while(1)
528 {
529 //読み込み
530
531 ret = _read_to_rlebuf(p);
532 if(ret) return ret;
533
534 //2byte データ
535
536 b1 = p->rlebuf_cur[0];
537 b2 = p->rlebuf_cur[1];
538 p->rlebuf_cur += 2;
539
540 //
541
542 if(b1 != 0)
543 {
544 //連続データ
545
546 if(x + b1 > width) return MLOADIMAGE_ERR_DECODE;
547
548 memset(pd, b2, b1);
549
550 pd += b1;
551 x += b1;
552 }
553 else if(b2 == 0 || b2 == 1)
554 {
555 //行終わり (0 + 0) or イメージ終わり (0 + 1)
556
557 memset(pd, 0, p->param->info.raw_pitch - x);
558 if(b2 == 1) p->end_of_bmp = TRUE;
559
560 break;
561 }
562 else if(b2 == 2)
563 //位置移動 (0 + 2) は非対応
564 return MLOADIMAGE_ERR_UNSUPPORTED;
565 else
566 {
567 //----- 非連続データ (0 + [3-255] + データxlen)
568
569 if(x + b2 > width) return MLOADIMAGE_ERR_DECODE;
570
571 bytes_wd = (b2 + 1) & (~1);
572
573 if(p->rlebuf_end - p->rlebuf_cur < bytes_wd)
574 return MLOADIMAGE_ERR_CORRUPT;
575
576 memcpy(pd, p->rlebuf_cur, b2);
577
578 p->rlebuf_cur += bytes_wd;
579
580 pd += b2;
581 x += b2;
582 }
583 }
584
585 return RET_OK;
586 }
587
588
589 //=======================
590 // sub
591 //=======================
592
593
594 /** イメージ変換 */
595
_convert_image(_LOADBMP * p)596 static void _convert_image(_LOADBMP *p)
597 {
598 int i,n,bits,shift,mask,convtype;
599 uint32_t c;
600 uint8_t *ps,*pd,*ppal,r,g,b,a;
601 mBool to_rgba;
602
603 bits = p->bits;
604 convtype = p->convtype;
605 to_rgba = (p->param->format == MLOADIMAGE_FORMAT_RGBA);
606
607 ps = p->rawbuf;
608 pd = p->convbuf;
609
610 if(bits <= 8)
611 {
612 shift = 8 - bits;
613 mask = (1 << bits) - 1;
614 }
615
616 //変換
617
618 for(i = p->param->info.width; i > 0; i--)
619 {
620 r = g = b = 0;
621 a = 255;
622
623 switch(convtype)
624 {
625 //24bit (B-G-R)
626 case CONVTYPE_24BIT:
627 r = ps[2];
628 g = ps[1];
629 b = ps[0];
630
631 ps += 3;
632 break;
633 //32bit (B-G-R-A)
634 case CONVTYPE_32BIT_BGRA:
635 r = ps[2];
636 g = ps[1];
637 b = ps[0];
638 if(p->maskA) a = ps[3];
639
640 ps += 4;
641 break;
642 //16bit/32bit (bitfield)
643 case CONVTYPE_BITFIELDS:
644 if(bits == 32)
645 {
646 c = ((uint32_t)ps[3] << 24) | (ps[2] << 16) | (ps[1] << 8) | ps[0];
647 ps += 4;
648 }
649 else
650 {
651 c = (ps[1] << 8) | ps[0];
652 ps += 2;
653 }
654
655 if(p->maskR) r = ((c & p->maskR) >> p->shiftR) * 255 / p->maxR;
656 if(p->maskG) g = ((c & p->maskG) >> p->shiftG) * 255 / p->maxG;
657 if(p->maskB) b = ((c & p->maskB) >> p->shiftB) * 255 / p->maxB;
658 if(p->maskA) a = ((c & p->maskA) >> p->shiftA) * 255 / p->maxA;
659 break;
660 //パレットカラー
661 default:
662 n = (*ps >> shift) & mask;
663 if(n >= p->palnum) n = 0;
664
665 ppal = p->palbuf + (n << 2);
666
667 r = ppal[0];
668 g = ppal[1];
669 b = ppal[2];
670
671 shift -= bits;
672 if(shift < 0)
673 {
674 shift = 8 - bits;
675 ps++;
676 }
677 break;
678 }
679
680 //セット
681
682 pd[0] = r;
683 pd[1] = g;
684 pd[2] = b;
685
686 if(to_rgba)
687 {
688 pd[3] = a;
689 pd += 4;
690 }
691 else
692 pd += 3;
693 }
694 }
695
696 /** イメージまでの情報読み込み */
697
_read_headers(_LOADBMP * p)698 static int _read_headers(_LOADBMP *p)
699 {
700 int ret;
701
702 //開く
703
704 p->io = mLoadImage_openIOFileBuf(&p->param->src);
705 if(!p->io) return MLOADIMAGE_ERR_OPENFILE;
706
707 //ファイルヘッダ
708
709 if((ret = _read_fileheader(p)))
710 return ret;
711
712 //情報ヘッダ
713
714 if((ret = _read_infoheader(p, &p->param->info)))
715 return ret;
716
717 //パレット
718
719 if(p->bits <= 8)
720 {
721 if((ret = _read_palette(p)))
722 return ret;
723
724 p->param->info.palette_num = p->palnum;
725 p->param->info.palette_buf = p->palbuf;
726 }
727
728 return RET_OK;
729 }
730
731 /** 作業用メモリ確保 */
732
_alloc_buf(_LOADBMP * p,mLoadImage * param)733 static int _alloc_buf(_LOADBMP *p,mLoadImage *param)
734 {
735 //Y1行、生データ
736
737 p->rawbuf = (uint8_t *)mMalloc(param->info.raw_pitch, FALSE);
738 if(!p->rawbuf) return MLOADIMAGE_ERR_ALLOC;
739
740 //Y1行、変換後データ
741
742 if(param->format != MLOADIMAGE_FORMAT_RAW)
743 {
744 p->convbuf = (uint8_t *)mMalloc(mLoadImage_getPitch(param), FALSE);
745 if(!p->convbuf) return MLOADIMAGE_ERR_ALLOC;
746 }
747
748 //RLE 用
749
750 if(p->compression == BI_RLE4 || p->compression == BI_RLE8)
751 {
752 p->rlebuf = (uint8_t *)mMalloc(RLE_BUFSIZE, FALSE);
753 if(!p->rlebuf) return MLOADIMAGE_ERR_ALLOC;
754
755 p->rlebuf_end = p->rlebuf_cur = p->rlebuf;
756 }
757
758 return RET_OK;
759 }
760
761 /** メイン処理 */
762
_main_proc(_LOADBMP * p)763 static int _main_proc(_LOADBMP *p)
764 {
765 int ret,i,pitch_dst,pitch_raw,rle;
766 mLoadImage *param = p->param;
767
768 //ヘッダ部分読み込み
769
770 if((ret = _read_headers(p)))
771 return ret;
772
773 //メモリ確保
774
775 if((ret = _alloc_buf(p, param)))
776 return ret;
777
778 //getinfo()
779
780 if(param->getinfo)
781 {
782 if((ret = (param->getinfo)(param, ¶m->info)))
783 return (ret < 0)? RET_ERR_NOMES: ret;
784 }
785
786 //イメージ読み込み
787
788 pitch_raw = param->info.raw_pitch;
789 pitch_dst = mLoadImage_getPitch(param);
790
791 rle = (p->compression == BI_RLE4 || p->compression == BI_RLE8);
792
793 for(i = param->info.height; i > 0; i--)
794 {
795 //p->rawbuf に生データ読み込み
796
797 if(rle)
798 {
799 //RLE 圧縮
800
801 if(p->end_of_bmp)
802 memset(p->rawbuf, 0, pitch_raw);
803 else
804 {
805 if(p->compression == BI_RLE4)
806 ret = _decompress_rle4(p);
807 else
808 ret = _decompress_rle8(p);
809
810 if(ret) return ret;
811 }
812 }
813 else
814 {
815 //無圧縮
816
817 if(!mIOFileBuf_readSize(p->io, p->rawbuf, pitch_raw))
818 return MLOADIMAGE_ERR_CORRUPT;
819 }
820
821 //getrow()
822
823 if(param->format == MLOADIMAGE_FORMAT_RAW)
824 ret = (param->getrow)(param, p->rawbuf, pitch_dst);
825 else
826 {
827 _convert_image(p);
828
829 ret = (param->getrow)(param, p->convbuf, pitch_dst);
830 }
831
832 if(ret)
833 return (ret < 0)? RET_ERR_NOMES: ret;
834 }
835
836 return RET_OK;
837 }
838
839
840 //========================
841 // main
842 //========================
843
844
845 /** BMP 読み込み
846 *
847 * @ingroup loadimage */
848
mLoadImageBMP(mLoadImage * param)849 mBool mLoadImageBMP(mLoadImage *param)
850 {
851 _LOADBMP *p;
852 int ret;
853
854 //確保
855
856 p = (_LOADBMP *)mMalloc(sizeof(_LOADBMP), TRUE);
857 if(!p) return FALSE;
858
859 p->param = param;
860
861 //処理
862
863 ret = _main_proc(p);
864
865 if(ret != RET_OK)
866 {
867 if(ret == RET_ERR_NOMES)
868 {
869 if(!param->message)
870 mLoadImage_setMessage(param, "error");
871 }
872 else
873 mLoadImage_setMessage_errno(param, ret);
874 }
875
876 //解放
877
878 mIOFileBuf_close(p->io);
879
880 mFree(p->rawbuf);
881 mFree(p->convbuf);
882 mFree(p->palbuf);
883 mFree(p->rlebuf);
884 mFree(p);
885
886 return (ret == RET_OK);
887 }
888
889