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 * JPEG 読み込み関数
22 *****************************************/
23
24 #include <stdio.h>
25 #include <string.h>
26 #include <setjmp.h>
27
28 #include <jpeglib.h>
29
30 #include "mDef.h"
31 #include "mLoadImage.h"
32 #include "mUtilStdio.h"
33
34
35 //---------------------------
36 /* メモリからの読み込み用 */
37
38 typedef struct
39 {
40 struct jpeg_source_mgr pub;
41 const uint8_t *buf;
42 uint32_t size;
43 uint8_t eof_buf[2]; //0xff, 0xd9
44 }_JPEG_MEM;
45
46 //--------------------
47 /* エラー用 */
48
49 typedef struct
50 {
51 struct jpeg_error_mgr jerr;
52 jmp_buf jmpbuf;
53 struct __LOADJPEG *loadjpg;
54 }_JPEG_ERR;
55
56 //--------------------
57
58 typedef struct __LOADJPEG
59 {
60 mLoadImage *param;
61
62 struct jpeg_decompress_struct jpg;
63 _JPEG_ERR jpgerr;
64
65 FILE *fp;
66 uint8_t *rowbuf;
67
68 uint8_t start_decompress,
69 need_fp_close;
70 }_LOADJPEG;
71
72 //--------------------
73
74 #define RET_OK 0
75 #define RET_ERR_NOMES -1
76
77 //--------------------
78
79
80 //===============================
81 // メモリからの読み込み用
82 //===============================
83
84
_mem_dummy(j_decompress_ptr p)85 static void _mem_dummy(j_decompress_ptr p)
86 {
87
88 }
89
90 /** バッファを埋める */
91
_mem_fill_input_buffer(j_decompress_ptr p)92 static boolean _mem_fill_input_buffer(j_decompress_ptr p)
93 {
94 p->src->next_input_byte = ((_JPEG_MEM *)p->src)->eof_buf;
95 p->src->bytes_in_buffer = 2;
96
97 return TRUE;
98 }
99
100 /** 指定バイト移動 */
101
_mem_skip_input_data(j_decompress_ptr p,long size)102 static void _mem_skip_input_data(j_decompress_ptr p,long size)
103 {
104 _JPEG_MEM *mem = (_JPEG_MEM *)p->src;
105
106 if(mem->pub.bytes_in_buffer < size)
107 //データが足りない
108 _mem_fill_input_buffer(p);
109 else if(size > 0)
110 {
111 mem->pub.next_input_byte += size;
112 mem->pub.bytes_in_buffer -= size;
113 }
114 }
115
116 /** ソースをメモリにセット */
117
_jpeg_memory_src(j_decompress_ptr cinfo,const void * buf,uint32_t size)118 static void _jpeg_memory_src(j_decompress_ptr cinfo,const void *buf,uint32_t size)
119 {
120 _JPEG_MEM *p;
121
122 //_JPEG_MEM 確保
123
124 if(!cinfo->src)
125 {
126 cinfo->src = (struct jpeg_source_mgr *)
127 (*cinfo->mem->alloc_small)((j_common_ptr)cinfo, JPOOL_PERMANENT, sizeof(_JPEG_MEM));
128 }
129
130 //セット
131
132 p = (_JPEG_MEM *)cinfo->src;
133
134 p->pub.init_source = _mem_dummy;
135 p->pub.fill_input_buffer = _mem_fill_input_buffer;
136 p->pub.skip_input_data = _mem_skip_input_data;
137 p->pub.resync_to_restart = jpeg_resync_to_restart;
138 p->pub.term_source = _mem_dummy;
139
140 p->pub.next_input_byte = (JOCTET *)buf;
141 p->pub.bytes_in_buffer = size;
142
143 p->buf = buf;
144 p->size = size;
145 p->eof_buf[0] = 0xff;
146 p->eof_buf[1] = JPEG_EOI;
147 }
148
149
150 //=======================
151 // sub
152 //=======================
153
154
155 /** エラー終了時のハンドラ */
156
_jpeg_error_exit(j_common_ptr p)157 static void _jpeg_error_exit(j_common_ptr p)
158 {
159 _JPEG_ERR *err = (_JPEG_ERR *)p->err;
160 char msg[JMSG_LENGTH_MAX];
161
162 //エラー文字列を取得
163
164 (err->jerr.format_message)(p, msg);
165
166 mLoadImage_setMessage(err->loadjpg->param, msg);
167
168 //setjmp の位置に飛ぶ
169
170 longjmp(err->jmpbuf, 1);
171 }
172
173 /** メッセージ表示ハンドラ */
174
_jpeg_output_message(j_common_ptr p)175 static void _jpeg_output_message(j_common_ptr p)
176 {
177
178 }
179
180 /** 解像度単位を取得 */
181
_get_resolution_unit(int unit)182 static int _get_resolution_unit(int unit)
183 {
184 if(unit == 0)
185 return MLOADIMAGE_RESOLITION_UNIT_ASPECT;
186 else if(unit == 1)
187 return MLOADIMAGE_RESOLITION_UNIT_DPI;
188 else if(unit == 2)
189 return MLOADIMAGE_RESOLITION_UNIT_DPCM;
190 else
191 return MLOADIMAGE_RESOLITION_UNIT_NONE;
192 }
193
194 /** EXIF 値取得 */
195
_get_exif_value(uint8_t ** pp,int size,uint8_t bigendian)196 static uint32_t _get_exif_value(uint8_t **pp,int size,uint8_t bigendian)
197 {
198 uint8_t *p = *pp;
199
200 *pp += size;
201
202 if(bigendian)
203 {
204 if(size == 2)
205 return (p[0] << 8) | p[1];
206 else
207 return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
208 }
209 else
210 {
211 if(size == 2)
212 return (p[1] << 8) | p[0];
213 else
214 return (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0];
215 }
216 }
217
218 /** EXIF から解像度取得 */
219
_get_exif_resolution(_LOADJPEG * p,mLoadImageInfo * info)220 static void _get_exif_resolution(_LOADJPEG *p,mLoadImageInfo *info)
221 {
222 struct jpeg_marker_struct *plist;
223 uint8_t *ps,*ps2,*tifftop,endian,flags = 0;
224 int fnum,tag,dattype,unit;
225 uint32_t pos,horz,vert;
226
227 for(plist = p->jpg.marker_list; plist; plist = plist->next)
228 {
229 if(plist->marker == 0xe1 && plist->data_length >= 16)
230 {
231 ps = (uint8_t *)plist->data;
232 tifftop = ps + 6;
233
234 if(strcmp((char *)ps, "Exif") != 0) return;
235
236 endian = (ps[6] == 'M'); //0=little-endian 1=big-endian
237
238 ps += 14;
239
240 //IFD-0th
241
242 fnum = _get_exif_value(&ps, 2, endian);
243
244 for(; fnum > 0 && flags != 7; fnum--)
245 {
246 tag = _get_exif_value(&ps, 2, endian);
247 dattype = _get_exif_value(&ps, 2, endian);
248 ps += 4;
249 pos = _get_exif_value(&ps, 4, endian);
250
251 if(tag == 0x011a && dattype == 5)
252 {
253 //解像度水平
254
255 ps2 = tifftop + pos;
256 horz = _get_exif_value(&ps2, 4, endian);
257 flags |= 1;
258 }
259 else if(tag == 0x011b && dattype == 5)
260 {
261 //解像度垂直
262
263 ps2 = tifftop + pos;
264 vert = _get_exif_value(&ps2, 4, endian);
265 flags |= 2;
266 }
267 else if(tag == 0x0128 && dattype == 3)
268 {
269 //解像度単位 (short)
270 /* 1:none 2:dpi 3:dpcm */
271
272 unit = pos;
273 flags |= 4;
274 }
275 }
276
277 //終了
278
279 if(flags == 7 && (unit == 2 || unit == 3))
280 {
281 info->resolution_unit = _get_resolution_unit(unit - 1);
282 info->resolution_horz = horz;
283 info->resolution_vert = vert;
284 }
285
286 break;
287 }
288 }
289 }
290
291 /** イメージ部分まで処理 */
292
_read_headers(_LOADJPEG * p)293 static int _read_headers(_LOADJPEG *p)
294 {
295 j_decompress_ptr jpg;
296 mLoadImageInfo *info = &p->param->info;
297 int colspace;
298
299 jpg = &p->jpg;
300
301 //エラー設定
302 /* デフォルトではエラー時にプロセスが終了するので、longjmp を行うようにする */
303
304 jpg->err = jpeg_std_error(&p->jpgerr.jerr);
305
306 p->jpgerr.jerr.error_exit = _jpeg_error_exit;
307 p->jpgerr.jerr.output_message = _jpeg_output_message;
308 p->jpgerr.loadjpg = p;
309
310 //エラー時
311
312 if(setjmp(p->jpgerr.jmpbuf))
313 return RET_ERR_NOMES;
314
315 //構造体初期化
316
317 jpeg_create_decompress(jpg);
318
319 //------ 各タイプ別の初期化
320
321 switch(p->param->src.type)
322 {
323 //ファイル
324 case MLOADIMAGE_SOURCE_TYPE_PATH:
325 p->fp = mFILEopenUTF8(p->param->src.filename, "rb");
326 if(!p->fp) return MLOADIMAGE_ERR_OPENFILE;
327
328 jpeg_stdio_src(jpg, p->fp);
329 p->need_fp_close = TRUE;
330 break;
331 //バッファ
332 case MLOADIMAGE_SOURCE_TYPE_BUF:
333 _jpeg_memory_src(jpg, p->param->src.buf, p->param->src.bufsize);
334 break;
335 //FILE*
336 case MLOADIMAGE_SOURCE_TYPE_STDIO:
337 jpeg_stdio_src(jpg, (FILE *)p->param->src.fp);
338 break;
339 }
340
341 //-------- 情報
342
343 //保存するマーカー
344
345 jpeg_save_markers(jpg, 0xe1, 0xffff); //EXIF
346
347 //ヘッダ読み込み
348
349 if(jpeg_read_header(jpg, TRUE) != JPEG_HEADER_OK)
350 return MLOADIMAGE_ERR_NONE_IMAGE;
351
352 //最大サイズ判定
353
354 if((p->param->max_width > 0 && jpg->image_width > p->param->max_width)
355 || (p->param->max_height > 0 && jpg->image_height > p->param->max_height))
356 return MLOADIMAGE_ERR_LARGE_SIZE;
357
358 //情報セット
359
360 colspace = jpg->jpeg_color_space;
361
362 info->width = jpg->image_width;
363 info->height = jpg->image_height;
364 info->sample_bits = 8;
365 info->raw_sample_bits = 8;
366 info->raw_pitch = info->width * ((colspace == JCS_GRAYSCALE)? 1: 3);
367
368 if(colspace == JCS_GRAYSCALE)
369 {
370 info->raw_bits = 8;
371 info->raw_coltype = MLOADIMAGE_COLTYPE_GRAY;
372 }
373 else
374 {
375 info->raw_bits = 24;
376 info->raw_coltype = MLOADIMAGE_COLTYPE_RGB;
377 }
378
379 //------- 開始
380
381 //出力フォーマット
382
383 if(p->param->format != MLOADIMAGE_FORMAT_RAW)
384 {
385 if(colspace == JCS_CMYK || colspace == JCS_YCCK)
386 jpg->out_color_space = JCS_CMYK;
387 else
388 jpg->out_color_space = JCS_RGB;
389 }
390
391 //展開開始
392
393 if(!jpeg_start_decompress(jpg))
394 return MLOADIMAGE_ERR_ALLOC;
395
396 p->start_decompress = TRUE;
397
398 //----- マーカー情報
399
400 //解像度
401
402 if(jpg->saw_JFIF_marker)
403 {
404 //JFIF
405 p->param->info.resolution_horz = jpg->X_density;
406 p->param->info.resolution_vert = jpg->Y_density;
407 p->param->info.resolution_unit = _get_resolution_unit(jpg->density_unit);
408 }
409 else
410 //EXIF
411 _get_exif_resolution(p, &p->param->info);
412
413 return RET_OK;
414 }
415
416 /** 出力用のY1行サイズ取得 */
417
_get_out_pitch(_LOADJPEG * p)418 static int _get_out_pitch(_LOADJPEG *p)
419 {
420 int cs,bytes;
421
422 cs = p->jpg.out_color_space;
423
424 if(cs == JCS_GRAYSCALE)
425 bytes = 1;
426 else if(cs == JCS_CMYK)
427 bytes = 4;
428 else
429 bytes = (p->param->format == MLOADIMAGE_FORMAT_RGBA)? 4: 3;
430
431 return p->jpg.image_width * bytes;
432 }
433
434
435 //=======================
436 // main
437 //=======================
438
439
440 /** イメージ変換 (CMYK -> RGB/RGBA) */
441
_convert_CMYK(_LOADJPEG * p)442 static void _convert_CMYK(_LOADJPEG *p)
443 {
444 int i,c,m,y,k;
445 uint8_t *ps,*pd,alpha;
446
447 alpha = (p->param->format == MLOADIMAGE_FORMAT_RGBA);
448
449 ps = pd = p->rowbuf;
450
451 for(i = p->jpg.image_width; i > 0; i--)
452 {
453 c = ps[0];
454 m = ps[1];
455 y = ps[2];
456 k = ps[3];
457
458 /* [基本の計算式]
459 * R,G,B = 1 - min(1, [C,M,Y] * (1 - K) + K)
460 *
461 * CMYK JPEG の場合、値は常に反転されている。
462 *
463 * [値の反転時]
464 * 1 - ((1 - C) * (1 - (1 - K)) + 1 - K)
465 * = 1 - ((1 - C) * K + 1 - K)
466 * = 1 - (K + C * K + 1 - K)
467 * = C * K */
468
469 pd[0] = (c * k + 127) / 255;
470 pd[1] = (m * k + 127) / 255;
471 pd[2] = (y * k + 127) / 255;
472
473 if(alpha)
474 {
475 pd[3] = 255;
476 pd += 4;
477 }
478 else
479 pd += 3;
480
481 ps += 4;
482 }
483 }
484
485 /** イメージ変換 (RGB->RGBA) */
486
_convert_RGBA(uint8_t * buf,uint32_t width)487 static void _convert_RGBA(uint8_t *buf,uint32_t width)
488 {
489 uint8_t *ps,*pd,r,g,b;
490
491 ps = buf + (width - 1) * 3;
492 pd = buf + ((width - 1) << 2);
493
494 for(; width; width--, ps -= 3, pd -= 4)
495 {
496 r = ps[0], g = ps[1], b = ps[2];
497
498 pd[0] = r;
499 pd[1] = g;
500 pd[2] = b;
501 pd[3] = 255;
502 }
503 }
504
505 /** メイン処理 */
506
_main_proc(_LOADJPEG * p)507 static int _main_proc(_LOADJPEG *p)
508 {
509 mLoadImage *param = p->param;
510 int ret,pitch,conv;
511
512 //イメージ部分まで処理
513
514 if((ret = _read_headers(p)))
515 return ret;
516
517 //Y1行バッファ確保
518
519 pitch = _get_out_pitch(p);
520
521 p->rowbuf = (uint8_t *)mMalloc(pitch, FALSE);
522 if(!p->rowbuf) return MLOADIMAGE_ERR_ALLOC;
523
524 //getinfo()
525
526 if(param->getinfo)
527 {
528 ret = (param->getinfo)(param, ¶m->info);
529 if(ret)
530 return (ret < 0)? RET_ERR_NOMES: RET_OK;
531 }
532
533 //変換
534
535 if(p->jpg.out_color_space == JCS_CMYK)
536 conv = (param->format == MLOADIMAGE_FORMAT_RAW)? 0: 1;
537 else if(param->format == MLOADIMAGE_FORMAT_RGBA)
538 conv = 2;
539 else
540 conv = 0;
541
542 //イメージ
543
544 while(p->jpg.output_scanline < p->jpg.output_height)
545 {
546 //読み込み
547
548 if(jpeg_read_scanlines(&p->jpg, (JSAMPARRAY)&p->rowbuf, 1) != 1)
549 return MLOADIMAGE_ERR_CORRUPT;
550
551 //変換
552
553 if(conv == 2)
554 _convert_RGBA(p->rowbuf, param->info.width);
555 else if(conv == 1)
556 _convert_CMYK(p);
557
558 //getrow()
559
560 ret = (param->getrow)(param, p->rowbuf, pitch);
561 if(ret)
562 return (ret < 0)? RET_ERR_NOMES: RET_OK;
563 }
564
565 return RET_OK;
566 }
567
568 /** 解放 */
569
_jpeg_free(_LOADJPEG * p)570 static void _jpeg_free(_LOADJPEG *p)
571 {
572 //jpeglib
573
574 if(p->start_decompress)
575 jpeg_finish_decompress(&p->jpg);
576
577 jpeg_destroy_decompress(&p->jpg);
578
579 //ファイル閉じる
580
581 if(p->fp && p->need_fp_close)
582 fclose(p->fp);
583
584 //
585
586 mFree(p->rowbuf);
587 mFree(p);
588 }
589
590 /** JPEG 読み込み
591 *
592 * @ingroup loadimage */
593
mLoadImageJPEG(mLoadImage * param)594 mBool mLoadImageJPEG(mLoadImage *param)
595 {
596 _LOADJPEG *p;
597 int ret;
598
599 //確保
600
601 p = (_LOADJPEG *)mMalloc(sizeof(_LOADJPEG), TRUE);
602 if(!p) return FALSE;
603
604 p->param = param;
605
606 //処理
607
608 ret = _main_proc(p);
609
610 if(ret != RET_OK)
611 {
612 if(ret == RET_ERR_NOMES)
613 {
614 if(!param->message)
615 mLoadImage_setMessage(param, "error");
616 }
617 else
618 mLoadImage_setMessage_errno(param, ret);
619 }
620
621 //解放
622
623 _jpeg_free(p);
624
625 return (ret == RET_OK);
626 }
627
628