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, &param->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