1 /*	png.c
2 	Copyright (C) 2004-2021 Mark Tyler and Dmitry Groshev
3 
4 	This file is part of mtPaint.
5 
6 	mtPaint 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 	mtPaint 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 mtPaint in the file COPYING.
18 */
19 
20 /* Rewritten for version 3.10 by Dmitry Groshev */
21 
22 #include <stdio.h>
23 #include <errno.h>
24 
25 #define PNG_READ_PACK_SUPPORTED
26 
27 #include <png.h>
28 #include <zlib.h>
29 #ifdef U_JPEG
30 #define NEED_CMYK
31 /* !!! libjpeg 9 headers conflict with these */
32 #undef TRUE
33 #undef FALSE
34 #include <jpeglib.h>
35 /* !!! Since libjpeg 7, this conflicts with <windows.h>; with libjpeg 8a,
36  * conflict can be avoided if windows.h is included BEFORE this - WJ */
37 #endif
38 #ifdef U_JP2
39 #if U_JP2 < 2
40 #define NEED_FILE2MEM
41 #endif
42 #define HANDLE_JP2
43 #include <openjpeg.h>
44 #endif
45 #ifdef U_JASPER
46 #define HANDLE_JP2
47 #include <jasper/jasper.h>
48 #endif
49 #ifdef U_TIFF
50 #define NEED_CMYK
51 #include <tiffio.h>
52 #endif
53 #ifdef U_WEBP
54 #include <webp/encode.h>
55 #include <webp/decode.h>
56 #endif
57 #if U_LCMS == 2
58 #include <lcms2.h>
59 /* For version 1.x compatibility */
60 #define icSigCmykData cmsSigCmykData
61 #define icSigRgbData cmsSigRgbData
62 #define icHeader cmsICCHeader
63 #elif defined U_LCMS
64 #include <lcms.h>
65 #endif
66 
67 #include "global.h"
68 #undef _
69 #define _(X) X
70 
71 #include "mygtk.h"
72 #include "memory.h"
73 #include "ani.h"
74 #include "png.h"
75 #include "canvas.h"
76 #include "toolbar.h"
77 #include "layer.h"
78 #include "spawn.h"
79 #include "thread.h"
80 
81 /* Make fseek() and ftell() on Win64 have the same limits as on 64-bit Unix */
82 #ifdef _WIN64 /* LLP64 */
83 #define F_LONG_MAX LLONG_MAX /* What can be handled - including allocated */
84 typedef long long f_long;
85 #define ftell(A) _ftelli64(A)
86 #define fseek(A,B,C) _fseeki64(A, B, C)
87 
88 #else /* LP64 or ILP32 */
89 #define F_LONG_MAX LONG_MAX /* What can be handled - including allocated */
90 typedef long f_long;
91 
92 #endif
93 
94 #if F_LONG_MAX > SIZE_MAX
95 #error "File offset limit exceeds allocation limit"
96 #endif
97 
98 
99 /* Macro for big-endian tags (IFF and BMP) */
100 #define TAG4B(A,B,C,D) (((A) << 24) + ((B) << 16) + ((C) << 8) + (D))
101 
102 /* All-in-one transport container for animation save/load */
103 typedef struct {
104 	frameset fset;
105 	ls_settings settings;
106 	int mode;
107 	/* Explode frames mode */
108 	int desttype;
109 	int error, miss, cnt;
110 	int lastzero;
111 	char *destdir;
112 } ani_settings;
113 
114 int silence_limit, jpeg_quality, png_compression;
115 int tga_RLE, tga_565, tga_defdir, jp2_rate;
116 int lzma_preset, zstd_level, tiff_predictor, tiff_rtype, tiff_itype, tiff_btype;
117 int webp_preset, webp_quality, webp_compression;
118 int lbm_mask, lbm_untrans, lbm_pack, lbm_pbm;
119 int apply_icc;
120 
121 fformat file_formats[NUM_FTYPES] = {
122 	{ "", "", "", 0},
123 	{ "PNG", "png", "apng", FF_256 | FF_RGB | FF_ANIM | FF_ALPHA | FF_MULTI
124 		| FF_MEM, XF_TRANS | XF_COMPZ },
125 #ifdef U_JPEG
126 	{ "JPEG", "jpg", "jpeg", FF_RGB, XF_COMPJ },
127 #else
128 	{ "", "", "", 0},
129 #endif
130 #ifdef HANDLE_JP2
131 	{ "JPEG2000", "jp2", "", FF_RGB | FF_ALPHA, XF_COMPJ2 },
132 	{ "J2K", "j2k", "jpc", FF_RGB | FF_ALPHA, XF_COMPJ2 },
133 #else
134 	{ "", "", "", 0},
135 	{ "", "", "", 0},
136 #endif
137 #ifdef U_TIFF
138 #define TIFF0FLAGS FF_LAYER | FF_MEM
139 #define TIFFLAGS (FF_BW | FF_256 | FF_RGB | FF_ALPHA | TIFF0FLAGS)
140 	{ "TIFF", "tif", "tiff", TIFFLAGS, XF_COMPT },
141 #else
142 	{ "", "", "", 0},
143 #endif
144 	{ "GIF", "gif", "", FF_256 | FF_ANIM, XF_TRANS },
145 	{ "BMP", "bmp", "", FF_256 | FF_RGB | FF_ALPHAR | FF_MEM },
146 	{ "XPM", "xpm", "", FF_256 | FF_RGB, XF_TRANS | XF_SPOT },
147 	{ "XBM", "xbm", "", FF_BW, XF_SPOT },
148 	{ "LSS16", "lss", "", FF_16 },
149 	{ "TGA", "tga", "", FF_256 | FF_RGB | FF_ALPHAR, XF_TRANS | XF_COMPR },
150 	{ "PCX", "pcx", "", FF_256 | FF_RGB },
151 	{ "PBM", "pbm", "", FF_BW | FF_LAYER },
152 	{ "PGM", "pgm", "", FF_256 | FF_LAYER | FF_NOSAVE },
153 	{ "PPM", "ppm", "pnm", FF_RGB | FF_LAYER },
154 	{ "PAM", "pam", "", FF_BW | FF_RGB | FF_ALPHA | FF_LAYER },
155 	{ "GPL", "gpl", "", FF_PALETTE },
156 	{ "TXT", "txt", "", FF_PALETTE },
157 	{ "PAL", "pal", "", FF_PALETTE },
158 	{ "ACT", "act", "", FF_PALETTE },
159 	{ "LAYERS", "txt", "", FF_LAYER },
160 /* !!! No 2nd layers format yet */
161 	{ "", "", "", 0},
162 /* An X pixmap - not a file at all */
163 	{ "PIXMAP", "", "", FF_RGB | FF_NOSAVE },
164 /* SVG image - import only */
165 	{ "SVG", "svg", "", FF_RGB | FF_ALPHA | FF_SCALE | FF_NOSAVE },
166 /* mtPaint's own format - extended PAM */
167 	{ "* PMM *", "pmm", "", FF_256 | FF_RGB | FF_ANIM | FF_ALPHA | FF_MULTI
168 		| FF_LAYER | FF_PALETTE | FF_MEM, XF_TRANS },
169 #ifdef U_WEBP
170 	{ "WEBP", "webp", "", FF_RGB | FF_ANIM | FF_ALPHA, XF_COMPW },
171 #else
172 	{ "", "", "", 0},
173 #endif
174 	{ "LBM", "lbm", "ilbm", FF_256 | FF_RGB | FF_ALPHA, XF_TRANS | XF_COMPRL },
175 };
176 
177 #ifndef U_TIFF
178 tiff_format tiff_formats[] = { { NULL } };
179 #endif
180 #ifndef U_WEBP
181 char *webp_presets[] = { NULL };
182 #endif
183 
file_type_by_ext(char * name,guint32 mask)184 int file_type_by_ext(char *name, guint32 mask)
185 {
186 	char *ext;
187 	int i, l = LONGEST_EXT;
188 
189 
190 	ext = strrchr(name, '.');
191 	if (!ext || !ext[0]) return (FT_NONE);
192 
193 	/* Special case for exploded frames (*.gif.000 etc.) */
194 	if (!ext[strspn(ext, ".0123456789")] && memchr(name, '.', ext - name))
195 	{
196 		char *tmp = ext;
197 
198 		while (*(--ext) != '.');
199 		if (tmp - ext - 1 < LONGEST_EXT) l = tmp - ext - 1;
200 	}
201 
202 	ext++;
203 	for (i = 0; i < NUM_FTYPES; i++)
204 	{
205 		unsigned int flags = file_formats[i].flags;
206 
207 		if ((flags & FF_NOSAVE) || !(flags & mask)) continue;
208 		if (!strncasecmp(ext, file_formats[i].ext, l))
209 			return (i);
210 		if (!file_formats[i].ext2[0]) continue;
211 		if (!strncasecmp(ext, file_formats[i].ext2, l))
212 			return (i);
213 	}
214 
215 	return (FT_NONE);
216 }
217 
218 /* Which of 2 palette colors is more like black */
get_bw(ls_settings * settings)219 static int get_bw(ls_settings *settings)
220 {
221 	return (pal2B(settings->pal + 0) > pal2B(settings->pal + 1));
222 }
223 
224 /* Set palette to white and black */
set_bw(ls_settings * settings)225 static void set_bw(ls_settings *settings)
226 {
227 	static const png_color wb[2] = { { 255, 255, 255 }, { 0, 0, 0 } };
228 	settings->colors = 2;
229 	memcpy(settings->pal, wb, sizeof(wb));
230 }
231 
232 /* Set palette to grayscale */
set_gray(ls_settings * settings)233 static void set_gray(ls_settings *settings)
234 {
235 	settings->colors = 256;
236 	mem_bw_pal(settings->pal, 0, 255);
237 }
238 
239 /* Map RGB transparency to indexed */
map_rgb_trans(ls_settings * settings)240 static void map_rgb_trans(ls_settings *settings)
241 {
242 	int i;
243 
244 	if ((settings->rgb_trans < 0) || (settings->bpp < 3)) return;
245 	// Look for transparent colour in palette
246 	for (i = 0; i < settings->colors; i++)
247 	{
248 		if (PNG_2_INT(settings->pal[i]) != settings->rgb_trans) continue;
249 		settings->xpm_trans = i;
250 		return;
251 	}
252 	// Colour not in palette so force it into last entry
253 	settings->pal[255].red = INT_2_R(settings->rgb_trans);
254 	settings->pal[255].green = INT_2_G(settings->rgb_trans);
255 	settings->pal[255].blue = INT_2_B(settings->rgb_trans);
256 	settings->xpm_trans = 255;
257 	settings->colors = 256;
258 }
259 
check_next_frame(frameset * fset,int mode,int anim)260 static int check_next_frame(frameset *fset, int mode, int anim)
261 {
262 	int lim = mode != FS_LAYER_LOAD ? FRAMES_MAX : anim ? MAX_LAYERS - 1 :
263 		MAX_LAYERS;
264 	return (fset->cnt < lim);
265 }
266 
267 static int write_out_frame(char *file_name, ani_settings *ani, ls_settings *f_set);
268 
process_page_frame(char * file_name,ani_settings * ani,ls_settings * w_set)269 static int process_page_frame(char *file_name, ani_settings *ani, ls_settings *w_set)
270 {
271 	image_frame *frame;
272 
273 	if (ani->settings.mode == FS_EXPLODE_FRAMES)
274 		return (write_out_frame(file_name, ani, w_set));
275 
276 	/* Store a new frame */
277 // !!! Currently, frames are allocated without checking any limits
278 	if (!mem_add_frame(&ani->fset, w_set->width, w_set->height,
279 		w_set->bpp, CMASK_NONE, w_set->pal)) return (FILE_MEM_ERROR);
280 	frame = ani->fset.frames + (ani->fset.cnt - 1);
281 	frame->cols = w_set->colors;
282 	frame->trans = w_set->xpm_trans;
283 	frame->delay = w_set->gif_delay > 0 ? w_set->gif_delay : 0;
284 	frame->x = w_set->x;
285 	frame->y = w_set->y;
286 	memcpy(frame->img, w_set->img, sizeof(chanlist));
287 	return (0);
288 }
289 
290 /* Receives struct with image parameters, and channel flags;
291  * returns 0 for success, or an error code;
292  * success doesn't mean that anything was allocated, loader must check that;
293  * loader may call this multiple times - say, for each channel */
allocate_image(ls_settings * settings,int cmask)294 static int allocate_image(ls_settings *settings, int cmask)
295 {
296 	size_t sz, l;
297 	int i, j, oldmask, wbpp, mode = settings->mode;
298 
299 	if ((settings->width < 1) || (settings->height < 1)) return (-1);
300 
301 	if ((settings->width > MAX_WIDTH) || (settings->height > MAX_HEIGHT))
302 		return (TOO_BIG);
303 
304 	/* Don't show progress bar where there's no need */
305 	if (settings->width * settings->height <= (1 << silence_limit))
306 		settings->silent = TRUE;
307 	if (mode == FS_PATTERN_LOAD) settings->silent = TRUE;
308 
309 	/* Reduce cmask according to mode */
310 	if (mode == FS_CLIP_FILE) cmask &= CMASK_CLIP;
311 	else if (mode == FS_CLIPBOARD) cmask &= CMASK_RGBA;
312 	else if ((mode == FS_CHANNEL_LOAD) || (mode == FS_PATTERN_LOAD))
313 		cmask &= CMASK_IMAGE;
314 
315 	/* Overwriting is allowed */
316 	oldmask = cmask_from(settings->img);
317 	cmask &= ~oldmask;
318 	if (!cmask) return (0); // Already allocated
319 
320 	/* No utility channels without image */
321 	oldmask |= cmask;
322 	if (!(oldmask & CMASK_IMAGE)) return (-1);
323 
324 	/* Can ask for RGBA-capable image channel */
325 	wbpp = settings->bpp;
326 	if (wbpp > 3) settings->bpp = 3;
327 
328 	j = TRUE; // For FS_LAYER_LOAD
329 	sz = (size_t)settings->width * settings->height;
330 	switch (mode)
331 	{
332 	case FS_PNG_LOAD: /* Regular image */
333 		/* Reserve memory */
334 		j = undo_next_core(UC_CREATE | UC_GETMEM, settings->width,
335 			settings->height, settings->bpp, oldmask);
336 		/* Drop current image if not enough memory for undo */
337 		if (j) mem_free_image(&mem_image, FREE_IMAGE);
338 	case FS_EXPLODE_FRAMES: /* Frames' temporaries */
339 	case FS_LAYER_LOAD: /* Layers */
340 		/* Allocate, or at least try to */
341 		for (i = 0; i < NUM_CHANNELS; i++)
342 		{
343 			if (!(cmask & CMASK_FOR(i))) continue;
344 			l = i == CHN_IMAGE ? sz * wbpp : sz;
345 			settings->img[i] = j ? malloc(l) : mem_try_malloc(l);
346 			if (!settings->img[i]) return (FILE_MEM_ERROR);
347 		}
348 		break;
349 	case FS_CLIP_FILE: /* Clipboard */
350 	case FS_CLIPBOARD:
351 		/* Allocate the entire batch at once */
352 		if (cmask & CMASK_IMAGE)
353 		{
354 			j = mem_clip_new(settings->width, settings->height,
355 				settings->bpp, cmask, NULL);
356 			if (j) return (FILE_MEM_ERROR);
357 			memcpy(settings->img, mem_clip.img, sizeof(chanlist));
358 			break;
359 		}
360 		/* Try to extend image channel to RGBA if asked */
361 		if (wbpp > 3)
362 		{
363 			unsigned char *w = realloc(mem_clipboard, sz * wbpp);
364 			if (!w) return (FILE_MEM_ERROR);
365 			settings->img[CHN_IMAGE] = mem_clipboard = w;
366 		}
367 		/* Try to add clipboard alpha and/or mask */
368 		for (i = 0; i < NUM_CHANNELS; i++)
369 		{
370 			if (!(cmask & CMASK_FOR(i))) continue;
371 			if (!(settings->img[i] = mem_clip.img[i] = malloc(sz)))
372 				return (FILE_MEM_ERROR);
373 		}
374 		break;
375 	case FS_CHANNEL_LOAD: /* Current channel */
376 		/* Dimensions & depth have to be the same */
377 		if ((settings->width != mem_width) ||
378 			(settings->height != mem_height) ||
379 			(settings->bpp != MEM_BPP)) return (-1);
380 		/* Reserve memory */
381 		j = undo_next_core(UC_CREATE | UC_GETMEM, settings->width,
382 			settings->height, settings->bpp, CMASK_CURR);
383 		if (j) return (FILE_MEM_ERROR);
384 		/* Allocate */
385 		settings->img[CHN_IMAGE] = mem_try_malloc(sz * wbpp);
386 		if (!settings->img[CHN_IMAGE]) return (FILE_MEM_ERROR);
387 		break;
388 	case FS_PATTERN_LOAD: /* Patterns */
389 		/* Check dimensions & depth */
390 		if (!set_patterns(settings)) return (-1);
391 		/* Allocate temp memory */
392 		settings->img[CHN_IMAGE] = calloc(1, sz * wbpp);
393 		if (!settings->img[CHN_IMAGE]) return (FILE_MEM_ERROR);
394 		break;
395 	case FS_PALETTE_LOAD: /* Palette */
396 	case FS_PALETTE_DEF:
397 		return (-1); // Should not arrive here if palette is present
398 	}
399 	return (0);
400 }
401 
402 /* Receives struct with image parameters, and which channels to deallocate */
deallocate_image(ls_settings * settings,int cmask)403 static void deallocate_image(ls_settings *settings, int cmask)
404 {
405 	int i;
406 
407 	/* No deallocating image channel */
408 	if (!(cmask &= ~CMASK_IMAGE)) return;
409 
410 	for (i = 0; i < NUM_CHANNELS; i++)
411 	{
412 		if (!(cmask & CMASK_FOR(i))) continue;
413 		if (!settings->img[i]) continue;
414 
415 		free(settings->img[i]);
416 		settings->img[i] = NULL;
417 
418 		/* Clipboard */
419 		if ((settings->mode == FS_CLIP_FILE) ||
420 			(settings->mode == FS_CLIPBOARD))
421 			mem_clip.img[i] = NULL;
422 	}
423 }
424 
425 /* Deallocate alpha channel if useless; namely, all filled with given value */
delete_alpha(ls_settings * settings,int v)426 static void delete_alpha(ls_settings *settings, int v)
427 {
428 	if (settings->img[CHN_ALPHA] && is_filled(settings->img[CHN_ALPHA], v,
429 		settings->width * settings->height))
430 		deallocate_image(settings, CMASK_ALPHA);
431 }
432 
433 typedef struct {
434 	FILE *file; // for traditional use
435 	memx2 m; // data
436 	int top;  // end of data
437 } memFILE;
438 #define MEMFILE_MAX INT_MAX /* How much it can hold */
439 
440 #if MEMFILE_MAX != MEMX2_MAX
441 #error "Mismatched max sizes"
442 #endif
443 
mfread(void * ptr,size_t size,size_t nmemb,memFILE * mf)444 static size_t mfread(void *ptr, size_t size, size_t nmemb, memFILE *mf)
445 {
446 	size_t l, m;
447 
448 	if (mf->file) return (fread(ptr, size, nmemb, mf->file));
449 
450 	if ((mf->m.here < 0) || (mf->m.here > mf->top)) return (0);
451 	l = size * nmemb; m = mf->top - mf->m.here;
452 	if (l > m) l = m , nmemb = m / size;
453 	memcpy(ptr, mf->m.buf + mf->m.here, l);
454 	mf->m.here += l;
455 	return (nmemb);
456 }
457 
mfwrite(void * ptr,size_t size,size_t nmemb,memFILE * mf)458 static size_t mfwrite(void *ptr, size_t size, size_t nmemb, memFILE *mf)
459 {
460 	size_t l;
461 
462 	if (mf->file) return (fwrite(ptr, size, nmemb, mf->file));
463 
464 	if (mf->m.here < 0) return (0);
465 	l = getmemx2(&mf->m, size * nmemb);
466 	nmemb = l / size;
467 	memcpy(mf->m.buf + mf->m.here, ptr, l);
468 	mf->m.here += l;
469 	if (mf->top < mf->m.here) mf->top = mf->m.here;
470 	return (nmemb);
471 }
472 
mfseek(memFILE * mf,f_long offset,int mode)473 static int mfseek(memFILE *mf, f_long offset, int mode)
474 {
475 // !!! For operating on tarballs, adjust fseek() params here
476 	if (mf->file) return (fseek(mf->file, offset, mode));
477 
478 	if (mode == SEEK_SET);
479 	else if (mode == SEEK_CUR) offset += mf->m.here;
480 	else if (mode == SEEK_END) offset += mf->top;
481 	else return (-1);
482 	if ((offset < 0) || (offset > MEMFILE_MAX)) return (-1);
483 	mf->m.here = offset;
484 	return (0);
485 }
486 
mfgets(char * s,int size,memFILE * mf)487 static char *mfgets(char *s, int size, memFILE *mf)
488 {
489 	size_t m;
490 	char *t, *v;
491 
492 	if (mf->file) return (fgets(s, size, mf->file));
493 
494 	if (size < 1) return (NULL);
495 	if ((mf->m.here < 0) || (mf->m.here > mf->top)) return (NULL);
496 	m = mf->top - mf->m.here;
497 	if (m >= (unsigned)size) m = size - 1;
498 	t = memchr(v = mf->m.buf + mf->m.here, '\n', m);
499 	if (t) m = t - v + 1;
500 	memcpy(s, v, m);
501 	s[m] = '\0';
502 	mf->m.here += m;
503 	return (s);
504 }
505 
mfputs(const char * s,memFILE * mf)506 static int mfputs(const char *s, memFILE *mf)
507 {
508 	size_t l;
509 
510 	if (mf->file) return (fputs(s, mf->file));
511 
512 	l = strlen(s);
513 	return (!l || mfwrite((void *)s, l, 1, mf) ? 0 : EOF);
514 }
515 
mfputss(memFILE * mf,const char * s,...)516 static int mfputss(memFILE *mf, const char *s, ...)
517 {
518 	va_list args;
519 	size_t l;
520 	int m = 0;
521 
522 	va_start(args, s);
523 	while (s)
524 	{
525 		if (mf->file) m = fputs(s, mf->file);
526 		else
527 		{
528 			l = strlen(s);
529 			m = !l || mfwrite((void *)s, l, 1, mf) ? 0 : EOF;
530 		}
531 		if (m < 0) break;
532 		s = va_arg(args, const char *);
533 	}
534 	va_end(args);
535 	return (m);
536 }
537 
copy_run(unsigned char * dest,unsigned char * src,int len,int dstep,int sstep,int bgr)538 static void copy_run(unsigned char *dest, unsigned char *src, int len,
539 	int dstep, int sstep, int bgr)
540 {
541 	if (bgr) bgr = 2;
542 	while (len-- > 0)
543 	{
544 		dest[0] = src[bgr];
545 		dest[1] = src[1];
546 		dest[2] = src[bgr ^ 2];
547 		dest += dstep;
548 		src += sstep;
549 	}
550 }
551 
552 /* Fills temp buffer row, or returns image row if no buffer */
prepare_row(unsigned char * buf,ls_settings * settings,int bpp,int y)553 static unsigned char *prepare_row(unsigned char *buf, ls_settings *settings,
554 	int bpp, int y)
555 {
556 	unsigned char *tmp, *tmi, *tma, *tms;
557 	int i, j, w = settings->width, h = y * w;
558 	int bgr = (settings->ftype == FT_BMP) || (settings->ftype == FT_TGA) ? 2 : 0;
559 
560 	tmi = settings->img[CHN_IMAGE] + h * settings->bpp;
561 	if (bpp < (bgr ? 3 : 4)) /* Return/copy image row */
562 	{
563 		if (!buf) return (tmi);
564 		memcpy(buf, tmi, w * bpp);
565 		return (buf);
566 	}
567 
568 	/* Produce BGR / BGRx / RGBx */
569 	tmp = buf;
570 	if (settings->bpp == 1) // Indexed
571 	{
572 		png_color *pal = settings->pal;
573 
574 		for (i = 0; i < w; tmp += bpp , i++)
575 		{
576 			png_color *col = pal + *tmi++;
577 			tmp[bgr] = col->red;
578 			tmp[1] = col->green;
579 			tmp[bgr ^ 2] = col->blue;
580 		}
581 	}
582 	else copy_run(tmp, tmi, w, bpp, 3, bgr); // RGB
583 
584 	/* Add alpha to the mix */
585 	tmp = buf + 3;
586 	tma = settings->img[CHN_ALPHA] + h;
587 	if (bpp == 3); // No alpha - all done
588 	else if ((settings->mode != FS_CLIPBOARD) || !settings->img[CHN_SEL])
589 	{
590 		// Only alpha here
591 		for (i = 0; i < w; tmp += bpp , i++)
592 			*tmp = *tma++;
593 	}
594 	else
595 	{
596 		// Merge alpha and selection
597 		tms = settings->img[CHN_SEL] + h;
598 		for (i = 0; i < w; tmp += bpp , i++)
599 		{
600 			j = *tma++ * *tms++;
601 			*tmp = (j + (j >> 8) + 1) >> 8;
602 		}
603 	}
604 
605 	return (buf);
606 }
607 
608 /* Converts palette-based transparency to color transparency or alpha channel */
palette_trans(ls_settings * settings,unsigned char ttb[256])609 static int palette_trans(ls_settings *settings, unsigned char ttb[256])
610 {
611 	int i, n, res;
612 
613 	/* Count transparent colors */
614 	for (i = n = 0; i < 256; i++) n += ttb[i] < 255;
615 	/* None means no transparency */
616 	settings->xpm_trans = -1;
617 	if (!n) return (0);
618 	/* One fully transparent color means color transparency */
619 	if (n == 1)
620 	{
621 		for (i = 0; i < 256; i++)
622 		{
623 			if (ttb[i]) continue;
624 			settings->xpm_trans = i;
625 			return (0);
626 		}
627 	}
628 	/* Anything else means alpha transparency */
629 	res = allocate_image(settings, CMASK_ALPHA);
630 	if (!res && settings->img[CHN_ALPHA])
631 	{
632 		unsigned char *src, *dest;
633 		size_t i = (size_t)settings->width * settings->height;
634 
635 		src = settings->img[CHN_IMAGE];
636 		dest = settings->img[CHN_ALPHA];
637 		while (i-- > 0) *dest++ = ttb[*src++];
638 	}
639 	return (res);
640 }
641 
ls_init(char * what,int save)642 static void ls_init(char *what, int save)
643 {
644 	what = g_strdup_printf(save ? __("Saving %s image") : __("Loading %s image"), what);
645 	progress_init(what, 0);
646 	g_free(what);
647 }
648 
ls_progress(ls_settings * settings,int n,int steps)649 static void ls_progress(ls_settings *settings, int n, int steps)
650 {
651 	int h = settings->height;
652 
653 	if (!settings->silent && ((n * steps) % h >= h - steps))
654 		progress_update((float)n / h);
655 }
656 
657 #if PNG_LIBPNG_VER >= 10400 /* 1.4+ */
658 #define png_set_gray_1_2_4_to_8(X) png_set_expand_gray_1_2_4_to_8(X)
659 #endif
660 
661 /* !!! libpng 1.2.17-1.2.24 was losing extra chunks if there was no callback */
buggy_libpng_handler()662 static int buggy_libpng_handler()
663 {
664 	return (0);
665 }
666 
png_memread(png_structp png_ptr,png_bytep data,png_size_t length)667 static void png_memread(png_structp png_ptr, png_bytep data, png_size_t length)
668 {
669 	memFILE *mf = (memFILE *)png_get_io_ptr(png_ptr);
670 //	memFILE *mf = (memFILE *)png_ptr->io_ptr;
671 	size_t l = mf->top - mf->m.here;
672 
673 	if (l > length) l = length;
674 	memcpy(data, mf->m.buf + mf->m.here, l);
675 	mf->m.here += l;
676 	if (l < length) png_error(png_ptr, "Read Error");
677 }
678 
png_memwrite(png_structp png_ptr,png_bytep data,png_size_t length)679 static void png_memwrite(png_structp png_ptr, png_bytep data, png_size_t length)
680 {
681 	memFILE *mf = (memFILE *)png_get_io_ptr(png_ptr);
682 //	memFILE *mf = (memFILE *)png_ptr->io_ptr;
683 
684 	if (getmemx2(&mf->m, length) < length)
685 		png_error(png_ptr, "Write Error");
686 	else
687 	{
688 		memcpy(mf->m.buf + mf->m.here, data, length);
689 		mf->top = mf->m.here += length;
690 	}
691 }
692 
png_memflush(png_structp png_ptr)693 static void png_memflush(png_structp png_ptr)
694 {
695 	/* Does nothing */
696 }
697 
698 #define PNG_BYTES_TO_CHECK 8
699 #define PNG_HANDLE_CHUNK_NEVER  1
700 #define PNG_HANDLE_CHUNK_ALWAYS 3
701 
702 static const char *chunk_names[NUM_CHANNELS] = { "", "alPh", "seLc", "maSk" };
703 
load_png(char * file_name,ls_settings * settings,memFILE * mf,int frame)704 static int load_png(char *file_name, ls_settings *settings, memFILE *mf, int frame)
705 {
706 	/* Description of PNG interlacing passes as X0, DX, Y0, DY */
707 	static const unsigned char png_interlace[8][4] = {
708 		{0, 1, 0, 1}, /* One pass for non-interlaced */
709 		{0, 8, 0, 8}, /* Seven passes for Adam7 interlaced */
710 		{4, 8, 0, 8},
711 		{0, 4, 4, 8},
712 		{2, 4, 0, 4},
713 		{0, 2, 2, 4},
714 		{1, 2, 0, 2},
715 		{0, 1, 1, 2}
716 	};
717 	static png_bytep *row_pointers;
718 	static char *msg;
719 	png_structp png_ptr;
720 	png_infop info_ptr;
721 	png_unknown_chunkp uk_p;
722 	png_uint_32 pwidth, pheight;
723 	char buf[PNG_BYTES_TO_CHECK + 1];
724 	unsigned char trans[256], *src, *dest, *dsta;
725 	long dest_len;
726 	FILE *fp = NULL;
727 	int i, j, k, bit_depth, color_type, interlace_type, num_uk, res = -1;
728 	int maxpass, x0, dx, y0, dy, n, nx, height, width, itrans = FALSE, anim = FALSE;
729 
730 	if (!mf)
731 	{
732 		if ((fp = fopen(file_name, "rb")) == NULL) return -1;
733 		i = fread(buf, 1, PNG_BYTES_TO_CHECK, fp);
734 	}
735 	else i = mfread(buf, 1, PNG_BYTES_TO_CHECK, mf);
736 	if (i != PNG_BYTES_TO_CHECK) goto fail;
737 	if (png_sig_cmp(buf, 0, PNG_BYTES_TO_CHECK)) goto fail;
738 
739 	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
740 	if (!png_ptr) goto fail;
741 
742 	row_pointers = NULL; msg = NULL;
743 	info_ptr = png_create_info_struct(png_ptr);
744 	if (!info_ptr) goto fail2;
745 
746 	if (setjmp(png_jmpbuf(png_ptr)))
747 	{
748 		res = settings->width ? FILE_LIB_ERROR : -1;
749 		goto fail2;
750 	}
751 
752 	/* Frame pseudo-files have wrong CRCs */
753 	if (frame) png_set_crc_action(png_ptr, PNG_CRC_QUIET_USE, PNG_CRC_QUIET_USE);
754 	/* !!! libpng 1.2.17-1.2.24 needs this to read extra channels */
755 	else png_set_read_user_chunk_fn(png_ptr, NULL, buggy_libpng_handler);
756 
757 	if (!mf) png_init_io(png_ptr, fp);
758 	else png_set_read_fn(png_ptr, mf, png_memread);
759 	png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK);
760 
761 	/* Stupid libpng handles private chunks on all-or-nothing basis */
762 	png_set_keep_unknown_chunks(png_ptr, frame ? PNG_HANDLE_CHUNK_NEVER :
763 		PNG_HANDLE_CHUNK_ALWAYS, NULL, 0);
764 
765 	png_read_info(png_ptr, info_ptr);
766 
767 	/* Check whether the file is APNG */
768 	num_uk = png_get_unknown_chunks(png_ptr, info_ptr, &uk_p);
769 	for (i = 0; i < num_uk; i++)
770 	{
771 		if (strcmp(uk_p[i].name, "acTL")) continue;
772 		anim = TRUE;
773 		/* mtPaint does not write APNGs with extra channels, and
774 		 * no reason to waste memory on APNG frames now */
775 		png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_NEVER, NULL, 0);
776 		png_set_read_user_chunk_fn(png_ptr, NULL, NULL);
777 	}
778 
779 	png_get_IHDR(png_ptr, info_ptr, &pwidth, &pheight, &bit_depth, &color_type,
780 		&interlace_type, NULL, NULL);
781 	if (png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE))
782 	{
783 		png_colorp png_palette;
784 
785 		png_get_PLTE(png_ptr, info_ptr, &png_palette, &settings->colors);
786 		memcpy(settings->pal, png_palette, settings->colors * sizeof(png_color));
787 		/* If palette is all we need */
788 		res = 1;
789 		if ((settings->mode == FS_PALETTE_LOAD) ||
790 			(settings->mode == FS_PALETTE_DEF)) goto fail3;
791 	}
792 
793 	res = TOO_BIG;
794 	if ((pwidth > MAX_WIDTH) || (pheight > MAX_HEIGHT)) goto fail2;
795 
796 	/* Call allocator for image data */
797 	settings->width = width = (int)pwidth;
798 	settings->height = height = (int)pheight;
799 	settings->bpp = 1;
800 	if ((color_type != PNG_COLOR_TYPE_PALETTE) || (bit_depth > 8))
801 		settings->bpp = 3;
802 	i = CMASK_IMAGE;
803 	if ((color_type == PNG_COLOR_TYPE_RGB_ALPHA) ||
804 		(color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) i = CMASK_RGBA;
805 	if ((res = allocate_image(settings, i))) goto fail2;
806 	res = FILE_MEM_ERROR;
807 
808 	i = sizeof(png_bytep) * height;
809 	row_pointers = malloc(i + width * 4);
810 	if (!row_pointers) goto fail2;
811 	row_pointers[0] = (char *)row_pointers + i;
812 
813 	if (!settings->silent)
814 	{
815 		switch(settings->mode)
816 		{
817 		case FS_PNG_LOAD:
818 			msg = "PNG";
819 			break;
820 		case FS_CLIP_FILE:
821 		case FS_CLIPBOARD:
822 			msg = __("Clipboard");
823 			break;
824 		}
825 	}
826 	if (msg) ls_init(msg, 0);
827 	res = -1;
828 
829 	/* RGB PNG file */
830 	if (settings->bpp == 3)
831 	{
832 		png_set_strip_16(png_ptr);
833 		png_set_gray_1_2_4_to_8(png_ptr);
834 		png_set_palette_to_rgb(png_ptr);
835 		png_set_gray_to_rgb(png_ptr);
836 
837 		/* Is there a transparent color? */
838 		settings->rgb_trans = -1;
839 		if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
840 		{
841 			png_color_16p trans_rgb;
842 
843 			png_get_tRNS(png_ptr, info_ptr, NULL, NULL, &trans_rgb);
844 			if (color_type == PNG_COLOR_TYPE_GRAY)
845 			{
846 				i = trans_rgb->gray;
847 				switch (bit_depth)
848 				{
849 				case 1: i *= 0xFF; break;
850 				case 2: i *= 0x55; break;
851 				case 4: i *= 0x11; break;
852 				case 8: default: break;
853 				/* Hope libpng compiled w/o accurate transform */
854 				case 16: i >>= 8; break;
855 				}
856 				settings->rgb_trans = RGB_2_INT(i, i, i);
857 			}
858 			else settings->rgb_trans = RGB_2_INT(trans_rgb->red,
859 				trans_rgb->green, trans_rgb->blue);
860 		}
861 
862 		if (settings->img[CHN_ALPHA]) /* RGBA */
863 		{
864 			nx = height;
865 			/* Have to do deinterlacing myself */
866 			if (interlace_type == PNG_INTERLACE_NONE)
867 			{
868 				k = 0; maxpass = 1;
869 			}
870 			else if (interlace_type == PNG_INTERLACE_ADAM7)
871 			{
872 				k = 1; maxpass = 8;
873 				nx = (nx + 7) & ~7; nx += 7 * (nx >> 3);
874 			}
875 			else goto fail2; /* Unknown type */
876 
877 			for (n = 0; k < maxpass; k++)
878 			{
879 				x0 = png_interlace[k][0];
880 				dx = png_interlace[k][1];
881 				y0 = png_interlace[k][2];
882 				dy = png_interlace[k][3];
883 				for (i = y0; i < height; i += dy , n++)
884 				{
885 					png_read_rows(png_ptr, &row_pointers[0], NULL, 1);
886 					src = row_pointers[0];
887 					dest = settings->img[CHN_IMAGE] + (i * width + x0) * 3;
888 					dsta = settings->img[CHN_ALPHA] + i * width;
889 					for (j = x0; j < width; j += dx)
890 					{
891 						dest[0] = src[0];
892 						dest[1] = src[1];
893 						dest[2] = src[2];
894 						dsta[j] = src[3];
895 						src += 4; dest += 3 * dx;
896 					}
897 					if (msg && ((n * 20) % nx >= nx - 20))
898 						progress_update((float)n / nx);
899 				}
900 			}
901 		}
902 		else /* RGB */
903 		{
904 			png_set_strip_alpha(png_ptr);
905 			for (i = 0; i < height; i++)
906 			{
907 				row_pointers[i] = settings->img[CHN_IMAGE] + i * width * 3;
908 			}
909 			png_read_image(png_ptr, row_pointers);
910 		}
911 	}
912 	/* Paletted PNG file */
913 	else
914 	{
915 		/* Is there a transparent index? */
916 		if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
917 		{
918 			png_bytep ptrans;
919 			int ltrans;
920 
921 			png_get_tRNS(png_ptr, info_ptr, &ptrans, &ltrans, NULL);
922 			memset(trans, 255, 256);
923 			memcpy(trans, ptrans, ltrans);
924 			itrans = TRUE;
925 		}
926 		png_set_strip_16(png_ptr);
927 		png_set_strip_alpha(png_ptr);
928 		png_set_packing(png_ptr);
929 		if ((color_type == PNG_COLOR_TYPE_GRAY) && (bit_depth < 8))
930 			png_set_gray_1_2_4_to_8(png_ptr);
931 		for (i = 0; i < height; i++)
932 		{
933 			row_pointers[i] = settings->img[CHN_IMAGE] + i * width;
934 		}
935 		png_read_image(png_ptr, row_pointers);
936 	}
937 	if (msg) progress_update(1.0);
938 
939 	png_read_end(png_ptr, info_ptr);
940 	res = 0;
941 
942 	/* Apply palette transparency */
943 	if (itrans) res = palette_trans(settings, trans);
944 
945 	num_uk = png_get_unknown_chunks(png_ptr, info_ptr, &uk_p);
946 	if (num_uk)	/* File contains mtPaint's private chunks */
947 	{
948 		for (i = 0; i < num_uk; i++)	/* Examine each chunk */
949 		{
950 			for (j = CHN_ALPHA; j < NUM_CHANNELS; j++)
951 			{
952 				if (!strcmp(uk_p[i].name, chunk_names[j])) break;
953 			}
954 			if (j >= NUM_CHANNELS) continue;
955 
956 			/* Try to allocate a channel */
957 			if ((res = allocate_image(settings, CMASK_FOR(j)))) break;
958 			/* Skip if not allocated */
959 			if (!settings->img[j]) continue;
960 
961 			dest_len = width * height;
962 			uncompress(settings->img[j], &dest_len, uk_p[i].data,
963 				uk_p[i].size);
964 		}
965 		/* !!! Is this call really needed? */
966 		png_free_data(png_ptr, info_ptr, PNG_FREE_UNKN, -1);
967 	}
968 	if (!res) res = anim ? FILE_HAS_FRAMES : 1;
969 
970 #ifdef U_LCMS
971 #ifdef PNG_iCCP_SUPPORTED
972 	/* Extract ICC profile if it's of use */
973 	if (!settings->icc_size)
974 	{
975 #if PNG_LIBPNG_VER >= 10600 /* 1.6+ */
976 		png_bytep icc;
977 #else
978 		png_charp icc;
979 #endif
980 		png_charp name;
981 		png_uint_32 len;
982 		int comp;
983 
984 		if (png_get_iCCP(png_ptr, info_ptr, &name, &comp, &icc, &len) &&
985 			(len < INT_MAX) && (settings->icc = malloc(len)))
986 		{
987 			settings->icc_size = len;
988 			memcpy(settings->icc, icc, len);
989 		}
990 	}
991 #endif
992 #endif
993 
994 fail2:	if (msg) progress_end();
995 	free(row_pointers);
996 fail3:	png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
997 fail:	if (fp) fclose(fp);
998 	return (res);
999 }
1000 
1001 #ifndef PNG_AFTER_IDAT
1002 #define PNG_AFTER_IDAT 8
1003 #endif
1004 
save_png(char * file_name,ls_settings * settings,memFILE * mf)1005 static int save_png(char *file_name, ls_settings *settings, memFILE *mf)
1006 {
1007 	png_unknown_chunk unknown0;
1008 	png_structp png_ptr;
1009 	png_infop info_ptr;
1010 	FILE *fp = NULL;
1011 	int h = settings->height, w = settings->width, bpp = settings->bpp;
1012 	int i, j, res = -1;
1013 	long uninit_(dest_len), res_len;
1014 	char *mess = NULL;
1015 	unsigned char trans[256], *tmp, *rgba_row = NULL;
1016 	png_color_16 trans_rgb;
1017 
1018 	/* Baseline PNG format does not support alpha for indexed images, so
1019 	 * we have to convert them to RGBA for clipboard export - WJ */
1020 	if (((settings->mode == FS_CLIPBOARD) || (bpp == 3)) &&
1021 		settings->img[CHN_ALPHA])
1022 	{
1023 		rgba_row = malloc(w * 4);
1024 		if (!rgba_row) return (-1);
1025 		bpp = 4;
1026 	}
1027 
1028 	if (!settings->silent)
1029 	switch(settings->mode)
1030 	{
1031 	case FS_PNG_SAVE:
1032 		mess = "PNG";
1033 		break;
1034 	case FS_CLIP_FILE:
1035 	case FS_CLIPBOARD:
1036 		mess = __("Clipboard");
1037 		break;
1038 	case FS_COMPOSITE_SAVE:
1039 		mess = __("Layer");
1040 		break;
1041 	case FS_CHANNEL_SAVE:
1042 		mess = __("Channel");
1043 		break;
1044 	default:
1045 		settings->silent = TRUE;
1046 		break;
1047 	}
1048 
1049 	if (!mf && ((fp = fopen(file_name, "wb")) == NULL)) goto exit0;
1050 
1051 	png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL);
1052 
1053 	if (!png_ptr) goto exit1;
1054 
1055 	info_ptr = png_create_info_struct(png_ptr);
1056 	if (!info_ptr) goto exit2;
1057 
1058 	res = 0;
1059 
1060 	if (!mf) png_init_io(png_ptr, fp);
1061 	else png_set_write_fn(png_ptr, mf, png_memwrite, png_memflush);
1062 	png_set_compression_level(png_ptr, settings->png_compression);
1063 
1064 	if (bpp == 1)
1065 	{
1066 		png_set_IHDR(png_ptr, info_ptr, w, h,
1067 			8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
1068 			PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1069 		png_set_PLTE(png_ptr, info_ptr, settings->pal, settings->colors);
1070 		/* Transparent index in use */
1071 		if ((settings->xpm_trans > -1) && (settings->xpm_trans < 256))
1072 		{
1073 			memset(trans, 255, 256);
1074 			trans[settings->xpm_trans] = 0;
1075 			png_set_tRNS(png_ptr, info_ptr, trans, settings->colors, 0);
1076 		}
1077 	}
1078 	else
1079 	{
1080 		png_set_IHDR(png_ptr, info_ptr, w, h,
1081 			8, bpp == 4 ? PNG_COLOR_TYPE_RGB_ALPHA :
1082 			PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
1083 			PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1084 		if (settings->pal) png_set_PLTE(png_ptr, info_ptr, settings->pal,
1085 			settings->colors);
1086 		/* Transparent index in use */
1087 		if ((settings->rgb_trans > -1) && !settings->img[CHN_ALPHA])
1088 		{
1089 			trans_rgb.red = INT_2_R(settings->rgb_trans);
1090 			trans_rgb.green = INT_2_G(settings->rgb_trans);
1091 			trans_rgb.blue = INT_2_B(settings->rgb_trans);
1092 			png_set_tRNS(png_ptr, info_ptr, 0, 1, &trans_rgb);
1093 		}
1094 	}
1095 
1096 	png_write_info(png_ptr, info_ptr);
1097 
1098 	if (mess) ls_init(mess, 1);
1099 
1100 	for (j = 0; j < h; j++)
1101 	{
1102 		tmp = prepare_row(rgba_row, settings, bpp, j);
1103 		png_write_row(png_ptr, (png_bytep)tmp);
1104 		ls_progress(settings, j, 20);
1105 	}
1106 
1107 	/* Save private chunks into PNG file if we need to */
1108 	/* !!! Uncomment if default setting ever gets inadequate (in 1.7+) */
1109 //	png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_ALWAYS, NULL, 0);
1110 	tmp = NULL;
1111 	i = bpp == 1 ? CHN_ALPHA : CHN_ALPHA + 1;
1112 	if (settings->mode == FS_CLIPBOARD) i = NUM_CHANNELS; // Disable extensions
1113 	for (j = 0; i < NUM_CHANNELS; i++)
1114 	{
1115 		if (!settings->img[i]) continue;
1116 		if (!tmp)
1117 		{
1118 			/* Get size required for each zlib compress */
1119 			w = settings->width * settings->height;
1120 #if ZLIB_VERNUM >= 0x1200
1121 			dest_len = compressBound(w);
1122 #else
1123 			dest_len = w + (w >> 8) + 32;
1124 #endif
1125 			res = -1;
1126 			tmp = malloc(dest_len);	  // Temporary space for compression
1127 			if (!tmp) break;
1128 			res = 0;
1129 		}
1130 		res_len = dest_len;
1131 		if (compress2(tmp, &res_len, settings->img[i], w,
1132 			settings->png_compression) != Z_OK) continue;
1133 		strncpy(unknown0.name, chunk_names[i], 5);
1134 		unknown0.data = tmp;
1135 		unknown0.size = res_len;
1136 		unknown0.location = PNG_AFTER_IDAT;
1137 		png_set_unknown_chunks(png_ptr, info_ptr, &unknown0, 1);
1138 #if PNG_LIBPNG_VER < 10600 /* before 1.6 */
1139 		png_set_unknown_chunk_location(png_ptr, info_ptr,
1140 			j++, PNG_AFTER_IDAT);
1141 #endif
1142 	}
1143 	free(tmp);
1144 	png_write_end(png_ptr, info_ptr);
1145 
1146 	if (mess) progress_end();
1147 
1148 	/* Tidy up */
1149 exit2:	png_destroy_write_struct(&png_ptr, &info_ptr);
1150 exit1:	if (fp) fclose(fp);
1151 exit0:	free(rgba_row);
1152 	return (res);
1153 }
1154 
1155 /* *** PREFACE ***
1156  * Contrary to what GIF89 docs say, all contemporary browser implementations
1157  * always render background in an animated GIF as transparent. So does mtPaint,
1158  * for some GIF animations depend on this rule.
1159  * An inter-frame delay of 0 normally means that the two (or more) frames
1160  * are parts of same animation frame and should be rendered as one resulting
1161  * frame; but some (ancient) GIFs have all delays set to 0, but still contain
1162  * animation sequences. So the handling of zero-delay frames is user-selectable
1163  * in mtPaint. */
1164 
1165 /* Animation state */
1166 typedef struct {
1167 	unsigned char lmap[MAX_DIM];
1168 	image_frame prev;
1169 	int prev_idx; // Frame index+1, so that 0 means None
1170 	int have_frames; // Set after first
1171 	int defw, defh, bk_rect[4];
1172 	int mode;
1173 	/* Extra fields for paletted images */
1174 	int global_cols, newcols, newtrans;
1175 	png_color global_pal[256], newpal[256];
1176 	unsigned char xlat[513];
1177 	/* Extra fields for RGBA images */
1178 	int blend;
1179 	unsigned char bkg[4];
1180 } ani_status;
1181 
1182 /* Initialize palette remapping table */
ani_init_xlat(ani_status * stat)1183 static void ani_init_xlat(ani_status *stat)
1184 {
1185 	int i;
1186 
1187 	for (i = 0; i < 256; i++) stat->xlat[i] = stat->xlat[i + 256] = i;
1188 	stat->xlat[512] = stat->newtrans;
1189 }
1190 
1191 /* Calculate new frame dimensions, and point-in-area bitmap */
ani_map_frame(ani_status * stat,ls_settings * settings)1192 static void ani_map_frame(ani_status *stat, ls_settings *settings)
1193 {
1194 	unsigned char *lmap;
1195 	int i, j, w, h;
1196 
1197 
1198 	/* Calculate the new dimensions */
1199 // !!! Offsets considered nonnegative (as in GIF, WebP and APNG)
1200 	w = settings->x + settings->width;
1201 	h = settings->y + settings->height;
1202 	if (!stat->have_frames) // Resize screen to fit the first frame
1203 	{
1204 		if (w > MAX_WIDTH) w = MAX_WIDTH;
1205 		if (h > MAX_HEIGHT) h = MAX_HEIGHT;
1206 		if (stat->defw < w) stat->defw = w;
1207 		if (stat->defh < h) stat->defh = h;
1208 		stat->have_frames = TRUE;
1209 	}
1210 	else // Clip all frames past the first to screen size
1211 	{
1212 		if (stat->defw < w) w = stat->defw;
1213 		if (stat->defh < h) h = stat->defh;
1214 	}
1215 
1216 	/* The bitmap works this way: "Xth byte & (Yth byte >> 4)" tells which
1217 	 * area(s) the pixel (X,Y) is in: bit 0 is for image (the new one),
1218 	 * bit 1 is for underlayer (the previous composited frame), and bit 2
1219 	 * is for hole in it (if "restore to background" was last) */
1220 	j = stat->defw > stat->defh ? stat->defw : stat->defh;
1221 	memset(lmap = stat->lmap, 0, j);
1222 	// Mark new frame
1223 	for (i = settings->x; i < w; i++) lmap[i] |= 0x01; // Image bit
1224 	for (i = settings->y; i < h; i++) lmap[i] |= 0x10; // Image mask bit
1225 	// Mark previous frame
1226 	if (stat->prev_idx)
1227 	{
1228 		for (i = stat->prev.x , j = i + stat->prev.width; i < j; i++)
1229 			lmap[i] |= 0x02; // Underlayer bit
1230 		for (i = stat->prev.y , j = i + stat->prev.height; i < j; i++)
1231 			lmap[i] |= 0x20; // Underlayer mask bit
1232 	}
1233 	// Mark disposal area
1234 	if (clip(stat->bk_rect, 0, 0, stat->defw, stat->defh, stat->bk_rect))
1235 	{
1236 		for (i = stat->bk_rect[0] , j = stat->bk_rect[2]; i < j; i++)
1237 			lmap[i] |= 0x04; // Background bit
1238 		for (i = stat->bk_rect[1] , j = stat->bk_rect[3]; i < j; i++)
1239 			lmap[i] |= 0x40; // Background mask bit
1240 	}
1241 }
1242 
1243 /* Allowed bpp: 0 - move, 1 - indexed, 3 - RGB, 4 - RGBA
1244  * Indexed+alpha not supported nor should be: cannot be saved as standard PNG */
add_frame(ani_settings * ani,ani_status * stat,ls_settings * settings,int bpp,int disposal)1245 static int add_frame(ani_settings *ani, ani_status *stat, ls_settings *settings,
1246 	int bpp, int disposal)
1247 {
1248 	int cmask = !bpp ? CMASK_NONE : bpp > 3 ? CMASK_RGBA : CMASK_IMAGE;
1249 	int fbpp = !bpp ? settings->bpp : bpp > 3 ? 3 : bpp;
1250 	image_frame *frame;
1251 
1252 	/* Allocate a new frame */
1253 	if (!mem_add_frame(&ani->fset, stat->defw, stat->defh, fbpp, cmask,
1254 		stat->newpal)) return (FILE_MEM_ERROR);
1255 	frame = ani->fset.frames + (ani->fset.cnt - 1);
1256 	frame->cols = stat->newcols;
1257 	frame->trans = stat->newtrans;
1258 	frame->delay = settings->gif_delay;
1259 	frame->flags = disposal; // Pass to compositing
1260 	/* Tag zero-delay frame for deletion if requested */
1261 	if ((ani->lastzero = (stat->mode == ANM_NOZERO) &&
1262 		!settings->gif_delay)) frame->flags |= FM_NUKE;
1263 	if (!bpp) // Same bpp & dimensions - reassign the chanlist
1264 	{
1265 		memcpy(frame->img, settings->img, sizeof(chanlist));
1266 		memset(settings->img, 0, sizeof(chanlist));
1267 	}
1268 	return (0);
1269 }
1270 
done_frame(char * file_name,ani_settings * ani,int last)1271 static int done_frame(char *file_name, ani_settings *ani, int last)
1272 {
1273 	int res = 1;
1274 
1275 	if ((ani->settings.mode == FS_EXPLODE_FRAMES) && (!last ^ ani->lastzero))
1276 		res = write_out_frame(file_name, ani, NULL);
1277 	return (res ? res : 1);
1278 }
1279 
composite_indexed_frame(image_frame * frame,ani_status * stat,ls_settings * settings)1280 static void composite_indexed_frame(image_frame *frame, ani_status *stat,
1281 		ls_settings *settings)
1282 {
1283 	unsigned char *dest, *fg0, *bg0 = NULL, *lmap = stat->lmap;
1284 	image_frame *bkf = &stat->prev;
1285 	int w, fgw, bgw = 0, urgb = 0, tp = settings->xpm_trans;
1286 
1287 	w = frame->width;
1288 	dest = frame->img[CHN_IMAGE];
1289 	fgw = settings->width;
1290 	fg0 = settings->img[CHN_IMAGE] ? settings->img[CHN_IMAGE] -
1291 		(settings->y * fgw + settings->x) : dest; // Always indexed (1 bpp)
1292 	/* Pointer to absent underlayer is no problem - it just won't get used */
1293 	bgw = bkf->width;
1294 	bg0 = bkf->img[CHN_IMAGE] - (bkf->y * bgw + bkf->x) * bkf->bpp;
1295 	urgb = bkf->bpp != 1;
1296 
1297 	if (frame->bpp == 1) // To indexed
1298 	{
1299 		unsigned char *fg = fg0, *bg = bg0, *xlat = stat->xlat;
1300 		int x, y;
1301 
1302 		for (y = 0; y < frame->height; y++)
1303 		{
1304 			int bmask = lmap[y] >> 4;
1305 
1306 			for (x = 0; x < w; x++)
1307 			{
1308 				int c0, bflag = lmap[x] & bmask;
1309 
1310 				if ((bflag & 1) && ((c0 = fg[x]) != tp)) // New frame
1311 					c0 += 256;
1312 				else if ((bflag & 6) == 2) // Underlayer
1313 					c0 = bg[x];
1314 				else c0 = 512; // Background (transparent)
1315 				*dest++ = xlat[c0];
1316 			}
1317 			fg += fgw; bg += bgw;
1318 		}
1319 	}
1320 	else // To RGB
1321 	{
1322 		unsigned char rgb[513 * 3], *fg = fg0, *bg = bg0;
1323 		int x, y, bpp = urgb + urgb + 1;
1324 
1325 		/* Setup global palette map: underlayer, image, background */
1326 		if (bkf->pal) pal2rgb(rgb, bkf->pal, 256, 0);
1327 		pal2rgb(rgb + 256 * 3,
1328 			settings->colors ? settings->pal : stat->global_pal, 256, 257);
1329 		frame->trans = -1; // No color-key transparency
1330 
1331 		for (y = 0; y < frame->height; y++)
1332 		{
1333 			int bmask = lmap[y] >> 4;
1334 
1335 			for (x = 0; x < w; x++)
1336 			{
1337 				unsigned char *src;
1338 				int c0, bflag = lmap[x] & bmask;
1339 
1340 				if ((bflag & 1) && ((c0 = fg[x]) != tp)) // New frame
1341 					src = rgb + (256 * 3) + (c0 * 3);
1342 				else if ((bflag & 6) == 2) // Underlayer
1343 					src = urgb ? bg + x * 3 : rgb + bg[x] * 3;
1344 				else src = rgb + 512 * 3; // Background (black)
1345 				dest[0] = src[0];
1346 				dest[1] = src[1];
1347 				dest[2] = src[2];
1348 				dest += 3;
1349 			}
1350 			fg += fgw; bg += bgw * bpp;
1351 		}
1352 	}
1353 
1354 	if (frame->img[CHN_ALPHA]) // To alpha
1355 	{
1356 		unsigned char *fg = fg0, *bg = NULL;
1357 		int x, y, af = 0, utp = -1;
1358 
1359 		dest = frame->img[CHN_ALPHA];
1360 		utp = bkf->bpp == 1 ? bkf->trans : -1;
1361 		af = !!bkf->img[CHN_ALPHA]; // Underlayer has alpha
1362 		bg = bkf->img[af ? CHN_ALPHA : CHN_IMAGE] - (bkf->y * bgw + bkf->x);
1363 
1364 		for (y = 0; y < frame->height; y++)
1365 		{
1366 			int bmask = lmap[y] >> 4;
1367 
1368 			for (x = 0; x < w; x++)
1369 			{
1370 				int c0, bflag = lmap[x] & bmask;
1371 
1372 				if ((bflag & 1) && (fg[x] != tp)) // New frame
1373 					c0 = 255;
1374 				else if ((bflag & 6) == 2) // Underlayer
1375 				{
1376 					c0 = bg[x];
1377 					if (!af) c0 = c0 != utp ? 255 : 0;
1378 				}
1379 				else c0 = 0; // Background (transparent)
1380 				*dest++ = c0;
1381 			}
1382 			fg += fgw; bg += bgw;
1383 		}
1384 	}
1385 }
1386 
composite_rgba_frame(image_frame * frame,ani_status * stat,ls_settings * settings)1387 static void composite_rgba_frame(image_frame *frame, ani_status *stat,
1388 		ls_settings *settings)
1389 {
1390 	static unsigned char bkg0[4]; // Default transparent black
1391 	unsigned char mask[MAX_WIDTH], alpha[MAX_WIDTH], pal[768];
1392 	unsigned char *dest, *src, *dsta, *srca, *bg, *bga, *lmap = stat->lmap;
1393 	image_frame *bkf = &stat->prev;
1394 	int rxy[4] = { 0, 0, frame->width, frame->height };
1395 	int x, y, w, bgw, bgoff, fgw, ww, fgoff, dstoff, bpp, tr;
1396 
1397 
1398 	/* Do the mixing if source is present */
1399 	if (!settings->img[CHN_IMAGE]) return;
1400 
1401 	w = frame->width;
1402 	bgw = bkf->width;
1403 	bgoff = bkf->y * bgw + bkf->x;
1404 	bpp = bkf->bpp;
1405 	if (bpp == 1) pal2rgb(pal, bkf->pal, bkf->cols, 256);
1406 
1407 	/* First, generate the destination RGB */
1408 	dest = frame->img[CHN_IMAGE];
1409 	bg = bkf->img[CHN_IMAGE] - bgoff * bpp; // Won't get used if not valid
1410 	for (y = 0; y < frame->height; y++)
1411 	{
1412 		int bmask = lmap[y] >> 4;
1413 
1414 		for (x = 0; x < w; x++)
1415 		{
1416 			unsigned char *rgb = bkg0; // Default black
1417 			int bflag = lmap[x] & bmask;
1418 
1419 			if (bflag & 4) rgb = stat->bkg; // Background in the hole
1420 			else if (bflag & 2) // Underlayer
1421 				rgb = bpp == 1 ? pal + bg[x] * 3 : bg + x * 3;
1422 			dest[0] = rgb[0];
1423 			dest[1] = rgb[1];
1424 			dest[2] = rgb[2];
1425 			dest += 3;
1426 		}
1427 		bg += bgw * bpp;
1428 	}
1429 
1430 	/* Then, destination alpha */
1431 	dsta = frame->img[CHN_ALPHA];
1432 	bga = bkf->img[CHN_ALPHA] ? bkf->img[CHN_ALPHA] - bgoff : NULL;
1433 	if (dsta) for (y = 0; y < frame->height; y++)
1434 	{
1435 		int bmask = lmap[y] >> 4;
1436 
1437 		for (x = 0; x < w; x++)
1438 		{
1439 			int bflag = lmap[x] & bmask, a = 0; // Default transparent
1440 			if (bflag & 2) a = bga ? bga[x] : 255; // Underlayer
1441 			if (bflag & 4) a = stat->bkg[3]; // Background in the hole
1442 			*dsta++ = a;
1443 		}
1444 		if (bga) bga += bgw;
1445 	}
1446 
1447 	/* Then, check if the new frame is in bounds */
1448 	if (!clip(rxy, settings->x, settings->y,
1449 		settings->x + settings->width, settings->y + settings->height, rxy)) return;
1450 
1451 	/* Then, paste it over */
1452 	fgw = settings->width;
1453 	ww = rxy[2] - rxy[0];
1454 	fgoff = (rxy[1] - settings->y) * fgw + (rxy[0] - settings->x);
1455 	dstoff = rxy[1] * w + rxy[0];
1456 	memset(alpha, 255, ww);
1457 	tr = settings->rgb_trans;
1458 	for (y = rxy[1]; y < rxy[3]; y++)
1459 	{
1460 		dsta = frame->img[CHN_ALPHA] ? frame->img[CHN_ALPHA] + dstoff : NULL;
1461 		srca = settings->img[CHN_ALPHA] ? settings->img[CHN_ALPHA] + fgoff : NULL;
1462 		dest = frame->img[CHN_IMAGE] + dstoff * 3;
1463 		src = settings->img[CHN_IMAGE] + fgoff * 3;
1464 
1465 		if (stat->blend) // Do alpha blend
1466 		{
1467 			memset(mask, 0, ww);
1468 			if (tr >= 0) mem_mask_colors(mask, src, 255, ww, 1, 3, tr, tr);
1469 			process_mask(0, 1, ww, mask, dsta, dsta, alpha, srca, 255, FALSE);
1470 			process_img(0, 1, ww, mask, dest, dest, src, NULL, 3, BLENDF_SET);
1471 		}
1472 		else // Do a copy
1473 		{
1474 			memcpy(dest, src, ww * 3); // Copy image
1475 			if (!dsta); // No alpha
1476 			else if (srca) memcpy(dsta, srca, ww); // Copy alpha
1477 			else
1478 			{
1479 				memset(dsta, 255, ww); // Fill alpha
1480 				if (tr >= 0) mem_mask_colors(dsta, src, 0, ww, 1, 3, tr, tr);
1481 			}
1482 		}
1483 		fgoff += fgw; dstoff += w;
1484 	}
1485 }
1486 
composite_frame(frameset * fset,ani_status * stat,ls_settings * settings)1487 static void composite_frame(frameset *fset, ani_status *stat, ls_settings *settings)
1488 {
1489 	image_frame *frame = fset->frames + (fset->cnt - 1);
1490 	int disposal;
1491 
1492 
1493 	/* In raw mode, just store the offsets */
1494 	if (stat->mode <= ANM_RAW)
1495 	{
1496 		frame->x = settings->x;
1497 		frame->y = settings->y;
1498 	}
1499 	else
1500 	{
1501 		/* Read & clear disposal mode */
1502 		disposal = frame->flags & FM_DISPOSAL;
1503 		frame->flags ^= disposal ^ FM_DISP_REMOVE;
1504 
1505 		/* For WebP and RGB[A] APNG */
1506 		if (settings->bpp == 3) composite_rgba_frame(frame, stat, settings);
1507 		/* For GIF & indexed[+T] APNG */
1508 		else
1509 		{
1510 			/* No blend means ignoring transparent color */
1511 			if (!stat->blend) settings->xpm_trans = -1;
1512 			composite_indexed_frame(frame, stat, settings);
1513 		}
1514 
1515 		/* Drop alpha if not used */
1516 		if (frame->img[CHN_ALPHA] && is_filled(frame->img[CHN_ALPHA], 255,
1517 			frame->width * frame->height))
1518 		{
1519 			free(frame->img[CHN_ALPHA]);
1520 			frame->img[CHN_ALPHA] = NULL;
1521 		}
1522 
1523 		/* If transparent color and alpha are both present, convert the
1524 		 * color into alpha, as PNG does not allow combining them */
1525 		if ((frame->trans >= 0) && frame->img[CHN_ALPHA])
1526 		{
1527 			/* RGBA: indexed+alpha blocked elsewhere for same reason */
1528 			/* Use palette that add_frame() assigns */
1529 			int tr = PNG_2_INT(stat->newpal[frame->trans]);
1530 			mem_mask_colors(frame->img[CHN_ALPHA], frame->img[CHN_IMAGE],
1531 				0, frame->width, frame->height, 3, tr, tr);
1532 			frame->trans = -1;
1533 		}
1534 
1535 		/* Prepare the disposal action */
1536 		if (disposal == FM_DISP_REMOVE) // Dispose to background
1537 		{
1538 			// Image-sized hole in underlayer
1539 			stat->bk_rect[2] = (stat->bk_rect[0] = settings->x) +
1540 				settings->width;
1541 			stat->bk_rect[3] = (stat->bk_rect[1] = settings->y) +
1542 				settings->height;
1543 		}
1544 		if (disposal == FM_DISP_LEAVE) // Don't dispose
1545 			memset(&stat->bk_rect, 0, sizeof(stat->bk_rect)); // Clear old
1546 		if ((disposal == FM_DISP_REMOVE) || (disposal == FM_DISP_LEAVE))
1547 		{
1548 			stat->prev = *frame; // Current frame becomes underlayer
1549 			if (!stat->prev.pal) stat->prev.pal = fset->pal;
1550 			if (stat->prev_idx &&
1551 				(fset->frames[stat->prev_idx - 1].flags & FM_NUKE))
1552 				/* Remove the unref'd frame */
1553 				mem_remove_frame(fset, stat->prev_idx - 1);
1554 			stat->prev_idx = fset->cnt;
1555 		}
1556 		/* if (disposal == FM_DISP_RESTORE); // Dispose to previous
1557 			// Underlayer and hole stay unchanged */
1558 	}
1559 	if ((fset->cnt > 1) && (stat->prev_idx != fset->cnt - 1) &&
1560 		(fset->frames[fset->cnt - 2].flags & FM_NUKE))
1561 	{
1562 		/* Remove the next-to-last frame */
1563 		mem_remove_frame(fset, fset->cnt - 2);
1564 		if (stat->prev_idx > fset->cnt)
1565 			stat->prev_idx = fset->cnt;
1566 	}
1567 }
1568 
analyze_rgba_frame(ani_status * stat,ls_settings * settings)1569 static int analyze_rgba_frame(ani_status *stat, ls_settings *settings)
1570 {
1571 	int same_size, holes, alpha0, alpha1, alpha, bpp;
1572 
1573 	if (stat->mode <= ANM_RAW) // Raw frame mode
1574 	{
1575 		stat->defw = settings->width;
1576 		stat->defh = settings->height;
1577 		return (0); // Output matches input
1578 	}
1579 	else if ((stat->defw > MAX_WIDTH) || (stat->defh > MAX_HEIGHT))
1580 		return (-1); // Too large
1581 
1582 	ani_map_frame(stat, settings);
1583 	same_size = !(settings->x | settings->y |
1584 		(stat->defw ^ settings->width) | (stat->defh ^ settings->height));
1585 	holes = !same_size || stat->blend;
1586 
1587 	if (same_size && !holes) return (0); // New replaces old
1588 
1589 	/* Indexed with transparent color (from APNG) stay as they were:
1590 	 * no local palettes there, upgrade to RGB/RGBA never needed */
1591 	if ((settings->bpp == 1) && (settings->xpm_trans >= 0))
1592 		return (same_size ? 0 : 1);
1593 
1594 	/* Alpha transparency on underlayer */
1595 	alpha0 = !stat->prev_idx || stat->prev.img[CHN_ALPHA];
1596 	/* Transparency from disposal to background */
1597 	if ((stat->bk_rect[0] < stat->bk_rect[2]) &&
1598 		(stat->bk_rect[1] < stat->bk_rect[3]))
1599 		alpha0 |= stat->bkg[3] < 255;
1600 	/* Alpha transparency from this layer */
1601 	alpha1 = !stat->blend && settings->img[CHN_ALPHA];
1602 	/* Result */
1603 	alpha = alpha1 | (alpha0 & holes);
1604 
1605 	/* Output bpp is max of underlayer & image */
1606 	bpp = (stat->prev.bpp == 3) || (settings->bpp == 3) ? 3 : 1;
1607 	/* Do not produce indexed+alpha as regular PNG does not support that */
1608 	if (alpha) bpp = 4;
1609 
1610 	/* !!! composite_rgba_frame() as of now cannot handle frame == dest, so
1611 	 * do not return 0 even if same size, bpp & alpha, w/o rewriting that */
1612 	return (bpp);
1613 }
1614 
1615 /* In absence of library support, APNG files are read through building in memory
1616  * a regular PNG file for a frame, and then feeding that to libpng - WJ */
1617 
1618 /* Macros for accessing values in Motorola byte order */
1619 #define GET16B(buf) (((buf)[0] << 8) + (buf)[1])
1620 #define GET32B(buf) (((unsigned)(buf)[0] << 24) + ((buf)[1] << 16) + \
1621 	((buf)[2] << 8) + (buf)[3])
1622 #define PUT16B(buf, v) (buf)[0] = (v) >> 8; (buf)[1] = (v) & 0xFF;
1623 #define PUT32B(buf, v) (buf)[0] = (v) >> 24; (buf)[1] = ((v) >> 16) & 0xFF; \
1624 	(buf)[2] = ((v) >> 8) & 0xFF; (buf)[3] = (v) & 0xFF;
1625 
1626 /* Macros for relevant PNG tags; big-endian */
1627 #define TAG4B_IHDR TAG4B('I', 'H', 'D', 'R')
1628 #define TAG4B_IDAT TAG4B('I', 'D', 'A', 'T')
1629 #define TAG4B_IEND TAG4B('I', 'E', 'N', 'D')
1630 #define TAG4B_acTL TAG4B('a', 'c', 'T', 'L')
1631 #define TAG4B_fcTL TAG4B('f', 'c', 'T', 'L')
1632 #define TAG4B_fdAT TAG4B('f', 'd', 'A', 'T')
1633 
1634 /* PNG block header */
1635 #define PNG_SIZE    0 /* 32b */
1636 #define PNG_TAG     4 /* 32b */
1637 #define PNG_HSIZE   8
1638 
1639 /* IHDR block */
1640 #define IHDR_W      0 /* 32b */
1641 #define IHDR_H      4 /* 32b */
1642 #define IHDR_SIZE  13
1643 
1644 /* acTL block */
1645 #define acTL_FCNT   0 /* 32b */
1646 #define acTL_SIZE   8
1647 
1648 /* fcTL block */
1649 #define fcTL_SEQ    0 /* 32b */
1650 #define fcTL_W      4 /* 32b */
1651 #define fcTL_H      8 /* 32b */
1652 #define fcTL_X     12 /* 32b */
1653 #define fcTL_Y     16 /* 32b */
1654 #define fcTL_DN    20 /* 16b */
1655 #define fcTL_DD    22 /* 16b */
1656 #define fcTL_DISP  24 /*  8b */
1657 #define fcTL_BLEND 25 /*  8b */
1658 #define fcTL_SIZE  26
1659 
1660 typedef struct {
1661 	int w, h, disp;
1662 	f_long ihdr, idat0, fdat0, fdat1;
1663 	unsigned frames;
1664 	unsigned char fctl[fcTL_SIZE];
1665 	int phase;
1666 	unsigned char *png;	// Buffer for fake file
1667 	size_t sz;		// Buffer size
1668 	memFILE mf;
1669 } pnghead;
1670 
1671 /* Build in-memory PNG from file header and frame data, ignoring CRCs */
assemble_png(FILE * fp,pnghead * pg)1672 static int assemble_png(FILE *fp, pnghead *pg)
1673 {
1674 	size_t l = pg->idat0 + (pg->fdat1 - pg->fdat0) + PNG_HSIZE + 4;
1675 	unsigned char *src, *dest, *wrk = pg->png;
1676 	unsigned tag, tl, u, seq;
1677 
1678 
1679 	/* Enlarge the buffer if needed */
1680 	if (l > pg->sz)
1681 	{
1682 		if (l > MEMFILE_MAX) return (FILE_MEM_ERROR);
1683 		dest = realloc(pg->png, l);
1684 		if (!dest) return (FILE_MEM_ERROR);
1685 		pg->png = dest;
1686 		pg->sz = l;
1687 	}
1688 	/* Read in the header on first pass */
1689 	if (!wrk)
1690 	{
1691 		fseek(fp, 0, SEEK_SET);
1692 		if (!fread(pg->png, pg->idat0, 1, fp)) return (-1);
1693 	}
1694 	/* Modify the header */
1695 	wrk = pg->png + pg->ihdr;
1696 	memcpy(wrk + IHDR_W, pg->fctl + fcTL_W, 4);
1697 	memcpy(wrk + IHDR_H, pg->fctl + fcTL_H, 4);
1698 	/* Read in body */
1699 	wrk = pg->png + pg->idat0;
1700 	fseek(fp, pg->fdat0, SEEK_SET);
1701 	l = pg->fdat1 - pg->fdat0;
1702 	if (!fread(wrk, l, 1, fp)) return (-1);
1703 	/* Reformat the body blocks if needed */
1704 	seq = GET32B(pg->fctl + fcTL_SEQ);
1705 	src = dest = wrk;
1706 	while (l)
1707 	{
1708 		tag = GET32B(src + PNG_TAG);
1709 		tl = GET32B(src + PNG_SIZE);
1710 		if (tl > l - PNG_HSIZE - 4) return (-1); // Paranoia
1711 		l -= u = PNG_HSIZE + tl + 4;
1712 		if (tag == TAG4B_fdAT)
1713 		{
1714 			if (tl < 4) return (-1); // Paranoia
1715 			if (GET32B(src + PNG_HSIZE) != ++seq) return (-1); // Sequence
1716 			tl -= 4;
1717 			PUT32B(dest + PNG_SIZE, tl);
1718 			memcpy(dest + PNG_TAG, "IDAT", 4);
1719 			memmove(dest + PNG_HSIZE, src + PNG_HSIZE + 4, tl);
1720 		}
1721 		else if (src != dest) memmove(dest, src, u);
1722 		src += u;
1723 		dest += PNG_HSIZE + tl + 4;
1724 	}
1725 	/* Add IEND */
1726 	PUT32B(dest + PNG_SIZE, 0);
1727 	memcpy(dest + PNG_TAG, "IEND", 4);
1728 	/* Prepare file buffer */
1729 	memset(&pg->mf, 0, sizeof(pg->mf));
1730 	pg->mf.m.buf = pg->png;
1731 	pg->mf.top = pg->mf.m.size = dest + PNG_HSIZE + 4 - pg->png;
1732 	return (0);
1733 }
1734 
png_scan(FILE * fp,pnghead * pg)1735 static int png_scan(FILE *fp, pnghead *pg)
1736 {
1737 	/* APNG disposal codes mapping */
1738 	static const unsigned short apng_disposal[3] = {
1739 		FM_DISP_LEAVE, FM_DISP_REMOVE, FM_DISP_RESTORE };
1740 	unsigned char buf[256];
1741 	unsigned tag, tl, w, h;
1742 	f_long p = ftell(fp);
1743 
1744 	if (p <= 0) return (-1); // Sanity check
1745 
1746 	/* Read block headers & see what we get */
1747 	pg->phase = 0;
1748 	while (TRUE)
1749 	{
1750 		if (fread(buf, 1, PNG_HSIZE, fp) < PNG_HSIZE)
1751 		{
1752 			if (pg->phase != 2) break; // Fail
1753 			pg->phase = 4; // Improper end
1754 			return (0); // Done
1755 		}
1756 		tag = GET32B(buf + PNG_TAG);
1757 		tl = GET32B(buf + PNG_SIZE);
1758 		if (tl > 0x7FFFFFFFU) break; // Limit
1759 		if (p > F_LONG_MAX - tl - PNG_HSIZE - 4) break; // File too large
1760 
1761 		if (tag == TAG4B_IHDR)
1762 		{
1763 			if (tl < IHDR_SIZE) break; // Bad
1764 			if (pg->ihdr) break; // There must be only one
1765 			pg->ihdr = p + PNG_HSIZE;
1766 			/* Get canvas dimensions */
1767 			if (!fread(buf, IHDR_SIZE, 1, fp)) break; // Fail
1768 			w = GET32B(buf + IHDR_W);
1769 			h = GET32B(buf + IHDR_H);
1770 			if ((w > 0x7FFFFFFFU) || (h > 0x7FFFFFFFU)) break; // Limit
1771 			pg->w = w;
1772 			pg->h = h;
1773 		}
1774 		else if (tag == TAG4B_IDAT)
1775 		{
1776 			if (!pg->ihdr) break; // Fail
1777 			if (!pg->idat0) pg->idat0 = p;
1778 			if (pg->phase == 1) // Had a fcTL
1779 			{
1780 				pg->fdat0 = p;
1781 				pg->phase = 2;
1782 			}
1783 			if (pg->phase > 1)
1784 			{
1785 				if (pg->fdat0 != pg->idat0) break; // Mixed IDAT & fdAT
1786 				pg->fdat1 = p + PNG_HSIZE + tl + 4;
1787 			}
1788 		}
1789 		else if (tag == TAG4B_acTL)
1790 		{
1791 			if (tl < acTL_SIZE) break; // Bad
1792 			if (!fread(buf, acTL_SIZE, 1, fp)) break; // Fail
1793 			/* Store frames count */
1794 			if (!pg->frames) pg->frames = GET32B(buf + acTL_FCNT);
1795 			if (pg->frames > 0x7FFFFFFFU) break; // Limit
1796 			if (!pg->frames) break; // Fail
1797 		}
1798 		else if (tag == TAG4B_fcTL)
1799 		{
1800 			if (pg->phase > 1)
1801 			{
1802 				/* End of frame data - step back & return */
1803 				fseek(fp, p, SEEK_SET);
1804 				return (0);
1805 			}
1806 			if (tl < fcTL_SIZE) break; // Bad
1807 			/* Store for later use */
1808 			if (!fread(pg->fctl, fcTL_SIZE, 1, fp)) break; // Fail
1809 			if (pg->fctl[fcTL_DISP] > 2) break; // Unknown value
1810 			pg->disp = apng_disposal[pg->fctl[fcTL_DISP]];
1811 			pg->phase = 1; // Ready for a new frame
1812 		}
1813 		else if (tag == TAG4B_fdAT)
1814 		{
1815 			if (!pg->ihdr) break; // Fail
1816 			if (!pg->phase) break; // Fail - no fcTL
1817 			if (pg->phase == 1) // Had a fcTL
1818 			{
1819 				pg->fdat0 = p;
1820 				pg->phase = 2;
1821 			}
1822 			if (pg->fdat0 == pg->idat0) break; // Mixed IDAT & fdAT
1823 			pg->fdat1 = p + PNG_HSIZE + tl + 4;
1824 		}
1825 		else if (tag == TAG4B_IEND)
1826 		{
1827 			if (pg->phase != 2) break; // Fail
1828 			pg->phase = 3; // End
1829 			return (0); // Done
1830 		}
1831 		/* Skip tag header, data, & CRC field */
1832 		p += PNG_HSIZE + tl + 4;
1833 		if (fseek(fp, p, SEEK_SET)) break;
1834 	}
1835 	return (-1); // Failed
1836 }
1837 
load_apng_frame(FILE * fp,pnghead * pg,ls_settings * settings)1838 static int load_apng_frame(FILE *fp, pnghead *pg, ls_settings *settings)
1839 {
1840 	unsigned char *w;
1841 	int l, res;
1842 
1843 	/* Try scanning the frame */
1844 	res = png_scan(fp, pg);
1845 	/* Prepare fake PNG */
1846 	if (!res) res = assemble_png(fp, pg);
1847 	/* Load the frame */
1848 	if (!res) res = load_png(NULL, settings, &pg->mf, TRUE);
1849 	if (res != 1) return (res); // Fail on any error
1850 	/* Convert indexed+alpha to RGBA, to let it be regular PNG */
1851 	w = settings->img[CHN_ALPHA];
1852 	if ((settings->bpp == 1) && w)
1853 	{
1854 		l = settings->width * settings->height;
1855 		w = malloc((size_t)l * 3);
1856 		if (!w) return (FILE_MEM_ERROR); // No memory
1857 		do_convert_rgb(0, 1, l, w, settings->img[CHN_IMAGE], settings->pal);
1858 		free(settings->img[CHN_IMAGE]);
1859 		settings->img[CHN_IMAGE] = w;
1860 		settings->bpp = 3;
1861 	}
1862 	/* Ensure transparent color is in palette */
1863 	else map_rgb_trans(settings);
1864 	return (res);
1865 }
1866 
load_apng_frames(char * file_name,ani_settings * ani)1867 static int load_apng_frames(char *file_name, ani_settings *ani)
1868 {
1869 	char buf[PNG_BYTES_TO_CHECK + 1];
1870 	pnghead pg;
1871 	ani_status stat;
1872 	ls_settings w_set;
1873 	unsigned wx, wy;
1874 	int n, d, bpp, frames = 0, res = -1;
1875 	FILE *fp;
1876 
1877 
1878 	if (!(fp = fopen(file_name, "rb"))) return (-1);
1879 	memset(w_set.img, 0, sizeof(chanlist));
1880 	memset(&pg, 0, sizeof(pg));
1881 
1882 	if (fread(buf, 1, PNG_BYTES_TO_CHECK, fp) != PNG_BYTES_TO_CHECK) goto fail;
1883 	if (png_sig_cmp(buf, 0, PNG_BYTES_TO_CHECK)) goto fail;
1884 
1885 	w_set = ani->settings;
1886 	res = load_apng_frame(fp, &pg, &w_set);
1887 	if (res != 1) goto fail;
1888 
1889 	/* Init state structure */
1890 	memset(&stat, 0, sizeof(stat));
1891 	stat.mode = ani->mode;
1892 	stat.defw = pg.w;
1893 	stat.defh = pg.h;
1894 	/* Use whatever palette we read */
1895 	mem_pal_copy(stat.newpal, w_set.pal);
1896 	stat.newcols = w_set.colors;
1897 	stat.newtrans = w_set.xpm_trans;
1898 	ani_init_xlat(&stat); // Init palette remapping to 1:1 and leave at that
1899 
1900 	/* Init frameset - palette in APNG is global */
1901 	res = FILE_MEM_ERROR;
1902 	if (!(ani->fset.pal = malloc(SIZEOF_PALETTE))) goto fail;
1903 	mem_pal_copy(ani->fset.pal, stat.newpal);
1904 
1905 	/* Go through images */
1906 	while (frames++ < pg.frames)
1907 	{
1908 		res = FILE_TOO_LONG;
1909 		if (!check_next_frame(&ani->fset, ani->settings.mode, TRUE))
1910 			goto fail;
1911 
1912 		/* Get the next frame, after the first */
1913 		if (frames > 1)
1914 		{
1915 			w_set = ani->settings;
1916 			res = load_apng_frame(fp, &pg, &w_set);
1917 			if (res != 1) goto fail;
1918 		}
1919 		delete_alpha(&w_set, 255);
1920 
1921 		stat.blend = pg.fctl[fcTL_BLEND] && (w_set.img[CHN_ALPHA] ||
1922 			(stat.newtrans >= 0));
1923 		/* Within mtPaint delays are 1/100s granular */
1924 		n = GET16B(pg.fctl + fcTL_DN);
1925 		d = GET16B(pg.fctl + fcTL_DD);
1926 		if (!d) d = 100;
1927 		w_set.gif_delay = (n * 100 + d - 1) / d; // Round up
1928 
1929 		wx = GET32B(pg.fctl + fcTL_X);
1930 		wy = GET32B(pg.fctl + fcTL_Y);
1931 		if (wx > MAX_WIDTH) wx = MAX_WIDTH; // Out is out
1932 		if (wy > MAX_HEIGHT) wy = MAX_HEIGHT; // Same
1933 		w_set.x = wx;
1934 		w_set.y = wy;
1935 
1936 		/* Analyze how we can merge the frames */
1937 		res = TOO_BIG;
1938 		bpp = analyze_rgba_frame(&stat, &w_set);
1939 		if (bpp < 0) goto fail;
1940 
1941 		/* Allocate a new frame */
1942 		res = add_frame(ani, &stat, &w_set, bpp, pg.disp);
1943 		if (res) goto fail;
1944 
1945 		/* Do actual compositing, remember disposal method */
1946 		composite_frame(&ani->fset, &stat, &w_set);
1947 		mem_free_chanlist(w_set.img);
1948 		memset(w_set.img, 0, sizeof(chanlist));
1949 
1950 		/* Write out those frames worthy to be stored */
1951 		res = done_frame(file_name, ani, FALSE);
1952 		if (res != 1) goto fail;
1953 
1954 		if (pg.phase > 2) break; // End of file
1955 	}
1956 	/* Write out the final frame if not written before */
1957 	res = done_frame(file_name, ani, TRUE);
1958 
1959 fail:	free(pg.png);
1960 	mem_free_chanlist(w_set.img);
1961 	fclose(fp);
1962 	return (res);
1963 }
1964 
analyze_gif_frame(ani_status * stat,ls_settings * settings)1965 static int analyze_gif_frame(ani_status *stat, ls_settings *settings)
1966 {
1967 	unsigned char cmap[513], *lmap, *fg, *bg;
1968 	png_color *pal, *prev;
1969 	int tmpal[257], same_size, show_under;
1970 	int i, k, l, x, y, ul, lpal, lprev, fgw, bgw, prevtr = -1;
1971 
1972 
1973 	/* Locate the new palette */
1974 	pal = prev = stat->global_pal;
1975 	lpal = lprev = stat->global_cols;
1976 	if (settings->colors > 0)
1977 	{
1978 		pal = settings->pal;
1979 		lpal = settings->colors;
1980 	}
1981 
1982 	/* Accept new palette as final, for now */
1983 	mem_pal_copy(stat->newpal, pal);
1984 	stat->newcols = lpal;
1985 	stat->newtrans = settings->xpm_trans;
1986 
1987 	/* Prepare for new frame */
1988 	if (stat->mode <= ANM_RAW) // Raw frame mode
1989 	{
1990 		stat->defw = settings->width;
1991 		stat->defh = settings->height;
1992 		return (0);
1993 	}
1994 	else if ((stat->defw > MAX_WIDTH) || (stat->defh > MAX_HEIGHT))
1995 		return (-1); // Too large
1996 	ani_map_frame(stat, settings);
1997 	same_size = !(settings->x | settings->y |
1998 		(stat->defw ^ settings->width) | (stat->defh ^ settings->height));
1999 
2000 	ani_init_xlat(stat); // Init palette remapping to 1:1
2001 
2002 	/* First frame is exceptional */
2003 	if (!stat->prev_idx)
2004 	{
2005 		// Trivial if no background gets drawn
2006 		if (same_size) return (0);
2007 		// Trivial if have transparent color
2008 		if (settings->xpm_trans >= 0) return (1);
2009 	}
2010 
2011 	/* Disable transparency by default, enable when needed */
2012 	stat->newtrans = -1;
2013 
2014 	/* Now scan the dest area, filling colors bitmap */
2015 	memset(cmap, 0, sizeof(cmap));
2016 	fgw = settings->width;
2017 	fg = settings->img[CHN_IMAGE] - (settings->y * fgw + settings->x);
2018 	// Set underlayer pointer & step (ignore bpp!)
2019 	bgw = stat->prev.width;
2020 	bg = stat->prev.img[CHN_IMAGE] - (stat->prev.y * bgw + stat->prev.x);
2021 	lmap = stat->lmap;
2022 	for (y = 0; y < stat->defh; y++)
2023 	{
2024 		int ww = stat->defw, tp = settings->xpm_trans;
2025 		int bmask = lmap[y] >> 4;
2026 
2027 		for (x = 0; x < ww; x++)
2028 		{
2029 			int c0, bflag = lmap[x] & bmask;
2030 
2031 			if ((bflag & 1) && ((c0 = fg[x]) != tp)) // New frame
2032 				c0 += 256;
2033 			else if ((bflag & 6) == 2) // Underlayer
2034 				c0 = bg[x];
2035 			else c0 = 512; // Background (transparency)
2036 			cmap[c0] = 1;
2037 		}
2038 		fg += fgw; bg += bgw;
2039 	}
2040 
2041 	/* If we have underlayer */
2042 	show_under = 0;
2043 	if (stat->prev_idx)
2044 	{
2045 		// Use per-frame palette if underlayer has it
2046 		prev = stat->prev.pal;
2047 		lprev = stat->prev.cols;
2048 		prevtr = stat->prev.trans;
2049 		// Move underlayer transparency to "transparent"
2050 		if (prevtr >= 0)
2051 		{
2052 			cmap[512] |= cmap[prevtr];
2053 			cmap[prevtr] = 0;
2054 		}
2055 		// Check if underlayer is at all visible
2056 		show_under = !!memchr(cmap, 1, 256);
2057 		// Visible RGB/RGBA underlayer means RGB/RGBA frame
2058 		if (show_under && (stat->prev.bpp == 3)) goto RGB;
2059 	}
2060 
2061 	/* Now, check if either frame's palette is enough */
2062 	ul = 2; // Default is new palette
2063 	if (show_under)
2064 	{
2065 		l = lprev > lpal ? lprev : lpal;
2066 		k = lprev > lpal ? lpal : lprev;
2067 		for (ul = 3 , i = 0; ul && (i < l); i++)
2068 		{
2069 			int tf2 = cmap[i] * 2 + cmap[256 + i];
2070 			if (tf2 && ((i >= k) ||
2071 				(PNG_2_INT(prev[i]) != PNG_2_INT(pal[i]))))
2072 				ul &= ~tf2; // Exclude mismatched palette(s)
2073 		}
2074 		if (ul == 1) // Need old palette
2075 		{
2076 			mem_pal_copy(stat->newpal, prev);
2077 			stat->newcols = lprev;
2078 		}
2079 	}
2080 	while (ul) // Place transparency
2081 	{
2082 		if (cmap[512]) // Need transparency
2083 		{
2084 			int i, l = prevtr, nc = stat->newcols;
2085 
2086 			/* If cannot use old transparent index */
2087 			if ((l < 0) || (l >= nc) || (cmap[l] | cmap[l + 256]))
2088 				l = settings->xpm_trans;
2089 			/* If cannot use new one either */
2090 			if ((l < 0) || (l >= nc) || (cmap[l] | cmap[l + 256]))
2091 			{
2092 				/* Try to find unused palette slot */
2093 				for (l = -1 , i = 0; (l < 0) && (i < nc); i++)
2094 					if (!(cmap[i] | cmap[i + 256])) l = i;
2095 			}
2096 			if (l < 0) /* Try to add a palette slot */
2097 			{
2098 				png_color *c;
2099 
2100 				if (nc >= 256) break; // Failure
2101 				l = stat->newcols++;
2102 				c = stat->newpal + l;
2103 				c->red = c->green = c->blue = 0;
2104 			}
2105 			// Modify mapping
2106 			if (prevtr >= 0) stat->xlat[prevtr] = l;
2107 			stat->xlat[512] = stat->newtrans = l;
2108 		}
2109 		// Successfully mapped everything - use paletted mode
2110 		return (same_size ? 0 : 1);
2111 	}
2112 
2113 	/* Try to build combined palette */
2114 	for (ul = i = 0; (ul < 257) && (i < 512); i++)
2115 	{
2116 		png_color *c;
2117 		int j, v;
2118 
2119 		if (!cmap[i]) continue;
2120 		c = (i < 256 ? prev : pal - 256) + i;
2121 		v = PNG_2_INT(*c);
2122 		for (j = 0; (j < ul) && (tmpal[j] != v); j++);
2123 		if (j == ul) tmpal[ul++] = v;
2124 		stat->xlat[i] = j;
2125 	}
2126 	// Add transparent color
2127 	if ((ul < 257) && cmap[512])
2128 	{
2129 		// Modify mapping
2130 		if (prevtr >= 0) stat->xlat[prevtr] = ul;
2131 		stat->xlat[512] = stat->newtrans = ul;
2132 		tmpal[ul++] = 0;
2133 	}
2134 	if (ul < 257) // Success!
2135 	{
2136 		png_color *c = stat->newpal;
2137 		for (i = 0; i < ul; i++ , c++) // Build palette
2138 		{
2139 			int v = tmpal[i];
2140 			c->red = INT_2_R(v);
2141 			c->green = INT_2_G(v);
2142 			c->blue = INT_2_B(v);
2143 		}
2144 		stat->newcols = ul;
2145 		// Use paletted mode
2146 		return (same_size ? 0 : 1);
2147 	}
2148 
2149 	/* Tried everything in vain - fall back to RGB/RGBA */
2150 RGB:	if (stat->global_cols > 0) // Use default palette if present
2151 	{
2152 		mem_pal_copy(stat->newpal, stat->global_pal);
2153 		stat->newcols = stat->global_cols;
2154 	}
2155 	stat->newtrans = -1; // No color-key transparency
2156 	// RGBA if underlayer with alpha, or transparent backround, is visible
2157 	if ((show_under && stat->prev.img[CHN_ALPHA]) || cmap[512])
2158 		return (4);
2159 	// RGB otherwise
2160 	return (3);
2161 }
2162 
2163 /* Macros for accessing values in Intel byte order */
2164 #define GET16(buf) (((buf)[1] << 8) + (buf)[0])
2165 #define GET32(buf) (((unsigned)(buf)[3] << 24) + ((buf)[2] << 16) + \
2166 	((buf)[1] << 8) + (buf)[0])
2167 #define GET32s(buf) (((signed char)(buf)[3] * 0x1000000) + ((buf)[2] << 16) + \
2168 	((buf)[1] << 8) + (buf)[0])
2169 #define PUT16(buf, v) (buf)[0] = (v) & 0xFF; (buf)[1] = (v) >> 8;
2170 #define PUT32(buf, v) (buf)[0] = (v) & 0xFF; (buf)[1] = ((v) >> 8) & 0xFF; \
2171 	(buf)[2] = ((v) >> 16) & 0xFF; (buf)[3] = (v) >> 24;
2172 
2173 #define GIF_ID       "GIF87a"
2174 #define GIF_IDLEN    6
2175 
2176 /* GIF header */
2177 #define GIF_VER       4 /* Where differing version digit goes */
2178 #define GIF_WIDTH     6 /* 16b */
2179 #define GIF_HEIGHT    8 /* 16b */
2180 #define GIF_GPBITS   10
2181 #define GIF_BKG      11
2182 #define GIF_ASPECT   12
2183 #define GIF_HDRLEN   13 /* Global palette starts here */
2184 
2185 #define GIF_GPFLAG   0x80
2186 #define GIF_8BPC     0x70 /* Color resolution to write out */
2187 
2188 /* Graphics Control Extension */
2189 #define GIF_GC_FLAGS 0
2190 #define GIF_GC_DELAY 1 /* 16b */
2191 #define GIF_GC_TRANS 3
2192 #define GIF_GC_LEN   4
2193 
2194 #define GIF_GC_TFLAG 1
2195 #define GIF_GC_DISP  2 /* Shift amount */
2196 
2197 /* Application Extension */
2198 #define GIF_AP_LEN   11
2199 
2200 /* Image */
2201 #define GIF_IX       0 /* 16b */
2202 #define GIF_IY       2 /* 16b */
2203 #define GIF_IWIDTH   4 /* 16b */
2204 #define GIF_IHEIGHT  6 /* 16b */
2205 #define GIF_IBITS    8
2206 #define GIF_IHDRLEN  9
2207 
2208 #define GIF_LPFLAG   0x80
2209 #define GIF_ILFLAG   0x40 /* Interlace */
2210 
2211 /* Read body of GIF block into buffer (or skip if NULL), return length */
getblock(unsigned char * buf,FILE * fp)2212 static int getblock(unsigned char *buf, FILE *fp)
2213 {
2214 	int l = getc(fp);
2215 	if (l == EOF) l = -1;
2216 	if (l > 0)
2217 	{
2218 		if (!buf) fseek(fp, l, SEEK_CUR); // Just skip
2219 		else if (fread(buf, 1, l, fp) < l) l = -1; // Error
2220 	}
2221 	return (l);
2222 }
2223 
2224 #ifdef U_LCMS /* No other uses for it now */
2225 /* Load a sequence of GIF blocks into memory */
getgifdata(FILE * fp,char ** res,int * len)2226 static int getgifdata(FILE *fp, char **res, int *len)
2227 {
2228 	unsigned char *src, *dest, *mem;
2229 	f_long r, p = ftell(fp);
2230 	int l, size;
2231 
2232 	*res = NULL;
2233 	*len = 0;
2234 	if (p < 0) return (1); /* Leave 2Gb+ GIFs to systems with longer f_long */
2235 
2236 	/* Measure */
2237 	while ((l = getblock(NULL, fp)) > 0);
2238 	if (l < 0) return (-1); // Error
2239 	r = ftell(fp);
2240 	fseek(fp, p, SEEK_SET);
2241 	if (r <= p) return (1); // Paranoia
2242 	if (r - p > INT_MAX) return (1); // A 2Gb+ profile is unusable anyway :-)
2243 
2244 	/* Allocate */
2245 	size = r - p;
2246 	mem = malloc(size);
2247 	if (!mem) return (1); // No memory for this
2248 
2249 	/* Read */
2250 	if (fread(mem, 1, size, fp) < size) goto fail; // Error
2251 
2252 	/* Merge */
2253 	src = dest = mem;
2254 	while ((l = *src++))
2255 	{
2256 		if (src - mem >= size - l) goto fail; // Paranoia
2257 		memmove(dest, src, l);
2258 		src += l; dest += l;
2259 	}
2260 	size = dest - mem; // Maybe realloc?
2261 
2262 	/* Done */
2263 	*res = mem;
2264 	*len = size;
2265 	return (0);
2266 
2267 fail:	free(mem);
2268 	return (-1); // Someone overwrote the file damaging it
2269 }
2270 #endif
2271 
2272 /* Space enough to hold palette, or longest block + longest decoded sequence */
2273 #define GIF_BUFSIZE (256 + 4096)
2274 typedef struct {
2275 	FILE *f;
2276 	int ptr, end, tail;
2277 	int lc0, lc, nxc, clear, cmask;
2278 	int w, bits, prev;
2279 	short nxcode[4096 + 1];
2280 	unsigned char buf[GIF_BUFSIZE], cchar[4096 + 1];
2281 } gifbuf;
2282 
resetlzw(gifbuf * gif)2283 static void resetlzw(gifbuf *gif)
2284 {
2285 	gif->nxc = gif->clear + 2; // First usable code
2286 	gif->lc = gif->lc0 + 1; // Actual code size
2287 	gif->cmask = (1 << gif->lc) - 1; // Actual code mask
2288 	gif->prev = -1; // Previous code
2289 }
2290 
initlzw(gifbuf * gif,FILE * fp)2291 static int initlzw(gifbuf *gif, FILE *fp)
2292 {
2293 	int i;
2294 
2295 	gif->f = fp;
2296 	gif->lc0 = i = getc(fp); // Min code size
2297 	/* Enforce hard upper limit but allow wasteful encoding */
2298 	if ((i == EOF) || (i > 11)) return (FALSE);
2299 	gif->clear = i = 1 << i; // Clear code
2300 	/* Initial 1-char codes */
2301 	while (--i >= 0) gif->nxcode[i] = -1 , gif->cchar[i] = (unsigned char)i;
2302 	resetlzw(gif);
2303 	gif->w = gif->bits = 0; // Ready bits in shifter
2304 	gif->ptr = gif->end = gif->tail = 0; // Ready data in buffer
2305 	return (TRUE);
2306 }
2307 
getlzw(unsigned char * dest,int cnt,gifbuf * gif)2308 static int getlzw(unsigned char *dest, int cnt, gifbuf *gif)
2309 {
2310 	int l, c, cx, w, bits, lc, cmask, prev, nxc, tail = gif->tail;
2311 
2312 	while (TRUE)
2313 	{
2314 		l = tail > cnt ? cnt : tail;
2315 		cnt -= l;
2316 		l = tail - l;
2317 		while (tail > l) *dest++ = gif->buf[GIF_BUFSIZE - tail--];
2318 		if (cnt <= 0) break; // No tail past this point
2319 		w = gif->w;
2320 		bits = gif->bits;
2321 		lc = gif->lc;
2322 		while (bits < lc)
2323 		{
2324 			if (gif->ptr >= gif->end)
2325 			{
2326 				gif->end = getblock(gif->buf, gif->f);
2327 				if (gif->end <= 0) return (FALSE); // No data
2328 				gif->ptr = 0;
2329 			}
2330 			w |= gif->buf[gif->ptr++] << bits;
2331 			bits += 8;
2332 		}
2333 		cmask = gif->cmask;
2334 		c = w & cmask;
2335 		gif->w = w >> lc;
2336 		gif->bits = bits - lc;
2337 		if (c == gif->clear)
2338 		{
2339 			resetlzw(gif);
2340 			continue;
2341 		}
2342 		if (c == gif->clear + 1) return (FALSE); // Premature EOI
2343 		/* Update for next code */
2344 		prev = gif->prev;
2345 		gif->prev = c;
2346 		nxc = gif->nxc;
2347 		gif->nxcode[nxc] = prev;
2348 		if ((prev >= 0) && (nxc < 4096))
2349 		{
2350 			if ((++gif->nxc > cmask) && (cmask < 4096 - 1))
2351 				gif->cmask = (1 << ++gif->lc) - 1;
2352 		}
2353 		/* Decode this one */
2354 		if (c > nxc) return (FALSE); // Broken code
2355 		if ((c == nxc) && (prev < 0)) return (FALSE); // Too early
2356 		for (cx = c; cx >= 0; cx = gif->nxcode[cx])
2357 			gif->buf[GIF_BUFSIZE - ++tail] = gif->cchar[cx];
2358 		gif->cchar[nxc] = gif->buf[GIF_BUFSIZE - tail];
2359 		/* In case c == nxc, its char was garbage till now, so reread it */
2360 		gif->buf[GIF_BUFSIZE - 1] = gif->cchar[c];
2361 	}
2362 	gif->tail = tail;
2363 	return (TRUE);
2364 }
2365 
load_gif_frame(FILE * fp,ls_settings * settings)2366 static int load_gif_frame(FILE *fp, ls_settings *settings)
2367 {
2368 	/* GIF interlace pattern: Y0, DY, ... */
2369 	static const unsigned char interlace[10] =
2370 		{ 0, 1, 0, 8, 4, 8, 2, 4, 1, 2 };
2371 	unsigned char hdr[GIF_IHDRLEN];
2372 	gifbuf gif;
2373 	int i, k, kx, n, w, h, dy, res;
2374 
2375 
2376 	/* Read the header */
2377 	if (fread(hdr, 1, GIF_IHDRLEN, fp) < GIF_IHDRLEN) return (-1);
2378 
2379 	/* Get local palette if any */
2380 	if (hdr[GIF_IBITS] & GIF_LPFLAG)
2381 	{
2382 		int cols = 2 << (hdr[GIF_IBITS] & 7);
2383 		if (fread(gif.buf, 3, cols, fp) < cols) return (-1);
2384 		rgb2pal(settings->pal, gif.buf, settings->colors = cols);
2385 	}
2386 	if (settings->colors < 0) return (-1); // No palette at all
2387 	/* If palette is all we need */
2388 	if ((settings->mode == FS_PALETTE_LOAD) ||
2389 		(settings->mode == FS_PALETTE_DEF)) return (EXPLODE_FAILED);
2390 
2391 	if (!initlzw(&gif, fp)) return (-1);
2392 
2393 	/* Store actual image parameters */
2394 	settings->x = GET16(hdr + GIF_IX);
2395 	settings->y = GET16(hdr + GIF_IY);
2396 	settings->width = w = GET16(hdr + GIF_IWIDTH);
2397 	settings->height = h = GET16(hdr + GIF_IHEIGHT);
2398 	settings->bpp = 1;
2399 
2400 	if ((res = allocate_image(settings, CMASK_IMAGE))) return (res);
2401 	res = FILE_LIB_ERROR;
2402 
2403 	if (!settings->silent) ls_init("GIF", 0);
2404 
2405 	if (hdr[GIF_IBITS] & GIF_ILFLAG) k = 2 , kx = 10; /* Interlace */
2406 	else k = 0 , kx = 2;
2407 
2408 	for (n = 0; k < kx; k += 2)
2409 	{
2410 		dy = interlace[k + 1];
2411 		for (i = interlace[k]; i < h; n++ , i += dy)
2412 		{
2413 			if (!getlzw(settings->img[CHN_IMAGE] + i * w, w, &gif))
2414 				goto fail;
2415 			ls_progress(settings, n, 10);
2416 		}
2417 	}
2418 	/* Skip data blocks till 0 */
2419 	while ((i = getblock(NULL, fp)) > 0);
2420 	if (!i) res = 1;
2421 fail:	if (!settings->silent) progress_end();
2422 	return (res);
2423 }
2424 
load_gif_frames(char * file_name,ani_settings * ani)2425 static int load_gif_frames(char *file_name, ani_settings *ani)
2426 {
2427 	/* GIF disposal codes mapping */
2428 	static const unsigned short gif_disposal[8] = {
2429 		FM_DISP_LEAVE, FM_DISP_LEAVE, FM_DISP_REMOVE, FM_DISP_RESTORE,
2430 		/* Handling (reserved) "4" same as "3" is what Mozilla does */
2431 		FM_DISP_RESTORE, FM_DISP_LEAVE, FM_DISP_LEAVE, FM_DISP_LEAVE
2432 	};
2433 	unsigned char hdr[GIF_HDRLEN], buf[768];
2434 	png_color w_pal[256];
2435 	ani_status stat;
2436 	ls_settings w_set, init_set;
2437 	int l, id, disposal, bpp, res = -1;
2438 	FILE *fp;
2439 
2440 	if (!(fp = fopen(file_name, "rb"))) return (-1);
2441 	memset(w_set.img, 0, sizeof(chanlist));
2442 
2443 	/* Read the header */
2444 	if (fread(hdr, 1, GIF_HDRLEN, fp) < GIF_HDRLEN) goto fail;
2445 
2446 	/* Check signature */
2447 	if (hdr[GIF_VER] == '9') hdr[GIF_VER] = '7'; // Does not matter anyway
2448 	if (memcmp(hdr, GIF_ID, GIF_IDLEN)) goto fail;
2449 
2450 	/* Init state structure */
2451 	memset(&stat, 0, sizeof(stat));
2452 	stat.mode = ani->mode;
2453 	stat.defw = GET16(hdr + GIF_WIDTH);
2454 	stat.defh = GET16(hdr + GIF_HEIGHT);
2455 	stat.global_cols = -1;
2456 	/* Get global palette */
2457 	if (hdr[GIF_GPBITS] & GIF_GPFLAG)
2458 	{
2459 		int cols = 2 << (hdr[GIF_GPBITS] & 7);
2460 		if (fread(buf, 3, cols, fp) < cols) goto fail;
2461 		rgb2pal(stat.global_pal, buf, stat.global_cols = cols);
2462 	}
2463 	stat.blend = TRUE; // No other case in GIF
2464 
2465 	/* Init temp container */
2466 	init_set = ani->settings;
2467 	init_set.colors = 0; // Nonzero will signal local palette
2468 	init_set.pal = w_pal;
2469 	init_set.xpm_trans = -1;
2470 	init_set.gif_delay = 0;
2471 	disposal = FM_DISP_LEAVE;
2472 
2473 	/* Init frameset */
2474 	if (stat.global_cols > 0) // Set default palette
2475 	{
2476 		res = FILE_MEM_ERROR;
2477 		if (!(ani->fset.pal = malloc(SIZEOF_PALETTE))) goto fail;
2478 		mem_pal_copy(ani->fset.pal, stat.global_pal);
2479 	}
2480 
2481 	/* Go through images */
2482 	while (TRUE)
2483 	{
2484 		res = -1;
2485 		id = getc(fp);
2486 		if (!id) continue; // Extra end-blocks do happen sometimes
2487 		if (id == ';') break; // Trailer block
2488 		if (id == '!') // Extension block
2489 		{
2490 			if ((id = getc(fp)) == EOF) goto fail;
2491 			if (id == 0xF9) // Graphics control - read it
2492 			{
2493 				if (getblock(buf, fp) < GIF_GC_LEN) goto fail;
2494 				/* !!! In practice, Graphics Control Extension
2495 				 * affects not only "the first block to follow"
2496 				 * as docs say, but EVERY following block - WJ */
2497 				init_set.xpm_trans = buf[GIF_GC_FLAGS] & GIF_GC_TFLAG ?
2498 					buf[GIF_GC_TRANS] : -1;
2499 				init_set.gif_delay = GET16(buf + GIF_GC_DELAY);
2500 				disposal = gif_disposal[(buf[GIF_GC_FLAGS] >> GIF_GC_DISP) & 7];
2501 			}
2502 			while ((l = getblock(NULL, fp)) > 0); // Skip till end
2503 			if (l < 0) goto fail;
2504 		}
2505 		else if (id == ',') // Image
2506 		{
2507 			res = FILE_TOO_LONG;
2508 			if (!check_next_frame(&ani->fset, ani->settings.mode, TRUE))
2509 				goto fail;
2510 			w_set = init_set;
2511 			res = load_gif_frame(fp, &w_set);
2512 			if (res != 1) goto fail;
2513 			/* Analyze how we can merge the frames */
2514 			res = TOO_BIG;
2515 			bpp = analyze_gif_frame(&stat, &w_set);
2516 			if (bpp < 0) goto fail;
2517 
2518 			/* Allocate a new frame */
2519 			res = add_frame(ani, &stat, &w_set, bpp, disposal);
2520 			if (res) goto fail;
2521 
2522 			/* Do actual compositing, remember disposal method */
2523 			composite_frame(&ani->fset, &stat, &w_set);
2524 			mem_free_chanlist(w_set.img);
2525 			memset(w_set.img, 0, sizeof(chanlist));
2526 
2527 			/* Write out those frames worthy to be stored */
2528 			res = done_frame(file_name, ani, FALSE);
2529 			if (res != 1) goto fail;
2530 		}
2531 		else goto fail; // Garbage or EOF
2532 	}
2533 	/* Write out the final frame if not written before */
2534 	res = done_frame(file_name, ani, TRUE);
2535 
2536 fail:	mem_free_chanlist(w_set.img);
2537 	fclose(fp);
2538 	return (res);
2539 }
2540 
load_gif(char * file_name,ls_settings * settings)2541 static int load_gif(char *file_name, ls_settings *settings)
2542 {
2543 	unsigned char hdr[GIF_HDRLEN], buf[768];
2544 	int trans = -1, delay = settings->gif_delay, frame = 0;
2545 	int l, id, res = -1;
2546 	FILE *fp;
2547 
2548 	if (!(fp = fopen(file_name, "rb"))) return (-1);
2549 
2550 	/* Read the header */
2551 	if (fread(hdr, 1, GIF_HDRLEN, fp) < GIF_HDRLEN) goto fail;
2552 
2553 	/* Check signature */
2554 	if (hdr[GIF_VER] == '9') hdr[GIF_VER] = '7'; // Does not matter anyway
2555 	if (memcmp(hdr, GIF_ID, GIF_IDLEN)) goto fail;
2556 
2557 	/* Get global palette */
2558 	settings->colors = -1;
2559 	if (hdr[GIF_GPBITS] & GIF_GPFLAG)
2560 	{
2561 		int cols = 2 << (hdr[GIF_GPBITS] & 7);
2562 		if (fread(buf, 3, cols, fp) < cols) goto fail;
2563 		rgb2pal(settings->pal, buf, settings->colors = cols);
2564 	}
2565 
2566 	/* Go read the first image */
2567 	while (TRUE)
2568 	{
2569 		res = frame ? FILE_LIB_ERROR : -1;
2570 		id = getc(fp);
2571 		if (!id) continue; // Extra end-blocks do happen sometimes
2572 		if (id == ';') break; // Trailer block
2573 		if (id == '!') // Extension block
2574 		{
2575 			if ((id = getc(fp)) == EOF) goto fail;
2576 			if (id == 0xF9) // Graphics control - read it
2577 			{
2578 				if (getblock(buf, fp) < GIF_GC_LEN) goto fail;
2579 				trans = buf[GIF_GC_FLAGS] & GIF_GC_TFLAG ?
2580 					buf[GIF_GC_TRANS] : -1;
2581 				delay = GET16(buf + GIF_GC_DELAY);
2582 			}
2583 #ifdef U_LCMS
2584 			/* Yes GIF can have a color profile - imagine that */
2585 			else if ((id == 0xFF) // Application extension
2586 				&& !settings->icc_size // No need of it otherwise
2587 				&& (getblock(buf, fp) >= GIF_AP_LEN) // Not broken
2588 				&& !memcmp(buf, "ICCRGBG1012", GIF_AP_LEN)) // The right ID
2589 			{
2590 				l = getgifdata(fp, &settings->icc, &settings->icc_size);
2591 				if (l < 0) goto fail;
2592 				if (!l) continue; // No trailing blocks to skip
2593 			}
2594 #endif
2595 			while ((l = getblock(NULL, fp)) > 0); // Skip till end
2596 			if (l < 0) goto fail;
2597 		}
2598 		else if (id == ',') // Image
2599 		{
2600 			if (frame++) /* Multipage GIF - notify user */
2601 			{
2602 				res = FILE_HAS_FRAMES;
2603 				goto fail;
2604 			}
2605 			settings->gif_delay = delay;
2606 			settings->xpm_trans = trans;
2607 			res = load_gif_frame(fp, settings);
2608 			if (res != 1) goto fail;
2609 		}
2610 		else goto fail; // Garbage or EOF
2611 	}
2612 	if (frame) res = 1; // No images is fail
2613 fail:	fclose(fp);
2614 	return (res);
2615 }
2616 
2617 /* Space enough to hold palette and all headers, or longest block */
2618 #define GIF_WBUFSIZE (768 + GIF_HDRLEN + (GIF_GC_LEN + 4) + (GIF_IHDRLEN + 2))
2619 
2620 /* A cuckoo hash would take 4x less space, but need much more code */
2621 #define GIF_CODESSIZE ((4096 * 2 * 16) * sizeof(short))
2622 typedef struct {
2623 	FILE *f;
2624 	int cnt, nxmap;
2625 	int lc0, lc, nxc, clear, nxc2;
2626 	int w, bits, prev;
2627 	short *codes;
2628 	unsigned char buf[GIF_WBUFSIZE];
2629 } gifcbuf;
2630 
resetclzw(gifcbuf * gif)2631 static void resetclzw(gifcbuf *gif)
2632 {
2633 	/* Send clear code at current length */
2634 	gif->w |= gif->clear << gif->bits;
2635 	gif->bits += gif->lc;
2636 	/* Reset parameters */
2637 	gif->nxc = gif->clear + 2; // First usable code
2638 	gif->lc = gif->lc0 + 1; // Actual code size
2639 	gif->nxc2 = 1 << gif->lc; // For next code size
2640 	memset(gif->codes, 0, GIF_CODESSIZE); // Maps
2641 	gif->nxmap = 1; // First usable intermediate map
2642 }
2643 
initclzw(gifcbuf * gif,int lc0,FILE * fp)2644 static void initclzw(gifcbuf *gif, int lc0, FILE *fp)
2645 {
2646 	if (lc0 < 2) lc0 = 2; // Minimum allowed
2647 	gif->f = fp;
2648 	gif->lc0 = lc0;
2649 	fputc(lc0, fp);
2650 	gif->clear = 1 << lc0; // Clear code
2651 	gif->prev = -1; // No previous code
2652 	gif->cnt = gif->w = gif->bits = 0; // No data yet
2653 	gif->lc = gif->lc0 + 1; // Actual code size
2654 	resetclzw(gif); // Initial clear
2655 }
2656 
emitlzw(gifcbuf * gif,int c)2657 static void emitlzw(gifcbuf *gif, int c)
2658 {
2659 	int bits = gif->bits, w = gif->w | (c << bits);
2660 
2661 	bits += gif->lc;
2662 	while (bits >= 8)
2663 	{
2664 		gif->buf[++gif->cnt] = (unsigned char)w;
2665 		w >>= 8;
2666 		bits -= 8;
2667 		if (gif->cnt >= 255)
2668 		{
2669 			gif->buf[0] = 255;
2670 			fwrite(gif->buf, 1, 256, gif->f);
2671 			gif->cnt = 0;
2672 		}
2673 	}
2674 	gif->bits = bits;
2675 	gif->w = w;
2676 	/* Extend code size if needed */
2677 	if (gif->nxc >= gif->nxc2) gif->nxc2 = 1 << ++gif->lc;
2678 }
2679 
putlzw(gifcbuf * gif,unsigned char * src,int cnt)2680 static void putlzw(gifcbuf *gif, unsigned char *src, int cnt)
2681 {
2682 	short *codes = gif->codes;
2683 	int i, j, c, prev = gif->prev;
2684 
2685 	while (cnt-- > 0)
2686 	{
2687 		c = *src++;
2688 		if (prev < 0) /* Begin */
2689 		{
2690 			prev = c;
2691 			continue;
2692 		}
2693 		/* Try compression */
2694 		i = prev * 16 + (c >> 4) + 4096 * 16;
2695 		j = codes[i] * 16 + (c & 0xF);
2696 		j = codes[j];
2697 		if (j) // Have match
2698 		{
2699 			prev = j - 4096;
2700 			continue;
2701 		}
2702 		/* Emit the code */
2703 		emitlzw(gif, prev);
2704 		prev = c;
2705 		/* Do a clear if needed */
2706 		if (gif->nxc >= 4096 - 1)
2707 		{
2708 			resetclzw(gif);
2709 			continue;
2710 		}
2711 		/* Add new code */
2712 		if (!codes[i]) codes[i] = gif->nxmap++;
2713 		j = codes[i] * 16 + (c & 0xF);
2714 		codes[j] = gif->nxc++ + 4096;
2715 	}
2716 	gif->prev = prev;
2717 }
2718 
donelzw(gifcbuf * gif)2719 static void donelzw(gifcbuf *gif) /* Flush */
2720 {
2721 	emitlzw(gif, gif->prev);
2722 	emitlzw(gif, gif->clear + 1); // EOD
2723 	if (gif->bits) gif->buf[++gif->cnt] = gif->w;
2724 //	gif->w = gif->bits = 0;
2725 	gif->buf[0] = gif->cnt;
2726 	gif->buf[gif->cnt + 1] = 0; // Block terminator
2727 	fwrite(gif->buf, 1, gif->cnt + 2, gif->f);
2728 //	gif->cnt = 0;
2729 }
2730 
save_gif(char * file_name,ls_settings * settings)2731 static int save_gif(char *file_name, ls_settings *settings)
2732 {
2733 	gifcbuf gif;
2734 	unsigned char *tmp;
2735 	FILE *fp = NULL;
2736 	int i, nc, ext = FALSE, w = settings->width, h = settings->height;
2737 
2738 
2739 	/* GIF save must be on indexed image */
2740 	if (settings->bpp != 1) return WRONG_FORMAT;
2741 
2742 	gif.codes = malloc(GIF_CODESSIZE);
2743 	if (!gif.codes) return (-1);
2744 
2745 	if (!(fp = fopen(file_name, "wb")))
2746 	{
2747 		free(gif.codes);
2748 		return (-1);
2749 	}
2750 
2751 	/* Get colormap size bits */
2752 	nc = nlog2(settings->colors) - 1;
2753 	if (nc < 0) nc = 0;
2754 
2755 	/* Prepare header */
2756 	tmp = gif.buf;
2757 	memset(tmp, 0, GIF_HDRLEN);
2758 	memcpy(tmp, GIF_ID, GIF_IDLEN);
2759 	PUT16(tmp + GIF_WIDTH, w);
2760 	PUT16(tmp + GIF_HEIGHT, h);
2761 	tmp[GIF_GPBITS] = GIF_GPFLAG | GIF_8BPC | nc;
2762 	tmp += GIF_HDRLEN;
2763 
2764 	/* Prepare global palette */
2765 	i = 2 << nc;
2766 	pal2rgb(tmp, settings->pal, settings->colors, i);
2767 	tmp += i * 3;
2768 
2769 	/* Prepare extension */
2770 	if (settings->xpm_trans >= 0)
2771 	{
2772 		ext = TRUE;
2773 		*tmp++ = '!';	// Extension block
2774 		*tmp++ = 0xF9;	// Graphics control
2775 		*tmp++ = GIF_GC_LEN;
2776 		memset(tmp, 0, GIF_GC_LEN + 1); // W/block terminator
2777 		tmp[GIF_GC_FLAGS] = GIF_GC_TFLAG;
2778 		tmp[GIF_GC_TRANS] = settings->xpm_trans;
2779 		tmp += GIF_GC_LEN + 1;
2780 	}
2781 
2782 	/* Prepare image header */
2783 	*tmp++ = ',';
2784 	memset(tmp, 0, GIF_IHDRLEN);
2785 	PUT16(tmp + GIF_IWIDTH, w);
2786 	PUT16(tmp + GIF_IHEIGHT, h);
2787 	tmp += GIF_IHDRLEN;
2788 
2789 	if (ext) gif.buf[GIF_VER] = '9'; // If we use extension
2790 
2791 	/* Write out all the headers */
2792 	fwrite(gif.buf, 1, tmp - gif.buf, fp);
2793 
2794 	if (!settings->silent) ls_init("GIF", 1);
2795 
2796 	initclzw(&gif, nc + 1, fp); // "Min code size" = palette index bits
2797 	for (i = 0; i < h; i++)
2798 	{
2799 		putlzw(&gif, settings->img[CHN_IMAGE] + i * w, w);
2800 		ls_progress(settings, i, 20);
2801 	}
2802 	donelzw(&gif);
2803 	fputc(';', fp); // Trailer block
2804 	fclose(fp);
2805 
2806 	if (!settings->silent) progress_end();
2807 
2808 	free(gif.codes);
2809 	return 0;
2810 }
2811 
2812 #ifdef NEED_CMYK
2813 #ifdef U_LCMS
2814 /* Guard against cmsHTRANSFORM changing into something overlong in the future */
2815 typedef char cmsHTRANSFORM_Does_Not_Fit_Into_Pointer[2 * (sizeof(cmsHTRANSFORM) <= sizeof(char *)) - 1];
2816 
init_cmyk2rgb(ls_settings * settings,unsigned char * icc,int len,int inverted)2817 static int init_cmyk2rgb(ls_settings *settings, unsigned char *icc, int len,
2818 	int inverted)
2819 {
2820 	cmsHPROFILE from, to;
2821 	cmsHTRANSFORM how = NULL;
2822 
2823 	from = cmsOpenProfileFromMem((void *)icc, len);
2824 	if (!from) return (TRUE); // Unopenable now, unopenable ever
2825 	to = cmsCreate_sRGBProfile();
2826 	if (cmsGetColorSpace(from) == icSigCmykData)
2827 		how = cmsCreateTransform(from, inverted ? TYPE_CMYK_8_REV :
2828 			TYPE_CMYK_8, to, TYPE_RGB_8, INTENT_PERCEPTUAL, 0);
2829 	if (from) cmsCloseProfile(from);
2830 	cmsCloseProfile(to);
2831 	if (!how) return (FALSE); // Better luck the next time
2832 
2833 	settings->icc = (char *)how;
2834 	settings->icc_size = -2;
2835 	return (TRUE);
2836 }
2837 
done_cmyk2rgb(ls_settings * settings)2838 static void done_cmyk2rgb(ls_settings *settings)
2839 {
2840 	if (settings->icc_size != -2) return;
2841 	cmsDeleteTransform((cmsHTRANSFORM)settings->icc);
2842 	settings->icc = NULL;
2843 	settings->icc_size = -1; // Not need profiles anymore
2844 }
2845 
2846 #else /* No LCMS */
2847 #define done_cmyk2rgb(X)
2848 #endif
2849 #endif
2850 
cmyk2rgb(unsigned char * dest,unsigned char * src,int cnt,int inverted,ls_settings * settings)2851 static void cmyk2rgb(unsigned char *dest, unsigned char *src, int cnt,
2852 	int inverted, ls_settings *settings)
2853 {
2854 	unsigned char xb;
2855 	int j, k, r, g, b;
2856 
2857 #ifdef U_LCMS
2858 	/* Convert CMYK to RGB using LCMS if possible */
2859 	if (settings->icc_size == -2)
2860 	{
2861 		cmsDoTransform((cmsHTRANSFORM)settings->icc, src, dest, cnt);
2862 		return;
2863 	}
2864 #endif
2865 	/* Simple CMYK->RGB conversion */
2866 	xb = inverted ? 0 : 255;
2867 	for (j = 0; j < cnt; j++ , src += 4 , dest += 3)
2868 	{
2869 		k = src[3] ^ xb;
2870 		r = (src[0] ^ xb) * k;
2871 		dest[0] = (r + (r >> 8) + 1) >> 8;
2872 		g = (src[1] ^ xb) * k;
2873 		dest[1] = (g + (g >> 8) + 1) >> 8;
2874 		b = (src[2] ^ xb) * k;
2875 		dest[2] = (b + (b >> 8) + 1) >> 8;
2876 	}
2877 }
2878 
2879 #ifdef U_JPEG
2880 struct my_error_mgr
2881 {
2882 	struct jpeg_error_mgr pub;	// "public" fields
2883 	jmp_buf setjmp_buffer;		// for return to caller
2884 };
2885 
2886 typedef struct my_error_mgr *my_error_ptr;
2887 
my_error_exit(j_common_ptr cinfo)2888 METHODDEF(void) my_error_exit (j_common_ptr cinfo)
2889 {
2890 	my_error_ptr myerr = (my_error_ptr) cinfo->err;
2891 	longjmp(myerr->setjmp_buffer, 1);
2892 }
2893 struct my_error_mgr jerr;
2894 
load_jpeg(char * file_name,ls_settings * settings)2895 static int load_jpeg(char *file_name, ls_settings *settings)
2896 {
2897 	static int pr;
2898 	struct jpeg_decompress_struct cinfo;
2899 	unsigned char *memp, *memx = NULL;
2900 	FILE *fp;
2901 	int i, width, height, bpp, res = -1, inv = 0;
2902 #ifdef U_LCMS
2903 	unsigned char *icc = NULL;
2904 #endif
2905 
2906 	if ((fp = fopen(file_name, "rb")) == NULL) return (-1);
2907 
2908 	pr = 0;
2909 	jpeg_create_decompress(&cinfo);
2910 	cinfo.err = jpeg_std_error(&jerr.pub);
2911 	jerr.pub.error_exit = my_error_exit;
2912 	if (setjmp(jerr.setjmp_buffer))
2913 	{
2914 		res = settings->width ? FILE_LIB_ERROR : -1;
2915 		goto fail;
2916 	}
2917 	jpeg_stdio_src(&cinfo, fp);
2918 
2919 #ifdef U_LCMS
2920 	/* Request ICC profile aka APP2 data be preserved */
2921 	if (!settings->icc_size)
2922 		jpeg_save_markers(&cinfo, JPEG_APP0 + 2, 0xFFFF);
2923 #endif
2924 
2925 	jpeg_read_header(&cinfo, TRUE);
2926 	jpeg_start_decompress(&cinfo);
2927 
2928 	bpp = 3;
2929 	switch (cinfo.out_color_space)
2930 	{
2931 	case JCS_RGB: break;
2932 	case JCS_GRAYSCALE:
2933 		set_gray(settings);
2934 		bpp = 1;
2935 		break;
2936 	case JCS_CMYK:
2937 		/* Photoshop writes CMYK data inverted */
2938 		inv = cinfo.saw_Adobe_marker;
2939 		if ((memx = malloc(cinfo.output_width * 4))) break;
2940 		res = FILE_MEM_ERROR;
2941 		// Fallthrough
2942 	default: goto fail; /* Unsupported colorspace */
2943 	}
2944 
2945 	settings->width = width = cinfo.output_width;
2946 	settings->height = height = cinfo.output_height;
2947 	settings->bpp = bpp;
2948 	if ((res = allocate_image(settings, CMASK_IMAGE))) goto fail;
2949 	res = -1;
2950 	pr = !settings->silent;
2951 
2952 #ifdef U_LCMS
2953 #define PARTHDR 14
2954 	while (!settings->icc_size)
2955 	{
2956 		jpeg_saved_marker_ptr mk;
2957 		unsigned char *tmp, *parts[256];
2958 		int i, part, nparts = -1, icclen = 0, lparts[256];
2959 
2960 		/* List parts */
2961 		memset(parts, 0, sizeof(parts));
2962 		for (mk = cinfo.marker_list; mk; mk = mk->next)
2963 		{
2964 			if ((mk->marker != JPEG_APP0 + 2) ||
2965 				(mk->data_length < PARTHDR) ||
2966 				strcmp(mk->data, "ICC_PROFILE")) continue;
2967 			part = GETJOCTET(mk->data[13]);
2968 			if (nparts < 0) nparts = part;
2969 			if (nparts != part) break;
2970 			part = GETJOCTET(mk->data[12]);
2971 			if (!part-- || (part >= nparts) || parts[part]) break;
2972 			parts[part] = (unsigned char *)(mk->data + PARTHDR);
2973 			icclen += lparts[part] = mk->data_length - PARTHDR;
2974 		}
2975 		if (nparts < 0) break;
2976 
2977 		icc = tmp = malloc(icclen);
2978 		if (!icc) break;
2979 
2980 		/* Assemble parts */
2981 		for (i = 0; i < nparts; i++)
2982 		{
2983 			if (!parts[i]) break;
2984 			memcpy(tmp, parts[i], lparts[i]);
2985 			tmp += lparts[i];
2986 		}
2987 		if (i < nparts) break; // Sequence had a hole
2988 
2989 		/* If profile is needed right now, for CMYK->RGB */
2990 		if (memx && init_cmyk2rgb(settings, icc, icclen, inv))
2991 			break; // Transform is ready, so drop the profile
2992 
2993 		settings->icc = icc;
2994 		settings->icc_size = icclen;
2995 		icc = NULL; // Leave the profile be
2996 		break;
2997 	}
2998 	free(icc);
2999 #undef PARTHDR
3000 #endif
3001 
3002 	if (pr) ls_init("JPEG", 0);
3003 
3004 	for (i = 0; i < height; i++)
3005 	{
3006 		memp = settings->img[CHN_IMAGE] + width * i * bpp;
3007 		jpeg_read_scanlines(&cinfo, memx ? &memx : &memp, 1);
3008 		if (memx) cmyk2rgb(memp, memx, width, inv, settings);
3009 		ls_progress(settings, i, 20);
3010 	}
3011 	done_cmyk2rgb(settings);
3012 	jpeg_finish_decompress(&cinfo);
3013 	res = 1;
3014 
3015 fail:	if (pr) progress_end();
3016 	jpeg_destroy_decompress(&cinfo);
3017 	fclose(fp);
3018 	free(memx);
3019 	return (res);
3020 }
3021 
save_jpeg(char * file_name,ls_settings * settings)3022 static int save_jpeg(char *file_name, ls_settings *settings)
3023 {
3024 	struct jpeg_compress_struct cinfo;
3025 	JSAMPROW row_pointer;
3026 	FILE *fp;
3027 	int i;
3028 
3029 
3030 	if (settings->bpp == 1) return WRONG_FORMAT;
3031 
3032 	if ((fp = fopen(file_name, "wb")) == NULL) return -1;
3033 
3034 	cinfo.err = jpeg_std_error(&jerr.pub);
3035 	jerr.pub.error_exit = my_error_exit;
3036 	if (setjmp(jerr.setjmp_buffer))
3037 	{
3038 		jpeg_destroy_compress(&cinfo);
3039 		fclose(fp);
3040 		return -1;
3041 	}
3042 
3043 	jpeg_create_compress(&cinfo);
3044 
3045 	jpeg_stdio_dest( &cinfo, fp );
3046 	cinfo.image_width = settings->width;
3047 	cinfo.image_height = settings->height;
3048 	cinfo.input_components = 3;
3049 	cinfo.in_color_space = JCS_RGB;
3050 	jpeg_set_defaults(&cinfo);
3051 	jpeg_set_quality(&cinfo, settings->jpeg_quality, TRUE );
3052 	jpeg_start_compress( &cinfo, TRUE );
3053 
3054 	row_pointer = settings->img[CHN_IMAGE];
3055 	if (!settings->silent) ls_init("JPEG", 1);
3056 	for (i = 0; i < settings->height; i++ )
3057 	{
3058 		jpeg_write_scanlines(&cinfo, &row_pointer, 1);
3059 		row_pointer += 3 * settings->width;
3060 		ls_progress(settings, i, 20);
3061 	}
3062 	jpeg_finish_compress( &cinfo );
3063 
3064 	if (!settings->silent) progress_end();
3065 
3066 	jpeg_destroy_compress( &cinfo );
3067 	fclose(fp);
3068 
3069 	return 0;
3070 }
3071 #endif
3072 
3073 #ifdef NEED_FILE2MEM
3074 /* Read in the entire file, up to max size if given */
file2mem(char * file_name,unsigned char ** where,size_t * len,size_t max)3075 static int file2mem(char *file_name, unsigned char **where, size_t *len, size_t max)
3076 {
3077 	FILE *fp;
3078 	unsigned char *buf;
3079 	f_long l;
3080 	int res = -1;
3081 
3082 	if (!(fp = fopen(file_name, "rb"))) return (-1);
3083 	fseek(fp, 0, SEEK_END);
3084 	l = ftell(fp);
3085 	/* Where a f_long is too short to hold the file's size, address space is
3086 	 * too small to usefully hold the whole file anyway - WJ */
3087 	/* And when a hard limit is set, it should be honored */
3088 	if ((l > 0) && (!max || (l <= max)))
3089 	{
3090 		fseek(fp, 0, SEEK_SET);
3091 		res = FILE_MEM_ERROR;
3092 		if ((buf = malloc(l)))
3093 		{
3094 			res = -1;
3095 			if (fread(buf, 1, l, fp) < l) free(buf);
3096 			else *where = buf , *len = l , res = 0;
3097 		}
3098 	}
3099 	fclose(fp);
3100 	return (res);
3101 }
3102 #endif
3103 
3104 #ifdef U_JP2
3105 
3106 /* *** PREFACE ***
3107  * OpenJPEG 1.x is wasteful in the extreme, with memory overhead of about
3108  * 7 times the unpacked image size. So it can fail to handle even such
3109  * resolutions that fit into available memory with lots of room to spare.
3110  * Still, JasPer is an even worse memory hog, if a somewhat faster one.
3111  * Another thing - Linux builds of OpenJPEG cannot properly encode an opacity
3112  * channel (fixed in SVN on 06.11.09, revision 541)
3113  * And JP2 images with 4 channels, produced by OpenJPEG, cause JasPer
3114  * to die horribly.
3115  * Version 2.3.0 (04.10.17) was a sharp improvement, being twice faster than
3116  * JasPer when decompressing and less memory hungry (overhead of 5x size). When
3117  * compressing however, as of 2.3.1 still was about twice slower than JasPer.
3118  * Version 2.4.0 (28.12.20) fixed that, becoming about twice faster than JasPer
3119  * when compressing too.
3120  * Decompression speedup happened only for 64-bit builds, but on 32-bit with
3121  * multiple cores, multithreading still can let it overtake JasPer - WJ */
3122 
parse_opj(opj_image_t * image,ls_settings * settings)3123 static int parse_opj(opj_image_t *image, ls_settings *settings)
3124 {
3125 	opj_image_comp_t *comp;
3126 	unsigned char xtb[256], *dest;
3127 	int i, j, k, w, h, w0, nc, step, shift;
3128 	unsigned delta;
3129 	int *src, cmask = CMASK_IMAGE, res;
3130 
3131 	if (image->numcomps < 3) /* Guess this is paletted */
3132 	{
3133 		set_gray(settings);
3134 		settings->bpp = 1;
3135 	}
3136 	else settings->bpp = 3;
3137 	if ((nc = settings->bpp) < image->numcomps) nc++ , cmask = CMASK_RGBA;
3138 	comp = image->comps;
3139 	settings->width = w = (comp->w + (1 << comp->factor) - 1) >> comp->factor;
3140 	settings->height = h = (comp->h + (1 << comp->factor) - 1) >> comp->factor;
3141 	for (i = 1; i < nc; i++) /* Check if all components are the same size */
3142 	{
3143 		comp++;
3144 		if ((w != (comp->w + (1 << comp->factor) - 1) >> comp->factor) ||
3145 			(h != (comp->h + (1 << comp->factor) - 1) >> comp->factor))
3146 			return (-1);
3147 	}
3148 	if ((res = allocate_image(settings, cmask))) return (res);
3149 
3150 	/* Unpack data */
3151 	for (i = 0 , comp = image->comps; i < nc; i++ , comp++)
3152 	{
3153 		if (i < settings->bpp) /* Image */
3154 		{
3155 			dest = settings->img[CHN_IMAGE] + i;
3156 			step = settings->bpp;
3157 		}
3158 		else /* Alpha */
3159 		{
3160 			dest = settings->img[CHN_ALPHA];
3161 			if (!dest) break; /* No alpha allocated */
3162 			step = 1;
3163 		}
3164 		w0 = comp->w;
3165 		delta = comp->sgnd ? 1U << (comp->prec - 1) : 0;
3166 		shift = comp->prec > 8 ? comp->prec - 8 : 0;
3167 		set_xlate(xtb, comp->prec - shift);
3168 		for (j = 0; j < h; j++)
3169 		{
3170 			src = comp->data + j * w0;
3171 			for (k = 0; k < w; k++)
3172 			{
3173 				*dest = xtb[(src[k] + delta) >> shift];
3174 				dest += step;
3175 			}
3176 		}
3177 	}
3178 
3179 #ifdef U_LCMS
3180 #if U_JP2 >= 2 /* 2.x */
3181 	/* Extract ICC profile if it's of use */
3182 	if (!settings->icc_size && image->icc_profile_buf &&
3183 		(image->icc_profile_len < INT_MAX) &&
3184 		(settings->icc = malloc(image->icc_profile_len)))
3185 		memcpy(settings->icc, image->icc_profile_buf,
3186 			settings->icc_size = image->icc_profile_len);
3187 #endif
3188 #endif
3189 	return (1);
3190 }
3191 
prepare_opj(ls_settings * settings)3192 static opj_image_t *prepare_opj(ls_settings *settings)
3193 {
3194 	opj_image_cmptparm_t channels[4];
3195 	opj_image_t *image;
3196 	unsigned char *src;
3197 	int i, j, k, nc, step;
3198 	int *dest, w = settings->width, h = settings->height;
3199 
3200 	nc = settings->img[CHN_ALPHA] ? 4 : 3;
3201 	memset(channels, 0, sizeof(channels));
3202 	for (i = 0; i < nc; i++)
3203 	{
3204 		channels[i].prec = channels[i].bpp = 8;
3205 		channels[i].dx = channels[i].dy = 1;
3206 		channels[i].w = w;
3207 		channels[i].h = h;
3208 	}
3209 
3210 	image = opj_image_create(nc, channels,
3211 #if U_JP2 < 2 /* 1.x */
3212 		CLRSPC_SRGB);
3213 #else /* 2.x */
3214 		OPJ_CLRSPC_SRGB);
3215 #endif
3216 	if (!image) return (NULL);
3217 	image->x0 = image->y0 = 0;
3218 	image->x1 = w; image->y1 = h;
3219 
3220 	/* Fill it */
3221 	k = w * h;
3222 	for (i = 0; i < nc; i++)
3223 	{
3224 		if (i < 3)
3225 		{
3226 			src = settings->img[CHN_IMAGE] + i;
3227 			step = 3;
3228 		}
3229 		else
3230 		{
3231 			src = settings->img[CHN_ALPHA];
3232 			step = 1;
3233 		}
3234 		dest = image->comps[i].data;
3235 		for (j = 0; j < k; j++ , src += step) dest[j] = *src;
3236 	}
3237 
3238 	return (image);
3239 }
3240 
3241 #if U_JP2 < 2 /* 1.x */
3242 
stupid_callback(const char * msg,void * client_data)3243 static void stupid_callback(const char *msg, void *client_data)
3244 {
3245 }
3246 
load_jpeg2000(char * file_name,ls_settings * settings)3247 static int load_jpeg2000(char *file_name, ls_settings *settings)
3248 {
3249 	opj_dparameters_t par;
3250 	opj_dinfo_t *dinfo;
3251 	opj_cio_t *cio = NULL;
3252 	opj_image_t *image = NULL;
3253 	opj_event_mgr_t useless_events; // !!! Silently made mandatory in v1.2
3254 	unsigned char *buf = NULL;
3255 	size_t l;
3256 	int pr, res;
3257 
3258 
3259 	/* Read in the entire file, provided its size fits into int */
3260 	if ((res = file2mem(file_name, &buf, &l, INT_MAX))) return (res);
3261 
3262 	/* Decompress it */
3263 	dinfo = opj_create_decompress(settings->ftype == FT_J2K ? CODEC_J2K :
3264 		CODEC_JP2);
3265 	if (!dinfo) goto lfail;
3266 	memset(&useless_events, 0, sizeof(useless_events));
3267 	useless_events.error_handler = useless_events.warning_handler =
3268 		useless_events.info_handler = stupid_callback;
3269 	opj_set_event_mgr((opj_common_ptr)dinfo, &useless_events, stderr);
3270 	opj_set_default_decoder_parameters(&par);
3271 	opj_setup_decoder(dinfo, &par);
3272 	cio = opj_cio_open((opj_common_ptr)dinfo, buf, l);
3273 	if (!cio) goto lfail;
3274 	if ((pr = !settings->silent)) ls_init("JPEG2000", 0);
3275 	image = opj_decode(dinfo, cio);
3276 	opj_cio_close(cio);
3277 	opj_destroy_decompress(dinfo);
3278 	free(buf);
3279 	if (!image) goto ifail;
3280 
3281 	/* Analyze what we got */
3282 // !!! OpenJPEG 1.1.1 does *NOT* properly set image->color_space !!!
3283 	res = parse_opj(image, settings);
3284 
3285 ifail:	if (pr) progress_end();
3286 	opj_image_destroy(image);
3287 	return (res);
3288 lfail:	opj_destroy_decompress(dinfo);
3289 	free(buf);
3290 	return (res);
3291 }
3292 
save_jpeg2000(char * file_name,ls_settings * settings)3293 static int save_jpeg2000(char *file_name, ls_settings *settings)
3294 {
3295 	opj_cparameters_t par;
3296 	opj_cinfo_t *cinfo;
3297 	opj_cio_t *cio = NULL;
3298 	opj_image_t *image;
3299 	opj_event_mgr_t useless_events; // !!! Silently made mandatory in v1.2
3300 	FILE *fp;
3301 	int k, res = -1;
3302 
3303 
3304 	if (settings->bpp == 1) return WRONG_FORMAT;
3305 
3306 	if ((fp = fopen(file_name, "wb")) == NULL) return -1;
3307 
3308 	/* Create intermediate structure */
3309 	image = prepare_opj(settings);
3310 	if (!image) goto ffail;
3311 
3312 	/* Compress it */
3313 	if (!settings->silent) ls_init("JPEG2000", 1);
3314 	cinfo = opj_create_compress(settings->ftype == FT_JP2 ? CODEC_JP2 :
3315 		CODEC_J2K);
3316 	if (!cinfo) goto fail;
3317 	memset(&useless_events, 0, sizeof(useless_events));
3318 	useless_events.error_handler = useless_events.warning_handler =
3319 		useless_events.info_handler = stupid_callback;
3320 	opj_set_event_mgr((opj_common_ptr)cinfo, &useless_events, stderr);
3321 	opj_set_default_encoder_parameters(&par);
3322 	par.tcp_numlayers = 1;
3323 	par.tcp_rates[0] = settings->jp2_rate;
3324 	par.cp_disto_alloc = 1;
3325 	opj_setup_encoder(cinfo, &par, image);
3326 	cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0);
3327 	if (!cio) goto fail;
3328 	if (!opj_encode(cinfo, cio, image, NULL)) goto fail;
3329 
3330 	/* Write it */
3331 	k = cio_tell(cio);
3332 	if (fwrite(cio->buffer, 1, k, fp) == k) res = 0;
3333 
3334 fail:	if (cio) opj_cio_close(cio);
3335 	opj_destroy_compress(cinfo);
3336 	opj_image_destroy(image);
3337 	if (!settings->silent) progress_end();
3338 ffail:	fclose(fp);
3339 	return (res);
3340 }
3341 
3342 #else /* 2.x */
3343 
load_jpeg2000(char * file_name,ls_settings * settings)3344 static int load_jpeg2000(char *file_name, ls_settings *settings)
3345 {
3346 	opj_dparameters_t par;
3347 	opj_codec_t *dinfo;
3348 	opj_stream_t *inp = NULL;
3349 	opj_image_t *image = NULL;
3350 	int i, pr, res = -1;
3351 #if !OPJ_VERSION_MINOR /* 2.0.x */
3352 	FILE *fp;
3353 #endif
3354 
3355 
3356 #if !OPJ_VERSION_MINOR /* 2.0.x */
3357 	if ((fp = fopen(file_name, "rb")) == NULL) return (-1);
3358 	if (!(inp = opj_stream_create_default_file_stream(fp, TRUE))) goto ffail;
3359 #else /* 2.1+ */
3360 	if (!(inp = opj_stream_create_default_file_stream(file_name, TRUE)))
3361 		return (-1);
3362 #endif
3363 
3364 	/* Decompress it */
3365 	dinfo = opj_create_decompress(settings->ftype == FT_J2K ? OPJ_CODEC_J2K :
3366 		OPJ_CODEC_JP2);
3367 	if (!dinfo) goto ffail;
3368 	opj_set_default_decoder_parameters(&par);
3369 	if (!opj_setup_decoder(dinfo, &par)) goto dfail;
3370 #if defined(U_THREADS) && (OPJ_VERSION_MINOR >= 2) /* 2.2+ */
3371 	/* Not much effect on 64 bit as of 2.3.0 - only 10% faster from a 2nd core
3372 	 * But since 2.3.1, 1.3x faster with 2 cores, 1.7x with 4+ */
3373 	opj_codec_set_threads(dinfo, helper_threads());
3374 #endif
3375 	if ((pr = !settings->silent)) ls_init("JPEG2000", 0);
3376 	i = opj_read_header(inp, dinfo, &image) &&
3377 		opj_decode(dinfo, inp, image) &&
3378 		opj_end_decompress(dinfo, inp);
3379 	opj_destroy_codec(dinfo);
3380 	opj_stream_destroy(inp);
3381 	if (!i) goto ifail;
3382 
3383 	/* Parse what we got */
3384 	if (image->color_space >= OPJ_CLRSPC_SYCC)
3385 		goto ifail; // sYCC and CMYK - unsupported till seen in the wild
3386 	res = parse_opj(image, settings);
3387 
3388 ifail:	if (pr) progress_end();
3389 	opj_image_destroy(image);
3390 	return (res);
3391 dfail:	opj_destroy_codec(dinfo);
3392 ffail:	opj_stream_destroy(inp);
3393 #if !OPJ_VERSION_MINOR /* 2.0.x */
3394 	fclose(fp);
3395 #endif
3396 	return (res);
3397 }
3398 
save_jpeg2000(char * file_name,ls_settings * settings)3399 static int save_jpeg2000(char *file_name, ls_settings *settings)
3400 {
3401 	opj_cparameters_t par;
3402 	opj_codec_t *cinfo;
3403 	opj_stream_t *outp = NULL;
3404 	opj_image_t *image;
3405 	int res = -1;
3406 #if !OPJ_VERSION_MINOR /* 2.0.x */
3407 	FILE *fp;
3408 #endif
3409 
3410 	if (settings->bpp == 1) return WRONG_FORMAT;
3411 
3412 #if !OPJ_VERSION_MINOR /* 2.0.x */
3413 	if ((fp = fopen(file_name, "wb")) == NULL) return (-1);
3414 	if (!(outp = opj_stream_create_default_file_stream(fp, FALSE))) goto ffail;
3415 #else /* 2.1+ */
3416 	if (!(outp = opj_stream_create_default_file_stream(file_name, FALSE)))
3417 		return (-1);
3418 #endif
3419 
3420 	/* Create intermediate structure */
3421 	image = prepare_opj(settings);
3422 	if (!image) goto ffail;
3423 
3424 	/* Compress it */
3425 	if (!settings->silent) ls_init("JPEG2000", 1);
3426 	cinfo = opj_create_compress(settings->ftype == FT_JP2 ? OPJ_CODEC_JP2 :
3427 		OPJ_CODEC_J2K);
3428 	if (!cinfo) goto fail;
3429 	opj_set_default_encoder_parameters(&par);
3430 	par.tcp_numlayers = 1;
3431 	par.tcp_rates[0] = settings->jp2_rate;
3432 	par.cp_disto_alloc = 1;
3433 	opj_setup_encoder(cinfo, &par, image);
3434 #if defined(U_THREADS) && (OPJ_VERSION_MINOR >= 4) /* 2.4+ */
3435 	/* As of 2.4.0, 1.4x faster with 2 cores, 1.7x with 4+ */
3436 	opj_codec_set_threads(cinfo, helper_threads());
3437 #endif
3438 	if (opj_start_compress(cinfo, image, outp) &&
3439 		opj_encode(cinfo, outp) &&
3440 		opj_end_compress(cinfo, outp)) res = 0;
3441 fail:	opj_destroy_codec(cinfo);
3442 	opj_image_destroy(image);
3443 	if (!settings->silent) progress_end();
3444 ffail:	opj_stream_destroy(outp);
3445 #if !OPJ_VERSION_MINOR /* 2.0.x */
3446 	fclose(fp);
3447 #endif
3448 	return (res);
3449 }
3450 #endif
3451 #endif
3452 
3453 #ifdef U_JASPER
3454 
3455 /* *** PREFACE ***
3456  * JasPer is QUITE a memory waster, with peak memory usage nearly TEN times the
3457  * unpacked image size. But what is worse, its API is 99% undocumented.
3458  * And to add insult to injury, it reacts to some invalid JP2 files (4-channel
3459  * ones written by OpenJPEG) by abort()ing, instead of returning error - WJ */
3460 
3461 static int jasper_init;
3462 
load_jpeg2000(char * file_name,ls_settings * settings)3463 static int load_jpeg2000(char *file_name, ls_settings *settings)
3464 {
3465 	jas_image_t *img;
3466 	jas_stream_t *inp;
3467 	jas_matrix_t *mx;
3468 	jas_seqent_t *src;
3469 	char *fmt;
3470 	unsigned char xtb[256], *dest;
3471 	int nc, cspace, mode, slots[4];
3472 	int bits, shift, chan, step;
3473 	unsigned delta;
3474 	int i, j, k, n, nx, w, h, bpp, pr = 0, res = -1;
3475 
3476 
3477 	/* Init the dumb library */
3478 	if (!jasper_init) jas_init();
3479 	jasper_init = TRUE;
3480 	/* Open the file */
3481 	inp = jas_stream_fopen(file_name, "rb");
3482 	if (!inp) return (-1);
3483 	/* Validate format */
3484 	fmt = jas_image_fmttostr(jas_image_getfmt(inp));
3485 	if (!fmt || strcmp(fmt, settings->ftype == FT_JP2 ? "jp2" : "jpc"))
3486 		goto ffail;
3487 
3488 	/* Decode the file into a halfbaked pile of bytes */
3489 	if ((pr = !settings->silent)) ls_init("JPEG2000", 0);
3490 	img = jas_image_decode(inp, -1, NULL);
3491 	jas_stream_close(inp);
3492 	if (!img) goto dfail;
3493 	/* Analyze the pile's contents */
3494 	nc = jas_image_numcmpts(img);
3495 	mode = jas_clrspc_fam(cspace = jas_image_clrspc(img));
3496 	if (mode == JAS_CLRSPC_FAM_GRAY) bpp = 1;
3497 	else if (mode == JAS_CLRSPC_FAM_RGB) bpp = 3;
3498 	else goto ifail;
3499 	if (bpp == 3)
3500 	{
3501 		slots[0] = jas_image_getcmptbytype(img,
3502 			JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_RGB_R));
3503 		slots[1] = jas_image_getcmptbytype(img,
3504 			JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_RGB_G));
3505 		slots[2] = jas_image_getcmptbytype(img,
3506 			JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_RGB_B));
3507 		if ((slots[1] < 0) | (slots[2] < 0)) goto ifail;
3508 	}
3509 	else
3510 	{
3511 		slots[0] = jas_image_getcmptbytype(img,
3512 			JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_GRAY_Y));
3513 		set_gray(settings);
3514 	}
3515 	if (slots[0] < 0) goto ifail;
3516 	if (nc > bpp)
3517 	{
3518 		slots[bpp] = jas_image_getcmptbytype(img, JAS_IMAGE_CT_OPACITY);
3519 /* !!! JasPer has a bug - it doesn't write out component definitions if color
3520  * channels are in natural order, thus losing the types of any extra components.
3521  * (See where variable "needcdef" in src/libjasper/jp2/jp2_enc.c gets unset.)
3522  * Then on reading, type will be replaced by component's ordinal number - WJ */
3523 		if (slots[bpp] < 0) slots[bpp] = jas_image_getcmptbytype(img, bpp);
3524 		/* Use an unlabeled extra component for alpha if no labeled one */
3525 		if (slots[bpp] < 0)
3526 			slots[bpp] = jas_image_getcmptbytype(img, JAS_IMAGE_CT_UNKNOWN);
3527 		nc = bpp + (slots[bpp] >= 0); // Ignore extra channels if no alpha
3528 	}
3529 	w = jas_image_cmptwidth(img, slots[0]);
3530 	h = jas_image_cmptheight(img, slots[0]);
3531 	for (i = 1; i < nc; i++) /* Check if all components are the same size */
3532 	{
3533 		if ((jas_image_cmptwidth(img, slots[i]) != w) ||
3534 			(jas_image_cmptheight(img, slots[i]) != h)) goto ifail;
3535 	}
3536 
3537 	/* Allocate "matrix" */
3538 	res = FILE_MEM_ERROR;
3539 	mx = jas_matrix_create(1, w);
3540 	if (!mx) goto ifail;
3541 	/* Allocate image */
3542 	settings->width = w;
3543 	settings->height = h;
3544 	settings->bpp = bpp;
3545 	if ((res = allocate_image(settings, nc > bpp ? CMASK_RGBA : CMASK_IMAGE)))
3546 		goto mfail;
3547 	if (!settings->img[CHN_ALPHA]) nc = bpp;
3548 	res = 1;
3549 #if U_LCMS
3550 	/* JasPer implements CMS internally, but without lcms, it makes no sense
3551 	 * to provide all the interface stuff for this one rare format - WJ */
3552 	while (!settings->icc_size && (bpp == 3) && (cspace != JAS_CLRSPC_SRGB))
3553 	{
3554 		jas_cmprof_t *prof;
3555 		jas_image_t *timg;
3556 
3557 		res = FILE_LIB_ERROR;
3558 		prof = jas_cmprof_createfromclrspc(JAS_CLRSPC_SRGB);
3559 		if (!prof) break;
3560 		timg = jas_image_chclrspc(img, prof, JAS_CMXFORM_INTENT_PER);
3561 		jas_cmprof_destroy(prof);
3562 		if (!timg) break;
3563 		jas_image_destroy(img);
3564 		img = timg;
3565 		res = 1; // Success - further code is fail-proof
3566 		break;
3567 	}
3568 #endif
3569 
3570 	/* Unravel the ugly thing into proper format */
3571 	nx = h * nc;
3572 	for (i = n = 0; i < nc; i++)
3573 	{
3574 		if (i < bpp) /* Image */
3575 		{
3576 			dest = settings->img[CHN_IMAGE] + i;
3577 			step = settings->bpp;
3578 		}
3579 		else /* Alpha */
3580 		{
3581 			dest = settings->img[CHN_ALPHA];
3582 			step = 1;
3583 		}
3584 		chan = slots[i];
3585 		bits = jas_image_cmptprec(img, chan);
3586 		delta = jas_image_cmptsgnd(img, chan) ? 1U << (bits - 1) : 0;
3587 		shift = bits > 8 ? bits - 8 : 0;
3588 		set_xlate(xtb, bits - shift);
3589 		for (j = 0; j < h; j++ , n++)
3590 		{
3591 			jas_image_readcmpt(img, chan, 0, j, w, 1, mx);
3592 			src = jas_matrix_getref(mx, 0, 0);
3593 			for (k = 0; k < w; k++)
3594 			{
3595 				*dest = xtb[(src[k] + delta) >> shift];
3596 				dest += step;
3597 			}
3598 			if (pr && ((n * 10) % nx >= nx - 10))
3599 				progress_update((float)n / nx);
3600 		}
3601 	}
3602 
3603 mfail:	jas_matrix_destroy(mx);
3604 ifail:	jas_image_destroy(img);
3605 dfail:	if (pr) progress_end();
3606 	return (res);
3607 ffail:	jas_stream_close(inp);
3608 	return (-1);
3609 }
3610 
save_jpeg2000(char * file_name,ls_settings * settings)3611 static int save_jpeg2000(char *file_name, ls_settings *settings)
3612 {
3613 	static const jas_image_cmpttype_t chans[4] = {
3614 		JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_RGB_R),
3615 		JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_RGB_G),
3616 		JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_RGB_B),
3617 		JAS_IMAGE_CT_OPACITY };
3618 	jas_image_cmptparm_t cp[4];
3619 	jas_image_t *img;
3620 	jas_stream_t *outp;
3621 	jas_matrix_t *mx;
3622 	jas_seqent_t *dest;
3623 	char buf[256], *opts = NULL;
3624 	unsigned char *src;
3625 	int w = settings->width, h = settings->height, res = -1;
3626 	int i, j, k, n, nx, nc, step, pr;
3627 
3628 
3629 	if (settings->bpp == 1) return WRONG_FORMAT;
3630 
3631 	/* Init the dumb library */
3632 	if (!jasper_init) jas_init();
3633 	jasper_init = TRUE;
3634 	/* Open the file */
3635 	outp = jas_stream_fopen(file_name, "wb");
3636 	if (!outp) return (-1);
3637 	/* Setup component parameters */
3638 	memset(cp, 0, sizeof(cp)); // Zero out all that needs zeroing
3639 	cp[0].hstep = cp[0].vstep = 1;
3640 	cp[0].width = w; cp[0].height = h;
3641 	cp[0].prec = 8;
3642 	cp[3] = cp[2] = cp[1] = cp[0];
3643 	/* Create image structure */
3644 	nc = 3 + !!settings->img[CHN_ALPHA];
3645 	img = jas_image_create(nc, cp, JAS_CLRSPC_SRGB);
3646 	if (!img) goto fail;
3647 	/* Allocate "matrix" */
3648 	mx = jas_matrix_create(1, w);
3649 	if (!mx) goto fail2;
3650 
3651 	if ((pr = !settings->silent)) ls_init("JPEG2000", 1);
3652 
3653 	/* Fill image structure */
3654 	nx = h * nc;
3655 	nx += nx / 10 + 1; // Show "90% done" while compressing
3656 	for (i = n = 0; i < nc; i++)
3657 	{
3658 	/* !!! The only workaround for JasPer losing extra components' types on
3659 	 * write is to reorder the RGB components - but then, dumb readers, such
3660 	 * as ones in Mozilla and GTK+, would read them in wrong order - WJ */
3661 		jas_image_setcmpttype(img, i, chans[i]);
3662 		if (i < 3) /* Image */
3663 		{
3664 			src = settings->img[CHN_IMAGE] + i;
3665 			step = settings->bpp;
3666 		}
3667 		else /* Alpha */
3668 		{
3669 			src = settings->img[CHN_ALPHA];
3670 			step = 1;
3671 		}
3672 		for (j = 0; j < h; j++ , n++)
3673 		{
3674 			dest = jas_matrix_getref(mx, 0, 0);
3675 			for (k = 0; k < w; k++)
3676 			{
3677 				dest[k] = *src;
3678 				src += step;
3679 			}
3680 			jas_image_writecmpt(img, i, 0, j, w, 1, mx);
3681 			if (pr && ((n * 10) % nx >= nx - 10))
3682 				if (progress_update((float)n / nx)) goto fail3;
3683 		}
3684 	}
3685 
3686 	/* Compress it */
3687 	if (pr) progress_update(0.9);
3688 	if (settings->jp2_rate) // Lossless if NO "rate" option passed
3689 		sprintf(opts = buf, "rate=%g", 1.0 / settings->jp2_rate);
3690 	if (!jas_image_encode(img, outp, jas_image_strtofmt(
3691 		settings->ftype == FT_JP2 ? "jp2" : "jpc"), opts)) res = 0;
3692 	jas_stream_flush(outp);
3693 	if (pr) progress_update(1.0);
3694 
3695 fail3:	if (pr) progress_end();
3696 	jas_matrix_destroy(mx);
3697 fail2:	jas_image_destroy(img);
3698 fail:	jas_stream_close(outp);
3699 	return (res);
3700 }
3701 #endif
3702 
3703 /* Slow-but-sure universal bitstream parsers; may read extra byte at the end */
stream_MSB(unsigned char * src,unsigned char * dest,int cnt,int bits,int bit0,int bitstep,int step)3704 static void stream_MSB(unsigned char *src, unsigned char *dest, int cnt,
3705 	int bits, int bit0, int bitstep, int step)
3706 {
3707 	int i, j, v, mask = (1 << bits) - 1;
3708 
3709 	for (i = 0; i < cnt; i++)
3710 	{
3711 		j = bit0 >> 3;
3712 		v = (src[j] << 8) | src[j + 1];
3713 		v >>= 16 - bits - (bit0 & 7);
3714 		*dest = (unsigned char)(v & mask);
3715 		bit0 += bitstep;
3716 		dest += step;
3717 	}
3718 }
3719 
stream_LSB(unsigned char * src,unsigned char * dest,int cnt,int bits,int bit0,int bitstep,int step)3720 static void stream_LSB(unsigned char *src, unsigned char *dest, int cnt,
3721 	int bits, int bit0, int bitstep, int step)
3722 {
3723 	int i, j, v, mask = (1 << bits) - 1;
3724 
3725 	for (i = 0; i < cnt; i++)
3726 	{
3727 		j = bit0 >> 3;
3728 		v = (src[j + 1] << 8) | src[j];
3729 		v >>= bit0 & 7;
3730 		*dest = (unsigned char)(v & mask);
3731 		bit0 += bitstep;
3732 		dest += step;
3733 	}
3734 }
3735 
pack_MSB(unsigned char * dest,unsigned char * src,int len,int bw)3736 static void pack_MSB(unsigned char *dest, unsigned char *src, int len, int bw)
3737 {
3738 	int i;
3739 
3740 	memset(dest, 0, (len + 7) >> 3);
3741 	for (i = 0; i < len; i++)
3742 		dest[i >> 3] |= (*src++ == bw) << (~i & 7);
3743 }
3744 
3745 static void copy_bytes(unsigned char *dest, unsigned char *src, int len,
3746 	int bpp, int step);
3747 
3748 #ifdef U_TIFF
3749 
3750 /* *** PREFACE ***
3751  * TIFF is a bitch, and libtiff is a joke. An unstable and buggy joke, at that.
3752  * It's a fact of life - and when some TIFFs don't load or are mangled, that
3753  * also is a fact of life. Installing latest libtiff may help - or not; sending
3754  * a bugreport with the offending file attached may help too - but again, it's
3755  * not guaranteed. But the common varieties of TIFF format should load OK. */
3756 
3757 tiff_format tiff_formats[TIFF_MAX_TYPES] = {
3758 	{ _("None"),	COMPRESSION_NONE, TIFFLAGS, XF_COMPT },
3759 	{ "Group 3",	COMPRESSION_CCITTFAX3, FF_BW | TIFF0FLAGS, XF_COMPT },
3760 	{ "Group 4",	COMPRESSION_CCITTFAX4, FF_BW | TIFF0FLAGS, XF_COMPT },
3761 	{ "PackBits",	COMPRESSION_PACKBITS, TIFFLAGS, XF_COMPT },
3762 	{ "LZW",	COMPRESSION_LZW, TIFFLAGS, XF_COMPT, 1 },
3763 	{ "ZIP",	COMPRESSION_ADOBE_DEFLATE, TIFFLAGS, XF_COMPT | XF_COMPZT, 1 },
3764 #ifdef COMPRESSION_LZMA
3765 	{ "LZMA2",	COMPRESSION_LZMA, TIFFLAGS, XF_COMPT | XF_COMPLZ, 1 },
3766 #endif
3767 #ifdef COMPRESSION_ZSTD
3768 	{ "ZSTD",	COMPRESSION_ZSTD, TIFFLAGS, XF_COMPT | XF_COMPZS, 1 },
3769 #endif
3770 	{ "JPEG",	COMPRESSION_JPEG, FF_RGB | TIFF0FLAGS, XF_COMPT | XF_COMPJ },
3771 #ifdef COMPRESSION_WEBP
3772 	{ "WebP",	COMPRESSION_WEBP, FF_RGB | FF_ALPHAR | TIFF0FLAGS, XF_COMPT | XF_COMPWT },
3773 #endif
3774 	{ NULL }
3775 };
3776 
3777 int tiff_lzma, tiff_zstd; /* FALSE by default */
3778 
init_tiff_formats()3779 void init_tiff_formats()	// Check what libtiff can handle
3780 {
3781 	tiff_format *src, *dest;
3782 
3783 	/* Try all compiled-in formats */
3784 	src = dest = tiff_formats + 1; // COMPRESSION_NONE is always there
3785 	while (src->name)
3786 	{
3787 		if (TIFFIsCODECConfigured(src->id)) *dest++ = *src;
3788 		src++;
3789 	}
3790 	/* Zero out extra slots */
3791 	while (dest != src) *dest++ = *src;
3792 	/* Set flag variables */
3793 #ifdef COMPRESSION_LZMA
3794 	tiff_lzma = TIFFIsCODECConfigured(COMPRESSION_LZMA);
3795 #endif
3796 #ifdef COMPRESSION_ZSTD
3797 	tiff_zstd = TIFFIsCODECConfigured(COMPRESSION_ZSTD);
3798 #endif
3799 }
3800 
load_tiff_frame(TIFF * tif,ls_settings * settings)3801 static int load_tiff_frame(TIFF *tif, ls_settings *settings)
3802 {
3803 	char cbuf[1024];
3804 	uint16 bpsamp, sampp, xsamp, pmetric, planar, orient, sform;
3805 	uint16 *sampinfo, *red16, *green16, *blue16;
3806 	uint32 width, height, tw = 0, th = 0, rps = 0;
3807 	uint32 *tr, *raster = NULL;
3808 	unsigned char *tmp, *buf = NULL;
3809 	int bpp = 3, cmask = CMASK_IMAGE, argb = FALSE, pr = FALSE;
3810 	int i, j, mirror, res;
3811 
3812 
3813 	/* Let's learn what we've got */
3814 	TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &sampp);
3815 	TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES, &xsamp, &sampinfo);
3816 	if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &pmetric))
3817 	{
3818 		/* Defaults like in libtiff */
3819 		if (sampp - xsamp == 1) pmetric = PHOTOMETRIC_MINISBLACK;
3820 		else if (sampp - xsamp == 3) pmetric = PHOTOMETRIC_RGB;
3821 		else return (-1);
3822 	}
3823 	TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLEFORMAT, &sform);
3824 	TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width);
3825 	TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);
3826 	TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &bpsamp);
3827 	TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planar);
3828 	planar = planar != PLANARCONFIG_CONTIG;
3829 	TIFFGetFieldDefaulted(tif, TIFFTAG_ORIENTATION, &orient);
3830 	switch (orient)
3831 	{
3832 	case ORIENTATION_TOPLEFT:
3833 	case ORIENTATION_LEFTTOP: mirror = 0; break;
3834 	case ORIENTATION_TOPRIGHT:
3835 	case ORIENTATION_RIGHTTOP: mirror = 1; break;
3836 	default:
3837 	case ORIENTATION_BOTLEFT:
3838 	case ORIENTATION_LEFTBOT: mirror = 2; break;
3839 	case ORIENTATION_BOTRIGHT:
3840 	case ORIENTATION_RIGHTBOT: mirror = 3; break;
3841 	}
3842 	if (TIFFIsTiled(tif))
3843 	{
3844 		TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw);
3845 		TIFFGetField(tif, TIFFTAG_TILELENGTH, &th);
3846 	}
3847 	else
3848 	{
3849 		TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rps);
3850 	}
3851 
3852 	/* Extract position from it */
3853 	settings->x = settings->y = 0;
3854 	while (TRUE)
3855 	{
3856 		float xres, yres, dxu = 0, dyu = 0;
3857 
3858 		if (!TIFFGetField(tif, TIFFTAG_XPOSITION, &dxu) &&
3859 			!TIFFGetField(tif, TIFFTAG_YPOSITION, &dyu)) break;
3860 		// Have position, now need resolution
3861 		if (!TIFFGetField(tif, TIFFTAG_XRESOLUTION, &xres)) break;
3862 		// X resolution we have, what about Y?
3863 		yres = xres; // Default
3864 		TIFFGetField(tif, TIFFTAG_YRESOLUTION, &yres);
3865 		// Convert ResolutionUnits (whatever they are) to pixels
3866 		settings->x = rint(dxu * xres);
3867 		settings->y = rint(dyu * yres);
3868 		break;
3869 	}
3870 
3871 	/* Let's decide how to store it */
3872 	if ((width > MAX_WIDTH) || (height > MAX_HEIGHT)) return (TOO_BIG);
3873 	settings->width = width;
3874 	settings->height = height;
3875 	if ((sform != SAMPLEFORMAT_UINT) && (sform != SAMPLEFORMAT_INT) &&
3876 		(sform != SAMPLEFORMAT_VOID)) argb = TRUE;
3877 	else	switch (pmetric)
3878 		{
3879 		case PHOTOMETRIC_PALETTE:
3880 		{
3881 			png_color *cp = settings->pal;
3882 			int i, j, k, na = 0, nd = 1; /* Old palette format */
3883 
3884 			if (bpsamp > 8)
3885 			{
3886 				argb = TRUE;
3887 				break;
3888 			}
3889 			if (!TIFFGetField(tif, TIFFTAG_COLORMAP,
3890 				&red16, &green16, &blue16)) return (-1);
3891 
3892 			settings->colors = j = 1 << bpsamp;
3893 			/* Analyze palette */
3894 			for (k = i = 0; i < j; i++)
3895 			{
3896 				k |= red16[i] | green16[i] | blue16[i];
3897 			}
3898 			if (k > 255) na = 128 , nd = 257; /* New palette format */
3899 
3900 			for (i = 0; i < j; i++ , cp++)
3901 			{
3902 				cp->red = (red16[i] + na) / nd;
3903 				cp->green = (green16[i] + na) / nd;
3904 				cp->blue = (blue16[i] + na) / nd;
3905 			}
3906 			/* If palette is all we need */
3907 			if ((settings->mode == FS_PALETTE_LOAD) ||
3908 				(settings->mode == FS_PALETTE_DEF))
3909 				return (EXPLODE_FAILED);
3910 			/* Fallthrough */
3911 		}
3912 		case PHOTOMETRIC_MINISWHITE:
3913 		case PHOTOMETRIC_MINISBLACK:
3914 			bpp = 1; break;
3915 		case PHOTOMETRIC_RGB:
3916 			break;
3917 		case PHOTOMETRIC_SEPARATED:
3918 			/* Leave non-CMYK separations to libtiff */
3919 			if (sampp - xsamp == 4) break;
3920 		default:
3921 			argb = TRUE;
3922 		}
3923 
3924 	/* libtiff can't handle this and neither can we */
3925 	if (argb && !TIFFRGBAImageOK(tif, cbuf)) return (-1);
3926 
3927 	settings->bpp = bpp;
3928 	/* Photoshop writes alpha as EXTRASAMPLE_UNSPECIFIED anyway */
3929 	if (xsamp) cmask = CMASK_RGBA;
3930 
3931 	/* !!! No alpha support for RGB mode yet */
3932 	if (argb) cmask = CMASK_IMAGE;
3933 
3934 	if ((res = allocate_image(settings, cmask))) return (res);
3935 	res = -1;
3936 
3937 #ifdef U_LCMS
3938 #ifdef TIFFTAG_ICCPROFILE
3939 	/* Extract ICC profile if it's of use */
3940 	if (!settings->icc_size)
3941 	{
3942 		uint32 size;
3943 		unsigned char *data;
3944 
3945 		/* TIFFTAG_ICCPROFILE was broken beyond hope in libtiff 3.8.0
3946 		 * (see libtiff 3.8.1+ changelog entry for 2006-01-04) */
3947 		if (!strstr(TIFFGetVersion(), " 3.8.0") &&
3948 			TIFFGetField(tif, TIFFTAG_ICCPROFILE, &size, &data) &&
3949 			(size < INT_MAX) &&
3950 			/* If profile is needed right now, for CMYK->RGB */
3951 			!((pmetric == PHOTOMETRIC_SEPARATED) && !argb &&
3952 				init_cmyk2rgb(settings, data, size, FALSE)) &&
3953 			(settings->icc = malloc(size)))
3954 		{
3955 			settings->icc_size = size;
3956 			memcpy(settings->icc, data, size);
3957 		}
3958 	}
3959 #endif
3960 #endif
3961 
3962 	if ((pr = !settings->silent)) ls_init("TIFF", 0);
3963 
3964 	/* Read it as ARGB if can't understand it ourselves */
3965 	if (argb)
3966 	{
3967 		/* libtiff is too much of a moving target if finer control is
3968 		 * needed, so let's trade memory for stability */
3969 		raster = (uint32 *)_TIFFmalloc(width * height * sizeof(uint32));
3970 		res = FILE_MEM_ERROR;
3971 		if (!raster) goto fail2;
3972 		res = FILE_LIB_ERROR;
3973 		if (!TIFFReadRGBAImage(tif, width, height, raster, 0)) goto fail2;
3974 		res = -1;
3975 
3976 		/* Parse the RGB part only - alpha might be eaten by bugs */
3977 		tr = raster;
3978 		for (i = height - 1; i >= 0; i--)
3979 		{
3980 			tmp = settings->img[CHN_IMAGE] + width * i * bpp;
3981 			j = width;
3982 			while (j--)
3983 			{
3984 				tmp[0] = TIFFGetR(*tr);
3985 				tmp[1] = TIFFGetG(*tr);
3986 				tmp[2] = TIFFGetB(*tr);
3987 				tmp += 3; tr++;
3988 			}
3989 			ls_progress(settings, height - i, 10);
3990 		}
3991 
3992 		_TIFFfree(raster);
3993 		raster = NULL;
3994 
3995 /* !!! Now it would be good to read in alpha ourselves - but not yet... */
3996 
3997 		res = 1;
3998 	}
3999 
4000 	/* Read & interpret it ourselves */
4001 	else
4002 	{
4003 		unsigned char xtable[256], *src, *tbuf = NULL;
4004 		uint32 x0, y0, xstep = tw ? tw : width, ystep = th ? th : rps;
4005 		int aalpha, tsz = 0, wbpp = bpp;
4006 		int bpr, bits1, bit0, db, n, nx;
4007 		int j, k, bsz, plane, nplanes;
4008 
4009 
4010 		if (pmetric == PHOTOMETRIC_SEPARATED) // Needs temp buffer
4011 			tsz = xstep * ystep * (wbpp = 4);
4012 		nplanes = planar ? wbpp + !!settings->img[CHN_ALPHA] : 1;
4013 
4014 		bsz = (tw ? TIFFTileSize(tif) : TIFFStripSize(tif)) + 1;
4015 		bpr = tw ? TIFFTileRowSize(tif) : TIFFScanlineSize(tif);
4016 
4017 		buf = _TIFFmalloc(bsz + tsz);
4018 		res = FILE_MEM_ERROR;
4019 		if (!buf) goto fail2;
4020 		res = FILE_LIB_ERROR;
4021 		if (tsz) tbuf = buf + bsz; // Temp buffer for CMYK->RGB
4022 
4023 		/* Flag associated alpha */
4024 		aalpha = settings->img[CHN_ALPHA] &&
4025 			(pmetric != PHOTOMETRIC_PALETTE) &&
4026 			(sampinfo[0] == EXTRASAMPLE_ASSOCALPHA);
4027 
4028 		bits1 = bpsamp > 8 ? 8 : bpsamp;
4029 
4030 		/* Setup greyscale palette */
4031 		if ((bpp == 1) && (pmetric != PHOTOMETRIC_PALETTE))
4032 		{
4033 			/* Demultiplied values are 0..255 */
4034 			j = aalpha ? 256 : 1 << bits1;
4035 			settings->colors = j--;
4036 			k = pmetric == PHOTOMETRIC_MINISBLACK ? 0 : j;
4037 			mem_bw_pal(settings->pal, k, j ^ k);
4038 		}
4039 
4040 		/* !!! Assume 16-, 32- and 64-bit data follow machine's
4041 		 * endianness, and everything else is packed big-endian way -
4042 		 * like TIFF 6.0 spec says; but TIFF 5.0 and before specs said
4043 		 * differently, so let's wait for examples to see if I'm right
4044 		 * or not; as for 24- and 128-bit, even different libtiff
4045 		 * versions handle them differently, so I leave them alone
4046 		 * for now - WJ */
4047 
4048 		bit0 = (G_BYTE_ORDER == G_LITTLE_ENDIAN) &&
4049 			((bpsamp == 16) || (bpsamp == 32) ||
4050 			(bpsamp == 64)) ? bpsamp - 8 : 0;
4051 		db = (planar ? 1 : sampp) * bpsamp;
4052 
4053 		/* Prepare to rescale what we've got */
4054 		memset(xtable, 0, 256);
4055 		set_xlate(xtable, bits1);
4056 
4057 		/* Progress steps */
4058 		nx = ((width + xstep - 1) / xstep) * nplanes * height;
4059 
4060 		/* Read image tile by tile - considering strip a wide tile */
4061 		for (n = y0 = 0; y0 < height; y0 += ystep)
4062 		for (x0 = 0; x0 < width; x0 += xstep)
4063 		for (plane = 0; plane < nplanes; plane++)
4064 		{
4065 			unsigned char *tmp, *tmpa;
4066 			uint32 x, y, w, h, l;
4067 			int i, k, dx, dxa, dy, dys;
4068 
4069 			/* Read one piece */
4070 			if (tw)
4071 			{
4072 				if (TIFFReadTile(tif, buf, x0, y0, 0, plane) < 0)
4073 					goto fail2;
4074 			}
4075 			else
4076 			{
4077 				if (TIFFReadEncodedStrip(tif,
4078 					TIFFComputeStrip(tif, y0, plane),
4079 					buf, bsz) < 0) goto fail2;
4080 			}
4081 
4082 			/* Prepare decoding loops */
4083 			if (mirror & 1) /* X mirror */
4084 			{
4085 				x = width - x0;
4086 				w = x < xstep ? x : xstep;
4087 				x -= w;
4088 			}
4089 			else
4090 			{
4091 				x = x0;
4092 				w = x + xstep > width ? width - x : xstep;
4093 			}
4094 			if (mirror & 2) /* Y mirror */
4095 			{
4096 				y = height - y0;
4097 				h = y < ystep ? y : ystep;
4098 				y -= h;
4099 			}
4100 			else
4101 			{
4102 				y = y0;
4103 				h = y + ystep > height ? height - y : ystep;
4104 			}
4105 
4106 			/* Prepare pointers */
4107 			dx = dxa = 1; dy = width;
4108 			i = y * width + x;
4109 			tmp = tmpa = settings->img[CHN_ALPHA] + i;
4110 			if (plane >= wbpp); // Alpha
4111 			else if (tbuf) // CMYK
4112 			{
4113 				dx = 4; dy = w;
4114 				tmp = tbuf + plane;
4115 			}
4116 			else // RGB/indexed
4117 			{
4118 				dx = bpp;
4119 				tmp = settings->img[CHN_IMAGE] + plane + i * bpp;
4120 			}
4121 			dy *= dx; dys = bpr;
4122 			src = buf;
4123 			/* Account for horizontal mirroring */
4124 			if (mirror & 1)
4125 			{
4126 				// Write bytes backward
4127 				tmp += (w - 1) * dx; tmpa += w - 1;
4128 				dx = -dx; dxa = -1;
4129 			}
4130 			/* Account for vertical mirroring */
4131 			if (mirror & 2)
4132 			{
4133 				// Read rows backward
4134 				src += (h - 1) * dys;
4135 				dys = -dys;
4136 			}
4137 
4138 			/* Decode it */
4139 			for (l = 0; l < h; l++ , n++ , src += dys , tmp += dy)
4140 			{
4141 				if (pr && ((n * 10) % nx >= nx - 10))
4142 					progress_update((float)n / nx);
4143 
4144 				stream_MSB(src, tmp, w, bits1, bit0, db, dx);
4145 				if (planar) continue;
4146 				for (k = 1; k < wbpp; k++)
4147 				{
4148 					stream_MSB(src, tmp + k, w, bits1,
4149 						bit0 + bpsamp * k, db, dx);
4150 				}
4151 				if (settings->img[CHN_ALPHA])
4152 				{
4153 					stream_MSB(src, tmpa, w, bits1,
4154 						bit0 + bpsamp * wbpp, db, dxa);
4155 					tmpa += width;
4156 				}
4157 			}
4158 
4159 			/* Convert CMYK to RGB if needed */
4160 			if (!tbuf || (planar && (plane != 3))) continue;
4161 			if (bits1 < 8)	// Rescale to 8-bit
4162 				do_xlate(xtable, tbuf, w * h * 4);
4163 			cmyk2rgb(tbuf, tbuf, w * h, FALSE, settings);
4164 			src = tbuf;
4165 			tmp = settings->img[CHN_IMAGE] + (y * width + x) * 3;
4166 			w *= 3;
4167 			for (l = 0; l < h; l++ , tmp += width * 3 , src += w)
4168 				memcpy(tmp, src, w);
4169 		}
4170 		done_cmyk2rgb(settings);
4171 
4172 		j = width * height;
4173 		tmp = settings->img[CHN_IMAGE];
4174 		src = settings->img[CHN_ALPHA];
4175 
4176 		/* Unassociate alpha */
4177 		if (aalpha)
4178 		{
4179 			if (wbpp > 3) // Converted from CMYK
4180 			{
4181 				unsigned char *img = tmp;
4182 				int i, k, a;
4183 
4184 				if (bits1 < 8) do_xlate(xtable, src, j);
4185 				bits1 = 8; // No further rescaling needed
4186 
4187 				/* Remove white background */
4188 				for (i = 0; i < j; i++ , img += 3)
4189 				{
4190 					a = src[i] - 255;
4191 					k = a + img[0];
4192 					img[0] = k < 0 ? 0 : k;
4193 					k = a + img[1];
4194 					img[1] = k < 0 ? 0 : k;
4195 					k = a + img[2];
4196 					img[2] = k < 0 ? 0 : k;
4197 				}
4198 			}
4199 			mem_demultiply(tmp, src, j, bpp);
4200 			tmp = NULL; // Image is done
4201 		}
4202 
4203 		if (bits1 < 8)
4204 		{
4205 			/* Rescale alpha */
4206 			if (src) do_xlate(xtable, src, j);
4207 			/* Rescale RGB */
4208 			if (tmp && (wbpp == 3)) do_xlate(xtable, tmp, j * 3);
4209 		}
4210 		res = 1;
4211 	}
4212 
4213 fail2:	if (pr) progress_end();
4214 	if (raster) _TIFFfree(raster);
4215 	if (buf) _TIFFfree(buf);
4216 	return (res);
4217 }
4218 
load_tiff_frames(char * file_name,ani_settings * ani)4219 static int load_tiff_frames(char *file_name, ani_settings *ani)
4220 {
4221 	TIFF *tif;
4222 	ls_settings w_set;
4223 	int res;
4224 
4225 
4226 	/* We don't want any echoing to the output */
4227 	TIFFSetErrorHandler(NULL);
4228 	TIFFSetWarningHandler(NULL);
4229 
4230 	if (!(tif = TIFFOpen(file_name, "r"))) return (-1);
4231 
4232 	while (TRUE)
4233 	{
4234 		res = FILE_TOO_LONG;
4235 		if (!check_next_frame(&ani->fset, ani->settings.mode, FALSE))
4236 			goto fail;
4237 		w_set = ani->settings;
4238 		w_set.gif_delay = -1; // Multipage
4239 		res = load_tiff_frame(tif, &w_set);
4240 		if (res != 1) goto fail;
4241 		res = process_page_frame(file_name, ani, &w_set);
4242 		if (res) goto fail;
4243 		/* Try to get next frame */
4244 		if (!TIFFReadDirectory(tif)) break;
4245 	}
4246 	res = 1;
4247 fail:	TIFFClose(tif);
4248 	return (res);
4249 }
4250 
4251 #ifndef TIFF_VERSION_BIG /* The ONLY useful way to detect libtiff 4.x vs 3.x */
4252 #define tmsize_t tsize_t
4253 #endif
4254 
mTIFFread(thandle_t fd,void * buf,tmsize_t size)4255 static tmsize_t mTIFFread(thandle_t fd, void* buf, tmsize_t size)
4256 {
4257 	return mfread(buf, 1, size, (memFILE *)fd);
4258 }
4259 
mTIFFwrite(thandle_t fd,void * buf,tmsize_t size)4260 static tmsize_t mTIFFwrite(thandle_t fd, void* buf, tmsize_t size)
4261 {
4262 	return mfwrite(buf, 1, size, (memFILE *)fd);
4263 }
4264 
mTIFFlseek(thandle_t fd,toff_t off,int whence)4265 static toff_t mTIFFlseek(thandle_t fd, toff_t off, int whence)
4266 {
4267 	return mfseek((memFILE *)fd, (f_long)off, whence) ? -1 : ((memFILE *)fd)->m.here;
4268 }
4269 
mTIFFclose(thandle_t fd)4270 static int mTIFFclose(thandle_t fd)
4271 {
4272 	return 0;
4273 }
4274 
mTIFFsize(thandle_t fd)4275 static toff_t mTIFFsize(thandle_t fd)
4276 {
4277 	return ((memFILE *)fd)->top;
4278 }
4279 
mTIFFmap(thandle_t fd,void ** base,toff_t * size)4280 static int mTIFFmap(thandle_t fd, void** base, toff_t* size)
4281 {
4282 	*base = ((memFILE *)fd)->m.buf;
4283 	*size = ((memFILE *)fd)->top;
4284 	return 1;
4285 }
4286 
mTIFFunmap(thandle_t fd,void * base,toff_t size)4287 static void mTIFFunmap(thandle_t fd, void* base, toff_t size)
4288 {
4289 }
4290 
load_tiff(char * file_name,ls_settings * settings,memFILE * mf)4291 static int load_tiff(char *file_name, ls_settings *settings, memFILE *mf)
4292 {
4293 	TIFF *tif;
4294 	int res;
4295 
4296 
4297 	/* We don't want any echoing to the output */
4298 	TIFFSetErrorHandler(NULL);
4299 	TIFFSetWarningHandler(NULL);
4300 
4301 	if (!mf) tif = TIFFOpen(file_name, "r");
4302 	else tif = TIFFClientOpen("", "r", (void *)mf, mTIFFread, mTIFFwrite,
4303 		mTIFFlseek, mTIFFclose, mTIFFsize, mTIFFmap, mTIFFunmap);
4304 	if (!tif) return (-1);
4305 	res = load_tiff_frame(tif, settings);
4306 	if ((res == 1) && TIFFReadDirectory(tif)) res = FILE_HAS_FRAMES;
4307 	TIFFClose(tif);
4308 	return (res);
4309 }
4310 
save_tiff(char * file_name,ls_settings * settings,memFILE * mf)4311 static int save_tiff(char *file_name, ls_settings *settings, memFILE *mf)
4312 {
4313 	unsigned char buf[MAX_WIDTH / 8], *src, *row = NULL;
4314 	uint16 rgb[256 * 3];
4315 	unsigned int tflags, sflags, xflags;
4316 	int i, l, type, bw, af, pf, res = 0, pmetric = -1;
4317 	int w = settings->width, h = settings->height, bpp = settings->bpp;
4318 	TIFF *tif;
4319 
4320 
4321 	/* Select output mode */
4322 	sflags = FF_SAVE_MASK_FOR(*settings);
4323 	type = settings->tiff_type;
4324 	if (type < 0) type = bpp == 3 ? tiff_rtype : // RGB
4325 		settings->colors <= 2 ?	tiff_btype : // BW
4326 		tiff_itype; // Indexed
4327 	if (settings->mode == FS_CLIPBOARD)
4328 	{
4329 		type = 0; // Uncompressed
4330 		/* RGB for clipboard mask */
4331 		if (settings->img[CHN_ALPHA]) sflags = FF_RGB , bpp = 3;
4332 	}
4333 	tflags = tiff_formats[type].flags;
4334 	sflags &= tflags;
4335 	bw = !(sflags & (FF_256 | FF_RGB));
4336 	if (!sflags) return WRONG_FORMAT; // Paranoia
4337 
4338 	af = settings->img[CHN_ALPHA] && (tflags & FF_ALPHA);
4339 
4340 	/* Use 1-bit mode where possible */
4341 	if (!bw && !af && (sflags & FF_BW))
4342 	{
4343 		/* No need of palette if the colors are full white and black */
4344 		i = PNG_2_INT(settings->pal[0]);
4345 		bw = (!i ? 0xFFFFFF : i == 0xFFFFFF ? 0 : -1) ==
4346 			PNG_2_INT(settings->pal[1]) ? 1 : -1;
4347 	}
4348 
4349 	/* !!! When using predictor, libtiff 3.8 modifies row buffer in-place */
4350 	pf = tiff_predictor && !bw && tiff_formats[type].pflag;
4351 	if (af || pf || (bpp > settings->bpp))
4352 	{
4353 		row = malloc(w * (bpp + af));
4354 		if (!row) return -1;
4355 	}
4356 
4357 	TIFFSetErrorHandler(NULL);	// We don't want any echoing to the output
4358 	TIFFSetWarningHandler(NULL);
4359 	if (!mf) tif = TIFFOpen(file_name, "w");
4360 	else tif = TIFFClientOpen("", "w", (void *)mf, mTIFFread, mTIFFwrite,
4361 		mTIFFlseek, mTIFFclose, mTIFFsize, mTIFFmap, mTIFFunmap);
4362 	if (!tif)
4363 	{
4364 		free(row);
4365 		return -1;
4366 	}
4367 
4368 	/* Write regular tags */
4369 	TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, w);
4370 	TIFFSetField(tif, TIFFTAG_IMAGELENGTH, h);
4371 	TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, bpp + af);
4372 	TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bw ? 1 : 8);
4373 	TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
4374 
4375 	/* Write compression-specific tags */
4376 	TIFFSetField(tif, TIFFTAG_COMPRESSION, tiff_formats[type].id);
4377 	xflags = tiff_formats[type].xflags;
4378 	if (xflags & XF_COMPZT)
4379 		TIFFSetField(tif, TIFFTAG_ZIPQUALITY, settings->png_compression);
4380 #ifdef COMPRESSION_LZMA
4381 	if (xflags & XF_COMPLZ)
4382 		TIFFSetField(tif, TIFFTAG_LZMAPRESET, settings->lzma_preset);
4383 #endif
4384 #ifdef COMPRESSION_ZSTD
4385 	if (xflags & XF_COMPZS)
4386 		TIFFSetField(tif, TIFFTAG_ZSTD_LEVEL, settings->zstd_level);
4387 #endif
4388 #ifdef COMPRESSION_WEBP
4389 	if (xflags & XF_COMPWT)
4390 	{
4391 		TIFFSetField(tif, TIFFTAG_WEBP_LEVEL, settings->webp_quality);
4392 		// !!! libtiff 4.0.10 *FAILS* to do it losslessly despite trying
4393 		if (settings->webp_quality == 100)
4394 			TIFFSetField(tif, TIFFTAG_WEBP_LOSSLESS, 1);
4395 	}
4396 #endif
4397 	if (xflags & XF_COMPJ)
4398 	{
4399 		TIFFSetField(tif, TIFFTAG_JPEGQUALITY, settings->jpeg_quality);
4400 		TIFFSetField(tif, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
4401 		pmetric = PHOTOMETRIC_YCBCR;
4402 	}
4403 	if (pf) TIFFSetField(tif, TIFFTAG_PREDICTOR, PREDICTOR_HORIZONTAL);
4404 
4405 	if (bw > 0) pmetric = get_bw(settings) ? PHOTOMETRIC_MINISWHITE :
4406 		PHOTOMETRIC_MINISBLACK;
4407 	else if (bpp == 1)
4408 	{
4409 		pmetric = PHOTOMETRIC_PALETTE;
4410 		memset(rgb, 0, sizeof(rgb));
4411 		l = bw ? 2 : 256;
4412 		for (i = 0; i < settings->colors; i++)
4413 		{
4414 			rgb[i] = settings->pal[i].red * 257;
4415 			rgb[i + l] = settings->pal[i].green * 257;
4416 			rgb[i + l * 2] = settings->pal[i].blue * 257;
4417 		}
4418 		TIFFSetField(tif, TIFFTAG_COLORMAP, rgb, rgb + l, rgb + l * 2);
4419 	}
4420 	else if (pmetric < 0) pmetric = PHOTOMETRIC_RGB;
4421 	TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, pmetric);
4422 	if (af)
4423 	{
4424 		rgb[0] = EXTRASAMPLE_UNASSALPHA;
4425 		TIFFSetField(tif, TIFFTAG_EXTRASAMPLES, 1, rgb);
4426 	}
4427 
4428 	/* Actually write the image */
4429 	if (!settings->silent) ls_init("TIFF", 1);
4430 	for (i = 0; i < h; i++)
4431 	{
4432 		src = settings->img[CHN_IMAGE] + w * i * settings->bpp;
4433 		if (bw) /* Pack the bits */
4434 		{
4435 			pack_MSB(buf, src, w, 1);
4436 			src = buf;
4437 		}
4438 		else if (row) /* Fill the buffer */
4439 			src = prepare_row(row, settings, bpp + af, i);
4440 		if (TIFFWriteScanline(tif, src, i, 0) == -1)
4441 		{
4442 			res = -1;
4443 			break;
4444 		}
4445 		ls_progress(settings, i, 20);
4446 	}
4447 	TIFFClose(tif);
4448 
4449 	if (!settings->silent) progress_end();
4450 
4451 	free(row);
4452 	return (res);
4453 }
4454 #endif
4455 
4456 #ifdef U_WEBP
4457 
4458 /* *** PREFACE ***
4459  * WebP Demux API is exceedingly cumbersome in case you don't feed the entire
4460  * file to it in one single memory block. Stepping through the RIFF container to
4461  * pick individual chunks is more manageable. */
4462 
4463 /* Macro for little-endian tags (RIFF) */
4464 #define TAG4(A,B,C,D) ((A) + ((B) << 8) + ((C) << 16) + ((D) << 24))
4465 
4466 #define GET24(buf) (((buf)[2] << 16) + ((buf)[1] << 8) + (buf)[0])
4467 #define PUT24(buf, v) (buf)[0] = (v) & 0xFF; (buf)[1] = ((v) >> 8) & 0xFF; \
4468 	(buf)[2] = ((v) >> 16) & 0xFF;
4469 
4470 /* !!! In documentation, bit fields are written in reverse; actual flag values
4471  * used by libwebp are as if bits are numbered right to left instead - WJ */
4472 
4473 /* Macros for WEBP tags */
4474 #define TAG4_RIFF TAG4('R', 'I', 'F', 'F')
4475 #define TAG4_WEBP TAG4('W', 'E', 'B', 'P')
4476 #define TAG4_VP8X TAG4('V', 'P', '8', 'X')
4477 #define TAG4_ANIM TAG4('A', 'N', 'I', 'M')
4478 #define TAG4_ANMF TAG4('A', 'N', 'M', 'F')
4479 #define TAG4_VP8  TAG4('V', 'P', '8', ' ')
4480 #define TAG4_VP8L TAG4('V', 'P', '8', 'L')
4481 #define TAG4_ALPH TAG4('A', 'L', 'P', 'H')
4482 #define TAG4_ICCP TAG4('I', 'C', 'C', 'P')
4483 #define TAG4_EXIF TAG4('E', 'X', 'I', 'F')
4484 #define TAG4_XMP  TAG4('X', 'M', 'P', ' ')
4485 
4486 #define RIFF_TAGSIZE 4
4487 
4488 /* RIFF block header */
4489 #define RIFF_TAG    0 /* 32b */
4490 #define RIFF_SIZE   4 /* 32b */
4491 #define RIFF_HSIZE  8
4492 
4493 /* WEBP header block (VP8X tag) */
4494 #define VP8X_FLAGS  0 /*  8b */
4495 #define VP8X_W1     4 /* 24b */
4496 #define VP8X_H1     7 /* 24b */
4497 #define VP8X_SIZE  10
4498 
4499 /* VP8X flags (ignore on read) */
4500 #define VP8XF_ANIM   2
4501 #define VP8XF_ALPHA 16
4502 #define VP8XF_ICC   32
4503 
4504 /* ANIM block */
4505 /* !!! Background color & alpha are ignored by vwebp */
4506 #define ANIM_BKG_B  0 /* 8b */
4507 #define ANIM_BKG_G  1 /* 8b */
4508 #define ANIM_BKG_R  2 /* 8b */
4509 #define ANIM_BKG_A  3 /* 8b */
4510 #define ANIM_LOOP   4 /* 16b */
4511 #define ANIM_SIZE   6
4512 
4513 /* ANMF block header */
4514 #define ANMF_X2     0 /* 24b */
4515 #define ANMF_Y2     3 /* 24b */
4516 #define ANMF_W1     6 /* 24b */
4517 #define ANMF_H1     9 /* 24b */
4518 #define ANMF_DELAY 12 /* 24b */
4519 #define ANMF_FLAGS 15 /*  8b */
4520 #define ANMF_HSIZE 16
4521 
4522 /* ANMF flags */
4523 #define ANMF_F_NOBLEND 2
4524 #define ANMF_F_BKG     1 /* Dispose to background */
4525 
4526 #define HAVE_IMG  0x01
4527 #define HAVE_VP8X 0x02
4528 #define HAVE_ANIM 0x04
4529 #define HAVE_XTRA 0x08
4530 #define HAVE_ALPH 0x10
4531 #define HAVE_ANMF 0x20
4532 
4533 typedef struct {
4534 	FILE *f;
4535 	unsigned len;	// File data left unparsed
4536 	unsigned size;	// How much to read for this frame
4537 	int blocks;
4538 	unsigned char hdr[VP8X_SIZE], bkg[4];
4539 	unsigned char anmf[ANMF_HSIZE + RIFF_TAGSIZE];
4540 } webphead;
4541 
load_webp_frame(webphead * wp,ls_settings * settings)4542 static int load_webp_frame(webphead *wp, ls_settings *settings)
4543 {
4544 	WebPDecoderConfig dconf;
4545 	unsigned char *buf;
4546 	int wh, bpp, wbpp = 3, cmask = CMASK_IMAGE, res = -1;
4547 
4548 
4549 	if (!WebPInitDecoderConfig(&dconf)) return (-1); // Wrong lib version
4550 	if (!(buf = malloc(wp->size))) return (FILE_MEM_ERROR);
4551 	if (fread(buf, 1, wp->size, wp->f) != wp->size) goto fail;
4552 	if (WebPGetFeatures((void *)buf, wp->size, &dconf.input) != VP8_STATUS_OK)
4553 		goto fail;
4554 
4555 	if (dconf.input.has_alpha) wbpp = 4 , cmask = CMASK_RGBA;
4556 	wh = dconf.input.width * dconf.input.height;
4557 	settings->width = dconf.input.width;
4558 	settings->height = dconf.input.height;
4559 	settings->bpp = wbpp;
4560 
4561 	/* Get the extras from frame header */
4562 	if (wp->blocks & HAVE_ANMF)
4563 	{
4564 		settings->x = GET24(wp->anmf + ANMF_X2) * 2;
4565 		settings->y = GET24(wp->anmf + ANMF_Y2) * 2;
4566 		/* Within mtPaint delays are 1/100s granular */
4567 		settings->gif_delay = (GET24(wp->anmf + ANMF_DELAY) + 9) / 10; // Round up
4568 	}
4569 
4570 	if ((res = allocate_image(settings, cmask))) goto fail;
4571 
4572 	bpp = settings->img[CHN_ALPHA] ? 4 : 3;
4573 	dconf.output.colorspace = bpp > 3 ? MODE_RGBA : MODE_RGB;
4574 	dconf.output.u.RGBA.rgba = settings->img[CHN_IMAGE];
4575 	dconf.output.u.RGBA.stride = settings->width * bpp;
4576 	dconf.output.u.RGBA.size = wh * bpp;
4577 	dconf.output.is_external_memory = 1;
4578 
4579 	if (!settings->silent) ls_init("WebP", 0);
4580 	res = FILE_LIB_ERROR;
4581 	if (WebPDecode(buf, wp->size, &dconf) == VP8_STATUS_OK)
4582 	{
4583 		if (bpp == 4) /* Separate out alpha from RGBA */
4584 		{
4585 			copy_bytes(settings->img[CHN_ALPHA],
4586 				settings->img[CHN_IMAGE] + 3, wh, 1, 4);
4587 			copy_bytes(settings->img[CHN_IMAGE],
4588 				settings->img[CHN_IMAGE], wh, 3, 4);
4589 		}
4590 		if (wbpp > 3) /* Downsize image channel */
4591 		{
4592 			unsigned char *w = realloc(settings->img[CHN_IMAGE], wh * 3);
4593 			if (w) settings->img[CHN_IMAGE] = w;
4594 		}
4595 		res = 1;
4596 	}
4597 	if (!settings->silent) progress_end();
4598 	WebPFreeDecBuffer(&dconf.output);
4599 
4600 fail:	free(buf);
4601 	return (res);
4602 }
4603 
webp_scan(webphead * wp,ls_settings * settings)4604 static int webp_scan(webphead *wp, ls_settings *settings)
4605 {
4606 	unsigned char buf[256];
4607 	FILE *fp = wp->f;
4608 	unsigned tag, tl;
4609 	f_long alph = -1;
4610 
4611 	if (!settings) // Next-frame mode
4612 	{
4613 		/* If a regular image was first, believe there are no other frames */
4614 		if (!(wp->blocks & HAVE_ANMF)) return (FALSE);
4615 
4616 		wp->blocks &= ~(HAVE_ALPH | HAVE_IMG); // Prepare for new frame
4617 	}
4618 
4619 	/* Read block headers & see what we get */
4620 	while ((wp->len >= RIFF_HSIZE) && (fread(buf, 1, RIFF_HSIZE, fp) == RIFF_HSIZE))
4621 	{
4622 		tag = GET32(buf);
4623 		tl = GET32(buf + RIFF_SIZE);
4624 		if (tl > 0xFFFFFFFFU - 1 - RIFF_HSIZE) break; // MAX_CHUNK_PAYLOAD
4625 		if (tl >= F_LONG_MAX) break; // Limit for what can be handled
4626 		tl += tl & 1; // Pad
4627 		if (wp->len < tl + RIFF_HSIZE) break; // Does not fit in RIFF
4628 		wp->len -= tl + RIFF_HSIZE;
4629 
4630 		if (tag == TAG4_ANMF)
4631 		{
4632 			if (tl < ANMF_HSIZE + RIFF_HSIZE) break;
4633 			if (fread(wp->anmf, 1, ANMF_HSIZE + RIFF_TAGSIZE, fp) !=
4634 				ANMF_HSIZE + RIFF_TAGSIZE) break;
4635 			fseek(fp, -RIFF_TAGSIZE, SEEK_CUR);
4636 			wp->blocks |= HAVE_ANMF;
4637 			tag = GET32(wp->anmf + ANMF_HSIZE);
4638 			if (tag == TAG4_ALPH) wp->blocks |= HAVE_ALPH;
4639 			else if ((tag != TAG4_VP8) && (tag != TAG4_VP8L)) break; // Damaged?
4640 			wp->size = tl - ANMF_HSIZE;
4641 			wp->blocks |= HAVE_IMG;
4642 			break; // Done
4643 		}
4644 		/* Be extra accepting - skip duplicates of header chunks w/o failing */
4645 		else if (!settings && ((tag == TAG4_VP8X) || (tag == TAG4_ANIM) ||
4646 			(tag == TAG4_ICCP)));
4647 		/* Fail on encountering image chunk where a frame should be */
4648 		else if (!settings && ((tag == TAG4_VP8) || (tag == TAG4_VP8L) ||
4649 			(tag == TAG4_ALPH))) break;
4650 		else if (tag == TAG4_VP8X)
4651 		{
4652 			if (tl != VP8X_SIZE) break;
4653 			if (fread(wp->hdr, 1, VP8X_SIZE, fp) != VP8X_SIZE) break;
4654 			wp->blocks |= HAVE_VP8X;
4655 			continue;
4656 		}
4657 		else if (tag == TAG4_ANIM)
4658 		{
4659 			if (tl != ANIM_SIZE) break;
4660 			if (fread(buf, 1, ANIM_SIZE, fp) != ANIM_SIZE) break;
4661 			/* Rearrange the bytes the sane way */
4662 			wp->bkg[0] = buf[ANIM_BKG_R];
4663 			wp->bkg[1] = buf[ANIM_BKG_G];
4664 			wp->bkg[2] = buf[ANIM_BKG_B];
4665 			wp->bkg[3] = buf[ANIM_BKG_A];
4666 			wp->blocks |= HAVE_ANIM;
4667 			continue;
4668 		}
4669 #ifdef U_LCMS
4670 		else if (tag == TAG4_ICCP)
4671 		{
4672 			unsigned char *tmp = NULL;
4673 
4674 			wp->blocks |= HAVE_XTRA;
4675 			if (!settings->icc_size &&
4676 				(tl < INT_MAX) && // For sanity (and icc_size size)
4677 				(tmp = malloc(tl)) &&
4678 				(fread(tmp, 1, tl, fp) == tl))
4679 			{
4680 				settings->icc = tmp;
4681 				settings->icc_size = tl;
4682 				continue;
4683 			}
4684 			if (tmp) /* Failed to read */
4685 			{
4686 				free(tmp);
4687 				break;
4688 			}
4689 		}
4690 #endif
4691 		else if (tag == TAG4_ALPH)
4692 		{
4693 			wp->blocks |= HAVE_ALPH;
4694 			alph = ftell(fp);
4695 			if (alph < 0) break;
4696 		}
4697 		else if ((tag == TAG4_VP8) || (tag == TAG4_VP8L))
4698 		{
4699 			fseek(fp, -RIFF_HSIZE, SEEK_CUR);
4700 			wp->size = tl + RIFF_HSIZE;
4701 			if (alph > 0) // Need to start with alpha
4702 			{
4703 				f_long here = ftell(fp);
4704 				if (here < 0) break; // Too long for us
4705 				/* From ALPH header to this block's end */
4706 				wp->size += here - alph + RIFF_HSIZE;
4707 				fseek(fp, alph - RIFF_HSIZE, SEEK_SET);
4708 			}
4709 			wp->blocks |= HAVE_IMG;
4710 			break;
4711 		}
4712 		else wp->blocks |= HAVE_XTRA;
4713 		/* Default: skip (the rest of) tag data */
4714 		if (tl && fseek(fp, tl, SEEK_CUR)) break;
4715 	}
4716 	return (wp->blocks & HAVE_IMG);
4717 }
4718 
webp_behead(FILE * fp,webphead * wp,ls_settings * settings)4719 static int webp_behead(FILE *fp, webphead *wp, ls_settings *settings)
4720 {
4721 	unsigned char buf[RIFF_HSIZE + RIFF_TAGSIZE];
4722 	unsigned tl;
4723 
4724 
4725 	memset(wp, 0, sizeof(webphead));
4726 	wp->f = fp;
4727 
4728 	/* Read the RIFF header & check signature */
4729 	if (fread(buf, 1, RIFF_HSIZE + RIFF_TAGSIZE, fp) < RIFF_HSIZE + RIFF_TAGSIZE)
4730 		return (FALSE);
4731 	if ((GET32(buf) != TAG4_RIFF) || (GET32(buf + RIFF_HSIZE) != TAG4_WEBP))
4732 		return (FALSE);
4733 
4734 	tl = GET32(buf + RIFF_SIZE);
4735 	if (tl < RIFF_TAGSIZE + RIFF_HSIZE) return (FALSE);
4736 	tl -= RIFF_TAGSIZE;
4737 	tl += tl & 1; // Pad
4738 	wp->len = tl;
4739 
4740 	webp_scan(wp, settings);
4741 	return (wp->blocks & HAVE_IMG);
4742 }
4743 
load_webp_frames(char * file_name,ani_settings * ani)4744 static int load_webp_frames(char *file_name, ani_settings *ani)
4745 {
4746 	webphead wp;
4747 	ani_status stat;
4748 	ls_settings w_set, init_set;
4749 	FILE *fp;
4750 	int bpp, disposal, res = -1;
4751 
4752 
4753 	if (!(fp = fopen(file_name, "rb"))) return (-1);
4754 	memset(w_set.img, 0, sizeof(chanlist));
4755 
4756 	/* Init temp container */
4757 	init_set = ani->settings;
4758 	if (!webp_behead(fp, &wp, &init_set)) goto fail;
4759 
4760 	/* Need to have them to read them */
4761 	if ((wp.blocks & (HAVE_VP8X | HAVE_ANMF)) != (HAVE_VP8X | HAVE_ANMF))
4762 		goto fail;
4763 
4764 	/* Init state structure */
4765 	memset(&stat, 0, sizeof(stat));
4766 	stat.mode = ani->mode;
4767 	stat.defw = GET24(wp.hdr + VP8X_W1) + 1;
4768 	stat.defh = GET24(wp.hdr + VP8X_H1) + 1;
4769 	/* WebP has no palette of its own, use the default one */
4770 	mem_pal_copy(stat.newpal, ani->settings.pal);
4771 	stat.newcols = ani->settings.colors;
4772 	stat.newtrans = -1; // No color-key transparency
4773 	/* !!! vwebp ignores the value by default, and one example animation
4774 	 * expects transparency despite background set to opaque white - WJ */
4775 //	memcpy(stat.bkg, wp.bkg, 4); // RGBA background
4776 
4777 	/* Go through images */
4778 	while (TRUE)
4779 	{
4780 		res = FILE_TOO_LONG;
4781 		if (!check_next_frame(&ani->fset, ani->settings.mode, TRUE))
4782 			goto fail;
4783 		w_set = init_set;
4784 		res = load_webp_frame(&wp, &w_set);
4785 		if (res != 1) goto fail;
4786 		disposal = wp.anmf[ANMF_FLAGS] & ANMF_F_BKG ? FM_DISP_REMOVE :
4787 			FM_DISP_LEAVE;
4788 		delete_alpha(&w_set, 255);
4789 		stat.blend = !(wp.anmf[ANMF_FLAGS] & ANMF_F_NOBLEND) && w_set.img[CHN_ALPHA];
4790 		/* Analyze how we can merge the frames */
4791 		res = TOO_BIG;
4792 		bpp = analyze_rgba_frame(&stat, &w_set);
4793 		if (bpp < 0) goto fail;
4794 
4795 		/* Allocate a new frame */
4796 		res = add_frame(ani, &stat, &w_set, bpp, disposal);
4797 		if (res) goto fail;
4798 
4799 		/* Do actual compositing, remember disposal method */
4800 		composite_frame(&ani->fset, &stat, &w_set);
4801 		mem_free_chanlist(w_set.img);
4802 		memset(w_set.img, 0, sizeof(chanlist));
4803 
4804 		/* Write out those frames worthy to be stored */
4805 		res = done_frame(file_name, ani, FALSE);
4806 		if (res != 1) goto fail;
4807 
4808 		/* Step to the next frame, if any */
4809 		if (!webp_scan(&wp, NULL)) break;
4810 	}
4811 	/* Write out the final frame if not written before */
4812 	res = done_frame(file_name, ani, TRUE);
4813 
4814 fail:	mem_free_chanlist(w_set.img);
4815 	fclose(fp);
4816 	return (res);
4817 }
4818 
load_webp(char * file_name,ls_settings * settings)4819 static int load_webp(char *file_name, ls_settings *settings)
4820 {
4821 	webphead wp;
4822 	FILE *fp;
4823 	int res = -1;
4824 
4825 
4826 	if (!(fp = fopen(file_name, "rb"))) return (-1);
4827 	if (webp_behead(fp, &wp, settings))
4828 	{
4829 		res = load_webp_frame(&wp, settings);
4830 		if ((res == 1) && webp_scan(&wp, NULL)) res = FILE_HAS_FRAMES;
4831 	}
4832 	fclose(fp);
4833 	return (res);
4834 }
4835 
webp_fwrite(const uint8_t * data,size_t data_size,const WebPPicture * picture)4836 static int webp_fwrite(const uint8_t *data, size_t data_size, const WebPPicture *picture)
4837 {
4838 	return (fwrite(data, sizeof(uint8_t), data_size, picture->custom_ptr) == data_size);
4839 }
4840 
webp_progress(int percent,const WebPPicture * picture)4841 static int webp_progress(int percent, const WebPPicture *picture)
4842 {
4843 	return (!progress_update((float)percent / 100));
4844 }
4845 
4846 char *webp_presets[] = { _("Lossless"), _("Default"), _("Picture"), _("Photo"),
4847 	_("Drawing"), _("Icon"), _("Text"), NULL };
4848 
4849 // !!! Min version 0.5.0
4850 
save_webp(char * file_name,ls_settings * settings)4851 static int save_webp(char *file_name, ls_settings *settings)
4852 {
4853 	static const signed char presets[] = {
4854 		WEBP_PRESET_DEFAULT, /* Lossless */
4855 		WEBP_PRESET_DEFAULT,
4856 		WEBP_PRESET_PICTURE,
4857 		WEBP_PRESET_PHOTO,
4858 		WEBP_PRESET_DRAWING,
4859 		WEBP_PRESET_ICON,
4860 		WEBP_PRESET_TEXT };
4861 	WebPConfig conf;
4862 	WebPPicture pic;
4863 	FILE *fp;
4864 	unsigned char *rgba;
4865 	int wh, st, res = -1;
4866 
4867 	if (settings->bpp == 1) return WRONG_FORMAT;
4868 
4869 	if ((fp = fopen(file_name, "wb")) == NULL) return (-1);
4870 
4871 	if (!WebPConfigPreset(&conf, presets[settings->webp_preset],
4872 		settings->webp_quality)) goto ffail; // Lib failure
4873 	if (!settings->webp_preset)
4874 		WebPConfigLosslessPreset(&conf, settings->webp_compression);
4875 	conf.exact = TRUE; // Preserve invisible parts
4876 
4877 	/* Prepare intermediate container */
4878 	if (!WebPPictureInit(&pic)) goto ffail; // Lib failure
4879 	pic.use_argb = TRUE;
4880 	pic.width = settings->width;
4881 	pic.height = settings->height;
4882 	wh = pic.width * pic.height;
4883 	pic.writer = webp_fwrite;
4884 	pic.custom_ptr = (void *)fp;
4885 	if (!settings->silent) pic.progress_hook = webp_progress;
4886 	if (settings->img[CHN_ALPHA]) /* Need RGBA */
4887 	{
4888 		rgba = malloc(wh * 4);
4889 		if (!rgba) goto ffail;
4890 		copy_bytes(rgba, settings->img[CHN_IMAGE], wh, 4, 3);
4891 		copy_bytes(rgba + 3, settings->img[CHN_ALPHA], wh, 4, 1);
4892 		st = WebPPictureImportRGBA(&pic, rgba, pic.width * 4);
4893 		free(rgba);
4894 	}
4895 	/* RGB is enough */
4896 	else st = WebPPictureImportRGB(&pic, settings->img[CHN_IMAGE], pic.width * 3);
4897 
4898 	/* Do encode */
4899 	if (st)
4900 	{
4901 		if (!settings->silent) ls_init("WebP", 1);
4902 		if (WebPEncode(&conf, &pic)) res = 0;
4903 		WebPPictureFree(&pic);
4904 		if (!settings->silent) progress_end();
4905 	}
4906 
4907 ffail:	fclose(fp);
4908 	return (res);
4909 }
4910 #endif
4911 
4912 /* Version 2 fields */
4913 #define BMP_FILESIZE  2		/* 32b */
4914 #define BMP_XHOT      6		/* 16b */
4915 #define BMP_YHOT      8		/* 16b */
4916 #define BMP_DATAOFS  10		/* 32b */
4917 #define BMP_HDR2SIZE 14		/* 32b */
4918 #define BMP_WIDTH    18		/* s32b */
4919 #define BMP_HEIGHT   22		/* s32b */
4920 #define BMP_PLANES   26		/* 16b */
4921 #define BMP_BPP      28		/* 16b */
4922 #define BMP2_HSIZE   30
4923 /* Version 3 fields */
4924 #define BMP_COMPRESS 30		/* 32b */
4925 #define BMP_DATASIZE 34		/* 32b */
4926 #define BMP_XDPI     38		/* s32b */
4927 #define BMP_YDPI     42		/* s32b */
4928 #define BMP_COLORS   46		/* 32b */
4929 #define BMP_ICOLORS  50		/* 32b */
4930 #define BMP3_HSIZE   54
4931 /* Version 4 fields */
4932 #define BMP_RMASK    54		/* 32b */
4933 #define BMP_GMASK    58		/* 32b */
4934 #define BMP_BMASK    62		/* 32b */
4935 #define BMP_AMASK    66		/* 32b */
4936 #define BMP_CSPACE   70		/* 32b */
4937 #define BMP4_HSIZE  122
4938 /* Version 5 fields */
4939 #define BMP_INTENT  122		/* 32b */
4940 #define BMP_ICCOFS  126		/* 32b */
4941 #define BMP_ICCSIZE 130		/* 32b */
4942 #define BMP5_HSIZE  138
4943 #define BMP_MAXHSIZE (BMP5_HSIZE + 256 * 4)
4944 
4945 /* OS/2 1.x alternative fields */
4946 #define OS2BMP_WIDTH  18	/* 16b */
4947 #define OS2BMP_HEIGHT 20	/* 16b */
4948 #define OS2BMP_PLANES 22	/* 16b */
4949 #define OS2BMP_BPP    24	/* 16b */
4950 #define OS2BMP_HSIZE  26
4951 
4952 /* OS/2 2.x bitmap header is version 3 fields plus some extra */
4953 #define OS2BMP2_HSIZE 78
4954 /* Shortened header variant encountered in the wild */
4955 #define OS2BMP2_HSIZE_S 38
4956 
4957 /* OS/2 bitmap array fields */
4958 #define OS2BA_HDRSIZE  2	/* 32b */
4959 #define OS2BA_NEXT     6	/* 32b */
4960 #define OS2BA_HSIZE   14
4961 
4962 /* In OS/2 files, BMP_FILESIZE may instead contain header size */
4963 
4964 /* Colorspace tags */
4965 #define BMPCS_WIN   TAG4B('W', 'i', 'n', ' ')
4966 #define BMPCS_SRGB  TAG4B('s', 'R', 'G', 'B')
4967 #define BMPCS_LINK  TAG4B('L', 'I', 'N', 'K')
4968 #define BMPCS_EMBED TAG4B('M', 'B', 'E', 'D')
4969 
load_bmp(char * file_name,ls_settings * settings,memFILE * mf)4970 static int load_bmp(char *file_name, ls_settings *settings, memFILE *mf)
4971 {
4972 	guint32 masks[4];
4973 	unsigned char hdr[BMP5_HSIZE], xlat[256], *dest, *tmp, *buf = NULL;
4974 	memFILE fake_mf;
4975 	FILE *fp = NULL;
4976 	unsigned l, ofs;
4977 	int shifts[4], bpps[4];
4978 	int def_alpha = FALSE, cmask = CMASK_IMAGE, comp = 0, ba = 0, rle = 0, res = -1;
4979 	int i, j, k, n, ii, w, h, bpp, wbpp;
4980 	int bl, rl, step, skip, dx, dy;
4981 
4982 
4983 	if (!mf)
4984 	{
4985 		if (!(fp = fopen(file_name, "rb"))) return (-1);
4986 		memset(mf = &fake_mf, 0, sizeof(fake_mf));
4987 		fake_mf.file = fp;
4988 	}
4989 
4990 	/* Read the largest header */
4991 	k = mfread(hdr, 1, BMP5_HSIZE, mf);
4992 
4993 	/* Bitmap array? */
4994 	if ((k > OS2BA_HSIZE) && (hdr[0] == 'B') && (hdr[1] == 'A'))
4995 	{
4996 		/* Just skip the header to go for 1st bitmap: no example files
4997 		 * with more than one bitmap anyway */
4998 		ba = OS2BA_HSIZE;
4999 		memmove(hdr, hdr + ba, k -= ba);
5000 	}
5001 	/* Check general validity */
5002 	if (k < OS2BMP_HSIZE) goto fail; /* Least supported header size */
5003 	if ((hdr[0] != 'B') || (hdr[1] != 'M')) goto fail; /* Signature */
5004 	l = GET32(hdr + BMP_HDR2SIZE);
5005 	if (k - BMP_HDR2SIZE < l) goto fail;
5006 	l += BMP_HDR2SIZE;
5007 	if (ba && (l > OS2BMP2_HSIZE)) goto fail; /* Should not exist */
5008 	ofs = GET32(hdr + BMP_DATAOFS);
5009 	if (l + ba > ofs) goto fail; // Overlap
5010 	if (ofs > F_LONG_MAX) goto fail; // Cannot handle this length
5011 
5012 	/* Check format type: OS/2 or Windows */
5013 	if (l == OS2BMP_HSIZE)
5014 	{
5015 		w = GET16(hdr + OS2BMP_WIDTH);
5016 		h = GET16(hdr + OS2BMP_HEIGHT);
5017 		bpp = GET16(hdr + OS2BMP_BPP);
5018 	}
5019 	else if (l >= BMP2_HSIZE)
5020 	{
5021 		w = GET32s(hdr + BMP_WIDTH);
5022 		h = GET32s(hdr + BMP_HEIGHT);
5023 		bpp = GET16(hdr + BMP_BPP);
5024 	}
5025 	else goto fail;
5026 
5027 	/* Check format */
5028 	if (l >= BMP3_HSIZE) comp = GET32(hdr + BMP_COMPRESS);
5029 	/* !!! Some 8bpp OS/2 BMPs in the wild have compression not marked */
5030 	if (!comp && (bpp == 8) && (h > 0) && (l == OS2BMP2_HSIZE_S))
5031 	{
5032 		unsigned fsize = GET32(hdr + BMP_DATASIZE);
5033 		if (fsize && (fsize != w * h)) comp = 1;
5034 	}
5035 	/* Only 1, 4, 8, 16, 24 and 32 bpp allowed */
5036 	rle = comp;
5037 	switch (bpp)
5038 	{
5039 	case 1: if (comp) goto fail; /* No compression */
5040 		break;
5041 	case 4: if (comp && (comp != 2)) goto fail; /* RLE4 */
5042 		break;
5043 	case 8: if (comp && (comp != 1)) goto fail; /* RLE8 */
5044 		break;
5045 	case 24: if (comp == 4) /* RLE24 or JPEG */
5046 		{
5047 			/* If not definitely OS/2 header, consider it JPEG */
5048 			if ((l != OS2BMP2_HSIZE) && (l != OS2BMP2_HSIZE_S)) goto fail;
5049 			break;
5050 		}
5051 		// Fallthrough
5052 	case 16: case 32:
5053 		rle = 0;
5054 		if (comp && (comp != 3)) goto fail; /* Bitfields */
5055 		shifts[3] = bpps[3] = masks[3] = 0; /* No alpha by default */
5056 		if (comp == 3)
5057 		{
5058 			/* V3-style bitfields? */
5059 			if ((l == BMP3_HSIZE) && (ofs >= BMP_AMASK)) l = BMP_AMASK;
5060 			if (l < BMP_AMASK) goto fail;
5061 			masks[0] = GET32(hdr + BMP_RMASK);
5062 			masks[1] = GET32(hdr + BMP_GMASK);
5063 			masks[2] = GET32(hdr + BMP_BMASK);
5064 			if (l >= BMP_AMASK + 4)
5065 				masks[3] = GET32(hdr + BMP_AMASK);
5066 			if (masks[3]) cmask = CMASK_RGBA;
5067 
5068 			/* Convert masks into bit lengths and offsets */
5069 			for (i = 0; i < 4; i++)
5070 			{
5071 				/* Bit length - just count bits */
5072 				j = bitcount(masks[i]);
5073 				/* Bit offset - add in bits _before_ mask */
5074 				k = bitcount(masks[i] - 1) + 1;
5075 				if (j > 8) j = 8;
5076 				shifts[i] = k - j;
5077 				bpps[i] = j;
5078 			}
5079 		}
5080 		else if (bpp == 16)
5081 		{
5082 			shifts[0] = 10;
5083 			shifts[1] = 5;
5084 			shifts[2] = 0;
5085 			bpps[0] = bpps[1] = bpps[2] = 5;
5086 		}
5087 		else
5088 		{
5089 			shifts[0] = 16;
5090 			shifts[1] = 8;
5091 			shifts[2] = 0;
5092 			bpps[0] = bpps[1] = bpps[2] = 8;
5093 			if (bpp == 32) /* Consider alpha present by default */
5094 			{
5095 				shifts[3] = 24;
5096 				bpps[3] = 8;
5097 				cmask = CMASK_RGBA;
5098 				def_alpha = TRUE; /* Uncertain if alpha */
5099 			}
5100 		}
5101 		break;
5102 	default: goto fail;
5103 	}
5104 	if (rle && (h < 0)) goto fail; // Forbidden
5105 
5106 	/* Load palette if needed */
5107 	if (bpp < 16)
5108 	{
5109 		unsigned char tbuf[1024];
5110 		unsigned n, j = 0;
5111 
5112 		if (l >= BMP_COLORS + 4) j = GET32(hdr + BMP_COLORS);
5113 		if (!j) j = 1 << bpp;
5114 
5115 		n = ofs - l - ba;
5116 		k = l < BMP2_HSIZE ? 3 : 4;
5117 		/* !!! Some OS/2 2.x BMPs have 3-bpc palettes too */
5118 		if ((l == OS2BMP2_HSIZE) && (n < j * 4) && (n >= j * 3)) k = 3;
5119 		n /= k;
5120 		if (n < j) j = n;
5121 		if (!j) goto fail; /* Wrong palette size */
5122 		if (j > 256) j = 256; /* Let overlarge palette be */
5123 		settings->colors = j;
5124 		mfseek(mf, l + ba, SEEK_SET);
5125 		i = mfread(tbuf, 1, j * k, mf);
5126 		if (i < j * k) goto fail; /* Cannot read palette */
5127 		tmp = tbuf;
5128 		for (i = 0; i < j; i++)
5129 		{
5130 			settings->pal[i].red = tmp[2];
5131 			settings->pal[i].green = tmp[1];
5132 			settings->pal[i].blue = tmp[0];
5133 			tmp += k;
5134 		}
5135 		/* If palette is all we need */
5136 		res = 1;
5137 		if ((settings->mode == FS_PALETTE_LOAD) ||
5138 			(settings->mode == FS_PALETTE_DEF)) goto fail;
5139 	}
5140 	res = -1;
5141 
5142 	/* Allocate buffer and image */
5143 	settings->width = w;
5144 	settings->height = abs(h);
5145 	settings->bpp = wbpp = bpp < 16 ? 1 : 3;
5146 	rl = ((w * bpp + 31) >> 3) & ~3; /* Row data length */
5147 	bl = rl; /* By default, only one row at a time */
5148 	/* For RLE, load all compressed data at once */
5149 	if (rle)
5150 	{
5151 		unsigned fsize = GET32(hdr + BMP_DATASIZE);
5152 		if (fsize > INT_MAX - 1) goto fail;
5153 		bl = fsize;
5154 	}
5155 	/* Sanity check */
5156 	if (bl <= 0) goto fail;
5157 	/* To accommodate bitparser's extra step */
5158 	buf = malloc(bl + 1);
5159 	res = FILE_MEM_ERROR;
5160 	if (!buf) goto fail;
5161 	if ((res = allocate_image(settings, cmask))) goto fail2;
5162 
5163 #ifdef U_LCMS
5164 	/* V5 can have embedded ICC profile */
5165 	while (!settings->icc_size && (l == BMP5_HSIZE) &&
5166 		(GET32(hdr + BMP_CSPACE) == BMPCS_EMBED))
5167 	{
5168 		unsigned char *icc = NULL;
5169 		unsigned n, size = GET32(hdr + BMP_ICCSIZE), ofs = GET32(hdr + BMP_ICCOFS);
5170 
5171 		if (!size || (size > INT_MAX)) break; // Avoid the totally crazy
5172 		if (ofs > F_LONG_MAX - BMP_HDR2SIZE) break; // Too far
5173 		if (mfseek(mf, ofs + BMP_HDR2SIZE, SEEK_SET)) break; // Cannot go there
5174 		icc = malloc(size);
5175 		if (!icc) break;
5176 		n = mfread(icc, 1, size, mf);
5177 		if (n != size) free(icc); // Failed
5178 		else settings->icc_size = size , settings->icc = icc; // Got it
5179 		break;
5180 	}
5181 #endif
5182 
5183 	if (!settings->silent) ls_init("BMP", 0);
5184 
5185 	mfseek(mf, ofs, SEEK_SET); /* Seek to data */
5186 	if (h < 0) /* Prepare row loop */
5187 	{
5188 		step = 1;
5189 		i = 0;
5190 		h = -h;
5191 	}
5192 	else
5193 	{
5194 		step = -1;
5195 		i = h - 1;
5196 	}
5197 	res = FILE_LIB_ERROR;
5198 
5199 	if (!rle) /* No RLE */
5200 	{
5201 		for (n = 0; (i < h) && (i >= 0); n++ , i += step)
5202 		{
5203 			j = mfread(buf, 1, rl, mf);
5204 			if (j < rl) goto fail3;
5205 			dest = settings->img[CHN_IMAGE] + w * i * wbpp;
5206 			if (bpp < 16) /* Indexed */
5207 				stream_MSB(buf, dest, w, bpp, 0, bpp, 1);
5208 			else /* RGB */
5209 			{
5210 				stream_LSB(buf, dest + 0, w, bpps[0],
5211 					shifts[0], bpp, 3);
5212 				stream_LSB(buf, dest + 1, w, bpps[1],
5213 					shifts[1], bpp, 3);
5214 				stream_LSB(buf, dest + 2, w, bpps[2],
5215 					shifts[2], bpp, 3);
5216 				if (settings->img[CHN_ALPHA])
5217 					stream_LSB(buf, settings->img[CHN_ALPHA] +
5218 						w * i, w, bpps[3], shifts[3], bpp, 1);
5219 			}
5220 			ls_progress(settings, n, 10);
5221 		}
5222 
5223 		/* Rescale shorter-than-byte RGBA components */
5224 		if (bpp > 8)
5225 		for (i = 0; i < 4; i++)
5226 		{
5227 			if (bpps[i] >= 8) continue;
5228 			k = 3;
5229 			if (i == 3)
5230 			{
5231 				tmp = settings->img[CHN_ALPHA];
5232 				if (!tmp) continue;
5233 				k = 1;
5234 			}
5235 			else tmp = settings->img[CHN_IMAGE] + i;
5236 			set_xlate(xlat, bpps[i] + !bpps[i]); // Let 0-wide fields be
5237 			n = w * h;
5238 			for (j = 0; j < n; j++ , tmp += k) *tmp = xlat[*tmp];
5239 		}
5240 
5241 		res = 1;
5242 	}
5243 	else /* RLE - always bottom-up */
5244 	{
5245 		k = mfread(buf, 1, bl, mf);
5246 		if (k < bl) goto fail3;
5247 		memset(settings->img[CHN_IMAGE], 0, w * h * wbpp);
5248 		skip = j = 0;
5249 
5250 		dest = settings->img[CHN_IMAGE] + w * i * wbpp;
5251 		for (tmp = buf; tmp - buf + 1 < k; )
5252 		{
5253 			/* Don't fail on out-of-bounds writes */
5254 			if (*tmp) /* Fill block */
5255 			{
5256 				dx = n = *tmp;
5257 				if (j + n > w) dx = j > w ? 0 : w - j;
5258 				if (bpp == 24) /* 24-bit */
5259 				{
5260 					copy_run(dest + j * 3, tmp + 1, dx, 3, 0, TRUE);
5261 					j += n; tmp += 4;
5262 					continue;
5263 				}
5264 				if (bpp == 8) /* 8-bit */
5265 				{
5266 					memset(dest + j, tmp[1], dx);
5267 					j += n; tmp += 2;
5268 					continue;
5269 				}
5270 				for (ii = 0; ii < dx; ii++) /* 4-bit */
5271 				{
5272 					dest[j++] = tmp[1] >> 4;
5273 					if (++ii >= dx) break;
5274 					dest[j++] = tmp[1] & 0xF;
5275 				}
5276 				j += n - dx;
5277 				tmp += 2;
5278 				continue;
5279 			}
5280 			if (tmp[1] > 2) /* Copy block */
5281 			{
5282 				dx = n = tmp[1];
5283 				if (j + n > w) dx = j > w ? 0 : w - j;
5284 				tmp += 2;
5285 				if (bpp == 24)
5286 				{
5287 					copy_run(dest + j * 3, tmp, dx, 3, 3, TRUE);
5288 					j += n; tmp += (n * 3 + 1) & ~1;
5289 					continue;
5290 				}
5291 				if (bpp == 8) /* 8-bit */
5292 				{
5293 					memcpy(dest + j, tmp, dx);
5294 					j += n; tmp += (n + 1) & ~1;
5295 					continue;
5296 				}
5297 				for (ii = 0; ii < dx; ii++) /* 4-bit */
5298 				{
5299 					dest[j++] = *tmp >> 4;
5300 					if (++ii >= dx) break;
5301 					dest[j++] = *tmp++ & 0xF;
5302 				}
5303 				j += n - dx;
5304 				tmp += (((n + 3) & ~3) - (dx & ~1)) >> 1;
5305 				continue;
5306 			}
5307 			if (tmp[1] == 2) /* Skip block */
5308 			{
5309 				dx = tmp[2] + j;
5310 				dy = tmp[3];
5311 				if (dx > w) goto fail3;
5312 				if (dy > i) dx = 0 , dy = i + 1; // To the end
5313 			}
5314 			else /* End-of-something block */
5315 			{
5316 				dx = 0;
5317 				dy = tmp[1] ? i + 1 : 1;
5318 			}
5319 			/* Transparency detected first time? */
5320 			if (!skip && ((dy != 1) || dx || (j < w)))
5321 			{
5322 				if ((res = allocate_image(settings, CMASK_ALPHA)))
5323 					goto fail3;
5324 				res = FILE_LIB_ERROR;
5325 				skip = 1;
5326 				if (settings->img[CHN_ALPHA]) /* Got alpha */
5327 				{
5328 					memset(settings->img[CHN_ALPHA], 255, w * h);
5329 					skip = 2;
5330 				}
5331 			}
5332 			/* Row skip */
5333 			for (ii = 0; ii < dy; ii++ , i--)
5334 			{
5335 				if ((skip > 1) && (j < w))
5336 					memset(settings->img[CHN_ALPHA] + w * i + j,
5337 						0, w - j);
5338 				j = 0;
5339 				ls_progress(settings, h - i - 1, 10);
5340 			}
5341 			/* Column skip */
5342 			if (skip > 1) memset(settings->img[CHN_ALPHA] +
5343 				w * i + j, 0, dx - j);
5344 			j = dx;
5345 			/* No more rows left */
5346 			if (i < 0)
5347 			{
5348 				res = 1;
5349 				break;
5350 			}
5351 			dest = settings->img[CHN_IMAGE] + w * i * wbpp;
5352 			tmp += 2 + tmp[1];
5353 		}
5354 	}
5355 
5356 	/* Delete all-zero "alpha" */
5357 	if (def_alpha) delete_alpha(settings, 0);
5358 
5359 fail3:	if (!settings->silent) progress_end();
5360 fail2:	free(buf);
5361 fail:	if (fp) fclose(fp);
5362 	return (res);
5363 }
5364 
5365 /* Use BMP4 instead of BMP3 for images with alpha */
5366 /* #define USE_BMP4 */ /* Most programs just use 32-bit RGB BMP3 for RGBA */
5367 
save_bmp(char * file_name,ls_settings * settings,memFILE * mf)5368 static int save_bmp(char *file_name, ls_settings *settings, memFILE *mf)
5369 {
5370 	unsigned char *buf, *tmp;
5371 	memFILE fake_mf;
5372 	FILE *fp = NULL;
5373 	int i, j, ll, hsz0, hsz, dsz, fsz;
5374 	int w = settings->width, h = settings->height, bpp = settings->bpp;
5375 
5376 	i = w > BMP_MAXHSIZE / 4 ? w * 4 : BMP_MAXHSIZE;
5377 	buf = malloc(i);
5378 	if (!buf) return (-1);
5379 	memset(buf, 0, i);
5380 
5381 	if (!mf)
5382 	{
5383 		if (!(fp = fopen(file_name, "wb")))
5384 		{
5385 			free(buf);
5386 			return (-1);
5387 		}
5388 		memset(mf = &fake_mf, 0, sizeof(fake_mf));
5389 		fake_mf.file = fp;
5390 	}
5391 
5392 	/* Sizes of BMP parts */
5393 	if (((settings->mode == FS_CLIPBOARD) || (bpp == 3)) &&
5394 		settings->img[CHN_ALPHA]) bpp = 4;
5395 	ll = (bpp * w + 3) & ~3;
5396 	j = bpp == 1 ? settings->colors : 0;
5397 
5398 #ifdef USE_BMP4
5399 	hsz0 = bpp == 4 ? BMP4_HSIZE : BMP3_HSIZE;
5400 #else
5401 	hsz0 = BMP3_HSIZE;
5402 #endif
5403 	hsz = hsz0 + j * 4;
5404 	dsz = ll * h;
5405 	fsz = hsz + dsz;
5406 
5407 	/* Prepare header */
5408 	buf[0] = 'B'; buf[1] = 'M';
5409 	PUT32(buf + BMP_FILESIZE, fsz);
5410 	PUT32(buf + BMP_DATAOFS, hsz);
5411 	i = hsz0 - BMP_HDR2SIZE;
5412 	PUT32(buf + BMP_HDR2SIZE, i);
5413 	PUT32(buf + BMP_WIDTH, w);
5414 	PUT32(buf + BMP_HEIGHT, h);
5415 	PUT16(buf + BMP_PLANES, 1);
5416 	PUT16(buf + BMP_BPP, bpp * 8);
5417 #ifdef USE_BMP4
5418 	i = bpp == 4 ? 3 : 0; /* Bitfield "compression" / no compression */
5419 	PUT32(buf + BMP_COMPRESS, i);
5420 #else
5421 	PUT32(buf + BMP_COMPRESS, 0); /* No compression */
5422 #endif
5423 	PUT32(buf + BMP_DATASIZE, dsz);
5424 	PUT32(buf + BMP_COLORS, j);
5425 	PUT32(buf + BMP_ICOLORS, j);
5426 #ifdef USE_BMP4
5427 	if (bpp == 4)
5428 	{
5429 		memset(buf + BMP_RMASK, 0, BMP4_HSIZE - BMP_RMASK);
5430 		buf[BMP_RMASK + 2] = buf[BMP_GMASK + 1] = buf[BMP_BMASK + 0] =
5431 			buf[BMP_AMASK + 3] = 0xFF; /* Masks for 8-bit BGRA */
5432 		buf[BMP_CSPACE] = 1; /* Device-dependent RGB */
5433 	}
5434 #endif
5435 	tmp = buf + hsz0;
5436 	for (i = 0; i < j; i++ , tmp += 4)
5437 	{
5438 		tmp[0] = settings->pal[i].blue;
5439 		tmp[1] = settings->pal[i].green;
5440 		tmp[2] = settings->pal[i].red;
5441 	}
5442 	mfwrite(buf, 1, tmp - buf, mf);
5443 
5444 	/* Write rows */
5445 	if (!settings->silent) ls_init("BMP", 1);
5446 	memset(buf + ll - 4, 0, 4);
5447 	for (i = h - 1; i >= 0; i--)
5448 	{
5449 		prepare_row(buf, settings, bpp, i);
5450 		mfwrite(buf, 1, ll, mf);
5451 		ls_progress(settings, h - i, 20);
5452 	}
5453 	if (fp) fclose(fp);
5454 
5455 	if (!settings->silent) progress_end();
5456 
5457 	free(buf);
5458 	return 0;
5459 }
5460 
5461 /* Partial ctype implementation for C locale;
5462  * space 1, digit 2, alpha 4, punctuation 8 */
5463 static unsigned char ctypes[256] = {
5464 	0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0,
5465 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5466 	1, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
5467 	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 8, 8, 8, 8, 8, 8,
5468 	8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
5469 	4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 4,
5470 	8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
5471 	4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 0,
5472 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5473 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5474 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5475 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5476 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5477 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5478 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5479 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
5480 #define ISSPACE(x) (ctypes[(unsigned char)(x)] & 1)
5481 #define ISALPHA(x) (ctypes[(unsigned char)(x)] & 4)
5482 #define ISALNUM(x) (ctypes[(unsigned char)(x)] & 6)
5483 #define ISCNTRL(x) (!ctypes[(unsigned char)(x)])
5484 #define WHITESPACE "\t\n\v\f\r "
5485 
5486 typedef struct {
5487 	FILE *fp;
5488 	char *buf, *ptr;
5489 	int size, str, nl;
5490 } cctx;
5491 
fsetC(cctx * ctx,FILE * fp,char * buf,int len)5492 static void fsetC(cctx *ctx, FILE *fp, char *buf, int len)
5493 {
5494 	if (fp) /* Full init */
5495 	{
5496 		ctx->fp = fp;
5497 		ctx->buf = ctx->ptr = buf;
5498 		ctx->buf[0] = '\0';
5499 		ctx->size = len;
5500 		ctx->str = 0;
5501 		ctx->nl = 1; // Not middle of line
5502 	}
5503 	else /* Switch buffers to a LARGER one */
5504 	{
5505 		int l = strlen(ctx->ptr);
5506 		memmove(buf, ctx->ptr, l);
5507 		buf[l] = '\0';
5508 		ctx->buf = ctx->ptr = buf;
5509 		ctx->size = len;
5510 	}
5511 }
5512 
5513 /* Reads text and cuts out C-style comments */
fgetsC(cctx * ctx)5514 static char *fgetsC(cctx *ctx)
5515 {
5516 	char *buf = ctx->buf;
5517 	int i, l = 0, has_chars = 0, in_comment = 0, in_string = ctx->str;
5518 
5519 	/* Keep unparsed tail if the line isn't yet terminated */
5520 	if (!ctx->nl && ((l = strlen(ctx->ptr))))
5521 	{
5522 		memmove(buf, ctx->ptr, l);
5523 		for (i = 0; i < l; i++) if (!ISSPACE(buf[i])) has_chars++;
5524 	}
5525 	ctx->ptr = buf;
5526 	buf[l] = '\0';
5527 
5528 	while (TRUE)
5529 	{
5530 		/* Read a line */
5531 		if (!fgets(buf + l, ctx->size - l, ctx->fp)) return (NULL);
5532 
5533 		/* Scan it for comments */
5534 		i = l;
5535 		l += strlen(buf + l);
5536 		ctx->nl = l && (buf[l - 1] == '\n'); // Remember line termination
5537 		for (; i < l; i++)
5538 		{
5539 			if (in_string)
5540 			{
5541 				/* Ignore backslash before quote, as libXpm does */
5542 				if (buf[i] == '"') in_string = 0; /* Close a string */
5543 				continue;
5544 			}
5545 			if (in_comment)
5546 			{
5547 				if ((buf[i] == '/') && i && (buf[i - 1] == '*'))
5548 				{
5549 					/* Replace comment by a single space */
5550 					buf[in_comment - 1] = ' ';
5551 					memcpy(buf + in_comment, buf + i + 1, l - i);
5552 					l = in_comment + l - i - 1;
5553 					i = in_comment - 1;
5554 					in_comment = 0;
5555 				}
5556 				continue;
5557 			}
5558 			if (!ISSPACE(buf[i])) has_chars++;
5559 			if (buf[i] == '"')
5560 				in_string = 1; /* Open a string */
5561 			else if ((buf[i] == '*') && i && (buf[i - 1] == '/'))
5562 			{
5563 				/* Open a comment */
5564 				in_comment = i;
5565 				has_chars -= 2;
5566 			}
5567 		}
5568 		/* Fail unterminated strings, forbid continuations for simplicity */
5569 		if (in_string && ctx->nl) return (NULL);
5570 
5571 		/* Whitespace ending in unclosed comment - reduce it */
5572 		if ((in_comment > 1) && !has_chars)
5573 		{
5574 			buf[0] = '/';
5575 			buf[1] = '*';
5576 			in_comment = 1;
5577 		}
5578 
5579 		/* Fail overlong lines ending in unclosed comment */
5580 		if (in_comment >= ctx->size - 3) return (NULL);
5581 
5582 		/* Continue reading till the comment closes */
5583 		if (in_comment)
5584 		{
5585 			l = in_comment + 1;
5586 			continue;
5587 		}
5588 
5589 		/* All line is whitespace - continue reading */
5590 		if (!has_chars)
5591 		{
5592 			l = !l || ctx->nl ? 0 : 1; // Remember 1 leading space
5593 			continue;
5594 		}
5595 
5596 		/* Remember if last string hasn't ended */
5597 		ctx->str = in_string;
5598 		return (buf);
5599 	}
5600 }
5601 
5602 /* Gets next C string out of buffer */
fstrC(cctx * ctx)5603 static char *fstrC(cctx *ctx)
5604 {
5605 	char *s, *t, *w = ctx->ptr;
5606 
5607 	/* String has to begin somewhere */
5608 	while (!(s = strchr(w, '"')))
5609 	{
5610 		*(ctx->ptr = ctx->buf) = '\0';
5611 		if (!(w = fgetsC(ctx))) return (NULL);
5612 	}
5613 	/* And to end on the same line */
5614 	t = strchr(s + 1, '"');
5615 	if (!t)
5616 	{
5617 		ctx->ptr = s;
5618 		if (!(s = fgetsC(ctx))) return (NULL);
5619 		t = strchr(s + 1, '"');
5620 	}
5621 	if (!t) return (NULL); // Overlong string
5622 	/* Cut off the remainder */
5623 	if (*++t)
5624 	{
5625 		*t++ = '\0'; // Ignoring whatever it was
5626 		while (ISSPACE(*t)) t++;
5627 	}
5628 	/* Remember the tail */
5629 	ctx->ptr = t;
5630 
5631 	return (s);
5632 }
5633 
5634 /* Gets next C line out of buffer */
flineC(cctx * ctx)5635 static char *flineC(cctx *ctx)
5636 {
5637 	/* Skip to end of this line */
5638 	while (!ctx->nl)
5639 	{
5640 		*(ctx->ptr = ctx->buf) = '\0';
5641 		if (!fgetsC(ctx)) return (NULL);
5642 	}
5643 	/* And read the next */
5644 	return (fgetsC(ctx));
5645 }
5646 
5647 /* "One at a time" hash function */
hashf(guint32 seed,char * key,int len)5648 static guint32 hashf(guint32 seed, char *key, int len)
5649 {
5650 	int i;
5651 
5652 	for (i = 0; i < len; i++)
5653 	{
5654 		seed += key[i];
5655 		seed += seed << 10;
5656 		seed ^= seed >> 6;
5657 	}
5658 	seed += seed << 3;
5659 	seed ^= seed >> 11;
5660 	seed += seed << 15;
5661 	return (seed);
5662 }
5663 
5664 #define HASHSEED 0x811C9DC5
5665 #define HASH_RND(X) ((X) * 0x10450405 + 1)
5666 #define HSIZE 16384
5667 #define HMASK 0x1FFF
5668 /* For cuckoo hashing of 4096 items into 16384 slots */
5669 #define MAXLOOP 39
5670 
5671 /* This is the limit from libXPM */
5672 #define XPM_MAXCOL 4096
5673 
5674 /* Cuckoo hash of IDs for load or RGB triples for save */
5675 typedef struct {
5676 	short hash[HSIZE];
5677 	char *keys;
5678 	int step, cpp, cnt;
5679 	guint32 seed;
5680 } str_hash;
5681 
ch_find(str_hash * cuckoo,char * str)5682 static int ch_find(str_hash *cuckoo, char *str)
5683 {
5684 	guint32 key;
5685 	int k, idx, step = cuckoo->step, cpp = cuckoo->cpp;
5686 
5687 	key = hashf(cuckoo->seed, str, cpp);
5688 	k = (key & HMASK) * 2;
5689 	while (TRUE)
5690 	{
5691 		idx = cuckoo->hash[k];
5692 		if (idx && !memcmp(cuckoo->keys + (idx - 1) * step, str, cpp))
5693 			return (idx);
5694 		if (k & 1) return (0); /* Not found */
5695 		k = ((key >> 16) & HMASK) * 2 + 1;
5696 	}
5697 }
5698 
ch_insert(str_hash * cuckoo,char * str)5699 static int ch_insert(str_hash *cuckoo, char *str)
5700 {
5701 	char *p, *keys;
5702 	guint32 key;
5703 	int i, j, k, n, idx, step, cpp;
5704 
5705 	n = ch_find(cuckoo, str);
5706 	if (n) return (n - 1);
5707 
5708 	keys = cuckoo->keys;
5709 	step = cuckoo->step; cpp = cuckoo->cpp;
5710 	if (cuckoo->cnt >= XPM_MAXCOL) return (-1);
5711 	p = keys + cuckoo->cnt++ * step;
5712 	memcpy(p, str, cpp); p[cpp] = 0;
5713 
5714 	for (n = cuckoo->cnt; n <= cuckoo->cnt; n++)
5715 	{
5716 		idx = n;
5717 		/* Normal cuckoo process */
5718 		for (i = 0; i < MAXLOOP; i++)
5719 		{
5720 			key = hashf(cuckoo->seed, keys + (idx - 1) * step, cpp);
5721 			key >>= (i & 1) << 4;
5722 			j = (key & HMASK) * 2 + (i & 1);
5723 			k = cuckoo->hash[j];
5724 			cuckoo->hash[j] = idx;
5725 			idx = k;
5726 			if (!idx) break;
5727 		}
5728 		if (!idx) continue;
5729 		/* Failed insertion - mutate seed */
5730 		cuckoo->seed = HASH_RND(cuckoo->seed);
5731 		memset(cuckoo->hash, 0, sizeof(short) * HSIZE);
5732 		n = 1; /* Rehash everything */
5733 	}
5734 	return (cuckoo->cnt - 1);
5735 }
5736 
5737 #define XPM_COL_DEFS 5
5738 
5739 #define BUCKET_SIZE 8
5740 
5741 /* Comments are allowed where valid */
load_xpm(char * file_name,ls_settings * settings)5742 static int load_xpm(char *file_name, ls_settings *settings)
5743 {
5744 	static const char *cmodes[XPM_COL_DEFS] =
5745 		{ "c", "g", "g4", "m", "s" };
5746 	unsigned char *cbuf, *src, *dest, pal[XPM_MAXCOL * 3], *dst0 = pal;
5747 	guint32 *slots;
5748 	char lbuf[4096], *buf = lbuf, *bh = NULL;
5749 	char ckeys[XPM_MAXCOL * 32], *cdefs[XPM_COL_DEFS], *r, *r2, *t;
5750 	str_hash cuckoo;
5751 	cctx ctx;
5752 	FILE *fp;
5753 	int uninit_(n), uninit_(nx), uninit_(nslots);
5754 	int w, h, cols, cpp, hx, hy, res = -1, bpp = 1, trans = -1;
5755 	int i, j, k, l, lsz = sizeof(lbuf), step = 3, pr = FALSE;
5756 
5757 
5758 	if (!(fp = fopen(file_name, "r"))) return (-1);
5759 
5760 	/* Read the header - accept XPM3 and nothing else */
5761 	j = 0; fscanf(fp, " /* XPM */%n", &j);
5762 	if (!j) goto fail;
5763 	fsetC(&ctx, fp, lbuf, sizeof(lbuf)); /* Init reader */
5764 
5765 	/* Skip right to the first string like libXpm does */
5766 	if (!(r = fstrC(&ctx))) goto fail;
5767 
5768 	/* Read the values section */
5769 	i = sscanf(r + 1, "%d%d%d%d%d%d", &w, &h, &cols, &cpp, &hx, &hy);
5770 	if (i == 4) hx = hy = -1;
5771 	else if (i != 6) goto fail;
5772 	/* Extension marker is ignored, as are extensions themselves */
5773 
5774 	/* More than 16M colors or no colors at all aren't accepted */
5775 	if ((cols < 1) || (cols > 0x1000000)) goto fail;
5776 	/* Stupid chars per pixel values aren't either */
5777 	if ((cpp < 1) || (cpp > 31)) goto fail;
5778 	/* More than 4096 colors accepted only if 4 cpp or less */
5779 	if ((cols > XPM_MAXCOL) && (cpp > 4)) goto fail;
5780 
5781 	/* RGB image if more than 256 colors */
5782 	if (cols > 256) bpp = 3;
5783 
5784 	/* Store values */
5785 	settings->width = w;
5786 	settings->height = h;
5787 	settings->bpp = bpp;
5788 	if (bpp == 1) settings->colors = cols;
5789 	settings->hot_x = hx;
5790 	settings->hot_y = hy;
5791 	settings->xpm_trans = -1;
5792 
5793 	/* Allocate things early, to avoid reading huge color table and THEN
5794 	 * failing for bad dimensions of / lack of memory for the image itself */
5795 	if ((settings->mode != FS_PALETTE_LOAD) && (settings->mode != FS_PALETTE_DEF))
5796 	{
5797 		if ((res = allocate_image(settings, CMASK_IMAGE))) goto fail;
5798 		/* Allocate row buffer */
5799 		i = w * cpp + 4 + 1024;
5800 		if (i > lsz) buf = malloc(lsz = i);
5801 		res = FILE_MEM_ERROR;
5802 		if (!buf) goto fail;
5803 		fsetC(&ctx, NULL, buf, lsz); /* Switch buffers */
5804 
5805 		/* Init bucketed hash */
5806 		if (cols > XPM_MAXCOL)
5807 		{
5808 			nslots = (cols + BUCKET_SIZE - 1) / BUCKET_SIZE;
5809 			bh = multialloc(MA_ALIGN_DEFAULT,
5810 				&slots, (nslots + 1) * sizeof(*slots),
5811 				&cbuf, cols * (4 + 3), NULL);
5812 			if (!bh) goto fail2;
5813 
5814 			dst0 = cbuf + 4;
5815 			step = 4 + 3;
5816 		}
5817 
5818 		if ((pr = !settings->silent))
5819 		{
5820 			ls_init("XPM", 0);
5821 			progress_update(0.0);
5822 			/* A color seems to cost like about 2 pixels to load */
5823 			n = (cols * 2) / w;
5824 			nx = n + h;
5825 		}
5826 	}
5827 	/* Too many colors do not a palette make */
5828 	else if (bpp > 1) goto fail;
5829 
5830 	/* Init cuckoo hash */
5831 	if (!bh)
5832 	{
5833 		memset(&cuckoo, 0, sizeof(cuckoo));
5834 		cuckoo.keys = ckeys;
5835 		cuckoo.step = 32;
5836 		cuckoo.cpp = cpp;
5837 		cuckoo.seed = HASHSEED;
5838 	}
5839 
5840 	/* Read colormap */
5841 	res = -1;
5842 	for (i = 0 , dest = dst0; i < cols; i++ , dest += step)
5843 	{
5844 		if (!(r = fstrC(&ctx))) goto fail3;
5845 		l = strlen(r);
5846 		if (l < cpp + 4) goto fail3;
5847 		r[l - 1] = '\0'; // Cut off closing quote
5848 
5849 		/* Insert color into hash */
5850 		if (bh) strncpy(dest - 4, r + 1, 4);
5851 		else ch_insert(&cuckoo, r + 1);
5852 
5853 		/* Parse color definitions */
5854 		memset(cdefs, 0, sizeof(cdefs));
5855 		r += cpp + 2;
5856 		k = -1; r2 = NULL;
5857 		while (TRUE)
5858 		{
5859 			while (ISSPACE(*r)) r++;
5860 			if (!*r) break;
5861 			t = r++;
5862 			while (*r && !ISSPACE(*r)) r++;
5863 			if (*r) *r++ = '\0';
5864 			if (k < 0) /* Mode */
5865 			{
5866 				for (j = 0; j < XPM_COL_DEFS; j++)
5867 				{
5868 					if (!strcmp(t, cmodes[j])) break;
5869 				}
5870 				if (j < XPM_COL_DEFS) /* Key */
5871 				{
5872 					k = j; r2 = NULL;
5873 					continue;
5874 				}
5875 			}
5876 			if (!r2) /* Color name */
5877 			{
5878 				if (k < 0) goto fail3;
5879 				cdefs[k] = r2 = t;
5880 				k = -1;
5881 			}
5882 			else /* Add next part of name */
5883 			{
5884 				l = strlen(r2);
5885 				r2[l] = ' ';
5886 				memmove(r2 + l + 1, t, strlen(t) + 1);
5887 			}
5888 		}
5889 		if (!r2) goto fail3; /* Key w/o name */
5890 
5891 		/* Translate the best one */
5892 		for (j = 0; j < XPM_COL_DEFS; j++)
5893 		{
5894 			int c;
5895 
5896 			if (!cdefs[j]) continue;
5897 			if (!strcasecmp(cdefs[j], "none")) /* Transparent */
5898 			{
5899 				trans = i;
5900 				break;
5901 			}
5902 			c = parse_color(cdefs[j]);
5903 			if (c < 0) continue;
5904 			dest[0] = INT_2_R(c);
5905 			dest[1] = INT_2_G(c);
5906 			dest[2] = INT_2_B(c);
5907 			break;
5908 		}
5909 		/* Not one understandable color */
5910 		if (j >= XPM_COL_DEFS) goto fail3;
5911 	}
5912 	/* With bucketed hashing, half the work per color is not done yet */
5913 	if (pr) progress_update((float)(bh ? n / 2 : n) / nx);
5914 
5915 	/* Create palette */
5916 	if (bpp == 1)
5917 	{
5918 		dest = dst0;
5919 		for (i = 0; i < cols; i++ , dest += step)
5920 		{
5921 			settings->pal[i].red = dest[0];
5922 			settings->pal[i].green = dest[1];
5923 			settings->pal[i].blue = dest[2];
5924 		}
5925 		if (trans >= 0)
5926 		{
5927 			settings->xpm_trans = trans;
5928 			settings->pal[trans].red = settings->pal[trans].green = 115;
5929 			settings->pal[trans].blue = 0;
5930 		}
5931 		/* If palette is all we need */
5932 		res = 1;
5933 		if ((settings->mode == FS_PALETTE_LOAD) ||
5934 			(settings->mode == FS_PALETTE_DEF)) goto fail3;
5935 	}
5936 
5937 	/* Find an unused color for transparency */
5938 	else if (trans >= 0)
5939 	{
5940 		unsigned char cmap[XPM_MAXCOL / 8], *cc = cmap;
5941 		int l = XPM_MAXCOL;
5942 
5943 		if (bh) // Allocate color cube
5944 		{
5945 			l = 0x1000000;
5946 			cc = malloc(l / 8);
5947 			res = FILE_MEM_ERROR;
5948 			if (!cc) goto fail3;
5949 		}
5950 		memset(cc, 0, l / 8);
5951 
5952 		for (i = 0 , dest = dst0; i < cols; i++ , dest += step)
5953 		{
5954 			if (i == trans) continue;
5955 			j = MEM_2_INT(dest, 0);
5956 			if (j < l) cc[j >> 3] |= 1 << (j & 7);
5957 		}
5958 		/* Unused color IS there, as buffer has bits per total colors;
5959 		 * if one is transparent, then a bit stays unset in there */
5960 		dest = cc;
5961 		while (*dest == 0xFF) dest++;
5962 		j = (dest - cc) * 8;
5963 		i = *dest;
5964 		while (i & 1) j++ , i >>= 1;
5965 
5966 		if (bh) free(cc);
5967 
5968 		/* Store the result */
5969 		settings->rgb_trans = j;
5970 		dest = dst0 + trans * step;
5971 		dest[0] = INT_2_R(j);
5972 		dest[1] = INT_2_G(j);
5973 		dest[2] = INT_2_B(j);
5974 	}
5975 
5976 	if (bh) /* Sort the colors by their buckets */
5977 	{
5978 		unsigned char *w, *ww, tbuf[4 + 3];
5979 		int ds, ins;
5980 
5981 		/* First, count how many goes where */
5982 		for (i = 0 , dest = cbuf; i < cols; i++ , dest += 4 + 3)
5983 			(slots + 1)[hashf(HASHSEED, dest, cpp) % nslots]++;
5984 		/* Then, prepare buckets' offsets */
5985 		for (i = 0; i < nslots; i++) slots[i + 1] += slots[i];
5986 		/* Now, starting from first, move colors where they belong */
5987 		for (i = 0; i < cols; )
5988 		{
5989 			/* Color */
5990 			w = cbuf + i * (4 + 3);
5991 			/* Its home */
5992 			ds = hashf(HASHSEED, w, cpp) % nslots;
5993 			/* Its insertion point */
5994 			ins = --slots[ds + 1];
5995 			/* Already in place */
5996 			if (ins <= i)
5997 			{
5998 				slots[ds + 1] = ++i; // Adjust
5999 				continue;
6000 			}
6001 			/* Move it */
6002 			ww = cbuf + ins * (4 + 3);
6003 			memcpy(tbuf, ww, 4 + 3);
6004 			memcpy(ww, w, 4 + 3);
6005 			memcpy(w, tbuf, 4 + 3);
6006 		}
6007 		if (pr) progress_update((float)n / nx);
6008 	}
6009 
6010 	/* Now, read the image */
6011 	res = FILE_LIB_ERROR;
6012 	dest = settings->img[CHN_IMAGE];
6013 	for (i = 0; i < h; i++)
6014 	{
6015 		if (!(r = fstrC(&ctx))) goto fail3;
6016 		/* libXpm allows overlong strings */
6017 		if (strlen(++r) < w * cpp + 1) goto fail3;
6018 		for (j = 0; j < w; j++ , dest += bpp)
6019 		{
6020 			if (bh)
6021 			{
6022 				unsigned char *w;
6023 				int ds, n;
6024 
6025 				ds = hashf(HASHSEED, r, cpp) % nslots;
6026 				k = slots[ds];
6027 				w = cbuf + k * (4 + 3);
6028 				n = slots[ds + 1];
6029 				for (; k < n; k++ , w += 4 + 3)
6030 					/* Trying to avoid function call */
6031 					if ((*w == *r) && !memcmp(w, r, cpp)) break;
6032 				k = k >= n ? 0 : k + 1;
6033 			}
6034 			else k = ch_find(&cuckoo, r);
6035 			if (!k) goto fail3;
6036 			r += cpp;
6037 			if (bpp == 1) *dest = k - 1;
6038 			else
6039 			{
6040 				src = dst0 + (k - 1) * step;
6041 				dest[0] = src[0];
6042 				dest[1] = src[1];
6043 				dest[2] = src[2];
6044 			}
6045 		}
6046 		if (pr && ((n++ * 10) % nx >= nx - 10))
6047 			progress_update((float)n / nx);
6048 	}
6049 	res = 1;
6050 
6051 fail3:	if (pr) progress_end();
6052 	free(bh);
6053 fail2:	if (buf != lbuf) free(buf);
6054 fail:	fclose(fp);
6055 	return (res);
6056 }
6057 
6058 static const char base64[] =
6059 	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
6060 	"!#$%&'()*,-.:;<=>?@[]^_`{|}~",
6061 	hex[] = "0123456789ABCDEF";
6062 
6063 /* Extract valid C identifier from filename */
extract_ident(char * fname,int * len)6064 static char *extract_ident(char *fname, int *len)
6065 {
6066 	char *tmp;
6067 	int l;
6068 
6069 	tmp = strrchr(fname, DIR_SEP);
6070 	tmp = tmp ? tmp + 1 : fname;
6071 	for (; *tmp && !ISALPHA(*tmp); tmp++);
6072 	for (l = 0; (l < 256) && ISALNUM(tmp[l]); l++);
6073 	*len = l;
6074 	return (tmp);
6075 }
6076 
6077 #define CTABLE_SIZE (0x1000000 / 32)
6078 #define CINDEX_SIZE (0x1000000 / 256)
6079 
6080 /* Find color index using bitmap with sparse counters */
ct_index(int rgb,guint32 * ctable)6081 static int ct_index(int rgb, guint32 *ctable)
6082 {
6083 	guint32 bit = 1U << (rgb & 31), *cindex = ctable + CTABLE_SIZE;
6084 	int n, d = rgb >> 5, m = d & 7;
6085 
6086 	if (!(ctable[d] & bit)) return (-1); // Not found
6087 	n = cindex[d >> 3];
6088 	while (m > 0) n += bitcount(ctable[d - m--]);
6089 	return (n + bitcount(ctable[d] & (bit - 1)));
6090 }
6091 
save_xpm(char * file_name,ls_settings * settings)6092 static int save_xpm(char *file_name, ls_settings *settings)
6093 {
6094 	unsigned char rgbmem[XPM_MAXCOL * 4], *src;
6095 	guint32 *cindex, *ctable = NULL;
6096 	const char *ctb;
6097 	char ws[5], tc[5] = "    ";
6098 	char *buf, *tmp;
6099 	str_hash cuckoo;
6100 	FILE *fp;
6101 	int bpp = settings->bpp, w = settings->width, h = settings->height;
6102 	int uninit_(ccmask);
6103 	int i, j, k, l, c, cpp, cols, trans = -1;
6104 
6105 
6106 	tmp = extract_ident(file_name, &l);
6107 	if (!l) return -1;
6108 
6109 	/* Collect RGB colors */
6110 	if (bpp == 3)
6111 	{
6112 		trans = settings->rgb_trans;
6113 
6114 		/* Init hash */
6115 		memset(&cuckoo, 0, sizeof(cuckoo));
6116 		cuckoo.keys = rgbmem;
6117 		cuckoo.step = 4;
6118 		cuckoo.cpp = 3;
6119 		cuckoo.seed = HASHSEED;
6120 
6121 		j = w * h;
6122 		src = settings->img[CHN_IMAGE];
6123 		for (i = 0; i < j; i++ , src += 3)
6124 		{
6125 			if (ch_insert(&cuckoo, src) < 0)
6126 				break; /* Too many colors for this mode */
6127 		}
6128 
6129 		if (i < j) /* Too many colors, collect & count 'em */
6130 		{
6131 			ctable = calloc(CTABLE_SIZE + CINDEX_SIZE, sizeof(*ctable));
6132 			if (!ctable) return (-1); // No memory
6133 			src = settings->img[CHN_IMAGE];
6134 			for (i = 0; i < j; i++ , src += 3)
6135 			{
6136 				int n = MEM_2_INT(src, 0);
6137 				ctable[n >> 5] |= 1U << (n & 31);
6138 			}
6139 			cindex = ctable + CTABLE_SIZE;
6140 			for (i = cols = 0; i < CTABLE_SIZE; i++)
6141 			{
6142 				if (!(i & 7)) cindex[i >> 3] = cols;
6143 				cols += bitcount(ctable[i]);
6144 			}
6145 			/* RGB to index */
6146 			if (trans > -1) trans = ct_index(trans, ctable);
6147 		}
6148 		else /* Sensible number of colors, cuckoo hashing works */
6149 		{
6150 			cols = cuckoo.cnt;
6151 			/* RGB to index */
6152 			if (trans > -1)
6153 			{
6154 				char trgb[3];
6155 				trgb[0] = INT_2_R(trans);
6156 				trgb[1] = INT_2_G(trans);
6157 				trgb[2] = INT_2_B(trans);
6158 				trans = ch_find(&cuckoo, trgb) - 1;
6159 			}
6160 		}
6161 	}
6162 
6163 	/* Process indexed colors */
6164 	else
6165 	{
6166 		cols = settings->colors;
6167 		src = rgbmem;
6168 		for (i = 0; i < cols; i++ , src += 4)
6169 		{
6170 			src[0] = settings->pal[i].red;
6171 			src[1] = settings->pal[i].green;
6172 			src[2] = settings->pal[i].blue;
6173 		}
6174 		trans = settings->xpm_trans;
6175 	}
6176 
6177 	cpp = cols > 92 * 92 * 92 ? 4 : cols > 92 * 92 ? 3 : cols > 92 ? 2 : 1;
6178 
6179 	buf = malloc(w * cpp + 16); // Prepare row buffer
6180 	if (!buf || !(fp = fopen(file_name, "w")))
6181 	{
6182 		free(buf);
6183 		free(ctable);
6184 		return -1;
6185 	}
6186 
6187 	if (!settings->silent) ls_init("XPM", 1);
6188 
6189 	fprintf(fp, "/* XPM */\n" );
6190 	fprintf(fp, "static char *%.*s_xpm[] = {\n", l, tmp);
6191 
6192 	if ((settings->hot_x >= 0) && (settings->hot_y >= 0))
6193 		fprintf(fp, "\"%d %d %d %d %d %d\",\n", w, h, cols, cpp,
6194 			settings->hot_x, settings->hot_y);
6195 	else fprintf(fp, "\"%d %d %d %d\",\n", w, h, cols, cpp);
6196 
6197 	/* Create colortable */
6198 	ctb = cols > 16 ? base64 : hex;
6199 	tc[cpp] = '\0';
6200 	if (ctable) // From bitmap
6201 	{
6202 		for (i = c = 0; i < CTABLE_SIZE; i++)
6203 		{
6204 			guint32 n = ctable[i];
6205 			for (k = 0; n; k++ , n >>= 1)
6206 			{
6207 				if (!(n & 1)) continue;
6208 				l = i * 32 + k; // Color
6209 
6210 				/* Color ID */
6211 				ws[0] = ctb[c % 92];
6212 				ws[1] = ctb[(c / 92) % 92];
6213 				ws[2] = ctb[(c / (92 * 92)) % 92];
6214 				ws[3] = ctb[c / (92 * 92 * 92)];
6215 				ws[cpp] = '\0';
6216 
6217 				if (c == trans) // Transparency
6218 					fprintf(fp, "\"%s\tc None\",\n", tc);
6219 				else fprintf(fp, "\"%s\tc #%02X%02X%02X\",\n", ws,
6220 					INT_2_R(l), INT_2_G(l), INT_2_B(l));
6221 
6222 				c++;
6223 			}
6224 		}
6225 	}
6226 	else // From cuckoo's keys
6227 	{
6228 		ccmask = 255 >> cpp; // 63 for 2 cpp, 127 for 1
6229 		for (i = 0; i < cols; i++)
6230 		{
6231 			if (i == trans)
6232 			{
6233 				fprintf(fp, "\"%s\tc None\",\n", tc);
6234 				continue;
6235 			}
6236 			ws[0] = ctb[i & ccmask];
6237 			ws[1] = ctb[i >> 6];
6238 			ws[cpp] = '\0';
6239 			src = rgbmem + i * 4;
6240 			fprintf(fp, "\"%s\tc #%02X%02X%02X\",\n", ws,
6241 				src[0], src[1], src[2]);
6242 		}
6243 	}
6244 
6245 	w *= bpp;
6246 	for (i = 0; i < h; i++)
6247 	{
6248 		src = settings->img[CHN_IMAGE] + i * w;
6249 		tmp = buf;
6250 		*tmp++ = '"';
6251 		for (j = 0; j < w; j += bpp, tmp += cpp)
6252 		{
6253 			if (bpp == 1) k = src[j];
6254 			else if (!ctable) k = ch_find(&cuckoo, src + j) - 1;
6255 			else k = ct_index(MEM_2_INT(src, j), ctable);
6256 			if (k == trans)
6257 				tmp[0] = tmp[1] = tmp[2] = tmp[3] = ' ';
6258 			else if (ctable)
6259 			{
6260 				tmp[0] = ctb[k % 92];
6261 				tmp[1] = ctb[(k / 92) % 92];
6262 				tmp[2] = ctb[(k / (92 * 92)) % 92];
6263 				tmp[3] = ctb[k / (92 * 92 * 92)];
6264 			}
6265 			else // Backward compatible mapping
6266 			{
6267 				tmp[0] = ctb[k & ccmask];
6268 				tmp[1] = ctb[k >> 6];
6269 			}
6270 		}
6271 		strcpy(tmp, i < h - 1 ? "\",\n" : "\"\n};\n");
6272 		fputs(buf, fp);
6273 		ls_progress(settings, i, 10);
6274 	}
6275 	fclose(fp);
6276 
6277 	if (!settings->silent) progress_end();
6278 
6279 	free(buf);
6280 	free(ctable);
6281 	return 0;
6282 }
6283 
load_xbm(char * file_name,ls_settings * settings)6284 static int load_xbm(char *file_name, ls_settings *settings)
6285 {
6286 	static const char XPMtext[] = "0123456789ABCDEFabcdef,} \t\n",
6287 		XPMval[] = {
6288 			0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
6289 			10, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16 };
6290 	unsigned char ctb[256], *dest;
6291 	char lbuf[4096], *r;
6292 	cctx ctx;
6293 	FILE *fp;
6294 	int w , h, hx = -1, hy = -1, bpn = 16, res = -1;
6295 	int i, j, k, c, v = 0;
6296 
6297 
6298 	if (!(fp = fopen(file_name, "r"))) return (-1);
6299 
6300 	/* Read & parse what serves as header to XBM */
6301 	fsetC(&ctx, fp, lbuf, sizeof(lbuf)); /* Init reader */
6302 	/* Width and height - required part in fixed order */
6303 	if (!(r = flineC(&ctx))) goto fail;
6304 	if (!sscanf(r, "#define %*s%n %d", &i, &w)) goto fail;
6305 	if (strncmp(r + i - 5, "width", 5)) goto fail;
6306 	if (!(r = flineC(&ctx))) goto fail;
6307 	if (!sscanf(r, "#define %*s%n %d", &i, &h)) goto fail;
6308 	if (strncmp(r + i - 6, "height", 6)) goto fail;
6309 	/* Hotspot X and Y - optional part in fixed order */
6310 	if (!(r = flineC(&ctx))) goto fail;
6311 	if (sscanf(r, "#define %*s%n %d", &i, &hx))
6312 	{
6313 		if (strncmp(r + i - 5, "x_hot", 5)) goto fail;
6314 		if (!(r = flineC(&ctx))) goto fail;
6315 		if (!sscanf(r, "#define %*s%n %d", &i, &hy)) goto fail;
6316 		if (strncmp(r + i - 5, "y_hot", 5)) goto fail;
6317 		if (!(r = flineC(&ctx))) goto fail;
6318 	}
6319 	/* "Intro" string */
6320 	j = 0; sscanf(r, " static short %*[^[]%n[] = {%n", &i, &j);
6321 	if (!j)
6322 	{
6323 		bpn = 8; /* X11 format - 8-bit data */
6324 		j = 0; sscanf(r, " static unsigned char %*[^[]%n[] = {%n", &i, &j);
6325 		if (!j) sscanf(r, " static char %*[^[]%n[] = {%n", &i, &j);
6326 		if (!j) goto fail;
6327 	}
6328 	if (strncmp(r + i - 4, "bits", 4)) goto fail;
6329 // !!! For now, newline is required between "intro" and data
6330 
6331 	/* Store values */
6332 	settings->width = w;
6333 	settings->height = h;
6334 	settings->bpp = 1;
6335 	settings->hot_x = hx;
6336 	settings->hot_y = hy;
6337 	/* Palette is white and black */
6338 	set_bw(settings);
6339 
6340 	/* Allocate image */
6341 	if ((res = allocate_image(settings, CMASK_IMAGE))) goto fail;
6342 
6343 	/* Prepare to read data */
6344 	memset(ctb, 17, sizeof(ctb));
6345 	for (i = 0; XPMtext[i]; i++)
6346 	{
6347 		ctb[(unsigned char)XPMtext[i]] = XPMval[i];
6348 	}
6349 
6350 	/* Now, read the image */
6351 	if (!settings->silent) ls_init("XBM", 0);
6352 	res = FILE_LIB_ERROR;
6353 	dest = settings->img[CHN_IMAGE];
6354 	for (i = 0; i < h; i++)
6355 	{
6356 		for (j = k = 0; j < w; j++ , k--)
6357 		{
6358 			if (!k) /* Get next value, the way X itself does */
6359 			{
6360 				v = 0;
6361 				while (TRUE)
6362 				{
6363 					if ((c = getc(fp)) == EOF) goto fail2;
6364 					c = ctb[c & 255];
6365 					if (c < 16) /* Accept hex digits */
6366 					{
6367 						v = (v << 4) + c;
6368 						k++;
6369 					}
6370 					/* Silently ignore out-of-place chars */
6371 					else if (c > 16) continue;
6372 					/* Stop on delimiters after digits */
6373 					else if (k) break;
6374 				}
6375 				k = bpn;
6376 			}
6377 			*dest++ = v & 1;
6378 			v >>= 1;
6379 		}
6380 		ls_progress(settings, i, 10);
6381 	}
6382 	res = 1;
6383 
6384 fail2:	if (!settings->silent) progress_end();
6385 fail:	fclose(fp);
6386 	return (res);
6387 }
6388 
6389 #define BPL 12 /* Bytes per line */
6390 #define CPB 6  /* Chars per byte */
save_xbm(char * file_name,ls_settings * settings)6391 static int save_xbm(char *file_name, ls_settings *settings)
6392 {
6393 	unsigned char bw, *src;
6394 	unsigned char row[MAX_WIDTH / 8];
6395 	char buf[CPB * BPL + 16], *tmp;
6396 	FILE *fp;
6397 	int i, j, k, l, w = settings->width, h = settings->height;
6398 
6399 	if ((settings->bpp != 1) || (settings->colors > 2)) return WRONG_FORMAT;
6400 
6401 	/* Extract valid C identifier from name */
6402 	tmp = extract_ident(file_name, &i);
6403 	if (!i) return -1;
6404 
6405 	if (!(fp = fopen(file_name, "w"))) return -1;
6406 
6407 	fprintf(fp, "#define %.*s_width %i\n", i, tmp, w);
6408 	fprintf(fp, "#define %.*s_height %i\n", i, tmp, h);
6409 	if ((settings->hot_x >= 0) && (settings->hot_y >= 0))
6410 	{
6411 		fprintf(fp, "#define %.*s_x_hot %i\n", i, tmp, settings->hot_x);
6412 		fprintf(fp, "#define %.*s_y_hot %i\n", i, tmp, settings->hot_y);
6413 	}
6414 	fprintf(fp, "static unsigned char %.*s_bits[] = {\n", i, tmp);
6415 
6416 	if (!settings->silent) ls_init("XBM", 1);
6417 
6418 	bw = get_bw(settings);
6419 	j = k = (w + 7) >> 3; i = l = 0;
6420 	while (TRUE)
6421 	{
6422 		if (j >= k)
6423 		{
6424 			if (i >= h) break;
6425 			src = settings->img[CHN_IMAGE] + i * w;
6426 			memset(row, 0, k);
6427 			for (j = 0; j < w; j++)
6428 			{
6429 				if (src[j] == bw) row[j >> 3] |= 1 << (j & 7);
6430 			}
6431 			j = 0;
6432 			ls_progress(settings, i, 10);
6433 			i++;
6434 		}
6435 		for (; (l < BPL) && (j < k); l++ , j++)
6436 		{
6437 			tmp = buf + l * CPB;
6438 			tmp[0] = ' '; tmp[1] = '0'; tmp[2] = 'x';
6439 			tmp[3] = hex[row[j] >> 4]; tmp[4] = hex[row[j] & 0xF];
6440 			tmp[5] = ',';
6441 		}
6442 		if ((l == BPL) && (j < k))
6443 		{
6444 			buf[BPL * CPB] = '\n'; buf[BPL * CPB + 1] = '\0';
6445 			fputs(buf, fp);
6446 			l = 0;
6447 		}
6448 	}
6449 	strcpy(buf + l * CPB - 1, " };\n");
6450 	fputs(buf, fp);
6451 	fclose(fp);
6452 
6453 	if (!settings->silent) progress_end();
6454 
6455 	return 0;
6456 }
6457 
6458 /*
6459  * Those who don't understand PCX are condemned to reinvent it, poorly. :-)
6460  */
6461 
6462 #define LSS_WIDTH   4 /* 16b */
6463 #define LSS_HEIGHT  6 /* 16b */
6464 #define LSS_PALETTE 8 /* 16 * 3 * 8b */
6465 #define LSS_HSIZE   56
6466 
load_lss(char * file_name,ls_settings * settings)6467 static int load_lss(char *file_name, ls_settings *settings)
6468 {
6469 	unsigned char hdr[LSS_HSIZE], *dest, *tmp, *buf = NULL;
6470 	FILE *fp;
6471 	f_long l;
6472 	int i, j, k, w, h, bl, idx, last, cnt, res = -1;
6473 
6474 
6475 	if (!(fp = fopen(file_name, "rb"))) return (-1);
6476 
6477 	/* Read the header */
6478 	k = fread(hdr, 1, LSS_HSIZE, fp);
6479 
6480 	/* Check general validity */
6481 	if (k < LSS_HSIZE) goto fail; /* Least supported header size */
6482 	if (strncmp(hdr, "\x3D\xF3\x13\x14", 4)) goto fail; /* Signature */
6483 
6484 	w = GET16(hdr + LSS_WIDTH);
6485 	h = GET16(hdr + LSS_HEIGHT);
6486 	settings->width = w;
6487 	settings->height = h;
6488 	settings->bpp = 1;
6489 	settings->colors = 16;
6490 
6491 	/* Read palette */
6492 	tmp = hdr + LSS_PALETTE;
6493 	for (i = 0; i < 16; i++)
6494 	{
6495 		settings->pal[i].red = tmp[0] << 2 | tmp[0] >> 4;
6496 		settings->pal[i].green = tmp[1] << 2 | tmp[1] >> 4;
6497 		settings->pal[i].blue = tmp[2] << 2 | tmp[2] >> 4;
6498 		tmp += 3;
6499 	}
6500 	/* If palette is all we need */
6501 	res = 1;
6502 	if ((settings->mode == FS_PALETTE_LOAD) ||
6503 		(settings->mode == FS_PALETTE_DEF)) goto fail;
6504 
6505 	/* Load all image at once */
6506 	fseek(fp, 0, SEEK_END);
6507 	l = ftell(fp);
6508 	if (l <= LSS_HSIZE) goto fail; /* Too large or too small */
6509 	l -= LSS_HSIZE;
6510 	fseek(fp, LSS_HSIZE, SEEK_SET);
6511 	bl = (w * h * 3) >> 1; /* Cannot possibly be longer */
6512 	if (bl > l) bl = l;
6513 	buf = malloc(bl);
6514 	res = FILE_MEM_ERROR;
6515 	if (!buf) goto fail2;
6516 	if ((res = allocate_image(settings, CMASK_IMAGE))) goto fail2;
6517 
6518 	if (!settings->silent) ls_init("LSS16", 0);
6519 
6520 	res = FILE_LIB_ERROR;
6521 	j = fread(buf, 1, bl, fp);
6522 	if (j < bl) goto fail3;
6523 
6524 	dest = settings->img[CHN_IMAGE];
6525 	idx = 0; bl += bl;
6526 	for (i = 0; i < h; i++)
6527 	{
6528 		last = 0; idx = (idx + 1) & ~1;
6529 		for (j = 0; j < w; )
6530 		{
6531 			if (idx >= bl) goto fail3;
6532 			k = (buf[idx >> 1] >> ((idx & 1) << 2)) & 0xF; ++idx;
6533 			if (k != last)
6534 			{
6535 				dest[j++] = last = k;
6536 				continue;
6537 			}
6538 			if (idx >= bl) goto fail3;
6539 			cnt = (buf[idx >> 1] >> ((idx & 1) << 2)) & 0xF; ++idx;
6540 			if (!cnt)
6541 			{
6542 				if (idx >= bl) goto fail3;
6543 				cnt = (buf[idx >> 1] >> ((idx & 1) << 2)) & 0xF; ++idx;
6544 				if (idx >= bl) goto fail3;
6545 				k = (buf[idx >> 1] >> ((idx & 1) << 2)) & 0xF; ++idx;
6546 				cnt = (k << 4) + cnt + 16;
6547 			}
6548 			if (cnt > w - j) cnt = w - j;
6549 			memset(dest + j, last, cnt);
6550 			j += cnt;
6551 		}
6552 		dest += w;
6553 	}
6554 	res = 1;
6555 
6556 fail3:	if (!settings->silent) progress_end();
6557 fail2:	free(buf);
6558 fail:	fclose(fp);
6559 	return (res);
6560 }
6561 
save_lss(char * file_name,ls_settings * settings)6562 static int save_lss(char *file_name, ls_settings *settings)
6563 {
6564 	unsigned char *buf, *tmp, *src;
6565 	FILE *fp;
6566 	int i, j, uninit_(k), last, cnt, idx;
6567 	int w = settings->width, h = settings->height;
6568 
6569 
6570 	if ((settings->bpp != 1) || (settings->colors > 16)) return WRONG_FORMAT;
6571 
6572 	i = w > LSS_HSIZE ? w : LSS_HSIZE;
6573 	buf = malloc(i);
6574 	if (!buf) return -1;
6575 	memset(buf, 0, i);
6576 
6577 	if (!(fp = fopen(file_name, "wb")))
6578 	{
6579 		free(buf);
6580 		return -1;
6581 	}
6582 
6583 	/* Prepare header */
6584 	buf[0] = 0x3D; buf[1] = 0xF3; buf[2] = 0x13; buf[3] = 0x14;
6585 	PUT16(buf + LSS_WIDTH, w);
6586 	PUT16(buf + LSS_HEIGHT, h);
6587 	j = settings->colors > 16 ? 16 : settings->colors;
6588 	tmp = buf + LSS_PALETTE;
6589 	for (i = 0; i < j; i++)
6590 	{
6591 		tmp[0] = settings->pal[i].red >> 2;
6592 		tmp[1] = settings->pal[i].green >> 2;
6593 		tmp[2] = settings->pal[i].blue >> 2;
6594 		tmp += 3;
6595 	}
6596 	fwrite(buf, 1, LSS_HSIZE, fp);
6597 
6598 	/* Write rows */
6599 	if (!settings->silent) ls_init("LSS16", 1);
6600 	src = settings->img[CHN_IMAGE];
6601 	for (i = 0; i < h; i++)
6602 	{
6603 		memset(buf, 0, w);
6604 		last = cnt = idx = 0;
6605 		for (j = 0; j < w; )
6606 		{
6607 			for (; j < w; j++)
6608 			{
6609 				k = *src++ & 0xF;
6610 				if ((k != last) || (++cnt >= 255 + 16)) break;
6611 			}
6612 			if (cnt)
6613 			{
6614 				buf[idx >> 1] |= last << ((idx & 1) << 2); ++idx;
6615 				if (cnt >= 16)
6616 				{
6617 					++idx; /* Insert zero */
6618 					cnt -= 16;
6619 					buf[idx >> 1] |= (cnt & 0xF) <<
6620 						((idx & 1) << 2); ++idx;
6621 					cnt >>= 4;
6622 				}
6623 				buf[idx >> 1] |= cnt << ((idx & 1) << 2); ++idx;
6624 			}
6625 			if (j++ >= w) break; /* Final repeat */
6626 			cnt = 0;
6627 			if (k == last) continue; /* Chain of repeats */
6628 			buf[idx >> 1] |= k << ((idx & 1) << 2); ++idx;
6629 			last = k;
6630 		}
6631 		idx = (idx + 1) & ~1;
6632 		fwrite(buf, 1, idx >> 1, fp);
6633 		ls_progress(settings, i, 10);
6634 	}
6635 	fclose(fp);
6636 
6637 	if (!settings->silent) progress_end();
6638 
6639 	free(buf);
6640 	return 0;
6641 }
6642 
6643 /* *** PREFACE ***
6644  * No other format has suffered so much at the hands of inept coders. With TGA,
6645  * exceptions are the rule, and files perfectly following the specification are
6646  * impossible to find. While I did my best to handle the format's perversions
6647  * that I'm aware of, there surely exist other kinds of weird TGAs that will
6648  * load wrong, or not at all. If you encounter one such, send a bugreport with
6649  * the file attached to it. */
6650 
6651 /* TGA header */
6652 #define TGA_IDLEN     0 /*  8b */
6653 #define TGA_PALTYPE   1 /*  8b */
6654 #define TGA_IMGTYPE   2 /*  8b */
6655 #define TGA_PALSTART  3 /* 16b */
6656 #define TGA_PALCOUNT  5 /* 16b */
6657 #define TGA_PALBITS   7 /*  8b */
6658 #define TGA_X0        8 /* 16b */
6659 #define TGA_Y0       10 /* 16b */
6660 #define TGA_WIDTH    12 /* 16b */
6661 #define TGA_HEIGHT   14 /* 16b */
6662 #define TGA_BPP      16 /*  8b */
6663 #define TGA_DESC     17 /*  8b */
6664 #define TGA_HSIZE    18
6665 
6666 /* Image descriptor bits */
6667 #define TGA_ALPHA 0x0F
6668 #define TGA_R2L   0x10
6669 #define TGA_T2B   0x20
6670 #define TGA_IL    0xC0 /* Interleave mode - obsoleted in TGA 2.0 */
6671 
6672 /* TGA footer */
6673 #define TGA_EXTOFS 0 /* 32b */
6674 #define TGA_DEVOFS 4 /* 32b */
6675 #define TGA_SIGN   8
6676 #define TGA_FSIZE  26
6677 
6678 /* TGA extension area */
6679 #define TGA_EXTLEN  0   /* 16b */
6680 #define TGA_SOFTID  426 /* 41 bytes */
6681 #define TGA_SOFTV   467 /* 16b */
6682 #define TGA_ATYPE   494 /* 8b */
6683 #define TGA_EXTSIZE 495
6684 
extend_bytes(unsigned char * dest,int len,int maxval)6685 static void extend_bytes(unsigned char *dest, int len, int maxval)
6686 {
6687 	unsigned char tb[256];
6688 
6689 	memset(tb, 255, 256);
6690 	set_xlate_n(tb, maxval);
6691 	do_xlate(tb, dest, len);
6692 }
6693 
load_tga(char * file_name,ls_settings * settings)6694 static int load_tga(char *file_name, ls_settings *settings)
6695 {
6696 	unsigned char hdr[TGA_HSIZE], ftr[TGA_FSIZE], ext[TGA_EXTSIZE];
6697 	unsigned char pal[256 * 4], xlat5[32], xlat6[64], trans[256];
6698 	unsigned char *buf = NULL, *dest, *dsta, *src = NULL, *srca = NULL;
6699 	unsigned char *bstart, *bstop;
6700 	FILE *fp;
6701 	f_long fl;
6702 	unsigned fofs;
6703 	int i, k, w, h, bpp, ftype, ptype, ibpp, rbits, abits, itrans = FALSE;
6704 	int rle, real_alpha = FALSE, assoc_alpha = FALSE, wmode = 0, res = -1;
6705 	int iofs, buflen;
6706 	int ix, ishift, imask, ax, ashift, amask;
6707 	int start, xstep, xstepb, ystep, ccnt, rcnt, strl, y;
6708 
6709 
6710 	if (!(fp = fopen(file_name, "rb"))) return (-1);
6711 
6712 	/* Read the header */
6713 	k = fread(hdr, 1, TGA_HSIZE, fp);
6714 	if (k < TGA_HSIZE) goto fail;
6715 
6716 	/* TGA has no signature as such - so check fields one by one */
6717 	ftype = hdr[TGA_IMGTYPE];
6718 	if (!(ftype & 3) || (ftype & 0xF4)) goto fail; /* Invalid type */
6719 	/* Fail on interleave, because of lack of example files */
6720 	if (hdr[TGA_DESC] & TGA_IL) goto fail;
6721 	rle = ftype & 8;
6722 
6723 	iofs = TGA_HSIZE + hdr[TGA_IDLEN];
6724 
6725 	rbits = hdr[TGA_BPP];
6726 	if (!rbits) goto fail; /* Zero bpp */
6727 	abits = hdr[TGA_DESC] & TGA_ALPHA;
6728 	if (abits > rbits) goto fail; /* Weird alpha */
6729 	/* Workaround for a rather frequent bug */
6730 	if (abits == rbits) abits = 0;
6731 	ibpp = (rbits + 7) >> 3;
6732 	rbits -= abits;
6733 
6734 	set_xlate(xlat5, 5);
6735 	ptype = hdr[TGA_PALTYPE];
6736 	switch (ftype & 3)
6737 	{
6738 	case 1: /* Paletted */
6739 	{
6740 		int pbpp, i, j, k, l;
6741 		png_color *pptr;
6742 
6743 		if (ptype != 1) goto fail; /* Invalid palette */
6744 		/* Don't want to bother with overlong palette without even
6745 		 * having one example where such a thing exists - WJ */
6746 		if (rbits > 8) goto fail;
6747 
6748 		k = GET16(hdr + TGA_PALSTART);
6749 		if (k >= 1 << rbits) goto fail; /* Weird palette start */
6750 		j = GET16(hdr + TGA_PALCOUNT);
6751 		if (!j || (k + j > 1 << rbits)) goto fail; /* Weird size */
6752 		ptype = hdr[TGA_PALBITS];
6753 		/* The options are quite limited here in practice */
6754 		if (!ptype || (ptype > 32) || ((ptype & 7) && (ptype != 15)))
6755 			goto fail;
6756 		pbpp = (ptype + 7) >> 3;
6757 		l = j * pbpp;
6758 
6759 		/* Read the palette */
6760 		fseek(fp, iofs, SEEK_SET);
6761 		if (fread(pal + k * pbpp, 1, l, fp) != l) goto fail;
6762 		iofs += l;
6763 
6764 		/* Store the palette */
6765 		settings->colors = j + k;
6766 		memset(settings->pal, 0, 256 * 3);
6767 		pptr = settings->pal + k;
6768 		for (i = 0; i < l; i += pbpp , pptr++)
6769 		{
6770 			switch (pbpp)
6771 			{
6772 			case 1: /* 8-bit greyscale */
6773 				pptr->red = pptr->green = pptr->blue = pal[i];
6774 				break;
6775 			case 2: /* 5:5:5 BGR */
6776 				pptr->blue = xlat5[pal[i] & 0x1F];
6777 				pptr->green = xlat5[(((pal[i + 1] << 8) +
6778 					pal[i]) >> 5) & 0x1F];
6779 				pptr->red = xlat5[(pal[i + 1] >> 2) & 0x1F];
6780 				break;
6781 			case 3: case 4: /* 8:8:8 BGR */
6782 				pptr->blue = pal[i + 0];
6783 				pptr->green = pal[i + 1];
6784 				pptr->red = pal[i + 2];
6785 				break;
6786 			}
6787 		}
6788 		/* If palette is all we need */
6789 		res = 1;
6790 		if ((settings->mode == FS_PALETTE_LOAD) ||
6791 			(settings->mode == FS_PALETTE_DEF)) goto fail;
6792 
6793 		/* Assemble transparency table */
6794 		memset(trans, 255, 256);
6795 		if (ptype == 15)
6796 		{
6797 			int i, n, tr;
6798 
6799 			for (i = n = 0; i < j; i++) n += pal[i + i + 1] & 0x80;
6800 			/* Assume the less frequent value is transparent */
6801 			tr = n >> 6 < j ? 0x80 : 0;
6802 			for (i = 0; i < j; i++)
6803 			{
6804 				if ((pal[i + i + 1] & 0x80) == tr) trans[i + k] = 0;
6805 			}
6806 		}
6807 		else if (ptype == 32)
6808 		{
6809 			for (i = 0; i < j; i++) trans[i + k] = pal[i * 4 + 3];
6810 		}
6811 		else break; /* Cannot have transparent color at all */
6812 
6813 		/* If all alphas are identical, ignore them */
6814 		itrans = !is_filled(trans + k, trans[k], j);
6815 		break;
6816 	}
6817 	case 2: /* RGB */
6818 		/* Options are very limited - and bugs abound. Presence or
6819 		 * absence of attribute bits can't be relied upon. */
6820 		switch (rbits)
6821 		{
6822 		case 16: /* 5:5:5 BGR or 5:6:5 BGR or 5:5:5:1 BGRA */
6823 			if (abits) goto fail;
6824 			if (tga_565)
6825 			{
6826 				set_xlate(xlat6, 6);
6827 				wmode = 4;
6828 				break;
6829 			}
6830 			rbits = 15;
6831 			/* Fallthrough */
6832 		case 15: /* 5:5:5 BGR or 5:5:5:1 BGRA */
6833 			if (abits > 1) goto fail;
6834 			abits = 1; /* Here it's unreliable to uselessness */
6835 			wmode = 2;
6836 			break;
6837 		case 32: /* 8:8:8 BGR or 8:8:8:8 BGRA */
6838 			if (abits) goto fail;
6839 			rbits = 24; abits = 8;
6840 			wmode = 6;
6841 			break;
6842 		case 24: /* 8:8:8 BGR or 8:8:8:8 BGRA */
6843 			if (abits && (abits != 8)) goto fail;
6844 			wmode = 6;
6845 			break;
6846 		default: goto fail;
6847 		}
6848 		break;
6849 	case 3: /* Greyscale */
6850 		/* Not enough examples - easier to handle all possibilities */
6851 		/* Create palette */
6852 		settings->colors = rbits > 8 ? 256 : 1 << rbits;
6853 		mem_bw_pal(settings->pal, 0, settings->colors - 1);
6854 		break;
6855 	}
6856 	/* Prepare for reading bitfields */
6857 	i = abits > 8 ? abits - 8 : 0;
6858 	abits -= i; i += rbits;
6859 	ax = i >> 3;
6860 	ashift = i & 7;
6861 	amask = (1 << abits) - 1;
6862 	i = rbits > 8 ? rbits - 8 : 0;
6863 	rbits -= i;
6864 	ix = i >> 3;
6865 	ishift = i & 7;
6866 	imask = (1 << rbits) - 1;
6867 
6868 	/* Now read the footer if one is available */
6869 	fseek(fp, 0, SEEK_END);
6870 	fl = ftell(fp);
6871 	while (fl >= iofs + TGA_FSIZE)
6872 	{
6873 		fseek(fp, fl - TGA_FSIZE, SEEK_SET);
6874 		k = fread(ftr, 1, TGA_FSIZE, fp);
6875 		if (k < TGA_FSIZE) break;
6876 		if (strcmp(ftr + TGA_SIGN, "TRUEVISION-XFILE.")) break;
6877 		fofs = GET32(ftr + TGA_EXTOFS);
6878 		if ((fofs > F_LONG_MAX - TGA_EXTSIZE - TGA_FSIZE) ||
6879 			(fofs < iofs) || (fofs + TGA_EXTSIZE + TGA_FSIZE > fl))
6880 			break; /* Invalid location */
6881 		fseek(fp, fofs, SEEK_SET);
6882 		k = fread(ext, 1, TGA_EXTSIZE, fp);
6883 		if ((k < TGA_EXTSIZE) ||
6884 			/* !!! 3D Studio writes 494 into this field */
6885 			(GET16(ext + TGA_EXTLEN) < TGA_EXTSIZE - 1))
6886 			break; /* Invalid size */
6887 		if ((ftype & 3) != 1) /* Premultiplied alpha? */
6888 			assoc_alpha = ext[TGA_ATYPE] == 4;
6889 		/* Can believe alpha bits contain alpha if this field says so */
6890 		real_alpha |= assoc_alpha | (ext[TGA_ATYPE] == 3);
6891 		break;
6892 	}
6893 
6894 	/* Allocate buffer and image */
6895 	settings->width = w = GET16(hdr + TGA_WIDTH);
6896 	settings->height = h = GET16(hdr + TGA_HEIGHT);
6897 	settings->bpp = bpp = (ftype & 3) == 2 ? 3 : 1;
6898 	buflen = ibpp * w;
6899 	if (rle && (w < 129)) buflen = ibpp * 129;
6900 	buf = malloc(buflen + 1); /* One extra byte for bitparser */
6901 	res = FILE_MEM_ERROR;
6902 	if (!buf) goto fail;
6903 	if ((res = allocate_image(settings, abits ? CMASK_RGBA : CMASK_IMAGE)))
6904 		goto fail2;
6905 	/* Don't even try reading alpha if nowhere to store it */
6906 	if (abits && settings->img[CHN_ALPHA]) wmode |= 1;
6907 	res = -1;
6908 
6909 	if (!settings->silent) ls_init("TGA", 0);
6910 
6911 	fseek(fp, iofs, SEEK_SET); /* Seek to data */
6912 	/* Prepare loops */
6913 	start = 0; xstep = 1; ystep = 0;
6914 	if (hdr[TGA_DESC] & TGA_R2L)
6915 	{
6916 		/* Right-to-left */
6917 		start = w - 1;
6918 		xstep = -1;
6919 		ystep = 2 * w;
6920 	}
6921 	if (!(hdr[TGA_DESC] & TGA_T2B))
6922 	{
6923 		/* Bottom-to-top */
6924 		start += (h - 1) * w;
6925 		ystep -= 2 * w;
6926 	}
6927 	xstepb = xstep * bpp;
6928 	res = FILE_LIB_ERROR;
6929 
6930 	dest = settings->img[CHN_IMAGE] + start * bpp;
6931 	dsta = settings->img[CHN_ALPHA] + start;
6932 	y = ccnt = rcnt = 0;
6933 	bstart = bstop = buf + buflen;
6934 	strl = w;
6935 	while (TRUE)
6936 	{
6937 		int j;
6938 
6939 		j = bstop - bstart;
6940 		if (j < ibpp)
6941 		{
6942 			if (bstop - buf < buflen) goto fail3; /* Truncated file */
6943 			memcpy(buf, bstart, j);
6944 			j += fread(buf + j, 1, buflen - j, fp);
6945 			bstop = (bstart = buf) + j;
6946 			if (!rle) /* Uncompressed */
6947 			{
6948 				if (j < buflen) goto fail3; /* Truncated file */
6949 				rcnt = w; /* "Copy block" a row long */
6950 			}
6951 		}
6952 		while (TRUE)
6953 		{
6954 			/* Read pixels */
6955 			if (rcnt)
6956 			{
6957 				int l, n;
6958 
6959 				l = rcnt < strl ? rcnt : strl;
6960 				if (j < ibpp * l) l = j / ibpp;
6961 				rcnt -= l; strl -= l;
6962 				while (l--)
6963 				{
6964 					switch (wmode)
6965 					{
6966 					case 1: /* Generic alpha */
6967 						*dsta = (((bstart[ax + 1] << 8) +
6968 							bstart[ax]) >> ashift) & amask;
6969 					case 0: /* Generic single channel */
6970 						*dest = (((bstart[ix + 1] << 8) +
6971 							bstart[ix]) >> ishift) & imask;
6972 						break;
6973 					case 3: /* One-bit alpha for 16 bpp */
6974 						*dsta = bstart[1] >> 7;
6975 					case 2: /* 5:5:5 BGR */
6976 						n = (bstart[1] << 8) + bstart[0];
6977 						dest[0] = xlat5[(n >> 10) & 0x1F];
6978 						dest[1] = xlat5[(n >> 5) & 0x1F];
6979 						dest[2] = xlat5[n & 0x1F];
6980 						break;
6981 					case 5: /* Cannot happen */
6982 					case 4: /* 5:6:5 BGR */
6983 						n = (bstart[1] << 8) + bstart[0];
6984 						dest[0] = xlat5[n >> 11];
6985 						dest[1] = xlat6[(n >> 5) & 0x3F];
6986 						dest[2] = xlat5[n & 0x1F];
6987 						break;
6988 					case 7: /* One-byte alpha for 32 bpp */
6989 						*dsta = bstart[3];
6990 					case 6: /* 8:8:8 BGR */
6991 						dest[0] = bstart[2];
6992 						dest[1] = bstart[1];
6993 						dest[2] = bstart[0];
6994 						break;
6995 					}
6996 					dest += xstepb;
6997 					dsta += xstep;
6998 					bstart += ibpp;
6999 				}
7000 				if (!strl || rcnt) break; /* Row end or buffer end */
7001 			}
7002 			/* Copy pixels */
7003 			if (ccnt)
7004 			{
7005 				int i, l;
7006 
7007 				l = ccnt < strl ? ccnt : strl;
7008 				ccnt -= l; strl -= l;
7009 				for (i = 0; i < l; i++ , dest += xstepb)
7010 				{
7011 					dest[0] = src[0];
7012 					if (bpp == 1) continue;
7013 					dest[1] = src[1];
7014 					dest[2] = src[2];
7015 				}
7016 				if (wmode & 1) memset(xstep < 0 ?
7017 					dsta - l + 1 : dsta, *srca, l);
7018 				dsta += xstep * l;
7019 				if (!strl || ccnt) break; /* Row end or buffer end */
7020 			}
7021 			/* Read block header */
7022 			j = bstop - bstart - 1;
7023 			if (j < 0) break; /* Nothing in buffer */
7024 			rcnt = *bstart++;
7025 			if (rcnt > 0x7F) /* Repeat block - one read + some copies */
7026 			{
7027 				ccnt = rcnt & 0x7F;
7028 				rcnt = 1;
7029 				src = dest;
7030 				srca = dsta;
7031 			}
7032 			else ++rcnt; /* Copy block - several reads */
7033 		}
7034 		if (strl) continue; /* It was buffer end */
7035 		ls_progress(settings, y, 10);
7036 		if (++y >= h) break; /* All done */
7037 		dest += ystep * bpp;
7038 		if (dsta) dsta += ystep;
7039 		strl = w;
7040 	}
7041 
7042 	/* Check if alpha channel is valid */
7043 	if (!real_alpha && settings->img[CHN_ALPHA])
7044 		delete_alpha(settings, settings->img[CHN_ALPHA][0]);
7045 
7046 	/* Check if alpha in 16-bpp BGRA is inverse */
7047 	if (settings->img[CHN_ALPHA] && (wmode == 3) && !assoc_alpha)
7048 	{
7049 		unsigned char *timg, *talpha;
7050 		int i, j = w * h, k = 0, l;
7051 
7052 		timg = settings->img[CHN_IMAGE];
7053 		talpha = settings->img[CHN_ALPHA];
7054 		for (i = 0; i < j; i++)
7055 		{
7056 			l = 5;
7057 			if (!(timg[0] | timg[1] | timg[2])) l = 1;
7058 			else if ((timg[0] & timg[1] & timg[2]) == 255) l = 4;
7059 			k |= l << talpha[i];
7060 			if (k == 0xF) break; /* Colors independent of alpha */
7061 			timg += 3;
7062 		}
7063 		/* If 0-covered parts more colorful than 1-covered, invert alpha */
7064 		if ((k & 5) > ((k >> 1) & 5))
7065 		{
7066 			for (i = 0; i < j; i++) talpha[i] ^= 1;
7067 		}
7068 	}
7069 
7070 	/* Rescale alpha */
7071 	if (settings->img[CHN_ALPHA] && (abits < 8))
7072 		extend_bytes(settings->img[CHN_ALPHA], w * h, (1 << abits) - 1);
7073 
7074 	/* Unassociate alpha */
7075 	if (settings->img[CHN_ALPHA] && assoc_alpha && (abits > 1))
7076 	{
7077 		mem_demultiply(settings->img[CHN_IMAGE],
7078 			settings->img[CHN_ALPHA], w * h, bpp);
7079 	}
7080 	res = 0;
7081 
7082 	/* Apply palette transparency */
7083 	if (itrans) res = palette_trans(settings, trans);
7084 
7085 	if (!res) res = 1;
7086 fail3:	if (!settings->silent) progress_end();
7087 fail2:	free(buf);
7088 fail:	fclose(fp);
7089 	return (res);
7090 }
7091 
save_tga(char * file_name,ls_settings * settings)7092 static int save_tga(char *file_name, ls_settings *settings)
7093 {
7094 	unsigned char hdr[TGA_HSIZE], ftr[TGA_FSIZE], pal[256 * 4];
7095 	unsigned char *buf, *src, *srca, *dest;
7096 	FILE *fp;
7097 	int i, j, y0, y1, vstep, pcn, pbpp = 3;
7098 	int w = settings->width, h = settings->height, bpp = settings->bpp;
7099 	int rle = settings->tga_RLE;
7100 
7101 	/* Indexed images not supposed to have alpha in TGA standard */
7102 	if ((bpp == 3) && settings->img[CHN_ALPHA]) bpp = 4;
7103 	i = w * bpp;
7104 	if (rle) i += i + (w >> 7) + 3;
7105 	buf = malloc(i);
7106 	if (!buf) return -1;
7107 
7108 	if (!(fp = fopen(file_name, "wb")))
7109 	{
7110 		free(buf);
7111 		return -1;
7112 	}
7113 
7114 	/* Prepare header */
7115 	memset(hdr, 0, TGA_HSIZE);
7116 	switch (bpp)
7117 	{
7118 	case 1: /* Indexed */
7119 		hdr[TGA_PALTYPE] = 1;
7120 		hdr[TGA_IMGTYPE] = 1;
7121 		PUT16(hdr + TGA_PALCOUNT, settings->colors);
7122 		if ((settings->xpm_trans >= 0) &&
7123 			(settings->xpm_trans < settings->colors)) pbpp = 4;
7124 		hdr[TGA_PALBITS] = pbpp * 8;
7125 		break;
7126 	case 4: /* RGBA */
7127 		hdr[TGA_DESC] = 8;
7128 	case 3: /* RGB */
7129 		hdr[TGA_IMGTYPE] = 2;
7130 		break;
7131 	}
7132 	hdr[TGA_BPP] = bpp * 8;
7133 	PUT16(hdr + TGA_WIDTH, w);
7134 	PUT16(hdr + TGA_HEIGHT, h);
7135 	if (rle) hdr[TGA_IMGTYPE] |= 8;
7136 	if (!tga_defdir) hdr[TGA_DESC] |= TGA_T2B;
7137 	fwrite(hdr, 1, TGA_HSIZE, fp);
7138 
7139 	/* Write palette */
7140 	if (bpp == 1)
7141 	{
7142 		dest = pal;
7143 		for (i = 0; i < settings->colors; i++ , dest += pbpp)
7144 		{
7145 			dest[0] = settings->pal[i].blue;
7146 			dest[1] = settings->pal[i].green;
7147 			dest[2] = settings->pal[i].red;
7148 			if (pbpp > 3) dest[3] = 255;
7149 		}
7150 		/* Mark transparent color */
7151 		if (pbpp > 3) pal[settings->xpm_trans * 4 + 3] = 0;
7152 		fwrite(pal, 1, dest - pal, fp);
7153 	}
7154 
7155 	/* Write rows */
7156 	if (!settings->silent) ls_init("TGA", 1);
7157 	if (tga_defdir)
7158 	{
7159 		y0 = h - 1; y1 = -1; vstep = -1;
7160 	}
7161 	else
7162 	{
7163 		y0 = 0; y1 = h; vstep = 1;
7164 	}
7165 	for (i = y0 , pcn = 0; i != y1; i += vstep , pcn++)
7166 	{
7167 		prepare_row(buf, settings, bpp, i); /* Fill uncompressed row */
7168 		src = buf;
7169 		dest = buf + w * bpp;
7170 		if (rle) /* Compress */
7171 		{
7172 			unsigned char *tmp;
7173 			int k, l;
7174 
7175 			for (j = 1; j <= w; j++)
7176 			{
7177 				tmp = srca = src;
7178 				src += bpp;
7179 				/* Scan row for repeats */
7180 				for (; j < w; j++ , src += bpp)
7181 				{
7182 					switch (bpp)
7183 					{
7184 					case 4: if (src[3] != srca[3]) break;
7185 					case 3: if (src[2] != srca[2]) break;
7186 					case 2: if (src[1] != srca[1]) break;
7187 					case 1: if (src[0] != srca[0]) break;
7188 					default: continue;
7189 					}
7190 					/* Useful repeat? */
7191 					if (src - srca > bpp + 2) break;
7192 					srca = src;
7193 				}
7194 				/* Avoid too-short repeats at row ends */
7195 				if (src - srca <= bpp + 2) srca = src;
7196 				/* Create copy blocks */
7197 				for (k = (srca - tmp) / bpp; k > 0; k -= 128)
7198 				{
7199 					l = k > 128 ? 128 : k;
7200 					*dest++ = l - 1;
7201 					memcpy(dest, tmp, l *= bpp);
7202 					dest += l; tmp += l;
7203 				}
7204 				/* Create repeat blocks */
7205 				for (k = (src - srca) / bpp; k > 0; k -= 128)
7206 				{
7207 					l = k > 128 ? 128 : k;
7208 					*dest++ = l + 127;
7209 					memcpy(dest, srca, bpp);
7210 					dest += bpp;
7211 				}
7212 			}
7213 		}
7214 		fwrite(src, 1, dest - src, fp);
7215 		ls_progress(settings, pcn, 20);
7216 	}
7217 
7218 	/* Write footer */
7219 	memcpy(ftr + TGA_SIGN, "TRUEVISION-XFILE.", TGA_FSIZE - TGA_SIGN);
7220 	memset(ftr, 0, TGA_SIGN);
7221 	fwrite(ftr, 1, TGA_FSIZE, fp);
7222 
7223 	fclose(fp);
7224 
7225 	if (!settings->silent) progress_end();
7226 
7227 	free(buf);
7228 	return 0;
7229 }
7230 
7231 /* PCX header */
7232 #define PCX_ID        0 /*  8b */
7233 #define PCX_VER       1 /*  8b */
7234 #define PCX_ENC       2 /*  8b */
7235 #define PCX_BPP       3 /*  8b */
7236 #define PCX_X0        4 /* 16b */
7237 #define PCX_Y0        6 /* 16b */
7238 #define PCX_X1        8 /* 16b */
7239 #define PCX_Y1       10 /* 16b */
7240 #define PCX_HDPI     12 /* 16b */
7241 #define PCX_VDPI     14 /* 16b */
7242 #define PCX_PAL      16 /* 8b*3*16 */
7243 #define PCX_NPLANES  65 /*  8b */
7244 #define PCX_LINELEN  66 /* 16b */
7245 #define PCX_PALTYPE  68 /* 16b */
7246 #define PCX_HRES     70 /* 16b */
7247 #define PCX_VRES     72 /* 16b */
7248 #define PCX_HSIZE   128
7249 
7250 #define PCX_BUFSIZE 16384 /* Bytes read at a time */
7251 
7252 /* Default EGA/VGA palette */
7253 static const png_color def_pal[16] = {
7254 {0x00, 0x00, 0x00}, {0x00, 0x00, 0xAA}, {0x00, 0xAA, 0x00}, {0x00, 0xAA, 0xAA},
7255 {0xAA, 0x00, 0x00}, {0xAA, 0x00, 0xAA}, {0xAA, 0x55, 0x00}, {0xAA, 0xAA, 0xAA},
7256 {0x55, 0x55, 0x55}, {0x55, 0x55, 0xFF}, {0x55, 0xFF, 0x55}, {0x55, 0xFF, 0xFF},
7257 {0xFF, 0x55, 0x55}, {0xFF, 0x55, 0xFF}, {0xFF, 0xFF, 0x55}, {0xFF, 0xFF, 0xFF},
7258 };
7259 
load_pcx(char * file_name,ls_settings * settings)7260 static int load_pcx(char *file_name, ls_settings *settings)
7261 {
7262 	static const unsigned char planarconfig[9] = {
7263 		0x11, /* BW */  0x12, /* 4c */ 0x21, /* 4c */ 0x31, /* 8c */
7264 		0x41, /* 16c */ 0x14, /* 16c */ 0x18, /* 256c */
7265 		0x38, /* RGB */	0x48  /* RGBA */ };
7266 	unsigned char hdr[PCX_HSIZE], pbuf[769];
7267 	unsigned char *buf, *row, *dest, *tmp;
7268 	FILE *fp;
7269 	int ver, bits, planes, ftype;
7270 	int y, ccnt, bstart, bstop, strl, plane, cf;
7271 	int w, h, cols, buflen, bpp = 3, res = -1;
7272 
7273 
7274 	if (!(fp = fopen(file_name, "rb"))) return (-1);
7275 
7276 	/* Read the header */
7277 	if (fread(hdr, 1, PCX_HSIZE, fp) < PCX_HSIZE) goto fail;
7278 
7279 	/* PCX has no real signature - so check fields one by one */
7280 	if ((hdr[PCX_ID] != 10) || (hdr[PCX_ENC] > 1)) goto fail;
7281 	ver = hdr[PCX_VER];
7282 	if (ver > 5) goto fail;
7283 
7284 	bits = hdr[PCX_BPP];
7285 	planes = hdr[PCX_NPLANES];
7286 	if ((bits == 24) && (planes == 1)) ftype = 7; /* Single-plane RGB */
7287 	else if ((bits | planes) > 15) goto fail;
7288 	else if ((tmp = memchr(planarconfig, (planes << 4) | bits, 9)))
7289 		ftype = tmp - planarconfig;
7290 	else goto fail;
7291 
7292 	/* Prepare palette */
7293 	if (ftype < 7)
7294 	{
7295 		bpp = 1;
7296 		settings->colors = cols = 1 << (bits * planes);
7297 		/* BW (0 is black) */
7298 		if (cols == 2)
7299 		{
7300 			settings->pal[0] = def_pal[0];
7301 			settings->pal[1] = def_pal[15];
7302 		}
7303 		/* Default 256-color palette - assumed greyscale */
7304 		else if ((ver == 3) && (cols == 256)) set_gray(settings);
7305 		/* Default 16-color palette */
7306 		else if ((ver == 3) && (cols == 16))
7307 			memcpy(settings->pal, def_pal, sizeof(def_pal));
7308 	/* !!! CGA palette is evil: what the PCX spec describes is the way it
7309 	 * was handled by PC Paintbrush 3.0, while 4.0 was using an entirely
7310 	 * different, undocumented encoding for palette selection.
7311 	 * The only seemingly sane way to differentiate the two is to look at
7312 	 * paletteinfo field: zeroed in 3.0, set in 4.0+ - WJ */
7313 		else if (cols == 4)
7314 		{
7315 			/* Bits 2:1:0 in index: color burst:palette:intensity */
7316 			static const unsigned char cga_pals[8 * 3] = {
7317 				2, 4, 6,  10, 12, 14,
7318 				3, 5, 7,  11, 13, 15,
7319 				3, 4, 7,  11, 12, 15,
7320 				3, 4, 7,  11, 12, 15 };
7321 			int i, idx = hdr[PCX_PAL + 3] >> 5; // PB 3.0
7322 
7323 			if (GET16(hdr + PCX_PALTYPE)) // PB 4.0
7324 			{
7325 				/* Pick green palette if G>B in slot 1 */
7326 				i = hdr[PCX_PAL + 5] >= hdr[PCX_PAL + 4];
7327 				/* Pick bright palette if max(G,B) > 200 */
7328 				idx = i * 2 + (hdr[PCX_PAL + 4 + i] > 200);
7329 			}
7330 
7331 			settings->pal[0] = def_pal[hdr[PCX_PAL] >> 4];
7332 			for (i = 1 , idx *= 3; i < 4; i++)
7333 				settings->pal[i] = def_pal[cga_pals[idx++]];
7334 		}
7335 		/* VGA palette - read from file */
7336 		else if (cols == 256)
7337 		{
7338 			if ((fseek(fp, -769, SEEK_END) < 0) ||
7339 				(fread(pbuf, 1, 769, fp) < 769) ||
7340 				(pbuf[0] != 0x0C)) goto fail;
7341 			rgb2pal(settings->pal, pbuf + 1, 256);
7342 		}
7343 		/* 8 or 16 colors - read from header */
7344 		else rgb2pal(settings->pal, hdr + PCX_PAL, cols);
7345 
7346 		/* If palette is all we need */
7347 		res = 1;
7348 		if ((settings->mode == FS_PALETTE_LOAD) ||
7349 			(settings->mode == FS_PALETTE_DEF)) goto fail;
7350 	}
7351 
7352 	/* Allocate buffer and image */
7353 	settings->width = w = GET16(hdr + PCX_X1) - GET16(hdr + PCX_X0) + 1;
7354 	settings->height = h = GET16(hdr + PCX_Y1) - GET16(hdr + PCX_Y0) + 1;
7355 	settings->bpp = bpp;
7356 	buflen = GET16(hdr + PCX_LINELEN);
7357 	res = -1;
7358 	if (buflen < ((w * bits + 7) >> 3)) goto fail;
7359 	/* To accommodate bitparser's extra step */
7360 	buf = malloc(PCX_BUFSIZE + buflen + 1);
7361 	res = FILE_MEM_ERROR;
7362 	if (!buf) goto fail;
7363 	row = buf + PCX_BUFSIZE;
7364 	if ((res = allocate_image(settings, ftype > 7 ? CMASK_RGBA : CMASK_IMAGE)))
7365 		goto fail2;
7366 
7367 	/* Read and decode the file */
7368 	if (!settings->silent) ls_init("PCX", 0);
7369 	res = FILE_LIB_ERROR;
7370 	fseek(fp, PCX_HSIZE, SEEK_SET);
7371 	dest = settings->img[CHN_IMAGE];
7372 	if (bits == 1) memset(dest, 0, w * h); // Write will be by OR
7373 	y = plane = ccnt = 0;
7374 	bstart = bstop = PCX_BUFSIZE;
7375 	strl = buflen;
7376 	cf = hdr[PCX_ENC] ? 0xC0 : 0x100; // Compressed, or not
7377 	while (TRUE)
7378 	{
7379 		unsigned char v;
7380 
7381 		/* Keep the buffer filled */
7382 		if (bstart >= bstop)
7383 		{
7384 			bstart -= bstop;
7385 			bstop = fread(buf, 1, PCX_BUFSIZE, fp);
7386 			if (bstop <= bstart) goto fail3; /* Truncated file */
7387 		}
7388 
7389 		/* Decode data */
7390 		v = buf[bstart];
7391 		if (ccnt) /* Middle of a run */
7392 		{
7393 			int l = strl < ccnt ? strl : ccnt;
7394 			memset(row + buflen - strl, v, l);
7395 			strl -= l; ccnt -= l;
7396 		}
7397 		else if (v >= cf) /* Start of a run */
7398 		{
7399 			ccnt = v & 0x3F;
7400 			bstart++;
7401 		}
7402 		else row[buflen - strl--] = v;
7403 		bstart += !ccnt;
7404 		if (strl) continue;
7405 
7406 		/* Store a line */
7407 		if (bits == 1) // N planes of 1-bit data (MSB first)
7408 		{
7409 			unsigned char uninit_(v), *tmp = row;
7410 			int i, n = 7 - plane;
7411 
7412 			for (i = 0; i < w; i++ , v += v)
7413 			{
7414 				if (!(i & 7)) v = *tmp++;
7415 				dest[i] |= (v & 0x80) >> n;
7416 			}
7417 		}
7418 		else if (bits == 24) // 1 plane of RGB
7419 			memcpy(dest, row, w * 3);
7420 		else if (plane < 3) // BPP planes of 2/4/8-bit data (MSB first)
7421 			stream_MSB(row, dest + plane, w, bits, 0, bits, bpp);
7422 		else if (settings->img[CHN_ALPHA]) // 8-bit alpha plane
7423 			memcpy(settings->img[CHN_ALPHA] + y * w, row, w);
7424 
7425 		if (++plane >= planes)
7426 		{
7427 			ls_progress(settings, y, 10);
7428 			if (++y >= h) break;
7429 			dest += w * bpp;
7430 			plane = 0;
7431 		}
7432 		strl = buflen;
7433 	}
7434 	res = 1;
7435 
7436 fail3:	if (!settings->silent) progress_end();
7437 fail2:	free(buf);
7438 fail:	fclose(fp);
7439 	return (res);
7440 }
7441 
save_pcx(char * file_name,ls_settings * settings)7442 static int save_pcx(char *file_name, ls_settings *settings)
7443 {
7444 	unsigned char *buf, *src, *dest;
7445 	FILE *fp;
7446 	int w = settings->width, h = settings->height, bpp = settings->bpp;
7447 	int i, l, plane, cnt;
7448 
7449 
7450 	/* Allocate buffer */
7451 	i = w * 2; // Buffer one plane, with worst-case RLE expansion factor 2
7452 	if (i < PCX_HSIZE) i = PCX_HSIZE;
7453 	if (i < 769) i = 769; // For palette
7454 	buf = calloc(1, i); // Zeroing out is for header
7455 	if (!buf) return (-1);
7456 
7457 	if (!(fp = fopen(file_name, "wb")))
7458 	{
7459 		free(buf);
7460 		return (-1);
7461 	}
7462 
7463 	/* Prepare header */
7464 	memcpy(buf, "\x0A\x05\x01\x08", 4); // Version 5 PCX, 8 bits/plane
7465 	PUT16(buf + PCX_X1, w - 1);
7466 	PUT16(buf + PCX_Y1, h - 1);
7467 	PUT16(buf + PCX_HDPI, 300); // GIMP sets DPI to this value
7468 	PUT16(buf + PCX_VDPI, 300);
7469 	buf[PCX_NPLANES] = bpp;
7470 	PUT16(buf + PCX_LINELEN, w);
7471 	buf[PCX_PALTYPE] = 1;
7472 	fwrite(buf, 1, PCX_HSIZE, fp);
7473 
7474 	/* Compress & write pixel rows */
7475 	if (!settings->silent) ls_init("PCX", 1);
7476 	src = settings->img[CHN_IMAGE];
7477 	for (i = 0; i < h; i++ , src += w * bpp)
7478 	{
7479 		for (plane = 0; plane < bpp; plane++)
7480 		{
7481 			unsigned char v, *tmp = src + plane;
7482 
7483 			dest = buf; cnt = 0; l = w;
7484 			while (l > 0)
7485 			{
7486 				v = *tmp; tmp += bpp; cnt++;
7487 				if ((--l <= 0) || (cnt == 0x3F) || (v != *tmp))
7488 				{
7489 					if ((cnt > 1) || (v >= 0xC0))
7490 						*dest++ = cnt | 0xC0;
7491 					*dest++ = v; cnt = 0;
7492 				}
7493 			}
7494 			fwrite(buf, 1, dest - buf, fp);
7495 		}
7496 		ls_progress(settings, i, 20);
7497 	}
7498 
7499 	/* Write palette */
7500 	if (bpp == 1)
7501 	{
7502 		buf[0] = 0x0C;
7503 		pal2rgb(buf + 1, settings->pal, settings->colors, 256);
7504 		fwrite(buf, 1, 769, fp);
7505 	}
7506 
7507 	fclose(fp);
7508 
7509 	if (!settings->silent) progress_end();
7510 
7511 	free(buf);
7512 	return (0);
7513 }
7514 
7515 /* *** PREFACE ***
7516  * LBM format has no one definitive documentation source, nor a good testsuite,
7517  * and while I found enough examples of some types, other ones I never observed
7518  * in the wild remain unsupported. If you encounter some such curiosity failing
7519  * to load or loading wrong, send a bugreport with the file attached to it. */
7520 
7521 /* Macros for IFF tags; big-endian too */
7522 #define TAG4B_FORM TAG4B('F', 'O', 'R', 'M')
7523 #define TAG4B_ILBM TAG4B('I', 'L', 'B', 'M')
7524 #define TAG4B_PBM  TAG4B('P', 'B', 'M', ' ')
7525 #define TAG4B_BMHD TAG4B('B', 'M', 'H', 'D')
7526 #define TAG4B_CMAP TAG4B('C', 'M', 'A', 'P')
7527 #define TAG4B_GRAB TAG4B('G', 'R', 'A', 'B')
7528 #define TAG4B_DEST TAG4B('D', 'E', 'S', 'T')
7529 #define TAG4B_CAMG TAG4B('C', 'A', 'M', 'G')
7530 #define TAG4B_BODY TAG4B('B', 'O', 'D', 'Y')
7531 /* Multipalette tags */
7532 #define TAG4B_SHAM TAG4B('S', 'H', 'A', 'M')
7533 #define TAG4B_CTBL TAG4B('C', 'T', 'B', 'L')
7534 #define TAG4B_PCHG TAG4B('P', 'C', 'H', 'G')
7535 
7536 /* LBM header block (BMHD tag) */
7537 #define BMHD_W     0 /* 16b */
7538 #define BMHD_H     2 /* 16b */
7539 #define BMHD_X0    4 /* 16b */
7540 #define BMHD_Y0    6 /* 16b */
7541 #define BMHD_BPP   8 /*  8b */
7542 #define BMHD_MASK  9 /*  8b */
7543 #define BMHD_COMP 10 /*  8b */
7544 #define BMHD_PAD  11 /*  8b */
7545 #define BMHD_TRAN 12 /* 16b */
7546 #define BMHD_ASPX 14 /*  8b */
7547 #define BMHD_ASPY 15 /*  8b */
7548 #define BMHD_SCW  16 /* 16b */
7549 #define BMHD_SCH  18 /* 16b */
7550 #define BMHD_SIZE 20
7551 
7552 /*  LBM DEST block */
7553 #define DEST_DEPTH 0 /*  8b */
7554 #define DEST_PAD   1 /*  8b */
7555 #define DEST_PICK  2 /* 16b */
7556 #define DEST_ONOFF 4 /* 16b */
7557 #define DEST_MASK  6 /* 16b */
7558 #define DEST_SIZE  8
7559 
7560 /* PCHG block header */
7561 #define PCHG_COMPR  0 /* 16b */
7562 #define PCHG_FLAGS  2 /* 16b */
7563 #define PCHG_START  4 /* 16b */
7564 #define PCHG_COUNT  6 /* 16b */
7565 #define PCHG_CHLIN  8 /* 16b */
7566 #define PCHG_MINR  10 /* 16b */
7567 #define PCHG_MAXR  12 /* 16b */
7568 #define PCHG_MAXCH 14 /* 16b */
7569 #define PCHG_TOTCH 16 /* 32b */
7570 #define PCHG_HSIZE 20
7571 
7572 #define HAVE_BMHD 1
7573 #define HAVE_CMAP 2
7574 #define HAVE_GRAB 4
7575 #define HAVE_DEST 8
7576 
load_lbm(char * file_name,ls_settings * settings)7577 static int load_lbm(char *file_name, ls_settings *settings)
7578 {
7579 	static const unsigned char bitdepths[] =
7580 		{ 1, 2, 3, 4, 5, 6, 7, 8, 21, 24, 32 };
7581 	unsigned char hdr[BMHD_SIZE], dbuf[DEST_SIZE], pchdr[PCHG_HSIZE];
7582 	unsigned char pbuf[768], wbuf[256];
7583 	unsigned char *buf, *row, *dest, *mpp, *pr = NULL;
7584 	FILE *fp;
7585 	int y, ccnt, bstart, bstop, strl, np, ap, mp;
7586 	f_long ctbl = 0, pchg = 0;
7587 	unsigned tag, tl;
7588 	int pstart = 0, ctbll = 0, pchgl = 0, pcnt = 0, sh2 = 0;
7589 	int w, h, bpp, bits, mask, tbits, buflen, plen, half = 0, ham = 0;
7590 	int pbm, palsize = 0, blocks = 0, hx = 0, hy = 0, res = -1;
7591 	int i, j, l, p, pad, want_pal;
7592 
7593 
7594 	if (!(fp = fopen(file_name, "rb"))) return (-1);
7595 
7596 	/* Read the IFF header & check signature */
7597 	if (fread(wbuf, 1, 12, fp) < 12) goto fail;
7598 	if (GET32B(wbuf) != TAG4B_FORM) goto fail;
7599 	tag = GET32B(wbuf + 8);
7600 	if (!(pbm = tag == TAG4B_PBM) && !(tag == TAG4B_ILBM)) goto fail;
7601 
7602 	/* Read block headers & see what we get */
7603 	want_pal = (settings->mode == FS_PALETTE_LOAD) ||
7604 		(settings->mode == FS_PALETTE_DEF);
7605 	while (fread(wbuf, 1, 8, fp) == 8)
7606 	{
7607 		tag = GET32B(wbuf);
7608 		tl = GET32B(wbuf + 4);
7609 		if (tl >= INT_MAX) break; // Sanity check
7610 		pad = tl & 1;
7611 		if (tag == TAG4B_BMHD)
7612 		{
7613 			if (tl != BMHD_SIZE) break;
7614 			if (fread(hdr, 1, BMHD_SIZE, fp) != BMHD_SIZE) break;
7615 			blocks |= HAVE_BMHD;
7616 			continue;
7617 		}
7618 		else if (tag == TAG4B_CMAP)
7619 		{
7620 			/* Allow palette being too long */
7621 			palsize = tl > 768 ? 768 : tl;
7622 			if (fread(pbuf, 1, palsize, fp) != palsize) break;
7623 			blocks |= HAVE_CMAP;
7624 			tl -= palsize;
7625 			/* If palette is all we need; hope there's only one */
7626 			if (want_pal)
7627 			{
7628 				res = 1;
7629 				break;
7630 			}
7631 			// Fallthrough
7632 		}
7633 		else if (tag == TAG4B_GRAB)
7634 		{
7635 			if ((tl != 4) || (fread(wbuf, 1, 4, fp) != 4)) break;
7636 			blocks |= HAVE_GRAB;
7637 			hx = GET16B(wbuf);
7638 			hy = GET16B(wbuf + 2);
7639 			continue;
7640 		}
7641 		else if (tag == TAG4B_DEST)
7642 		{
7643 			if (tl != DEST_SIZE) break;
7644 			if (fread(dbuf, 1, DEST_SIZE, fp) != DEST_SIZE) break;
7645 			blocks |= HAVE_DEST;
7646 			continue;
7647 		}
7648 		else if (tag == TAG4B_CAMG)
7649 		{
7650 			if ((tl != 4) || (fread(wbuf, 1, 4, fp) != 4)) break;
7651 			tag = GET32B(wbuf);
7652 			half = tag & 0x80;
7653 			ham = tag & 0x800;
7654 			continue;
7655 		}
7656 		else if ((tag == TAG4B_SHAM) || (tag == TAG4B_CTBL))
7657 		{
7658 			ctbl = ftell(fp);
7659 			ctbll = tl;
7660 			// SHAM has "version" word at the beginning
7661 			if (tag == TAG4B_SHAM)
7662 			{
7663 				if (tl < 2) break;
7664 				ctbl += 2 , ctbll -= 2;
7665 			}
7666 		}
7667 		else if (tag == TAG4B_PCHG)
7668 		{
7669 			if ((tl < PCHG_HSIZE) ||
7670 				(fread(pchdr, 1, PCHG_HSIZE, fp) != PCHG_HSIZE)) break;
7671 			pchg = ftell(fp);
7672 			pchgl = tl -= PCHG_HSIZE;
7673 		}
7674 		else if (tag == TAG4B_BODY)
7675 		{
7676 			/* Palette & header must be before body */
7677 			if (!want_pal && (blocks & HAVE_BMHD)) res = 0;
7678 			break;
7679 		}
7680 		/* Default: skip (the rest of) tag data */
7681 		tl += pad;
7682 		if (tl && fseek(fp, tl, SEEK_CUR)) break;
7683 	}
7684 	if (res < 0) goto fail;
7685 
7686 	/* Parse bitplanes */
7687 	tbits = !(blocks & HAVE_BMHD) ? 0 : // Palette may happen before header
7688 		blocks & HAVE_DEST ? dbuf[DEST_DEPTH] : hdr[BMHD_BPP];
7689 
7690 	/* Prepare palette */
7691 	if (blocks & HAVE_CMAP)
7692 	{
7693 		/* Corrective multipliers to counteract dumb shift */
7694 		static const unsigned char mult[8] =
7695 			{ 128, 128, 130, 132, 136, 146, 170, 255 };
7696 
7697 		/* Limit palette to actual bitplanes */
7698 		l = palsize / 3;
7699 		if (tbits && (tbits < 9))
7700 		{
7701 			i = tbits;
7702 			if (ham) i = i > 6 ? 6 : 4;
7703 			else if (half && (i > 5)) i = 5;
7704 			i = 1 << i;
7705 			if (l > i) l = i;
7706 		}
7707 		/* Detect and correct palettes where 6..1-bit color was shifted
7708 		 * left by 2..7 without replicating high bits into low */
7709 		l *= 3;
7710 		for (i = 0 , j = 0x80; i < l; i++) j |= pbuf[i];
7711 		for (i = 0; !(j & 1); i++) j >>= 1;
7712 		for (j = mult[i] , i = 0; i < l; i++)
7713 			pbuf[i] = (pbuf[i] * j) >> 7;
7714 		/* Apply half-brite mode */
7715 		if (half && (l <= 32 * 3))
7716 		{
7717 			memset(pbuf + l, 0, 32 * 3 - l);
7718 			for (i = 0; i < l; i++)
7719 				pbuf[i + 32 * 3] = pbuf[i] >> 1;
7720 			l += 32 * 3;
7721 		}
7722 		/* Store the result */
7723 		rgb2pal(settings->pal, pbuf, settings->colors = l / 3);
7724 	}
7725 	if (want_pal) goto fail;
7726 
7727 	/* Check sanity */
7728 	res = -1;
7729 	if (hdr[BMHD_COMP] > 1) goto fail; // Unknown compression type
7730 	bits = hdr[BMHD_BPP];
7731 	if (!memchr(bitdepths, bits, sizeof(bitdepths))) goto fail;
7732 	if (ham)
7733 	{
7734  		if ((bits < 5) || (bits > 8)) goto fail;
7735 		// No reason for grayscale HAM to exist
7736 		if (!(blocks & HAVE_CMAP)) goto fail;
7737 		ham = bits > 6 ? 6 : 4; // Shift value
7738 	}
7739 	if (ctbl)
7740 	{
7741 		h = GET16B(hdr + BMHD_H);
7742 		sh2 = ctbll == (h >> 1) * 32;
7743 		if (!sh2 && (ctbll != h * 32)) goto fail; // Size must match
7744 		pchg = pchgl = 0; // If both present, simpler is better
7745 		if (bits > (ham ? 6 : 4)) goto fail;
7746 	}
7747 	if (pchg)
7748 	{
7749 		/* No examples of anything but uncompressed 12-bit PCHG blocks,
7750 		 * so no reason to waste code supporting anything else */
7751 		if (GET16B(pchdr + PCHG_COMPR)) goto fail;
7752 		if (GET16B(pchdr + PCHG_FLAGS) != 1) goto fail;
7753 		if (bits > (half || ham ? 6 : 5)) goto fail;
7754 		pstart = GET16B(pchdr + PCHG_START);
7755 		pcnt = GET16B(pchdr + PCHG_COUNT);
7756 
7757 	}
7758 	mask = hdr[BMHD_MASK] == 1;
7759 	if (pbm && (mask || ham || ctbl || pchg || (bits != 8)))
7760 		goto fail; // Not compatible
7761 
7762 	/* DEST block if any */
7763 	if (blocks & HAVE_DEST)
7764 	{
7765 		unsigned skip, setv, v;
7766 
7767 		/* For simplicity, as no one ever saw files w/DEST anyway */
7768 		if ((tbits < bits) || (tbits > 8) || ham) goto fail;
7769 		/* Make a lookup table for remapping bits after the fact;
7770 		 * ignore planeMask in hope it masks only planeOnOff */
7771 		skip = ((1 << tbits) - 1) & ~GET16B(dbuf + DEST_PICK); // Skipmask
7772 		setv = skip & GET16B(dbuf + DEST_ONOFF); // Setmask
7773 		for (v = i = 0; !(i >> bits); i++)
7774 		{
7775 			wbuf[i] = v | setv;
7776 			v = (v + skip + 1) & ~skip; // Increment across gaps
7777 		}
7778 	}
7779 	/* 21-bit RGB */
7780 	else if (bits == 21)
7781 	{
7782 		set_xlate(wbuf, 7);
7783 		blocks |= HAVE_DEST; // !!! Let same xlate do either thing
7784 	}
7785 
7786 	/* Make greyscale palette if needed */
7787 	if ((tbits <= 8) && !(blocks & HAVE_CMAP))
7788 		mem_bw_pal(settings->pal, 0, (settings->colors = 1 << tbits) - 1);
7789 
7790 	/* Transparent color - nearly always a glitch, rarely a real thing */
7791 	if (!lbm_untrans && (hdr[BMHD_MASK] > 1))
7792 	{
7793 		j = GET16B(hdr + BMHD_TRAN);
7794 		if (j < settings->colors) settings->xpm_trans = j;
7795 	}
7796 
7797 	if (blocks & HAVE_GRAB) settings->hot_x = hx , settings->hot_y = hy;
7798 
7799 	/* Allocate buffer and image */
7800 	settings->width = w = GET16B(hdr + BMHD_W);
7801 	settings->height = h = GET16B(hdr + BMHD_H);
7802 	plen = ctbll + pchgl;
7803 	settings->bpp = bpp = ham || plen || (bits > 8) ? 3 : 1;
7804 	buflen = pbm ? w + (w & 1) : ((w + 15) >> 4) * 2 * (bits + mask);
7805 	buf = multialloc(MA_ALIGN_DEFAULT, &buf, PCX_BUFSIZE, &row, buflen,
7806 		&mpp, plen, NULL);
7807 	res = FILE_MEM_ERROR;
7808 	if (!buf) goto fail;
7809 	i = bits == 32 ? CMASK_RGBA : CMASK_IMAGE;
7810 	if (mask) i |= CMASK_FOR(lbm_mask);
7811 	if ((res = allocate_image(settings, i))) goto fail2;
7812 	if (!pbm) // Prepare for writes by OR
7813 	{
7814 		memset(settings->img[CHN_IMAGE], 0, w * h * bpp);
7815 		if (settings->img[CHN_ALPHA])
7816 			memset(settings->img[CHN_ALPHA], 0, w * h);
7817 		if ((i & ~CMASK_RGBA) && settings->img[lbm_mask])
7818 			memset(settings->img[lbm_mask], 0, w * h);
7819 	}
7820 
7821 	/* Load color change table if any */
7822 	if (plen)
7823 	{
7824 		f_long b = ftell(fp);
7825 		if (fseek(fp, ctbl + pchg, SEEK_SET) ||
7826 			(fread(mpp, 1, plen, fp) != plen)) goto fail2;
7827 		fseek(fp, b, SEEK_SET);
7828 		if (!ham) ham = 8; // Use same decoding loop in mode 0
7829 		pr = mpp + ((pcnt + 31) >> 5) * 4;
7830 	}
7831 
7832 	/* Read and decode the file */
7833 	if (!settings->silent) ls_init("LBM", 0);
7834 	res = FILE_LIB_ERROR;
7835 	ap = bits > 24 ? 24 : -1; // First alpha plane
7836 	if (!settings->img[CHN_ALPHA]) ap = -1; // No alpha
7837 	mp = bits; // Mask plane
7838 	if (!mask || !lbm_mask || !settings->img[lbm_mask] ||
7839 		((lbm_mask == CHN_ALPHA) && (ap > 0))) mp = -1;
7840 	np = mp > 0 ? bits + 1 : (ap > 0) || (bits < 24) ? bits : 24; // Planes to read
7841 	y = ccnt = 0;
7842 	if (!hdr[BMHD_COMP]) ccnt = buflen * h; // Uncompressed is file-sized copy run
7843 	bstart = bstop = PCX_BUFSIZE;
7844 	strl = buflen;
7845 	while (TRUE)
7846 	{
7847 		/* Keep the buffer filled */
7848 		if (bstart >= bstop)
7849 		{
7850 			bstart -= bstop;
7851 			bstop = fread(buf, 1, PCX_BUFSIZE, fp);
7852 			if (bstop <= bstart) goto fail3; /* Truncated file */
7853 		}
7854 
7855 		/* Decode data */
7856 		if (ccnt < 0) /* Middle of a repeat run */
7857 		{
7858 			int l = strl + ccnt < 0 ? strl : -ccnt;
7859 			memset(row + buflen - strl, buf[bstart], l);
7860 			strl -= l; bstart += !(ccnt += l);
7861 		}
7862 		else if (ccnt > 0) /* Middle of a copy run */
7863 		{
7864 			int l = strl < ccnt ? strl : ccnt;
7865 			if (l > bstop - bstart) l = bstop - bstart;
7866 			memcpy(row + buflen - strl, buf + bstart, l);
7867 			strl -= l; ccnt -= l; bstart += l;
7868 		}
7869 		else /* Start of a run */
7870 		{
7871 			ccnt = buf[bstart];
7872 			ccnt += ccnt < 128 ? 1 : -257;
7873 			bstart++;
7874 		}
7875 		if (strl) continue;
7876 
7877 		/* Store a line */
7878 		p = y * w;
7879 		dest = settings->img[CHN_IMAGE] + p * bpp;
7880 		if (pbm) memcpy(dest, row, w);
7881 		while (!pbm)
7882 		{
7883 			unsigned char *dsta = NULL, *dstm = NULL;
7884 			unsigned char uninit_(v), *tmp, *dp;
7885 			int i, n, plane, step = bpp;
7886 
7887 			if (ap > 0) dsta = settings->img[CHN_ALPHA] + p;
7888 			if (mp > 0) dstm = settings->img[lbm_mask] + p;
7889 			for (plane = 0; plane < np; plane++)
7890 			{
7891 				tmp = row + ((w + 15) >> 4) * 2 * plane;
7892 				if (bits == 21)
7893 					dp = dest + plane % 3 , n = 1 + plane / 3;
7894 				else dp = dest + (plane >> 3) , n = 7 - (plane & 7);
7895 				if (plane == mp) dp = dstm , step = 1; // Mask
7896 				else if (plane >= 24) dp = dsta , step = 1; // Alpha
7897 				if (!dp) continue; // Skipping alpha till mask
7898 				for (i = 0; i < w; i++ , v += v , dp += step)
7899 				{
7900 					if (!(i & 7)) v = *tmp++;
7901 					*dp |= (v & 0x80) >> n;
7902 				}
7903 			}
7904 
7905 			if (!ham) break;
7906 
7907 			/* Multipalette, simpler kind */
7908 			if (ctbl && !(y & sh2))
7909 			{
7910 				unsigned char *dest = pbuf;
7911 				for (i = 0; i < 16; i++ , pr += 2 , dest += 3)
7912 				{
7913 					int v = GET16B(pr);
7914 					dest[0] = ((v >> 8) & 0xF) * 0x11;
7915 					dest[1] = ((v >> 4) & 0xF) * 0x11;
7916 					dest[2] = (v & 0xF) * 0x11;
7917 				}
7918 			}
7919 			/* Multipalette, complex kind */
7920 			while (pchg && (y >= pstart) && (y < pstart + pcnt))
7921 			{
7922 				unsigned char *dest;
7923 				int n, n16, v, i, j;
7924 				i = y - pstart;
7925 				j = (i >> 5) * 4;
7926 				if (!((GET32B(mpp + j) >> (~i & 0x1F)) & 1))
7927 					break; // Nothing to do for this line
7928 				n16 = pr[1]; // Colors 16-31 for this many
7929 				n = pr[0] + n16; // Total indices
7930 				pr += 2;
7931 				while (n-- > 0)
7932 				{
7933 					v = GET16B(pr);
7934 					pr += 2;
7935 					dest = pbuf + (n < n16) * 16 * 3 + (v >> 12) * 3;
7936 					dest[0] = ((v >> 8) & 0xF) * 0x11;
7937 					dest[1] = ((v >> 4) & 0xF) * 0x11;
7938 					dest[2] = (v & 0xF) * 0x11;
7939 				}
7940 				if (half) for (i = 0; i < 32 * 3; i++)
7941 					pbuf[i + 32 * 3] = pbuf[i] >> 1;
7942 				break;
7943 			}
7944 
7945 			/* Recode the row */
7946 			/* !!! Start with palette color 0 as amigaos.net says and
7947 			 * GrafX2 does, not RGB 0 as ilbmtopnm does */
7948 			tmp = pbuf;
7949 			dp = dest;
7950 			for (i = 0; i < w; i++ , dp += 3)
7951 			{
7952 				n = (v = *dp) >> ham;
7953 				if (!n) tmp = pbuf + v * 3; // Palette color
7954 				dp[0] = tmp[0];
7955 				dp[1] = tmp[1];
7956 				dp[2] = tmp[2];
7957 				tmp = dp;
7958 				if (!n) continue;
7959 				v ^= n << ham;
7960 				n ^= (n >> 1) ^ 3; // 0BRG -> RGB
7961 				/* !!! In HAM8, preserve low 2 bits as Amiga docs
7962 				 * say and ilbmtopnm does; but in HAM6, put value
7963 				 * into lower & upper bits like GrafX2 and unlike
7964 				 * ilbmtopnm: those old Amigas did not HAVE any
7965 				 * color bits beyond the 4 */
7966 				dp[n] = ham == 4 ? v + (v << 4) :
7967 					(v << 2) + (dp[n] & 3);
7968 			}
7969 			break;
7970 		}
7971 		ls_progress(settings, y, 10);
7972 		if (++y >= h) break;
7973 		strl = buflen;
7974 	}
7975 	res = 1;
7976 
7977 	/* Finalize DEST or 21-bit */
7978 	if (blocks & HAVE_DEST) do_xlate(wbuf, settings->img[CHN_IMAGE], w * h * bpp);
7979 	/* Finalize mask */
7980 	if (mp < 0); // No mask
7981 	else if (is_filled(settings->img[lbm_mask], settings->img[lbm_mask][0], w * h))
7982 		deallocate_image(settings, CMASK_FOR(lbm_mask)); // Useless mask
7983 	else
7984 	{
7985 		memset(wbuf + 1, 255, 255); // Nonzero means fully opaque
7986 		wbuf[0] = 0;
7987 		do_xlate(wbuf, settings->img[lbm_mask], w * h);
7988 	}
7989 
7990 fail3:	if (!settings->silent) progress_end();
7991 fail2:	free(buf);
7992 fail:	fclose(fp);
7993 	return (res);
7994 }
7995 
save_lbm(char * file_name,ls_settings * settings)7996 static int save_lbm(char *file_name, ls_settings *settings)
7997 {
7998 	unsigned char *buf, *wb, *src, *dest;
7999 	FILE *fp;
8000 	f_long bstart, fend;
8001 	unsigned l;
8002 	int w = settings->width, h = settings->height, bpp = settings->bpp;
8003 	int pbm = settings->lbm_pbm && (bpp == 1), comp = !!settings->lbm_pack;
8004 	int i, j, np1, rl, plane, st, cnt, np = 0, mask = 0;
8005 
8006 	/* Count bitplanes */
8007 	if (!pbm)
8008 	{
8009 		mask = settings->img[lbm_mask] ? lbm_mask : 0;
8010 		if (bpp == 1) // Planes to hold indexed color
8011 		{
8012 			i = settings->colors - 1;
8013 			if (i > 15) np = 4 , i >>= 4;
8014 			if (i > 3) np += 2 , i >>= 2;
8015 			if (i > 1) np++ , i >>= 1;
8016 			np += i;
8017 		}
8018 		else np = settings->img[CHN_ALPHA] ? 32 : 24; // RGBA/RGB
8019 		if ((np == 32) && (mask == CHN_ALPHA)) mask = 0; // No need
8020 	}
8021 
8022 	/* Allocate buffer */
8023 	rl = pbm ? w + (w & 1) : ((w + 15) >> 4) * 2; // One plane
8024 	i = rl + (rl + 127) / 128; // Worst-case RLE expansion
8025 	if (!pbm) i *= np + !!mask; // Buffer all planes
8026 	i += comp * rl; // Uncompressed source
8027 	if (i < 8 + 768) i = 8 + 768; // For CMAP & header
8028 	buf = calloc(1, i); // Zeroing out is for header
8029 	if (!buf) return (-1);
8030 	wb = buf + comp * rl; // Compressed data go here
8031 
8032 	if (!(fp = fopen(file_name, "wb")))
8033 	{
8034 		free(buf);
8035 		return (-1);
8036 	}
8037 
8038 	/* Prepare header */
8039 	memcpy(buf, "FORM\0\0\0\0", 8);
8040 	memcpy(buf + 8, pbm ? "PBM " : "ILBM", 4);
8041 	memcpy(buf + 12, "BMHD", 4);
8042 	PUT32B(buf + 16, BMHD_SIZE);
8043 	PUT16B(buf + 20 + BMHD_W, w);
8044 	PUT16B(buf + 20 + BMHD_H, h);
8045 	buf[20 + BMHD_BPP] = pbm ? 8 : np;
8046 	buf[20 + BMHD_MASK] = mask ? 1 : 0;
8047 	buf[20 + BMHD_COMP] = comp;
8048 	if (!mask && (settings->xpm_trans >= 0))
8049 	{
8050 		buf[20 + BMHD_MASK] = 2;
8051 		PUT16B(buf + 20 + BMHD_TRAN, settings->xpm_trans);
8052 	}
8053 	buf[20 + BMHD_ASPX] = buf[20 + BMHD_ASPY] = 1;
8054 	/* Leave page size unset */
8055 //	PUT16B(buf + 20 + BMHD_W, w);
8056 //	PUT16B(buf + 20 + BMHD_H, h);
8057 	fwrite(buf, 1, 20 + BMHD_SIZE, fp);
8058 
8059 	/* Palette (none for RGB/RGBA, to avoid confusing readers) */
8060 	if (bpp == 1)
8061 	{
8062 		memcpy(buf, "CMAP", 4);
8063 		i = settings->colors * 3;
8064 		i += i & 1; // Align the size itself, as in every example observed
8065 		PUT32B(buf + 4, i);
8066 		pal2rgb(buf + 8, settings->pal, settings->colors, 256);
8067 		fwrite(buf, 1, 8 + i, fp);
8068 	}
8069 
8070 	/* Anchor point */
8071 	if ((settings->hot_x >= 0) && (settings->hot_y >= 0))
8072 	{
8073 		memcpy(buf, "GRAB", 4);
8074 		PUT32B(buf + 4, 4);
8075 		PUT16B(buf + 8, settings->hot_x);
8076 		PUT16B(buf + 10, settings->hot_y);
8077 		fwrite(buf, 1, 8 + 4, fp);
8078 	}
8079 
8080 	/* Compress & write pixel rows */
8081 	if (!settings->silent) ls_init("LBM", 1);
8082 	fwrite("BODY\0\0\0\0", 1, 8, fp);
8083 	bstart = ftell(fp);
8084 	np1 = np + (pbm || mask); // Total planes
8085 	for (i = 0; i < h; i++)
8086 	{
8087 		src = settings->img[CHN_IMAGE] + w * bpp * i;
8088 		dest = wb;
8089 		for (plane = 0; plane < np1; plane++)
8090 		{
8091 			unsigned char v, *d, *s = src + (plane >> 3);
8092 			int n = plane & 7, step = bpp;
8093 
8094 			d = comp ? buf : dest;
8095 			if (pbm)
8096 			{
8097 				/* Copy indexed row */
8098 				memcpy(d, src, w);
8099 				d += w;
8100 			}
8101 			else
8102 			{
8103 				/* Extract a bitplane */
8104 				if (plane >= 24) // Alpha
8105 					s = settings->img[CHN_ALPHA] + w * i , step = 1;
8106 				if (plane == np) // Mask - threshold at 128
8107 					s = settings->img[mask] + w * i , step = 1 , n = 7;
8108 				for (j = v = 0; j < w; j++ , s += step)
8109 				{
8110 					v |= ((*s >> n) & 1) << (~j & 7);
8111 					if (~j & 7) continue;
8112 					*d++ = v;
8113 					v = 0;
8114 				}
8115 				if (w & 7) *d++ = v;
8116 			}
8117 			if ((d - buf) & 1) *d++ = 0; // Align
8118 
8119 			if (!comp)
8120 			{
8121 				dest = d;
8122 				continue;
8123 			}
8124 
8125 			/* Compress a bitplane */
8126 #define FILL 1
8127 #define EMIT 2
8128 #define STOP 4
8129 #define NFIL 8
8130 			s = buf;
8131 			st = cnt = 0;
8132 			while (TRUE)
8133 			{
8134 				if (d - s <= 0) st |= EMIT + STOP;
8135 				else if (cnt == 128) st |= EMIT;
8136 				else if (st & FILL)
8137 				{
8138 					if (s[0] != *(s - 1)) st = EMIT + FILL;
8139 				}
8140 				else if ((d - s > 1) && (s[0] == s[1]))
8141 				{
8142 				/* Code pairs as repeats only when NOT following
8143 				 * a copy block; code triples as repeats always */
8144 					if (!cnt || ((d - s > 2) && (s[0] == s[2])))
8145 						st = EMIT + NFIL;
8146 				}
8147 				if (!(st & EMIT))
8148 				{
8149 					s++ , cnt++;
8150 					continue;
8151 				}
8152 				if (st & FILL)
8153 				{
8154 					*dest++ = 257 - cnt;
8155 					*dest++ = *(s - 1);
8156 				}
8157 				else if (cnt)
8158 				{
8159 					*dest++ = cnt - 1;
8160 					memcpy(dest, s - cnt, cnt);
8161 					dest += cnt;
8162 				}
8163 				if (st & STOP) break;
8164 				if (st & NFIL)
8165 				{
8166 					s += cnt = 2;
8167 					st = FILL;
8168 				}
8169 				else st = cnt = 0;
8170 			}
8171 #undef FILL
8172 #undef EMIT
8173 #undef STOP
8174 #undef NFIL
8175 		}
8176 		fwrite(wb, 1, dest - wb, fp);
8177 		ls_progress(settings, i, 20);
8178 	}
8179 
8180 	/* Align last block & write sizes */
8181 	fend = ftell(fp);
8182 	l = fend - bstart;
8183 	if (l & 1) fwrite("", 1, 1, fp); // Padding
8184 	PUT32B(buf, l);
8185 	fseek(fp, bstart - 4, SEEK_SET);
8186 	fwrite(buf, 1, 4, fp);
8187 	l = fend - 8;
8188 	l += l & 1; // Aligned
8189 	PUT32B(buf, l);
8190 	fseek(fp, 4, SEEK_SET);
8191 	fwrite(buf, 1, 4, fp);
8192 	fclose(fp);
8193 
8194 	if (!settings->silent) progress_end();
8195 
8196 	free(buf);
8197 	return (0);
8198 }
8199 
8200 typedef void (*cvt_func)(unsigned char *dest, unsigned char *src, int len,
8201 	int bpp, int step, int maxval);
8202 
convert_16b(unsigned char * dest,unsigned char * src,int len,int bpp,int step,int maxval)8203 static void convert_16b(unsigned char *dest, unsigned char *src, int len,
8204 	int bpp, int step, int maxval)
8205 {
8206 	int i, v, m = maxval * 2;
8207 
8208 	if (!(step -= bpp)) bpp *= len , len = 1;
8209 	step *= 2;
8210 	while (len-- > 0)
8211 	{
8212 		i = bpp;
8213 		while (i--)
8214 		{
8215 			v = (src[0] << 8) + src[1];
8216 			src += 2;
8217 			*dest++ = (v * (255 * 2) + maxval) / m;
8218 		}
8219 		src += step;
8220 	}
8221 }
8222 
copy_bytes(unsigned char * dest,unsigned char * src,int len,int bpp,int step)8223 static void copy_bytes(unsigned char *dest, unsigned char *src, int len,
8224 	int bpp, int step)
8225 {
8226 	int i, dd = 0;
8227 
8228 	if (!(step -= bpp)) bpp *= len , len = 1;
8229 	else if (step < 0) bpp -= dd = -step , step = 0;
8230 	while (len-- > 0)
8231 	{
8232 		i = bpp;
8233 		while (i--) *dest++ = *src++;
8234 		src += step; dest += dd;
8235 	}
8236 }
8237 
check_next_pnm(FILE * fp,char id)8238 static int check_next_pnm(FILE *fp, char id)
8239 {
8240 	char buf[2];
8241 
8242 	if (fread(buf, 2, 1, fp))
8243 	{
8244 		fseek(fp, -2, SEEK_CUR);
8245 		if ((buf[0] == 'P') && (buf[1] == id)) return (FILE_HAS_FRAMES);
8246 	}
8247 	return (1);
8248 }
8249 
8250 /* Parse PAM header */
pam_behead(memFILE * mf,int whdm[4])8251 static char *pam_behead(memFILE *mf, int whdm[4])
8252 {
8253 	char wbuf[2048];
8254 	char *t1, *t2, *tail, *res = NULL;
8255 	int i, n, l, flag = 0;
8256 
8257 	/* Read header, check for basic PAM */
8258 	if (!mfgets(wbuf, sizeof(wbuf), mf) || strncmp(wbuf, "P7", 2))
8259 		return (NULL);
8260 	while (TRUE)
8261 	{
8262 		if (!mfgets(wbuf, sizeof(wbuf), mf)) break;
8263 		if (!wbuf[0] || (wbuf[0] == '#')) continue; // Empty line or comment
8264 		t1 = wbuf + strspn(wbuf, WHITESPACE);
8265 		l = strcspn(t1, WHITESPACE);
8266 		t2 = t1 + l + strspn(t1 + l, WHITESPACE);
8267 		t1[l] = '\0';
8268 		if (!strcmp(t1, "ENDHDR"))
8269 		{
8270 			if (flag < 0x0F) break; // Incomplete header
8271 			return (res ? res : strdup("")); // TUPLTYPE is optional
8272 		}
8273 		if (!*t2) break; // There must be something but whitespace
8274 		tail = t2 + strcspn(t2, WHITESPACE);
8275 		if (!strcmp(t1, "TUPLTYPE"))
8276 		{
8277 			if (res) continue; // Only first value matters
8278 			while (TRUE)
8279 			{
8280 				t1 = tail + strspn(tail, WHITESPACE);
8281 				if (!*t1) break;
8282 				tail = t1 + strcspn(t1, WHITESPACE);
8283 			}
8284 			// Preserve value for caller
8285 			*tail = '\0';
8286 			res = strdup(t2);
8287 			continue;
8288 		}
8289 		// Other fields are numeric
8290 		*tail = '\0';
8291 		i = strtol(t2, &tail, 10);
8292 		if (*tail) break;
8293 		if (i < 1) break; // Must be at least 1
8294 
8295 		if (!strcmp(t1, "WIDTH")) n = 0;
8296 		else if (!strcmp(t1, "HEIGHT")) n = 1;
8297 		else if (!strcmp(t1, "DEPTH")) n = 2;
8298 		else if (!strcmp(t1, "MAXVAL")) n = 3;
8299 		else break; // Unknown IDs not allowed
8300 
8301 		whdm[n] = i;
8302 		n = 1 << n;
8303 		if (flag & n) break; // No duplicate entries
8304 		flag |= n;
8305 	}
8306 	free(res);
8307 	return (NULL);
8308 }
8309 
8310 /* PAM loader does not support nonstandard types "GRAYSCALEFP" and "RGBFP",
8311  * because handling format variations which aren't found in the wild
8312  * is a waste of code - WJ */
8313 
load_pam_frame(FILE * fp,ls_settings * settings)8314 static int load_pam_frame(FILE *fp, ls_settings *settings)
8315 {
8316 	static const char *typenames[] = {
8317 		"BLACKANDWHITE", "BLACKANDWHITE_ALPHA",
8318 		"GRAYSCALE", "GRAYSCALE_ALPHA",
8319 		"RGB", "RGB_ALPHA",
8320 		"CMYK", "CMYK_ALPHA", NULL };
8321 	static const char depths[] = { 1, 2, 1, 2, 3, 4, 4, 5 };
8322 	memFILE fake_mf;
8323 	cvt_func cvt_stream;
8324 	char *t1;
8325 	unsigned char *dest, *buf = NULL;
8326 	int maxval, w, h, depth, ftype = -1;
8327 	int i, j, ll, bpp, trans, vl, res, whdm[4];
8328 
8329 
8330 	/* Read header */
8331 	memset(&fake_mf, 0, sizeof(fake_mf));
8332 	fake_mf.file = fp;
8333 	if (!(t1 = pam_behead(&fake_mf, whdm))) return (-1);
8334 	/* Compare TUPLTYPE to list of known ones */
8335 	if (*t1) for (i = 0; typenames[i]; i++)
8336 	{
8337 		if (strcmp(t1, typenames[i])) continue;
8338 		ftype = i;
8339 		break;
8340 	}
8341 	free(t1); // No use anymore
8342 	w = whdm[0]; h = whdm[1]; depth = whdm[2]; maxval = whdm[3];
8343 	/* Interpret unknown content as RGB or grayscale */
8344 	if (ftype < 0) ftype = depth >= 3 ? 4 : 2;
8345 
8346 	/* Validate */
8347 	if ((depth < depths[ftype]) || (depth > 16) || (maxval > 65535))
8348 		return (-1);
8349 	bpp = ftype < 4 ? 1 : 3;
8350 	trans = ftype & 1;
8351 	vl = maxval < 256 ? 1 : 2;
8352 	ll = w * depth * vl;
8353 	/* !!! ImageMagick writes BLACKANDWHITE as GRAYSCALE */
8354 	if ((ftype < 2) && (maxval > 1)) ftype += 2;
8355 	if (ftype < 2) set_bw(settings); // BW
8356 	else if (bpp == 1) set_gray(settings); // Grayscale
8357 
8358 	/* Allocate row buffer if cannot read directly into image */
8359 	if (trans || (vl > 1) || (bpp != depth))
8360 	{
8361 		buf = malloc(ll);
8362 		if (!buf) return (FILE_MEM_ERROR);
8363 	}
8364 
8365 	/* Allocate image */
8366 	settings->width = w;
8367 	settings->height = h;
8368 	settings->bpp = bpp;
8369 	res = allocate_image(settings, trans ? CMASK_RGBA : CMASK_IMAGE);
8370 	if (res) goto fail;
8371 
8372 	/* Read the image */
8373 	if (!settings->silent) ls_init("PAM", 0);
8374 	res = FILE_LIB_ERROR;
8375 	cvt_stream = vl > 1 ? convert_16b : (cvt_func)copy_bytes;
8376 	for (i = 0; i < h; i++)
8377 	{
8378 		dest = buf ? buf : settings->img[CHN_IMAGE] + ll * i;
8379 		j = fread(dest, 1, ll, fp);
8380 		if (j < ll) goto fail2;
8381 		ls_progress(settings, i, 10);
8382 
8383 		if (!buf) continue; // Nothing else to do here
8384 		if (settings->img[CHN_ALPHA]) // Have alpha - parse it
8385 		{
8386 			cvt_stream(settings->img[CHN_ALPHA] + w * i,
8387 				buf + depths[ftype] * vl - vl, w, 1, depth, maxval);
8388 		}
8389 		dest = settings->img[CHN_IMAGE] + w * bpp * i;
8390 		if (ftype >= 6) // CMYK
8391 		{
8392 			cvt_stream(buf, buf, w, 4, depth, maxval);
8393 			if (maxval < 255) extend_bytes(buf, w * 4, maxval);
8394 			cmyk2rgb(dest, buf, w, FALSE, settings);
8395 		}
8396 		else cvt_stream(dest, buf, w, bpp, depth, maxval);
8397 	}
8398 
8399 	/* Check for next frame */
8400 	res = check_next_pnm(fp, '7');
8401 
8402 fail2:	if (maxval < 255) // Extend what we've read
8403 	{
8404 		j = w * h;
8405 		if (settings->img[CHN_ALPHA])
8406 			extend_bytes(settings->img[CHN_ALPHA], j, maxval);
8407 		j *= bpp;
8408 		dest = settings->img[CHN_IMAGE];
8409 		if (ftype >= 6); // CMYK is done already
8410 		else if (ftype > 1) extend_bytes(dest, j, maxval);
8411 		else // Convert BW from 1-is-white to 1-is-black
8412 		{
8413 			for (i = 0; i < j; i++ , dest++) *dest = !*dest;
8414 		}
8415 	}
8416 	if (!settings->silent) progress_end();
8417 
8418 fail:	free(buf);
8419 	return (res);
8420 }
8421 
8422 #define PNM_BUFSIZE 4096
8423 typedef struct {
8424 	FILE *f;
8425 	int ptr, end, eof, comment;
8426 	char buf[PNM_BUFSIZE + 2];
8427 } pnmbuf;
8428 
8429 /* What PBM documentation says is NOT what Netpbm actually does; skipping a
8430  * comment in file header, it does not consume the newline after it - WJ */
pnm_skip_comment(pnmbuf * pnm)8431 static void pnm_skip_comment(pnmbuf *pnm)
8432 {
8433 	pnm->comment = !pnm->buf[pnm->ptr += strcspn(pnm->buf + pnm->ptr, "\r\n")];
8434 }
8435 
pnm_gets(pnmbuf * pnm,int data)8436 static char *pnm_gets(pnmbuf *pnm, int data)
8437 {
8438 	int k, l;
8439 
8440 	while (TRUE)
8441 	{
8442 		while (pnm->ptr < pnm->end)
8443 		{
8444 			l = pnm->ptr + strspn(pnm->buf + pnm->ptr, WHITESPACE);
8445 			if (pnm->buf[l] == '#')
8446 			{
8447 				if (data) return (NULL);
8448 				pnm->ptr = l;
8449 				pnm_skip_comment(pnm);
8450 				continue;
8451 			}
8452 			k = l + strcspn(pnm->buf + l, WHITESPACE "#");
8453 			if (pnm->buf[k] || pnm->eof)
8454 			{
8455 				pnm->ptr = k + 1;
8456 				if (pnm->buf[k] == '#')
8457 				{
8458 					if (data) return (NULL);
8459 					pnm_skip_comment(pnm);
8460 				}
8461 				pnm->buf[k] = '\0';
8462 				return (pnm->buf + l);
8463 			}
8464 			memmove(pnm->buf, pnm->buf + l, pnm->end -= l);
8465 			pnm->ptr = 0;
8466 			break;
8467 		}
8468 		if (pnm->eof) return (NULL);
8469 		if (pnm->ptr >= pnm->end) pnm->ptr = pnm->end = 0;
8470 		l = PNM_BUFSIZE - pnm->end;
8471 		if (l <= 0) return (NULL); // A "token" of 4096 chars means failure
8472 		pnm->end += k = fread(pnm->buf + pnm->end, 1, l, pnm->f);
8473 		pnm->eof = k < l;
8474 		if (pnm->comment) pnm_skip_comment(pnm);
8475 	}
8476 }
8477 
pnm_endhdr(pnmbuf * pnm,int plain)8478 static int pnm_endhdr(pnmbuf *pnm, int plain)
8479 {
8480 	while (pnm->comment)
8481 	{
8482 		pnm_skip_comment(pnm);
8483 		if (!pnm->comment) break;
8484 		if (pnm->eof) return (FALSE);
8485 		pnm->end = fread(pnm->buf, 1, PNM_BUFSIZE, pnm->f);
8486 		pnm->eof = pnm->end < PNM_BUFSIZE;
8487 	}
8488 	/* Last whitespace in header already got consumed while parsing */
8489 
8490 	/* Buffer will remain in use in plain mode */
8491 	if (!plain && (pnm->ptr < pnm->end))
8492 		fseek(pnm->f, pnm->ptr - pnm->end, SEEK_CUR);
8493 	return (TRUE);
8494 }
8495 
load_pnm_frame(FILE * fp,ls_settings * settings)8496 static int load_pnm_frame(FILE *fp, ls_settings *settings)
8497 {
8498 	pnmbuf pnm;
8499 	char *s, *tail;
8500 	unsigned char *dest;
8501 	int i, l, m, w, h, bpp, maxval, plain, mode, fid, res;
8502 
8503 
8504 	/* Identify*/
8505 	memset(&pnm, 0, sizeof(pnm));
8506 	pnm.f = fp;
8507 	fid = settings->ftype == FT_PBM ? 0 : settings->ftype == FT_PGM ? 1 : 2;
8508 	if (!(s = pnm_gets(&pnm, FALSE))) return (-1);
8509 	if ((s[0] != 'P') || ((s[1] != fid + '1') && (s[1] != fid + '4')))
8510 		 return (-1);
8511 	plain = s[1] < '4';
8512 
8513 	/* Read header */
8514 	if (!(s = pnm_gets(&pnm, FALSE))) return (-1);
8515 	w = strtol(s, &tail, 10);
8516 	if (*tail) return (-1);
8517 	if (!(s = pnm_gets(&pnm, FALSE))) return (-1);
8518 	h = strtol(s, &tail, 10);
8519 	if (*tail) return (-1);
8520 	bpp = maxval = 1;
8521 	if (settings->ftype == FT_PBM) set_bw(settings);
8522 	else
8523 	{
8524 		if (!(s = pnm_gets(&pnm, FALSE))) return (-1);
8525 		maxval = strtol(s, &tail, 10);
8526 		if (*tail) return (-1);
8527 		if ((maxval <= 0) || (maxval > 65535)) return (-1);
8528 		if (settings->ftype == FT_PGM) set_gray(settings);
8529 		else bpp = 3;
8530 	}
8531 	if (!pnm_endhdr(&pnm, plain)) return (-1);
8532 
8533 	/* Store values */
8534 	settings->width = w;
8535 	settings->height = h;
8536 	settings->bpp = bpp;
8537 
8538 	/* Allocate image */
8539 	if ((res = allocate_image(settings, CMASK_IMAGE))) return (res);
8540 
8541 	/* Now, read the image */
8542 	mode = settings->ftype == FT_PBM ? plain /* 0 and 1 */ :
8543 		plain ? 2 : maxval < 255 ? 3 : maxval > 255 ? 4 : 5;
8544 	s = "";
8545 	if (!settings->silent) ls_init("PNM", 0);
8546 	res = FILE_LIB_ERROR;
8547 	l = w * bpp;
8548 	m = maxval * 2;
8549 	for (i = 0; i < h; i++)
8550 	{
8551 		dest = settings->img[CHN_IMAGE] + l * i;
8552 		switch (mode)
8553 		{
8554 		case 0: /* Raw packed bits */
8555 		{
8556 #if PNM_BUFSIZE * 8 < MAX_WIDTH
8557 #error "Buffer too small to read PBM row all at once"
8558 #endif
8559 			int i, j, k;
8560 			unsigned char *tp = pnm.buf;
8561 
8562 			k = (w + 7) >> 3;
8563 			j = fread(tp, 1, k, fp);
8564 			for (i = 0; i < w; i++)
8565 				*dest++ = (tp[i >> 3] >> (~i & 7)) & 1;
8566 			if (j < k) goto fail2;
8567 			break;
8568 		}
8569 		case 3: /* Raw byte values - extend later */
8570 		case 5: /* Raw 0..255 values - trivial */
8571 			if (fread(dest, 1, l, fp) < l) goto fail2;
8572 			break;
8573 		case 1: /* Chars "0" and "1" */
8574 		{
8575 			int i;
8576 			unsigned char ch;
8577 
8578 			for (i = 0; i < l; i++)
8579 			{
8580 				if (!s[0] && !(s = pnm_gets(&pnm, TRUE)))
8581 					goto fail2;
8582 				ch = *s++ - '0';
8583 				if (ch > 1) goto fail2;
8584 				*dest++ = ch;
8585 			}
8586 			break;
8587 		}
8588 		case 2: /* Integers in ASCII */
8589 		{
8590 			int i, n;
8591 
8592 			for (i = 0; i < l; i++)
8593 			{
8594 				if (!(s = pnm_gets(&pnm, TRUE))) goto fail2;
8595 				n = strtol(s, &tail, 10);
8596 				if (*tail) goto fail2;
8597 				if ((n < 0) || (n > maxval)) goto fail2;
8598 				n = (n * (255 * 2) + maxval) / m;
8599 				*dest++ = n;
8600 			}
8601 			break;
8602 		}
8603 		case 4: /* Raw ushorts in MSB order */
8604 		{
8605 			int i, j, k, ll;
8606 
8607 			for (ll = l * 2; ll > 0; ll -= k)
8608 			{
8609 				k = PNM_BUFSIZE < ll ? PNM_BUFSIZE : ll;
8610 				j = fread(pnm.buf, 1, k, fp);
8611 				i = j >> 1;
8612 				convert_16b(dest, pnm.buf, i, 1, 1, maxval);
8613 				dest += i;
8614 				if (j < k) goto fail2;
8615 			}
8616 			break;
8617 		}
8618 		}
8619 		ls_progress(settings, i, 10);
8620 	}
8621 	res = 1;
8622 
8623 	/* Check for next frame */
8624 	if (!plain) res = check_next_pnm(fp, fid + '4');
8625 
8626 fail2:	if (mode == 3) // Extend what we've read
8627 		extend_bytes(settings->img[CHN_IMAGE], l * h, maxval);
8628 	if (!settings->silent) progress_end();
8629 
8630 	return (res);
8631 }
8632 
load_pnm_frames(char * file_name,ani_settings * ani)8633 static int load_pnm_frames(char *file_name, ani_settings *ani)
8634 {
8635 	FILE *fp;
8636 	ls_settings w_set;
8637 	int res, is_pam = ani->settings.ftype == FT_PAM, next = TRUE;
8638 
8639 
8640 	if (!(fp = fopen(file_name, "rb"))) return (-1);
8641 	while (next)
8642 	{
8643 		res = FILE_TOO_LONG;
8644 		if (!check_next_frame(&ani->fset, ani->settings.mode, FALSE))
8645 			goto fail;
8646 		w_set = ani->settings;
8647 		w_set.gif_delay = -1; // Multipage
8648 		res = (is_pam ? load_pam_frame : load_pnm_frame)(fp, &w_set);
8649 		next = res == FILE_HAS_FRAMES;
8650 		if ((res != 1) && !next) goto fail;
8651 		res = process_page_frame(file_name, ani, &w_set);
8652 		if (res) goto fail;
8653 	}
8654 	res = 1;
8655 fail:	fclose(fp);
8656 	return (res);
8657 }
8658 
load_pnm(char * file_name,ls_settings * settings)8659 static int load_pnm(char *file_name, ls_settings *settings)
8660 {
8661 	FILE *fp;
8662 	int res;
8663 
8664 	if (!(fp = fopen(file_name, "rb"))) return (-1);
8665 	res = (settings->ftype == FT_PAM ? load_pam_frame :
8666 		load_pnm_frame)(fp, settings);
8667 	fclose(fp);
8668 	return (res);
8669 }
8670 
save_pbm(char * file_name,ls_settings * settings)8671 static int save_pbm(char *file_name, ls_settings *settings)
8672 {
8673 	unsigned char buf[MAX_WIDTH / 8], bw, *src;
8674 	FILE *fp;
8675 	int i, l, w = settings->width, h = settings->height;
8676 
8677 
8678 	if ((settings->bpp != 1) || (settings->colors > 2)) return WRONG_FORMAT;
8679 
8680 	if (!(fp = fopen(file_name, "wb"))) return (-1);
8681 
8682 	if (!settings->silent) ls_init("PBM", 1);
8683 	fprintf(fp, "P4\n%d %d\n", w, h);
8684 
8685 	bw = get_bw(settings);
8686 
8687 	/* Write rows */
8688 	src = settings->img[CHN_IMAGE];
8689 	l = (w + 7) >> 3;
8690 	for (i = 0; i < h; i++)
8691 	{
8692 		pack_MSB(buf, src, w, bw);
8693 		src += w;
8694 		fwrite(buf, l, 1, fp);
8695 		ls_progress(settings, i, 20);
8696 	}
8697 	fclose(fp);
8698 
8699 	if (!settings->silent) progress_end();
8700 
8701 	return (0);
8702 }
8703 
save_ppm(char * file_name,ls_settings * settings)8704 static int save_ppm(char *file_name, ls_settings *settings)
8705 {
8706 	FILE *fp;
8707 	int i, l, m, w = settings->width, h = settings->height;
8708 
8709 
8710 	if (settings->bpp != 3) return WRONG_FORMAT;
8711 
8712 	if (!(fp = fopen(file_name, "wb"))) return (-1);
8713 
8714 	if (!settings->silent) ls_init("PPM", 1);
8715 	fprintf(fp, "P6\n%d %d\n255\n", w, h);
8716 
8717 	/* Write rows */
8718 	m = (l = w * 3) * h;
8719 	// Write entire file at once if no progressbar
8720 	if (settings->silent) l = m;
8721 	for (i = 0; m > 0; m -= l , i++)
8722 	{
8723 		fwrite(settings->img[CHN_IMAGE] + l * i, l, 1, fp);
8724 		ls_progress(settings, i, 20);
8725 	}
8726 	fclose(fp);
8727 
8728 	if (!settings->silent) progress_end();
8729 
8730 	return (0);
8731 }
8732 
save_pam(char * file_name,ls_settings * settings)8733 static int save_pam(char *file_name, ls_settings *settings)
8734 {
8735 	unsigned char xv, xa, *dest, *src, *srca, *buf = NULL;
8736 	FILE *fp;
8737 	int ibpp = settings->bpp, w = settings->width, h = settings->height;
8738 	int i, j, bpp;
8739 
8740 
8741 	if ((ibpp != 3) && (settings->colors > 2)) return WRONG_FORMAT;
8742 
8743 	bpp = ibpp + !!settings->img[CHN_ALPHA];
8744 	/* For BW: image XOR 1 if white is 0, alpha AND 1 */
8745 	xv = 0; xa = 255;
8746 	if (ibpp == 1) xv = get_bw(settings) , xa = 1;
8747 	if (bpp != 3) // BW needs inversion, and alpha, interlacing
8748 	{
8749 		buf = malloc(w * bpp);
8750 		if (!buf) return (-1);
8751 	}
8752 
8753 	if (!(fp = fopen(file_name, "wb")))
8754 	{
8755 		free(buf);
8756 		return (-1);
8757 	}
8758 
8759 	if (!settings->silent) ls_init("PAM", 1);
8760 	fprintf(fp, "P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\n"
8761 		"TUPLTYPE %s%s\nENDHDR\n", w, h, bpp, ibpp == 1 ? 1 : 255,
8762 		ibpp == 1 ? "BLACKANDWHITE" : "RGB", bpp > ibpp ? "_ALPHA" : "");
8763 
8764 	for (i = 0; i < h; i++)
8765 	{
8766 		src = settings->img[CHN_IMAGE] + i * w * ibpp;
8767 		if ((dest = buf))
8768 		{
8769 			srca = NULL;
8770 			if (settings->img[CHN_ALPHA])
8771 				srca = settings->img[CHN_ALPHA] + i * w;
8772 			for (j = 0; j < w; j++)
8773 			{
8774 				*dest++ = *src++ ^ xv;
8775 				if (ibpp > 1)
8776 				{
8777 					*dest++ = *src++;
8778 					*dest++ = *src++;
8779 				}
8780 				if (srca) *dest++ = *srca++ & xa;
8781 			}
8782 			src = buf;
8783 		}
8784 		fwrite(src, 1, w * bpp, fp);
8785 		ls_progress(settings, i, 20);
8786 	}
8787 	fclose(fp);
8788 
8789 	if (!settings->silent) progress_end();
8790 	free(buf);
8791 
8792 	return (0);
8793 }
8794 
8795 /* *** PREFACE ***
8796  * PMM is mtPaint's own format, extending the PAM format in a compatible way;
8797  * PAM tools from Netpbm can easily split a PMM file into regular PAM files, or
8798  * build it back from these. Some extra values are stored inside the "TUPLTYPE"
8799  * fields, because Netpbm tools do NOT preserve comments but don't much care
8800  * about TUPLTYPE. Other things, like palette, are stored as separate
8801  * pseudo-images preceding the bitmap, with their own TUPLTYPE and extra values.
8802  * When building a PMM file out of PAMs by hand, just write out the PMM_ID1
8803  * string, below, before the first PAM file - WJ */
8804 
8805 # define PMM_ID1 "P7\n#MTPAINT#"
8806 
8807 typedef struct {
8808 	char *next; // the rest of string
8809 	char *tag; // last found tag
8810 	int val; // its value if any
8811 } tagline;
8812 
8813 /* Parse a tag out of string */
nexttag(tagline * iter,int split_under)8814 static int nexttag(tagline *iter, int split_under)
8815 {
8816 	char *s, *tail, *str = iter->next;
8817 	int l, n, res = 1;
8818 
8819 	iter->tag = str;
8820 	if (!str || !*str) return (0); // Empty
8821 	l = strcspn(str, "_=" WHITESPACE + !split_under);
8822 	if (!l) return (0); // No tag here - format violation
8823 	s = str + l;
8824 	if (*s == '=') /* NAME=VALUE */
8825 	{
8826 		n = strtol(++s, &tail, 10);
8827 		if ((tail == s) || (*tail && !strchr(WHITESPACE, *tail)))
8828 			return (0); // Unparsable or no value - format violation
8829 		iter->val = n;
8830 		s = tail;
8831 		res = 2; // Have value
8832 	}
8833 	else s += (*s == '_'); /* NAME_ */
8834 
8835 	iter->next = s + strspn(s, WHITESPACE);
8836 	str[l] = '\0';
8837 
8838 	return (res); // Parsed another tag
8839 }
8840 
8841 /* Interpret known value tags, ignore unknown ones */
readtags(tagline * tl,ls_settings * settings,int bpp)8842 static void readtags(tagline *tl, ls_settings *settings, int bpp)
8843 {
8844 	static const char *tags[] = { "TRANS", "DELAY", "X", "Y", NULL };
8845 	int j, i = 2;
8846 
8847 	// Skip channel tags if no extra channels
8848 	if (!bpp) while ((i = nexttag(tl, FALSE)) == 1);
8849 
8850 	while (i == 2)
8851 	{
8852 		for (j = 0; tags[j] && strcmp(tl->tag, tags[j]); j++);
8853 		i = tl->val;
8854 
8855 		switch (j)
8856 		{
8857 		case 0: // Transparent color
8858 			/* Invalid value - ignore */
8859 			if (i < -1) break;
8860 			/* No transparency - disable */
8861 			if (i == -1) settings->xpm_trans =
8862 				settings->rgb_trans = -1;
8863 			/* Indexed transparency */
8864 			else if (bpp < 3)
8865 			{
8866 				if (i < settings->colors) settings->xpm_trans = i;
8867 			}
8868 			/* RGB transparency */
8869 			else if (i <= 0xFFFFFF)
8870 			{
8871 				int j = settings->xpm_trans;
8872 				png_color *p = settings->pal + j;
8873 				// Only if differs from indexed
8874 				if ((j < 0) || (PNG_2_INT(*p) != i))
8875 					settings->rgb_trans = i;
8876 			}
8877 			break;
8878 		case 1: // Anim delay, in 0.01 sec
8879 			if (i >= 0) settings->gif_delay = i;
8880 			break;
8881 		case 2: // X offset
8882 			settings->x = i;
8883 			break;
8884 		case 3: // Y offset
8885 			settings->y = i;
8886 			break;
8887 		// !!! No other parameters yet
8888 		}
8889 		i = nexttag(tl, FALSE);
8890 	}
8891 }
8892 
load_pmm_frame(memFILE * mf,ls_settings * settings)8893 static int load_pmm_frame(memFILE *mf, ls_settings *settings)
8894 {
8895 	/* !!! INDEXED is at index 1, RGB at index 3 to use index as BPP */
8896 	static const char *blocks[] = { "TAGS", "INDEXED", "PALETTE", "RGB", NULL };
8897 	tagline tl;
8898 	unsigned char *dest, *buf = NULL;
8899 	char *ttype = NULL;
8900 	int w, h, depth, rgbpp, cmask = CMASK_IMAGE;
8901 	int i, j, l, res, whdm[4], slots[NUM_CHANNELS];
8902 
8903 	while (TRUE)
8904 	{
8905 		res = -1;
8906 		free(ttype);
8907 		if (!(tl.next = ttype = pam_behead(mf, whdm))) break;
8908 		if (whdm[3] > 255) break; // 16-bit values not allowed
8909 		depth = whdm[2];
8910 		if (depth > 16) break; // Depth limited to sane values
8911 		w = whdm[0]; h = whdm[1];
8912 
8913 		/* Parse out type tag */
8914 		j = -1;
8915 		if (nexttag(&tl, TRUE) == 1)
8916 		{
8917 			for (j = 0; blocks[j] && strcmp(blocks[j], tl.tag); j++);
8918 			if (!blocks[j]) j = -1;
8919 		}
8920 
8921 		if (!j) readtags(&tl, settings, 0); /* TAGS */
8922 
8923 		if (j <= 0) /* !!! IGNORE anything unrecognized & skip "TAGS" */
8924 		{
8925 			mfseek(mf, w * h * depth, SEEK_CUR);
8926 			continue;
8927 		}
8928 
8929 		if (j == 2) /* PALETTE */
8930 		{
8931 			unsigned char pbuf[256 * 16], *tp = pbuf;
8932 
8933 			/* Validate */
8934 			if ((depth < 3) || (w < 2) || (w > 256) || (h != 1)) break;
8935 			settings->colors = w;
8936 			settings->xpm_trans = settings->rgb_trans = -1; // Default
8937 
8938 			/* Skip channel tags, interpret value tags */
8939 			readtags(&tl, settings, 0);
8940 
8941 			if (mfread(pbuf, depth, w, mf) != w) break; // Failed
8942 			/* Store palette */
8943 			extend_bytes(tp, w * depth, whdm[3]);
8944 			for (i = 0; i < w; i++)
8945 			{
8946 				settings->pal[i].red = tp[0];
8947 				settings->pal[i].green = tp[1];
8948 				settings->pal[i].blue = tp[2];
8949 				tp += depth;
8950 			}
8951 			/* If palette is all we need */
8952 			res = EXPLODE_FAILED;
8953 			if ((settings->mode == FS_PALETTE_LOAD) ||
8954 				(settings->mode == FS_PALETTE_DEF)) break;
8955 			continue;
8956 		}
8957 
8958 		/* Got an image bitmap */
8959 		// !!! Only slots 1 & 3 fall through to here
8960 		rgbpp = j;
8961 		/* Add up extra channels */
8962 		memset(slots, 0, sizeof(slots));
8963 		while ((i = nexttag(&tl, FALSE)) == 1)
8964 		{
8965 			if (!strcmp(tl.tag, "ALPHA")) i = CHN_ALPHA;
8966 			else if (!strcmp(tl.tag, "SELECTION")) i = CHN_SEL;
8967 			else if (!strcmp(tl.tag, "MASK")) i = CHN_MASK;
8968 			else // Unknown channel - skip
8969 			{
8970 				j++;
8971 				continue;
8972 			}
8973 			slots[i] = j++;
8974 			cmask |= CMASK_FOR(i);
8975 		}
8976 		if (j > depth) break; // Cannot be
8977 
8978 		/* Interpret value tags */
8979 		if (i == 2) readtags(&tl, settings, rgbpp);
8980 
8981 		l = w * depth;
8982 		/* Allocate row buffer if cannot read directly into image */
8983 		if (rgbpp != depth)
8984 		{
8985 			res = FILE_MEM_ERROR;
8986 			if (!(buf = malloc(l))) break;
8987 		}
8988 		/* Allocate image */
8989 		settings->width = w;
8990 		settings->height = h;
8991 		settings->bpp = rgbpp;
8992 		if ((res = allocate_image(settings, cmask))) break;
8993 
8994 		/* Read the image */
8995 		if (!settings->silent) ls_init("* PMM *", 0);
8996 		res = FILE_LIB_ERROR;
8997 		for (i = 0; i < h; i++)
8998 		{
8999 			dest = settings->img[CHN_IMAGE] + w * rgbpp * i;
9000 			if (!mfread(buf ? buf : dest, l, 1, mf)) goto fail;
9001 			ls_progress(settings, i, 10);
9002 			if (!buf) continue; // Nothing else to do here
9003 
9004 			copy_bytes(dest, buf, w, rgbpp, depth);
9005 			for (j = CHN_ALPHA; j < NUM_CHANNELS; j++)
9006 				if (settings->img[j]) copy_bytes(
9007 					settings->img[j] + w * i,
9008 					buf + slots[j], w, 1, depth);
9009 		}
9010 
9011 		/* Extend what we've read */
9012 		if (whdm[3] < 255)
9013 		{
9014 			i = w * h * rgbpp;
9015 			for (j = CHN_IMAGE; j < NUM_CHANNELS; j++)
9016 			{
9017 				if (settings->img[j]) extend_bytes(
9018 					settings->img[j], i, whdm[3]);
9019 				i = w * h;
9020 			}
9021 		}
9022 
9023 		/* Check for next frame */
9024 		res = 1;
9025 		if (mfread(ttype, 2, 1, mf)) // it was no shorter than "RGB"
9026 		{
9027 			mfseek(mf, -2, SEEK_CUR);
9028 			if (!strncmp(ttype, "P7", 2)) res = FILE_HAS_FRAMES;
9029 		}
9030 
9031 fail:		if (!settings->silent) progress_end();
9032 		break;
9033 	}
9034 	free(buf);
9035 	free(ttype);
9036 	return (res);
9037 }
9038 
load_pmm_frames(char * file_name,ani_settings * ani,memFILE * mf)9039 static int load_pmm_frames(char *file_name, ani_settings *ani, memFILE *mf)
9040 {
9041 	memFILE fake_mf;
9042 	FILE *fp = NULL;
9043 	ls_settings w_set, init_set;
9044 	int res, next;
9045 
9046 
9047 	if (!mf)
9048 	{
9049 		if (!(fp = fopen(file_name, "rb"))) return (-1);
9050 		memset(mf = &fake_mf, 0, sizeof(fake_mf));
9051 		fake_mf.file = fp;
9052 	}
9053 	init_set = ani->settings;
9054 	init_set.gif_delay = -1; // Multipage by default
9055 	while (TRUE)
9056 	{
9057 		w_set = init_set;
9058 		res = load_pmm_frame(mf, &w_set);
9059 		next = res == FILE_HAS_FRAMES;
9060 		if ((res != 1) && !next) break;
9061 		/* !!! RGB transparency may modify the palette */
9062 		map_rgb_trans(&w_set);
9063 		if ((res = process_page_frame(file_name, ani, &w_set))) break;
9064 		res = 1;
9065 		if (!next) break;
9066 		res = FILE_TOO_LONG;
9067 		if (!check_next_frame(&ani->fset, ani->settings.mode,
9068 			w_set.gif_delay >= 0)) break;
9069 		/* Update initial values */
9070 		init_set.colors = w_set.colors; // Palettes are inheritable
9071 		init_set.xpm_trans = w_set.xpm_trans;
9072 		init_set.rgb_trans = w_set.rgb_trans;
9073 		init_set.gif_delay = w_set.gif_delay;
9074 	}
9075 	fclose(fp);
9076 	return (res);
9077 }
9078 
load_pmm(char * file_name,ls_settings * settings,memFILE * mf)9079 static int load_pmm(char *file_name, ls_settings *settings, memFILE *mf)
9080 {
9081 	memFILE fake_mf;
9082 	FILE *fp = NULL;
9083 	int res;
9084 
9085 	if (!mf)
9086 	{
9087 		if (!(fp = fopen(file_name, "rb"))) return (-1);
9088 		memset(mf = &fake_mf, 0, sizeof(fake_mf));
9089 		fake_mf.file = fp;
9090 	}
9091 	res = load_pmm_frame(mf, settings);
9092 	if (fp) fclose(fp);
9093 	return (res);
9094 }
9095 
save_pmm(char * file_name,ls_settings * settings,memFILE * mf)9096 static int save_pmm(char *file_name, ls_settings *settings, memFILE *mf)
9097 {
9098 	unsigned char *dest, *src, *buf = NULL;
9099 	unsigned char sbuf[768];
9100 	memFILE fake_mf;
9101 	FILE *fp = NULL;
9102 	int rgbpp = settings->bpp, w = settings->width, h = settings->height;
9103 	int i, k, bpp;
9104 
9105 
9106 	for (i = bpp = 0; i < NUM_CHANNELS; i++) bpp += !!settings->img[i];
9107 	bpp += rgbpp - 1;
9108 	/* Allocate row buffer if needed */
9109 	if ((bpp != rgbpp) && (settings->mode != FS_PALETTE_SAVE))
9110 	{
9111 		buf = malloc(w * bpp);
9112 		if (!buf) return (-1);
9113 	}
9114 
9115 	if (!mf)
9116 	{
9117 		if (!(fp = fopen(file_name, "wb")))
9118 		{
9119 			free(buf);
9120 			return (-1);
9121 		}
9122 		memset(mf = &fake_mf, 0, sizeof(fake_mf));
9123 		fake_mf.file = fp;
9124 	}
9125 
9126 	if (!settings->silent) ls_init("* PMM *", 1);
9127 
9128 	/* First, write palette */
9129 	if (settings->pal)
9130 	{
9131 		mfputs(PMM_ID1 "\n", mf);
9132 		snprintf(sbuf, sizeof(sbuf), "WIDTH %d\n", settings->colors);
9133 		mfputs(sbuf, mf);
9134 		// Extra data for palette: transparent index if any
9135 		sbuf[0] = '\0';
9136 		if (settings->xpm_trans >= 0) snprintf(sbuf, sizeof(sbuf),
9137 			" TRANS=%d", settings->xpm_trans);
9138 		mfputss(mf, "HEIGHT 1\nDEPTH 3\nMAXVAL 255\nTUPLTYPE PALETTE",
9139 			sbuf, "\nENDHDR\n", NULL);
9140 		pal2rgb(sbuf, settings->pal, settings->colors, 0);
9141 		mfwrite(sbuf, 1, settings->colors * 3, mf);
9142 	}
9143 	/* All done if only writing palette */
9144 	if (settings->mode == FS_PALETTE_SAVE) goto done;
9145 
9146 	/* Now, write image bitmap */
9147 	mfputs(PMM_ID1 "\n", mf);
9148 	snprintf(sbuf, sizeof(sbuf), "WIDTH %d\nHEIGHT %d\nDEPTH %d\n",
9149 		w, h, bpp);
9150 	mfputss(mf, sbuf, "MAXVAL 255\nTUPLTYPE ",
9151 		rgbpp > 1 ? "RGB" : "INDEXED",
9152 		settings->img[CHN_ALPHA] ? "_ALPHA" : "",
9153 		settings->img[CHN_SEL] ? " SELECTION" : "",
9154 		settings->img[CHN_MASK] ? " MASK" : "",
9155 		"\nENDHDR\n", NULL);
9156 
9157 	for (i = 0; i < h; i++)
9158 	{
9159 		src = settings->img[CHN_IMAGE] + i * w * rgbpp;
9160 		if ((dest = buf))
9161 		{
9162 			copy_bytes(dest, src, w, bpp, rgbpp);
9163 			dest += rgbpp;
9164 			for (k = CHN_ALPHA; k < NUM_CHANNELS; k++)
9165 				if (settings->img[k]) copy_bytes(dest++,
9166 					settings->img[k] + i * w, w, bpp, 1);
9167 			src = buf;
9168 		}
9169 		mfwrite(src, 1, w * bpp, mf);
9170 		ls_progress(settings, i, 20);
9171 	}
9172 done:	if (fp) fclose(fp);
9173 
9174 	if (!settings->silent) progress_end();
9175 
9176 	free(buf);
9177 	return 0;
9178 }
9179 
9180 /* Put screenshots and X pixmaps on an equal footing with regular files */
9181 
9182 #ifdef HAVE_PIXMAPS
9183 
save_pixmap(ls_settings * settings,memFILE * mf)9184 static int save_pixmap(ls_settings *settings, memFILE *mf)
9185 {
9186 	pixmap_info p;
9187 	unsigned char *src, *dest, *sel, *buf = NULL;
9188 	int i, j, l, w = settings->width, h = settings->height;
9189 
9190 	/* !!! Pixmap export used only for FS_CLIPBOARD, where the case of
9191 	 * selection without alpha is already prevented */
9192 	if ((settings->bpp == 1) || settings->img[CHN_ALPHA])
9193 	{
9194 		buf = malloc(w * 3);
9195 		if (!buf) return (-1);
9196 	}
9197 
9198 	if (!export_pixmap(&p, w, h))
9199 	{
9200 		free(buf);
9201 		return (-1);
9202 	}
9203 
9204 	/* Plain RGB - copy it whole */
9205 	if (!buf) pixmap_put_rows(&p, settings->img[CHN_IMAGE], 0, h);
9206 
9207 	/* Something else - render & copy row by row */
9208 	else
9209 	{
9210 		l = w * settings->bpp;
9211 		for (i = 0; i < h; i++)
9212 		{
9213 			src = settings->img[CHN_IMAGE] + l * i;
9214 			if (settings->bpp == 3) memcpy(buf, src, l);
9215 			else do_convert_rgb(0, 1, w, buf, src, settings->pal);
9216 			/* There is no way to send alpha to XPaint, so I use
9217 			 * alpha (and selection if any) to blend image with
9218 			 * white and send the result - WJ */
9219 			if (settings->img[CHN_ALPHA])
9220 			{
9221 				src = settings->img[CHN_ALPHA] + w * i;
9222 				sel = settings->img[CHN_SEL] ?
9223 					settings->img[CHN_SEL] + w * i : NULL;
9224 				dest = buf;
9225 				for (j = 0; j < w; j++)
9226 				{
9227 					int ii, jj, k = *src++;
9228 
9229 					if (sel)
9230 					{
9231 						k *= *sel++;
9232 						k = (k + (k >> 8) + 1) >> 8;
9233 					}
9234 					for (ii = 0; ii < 3; ii++)
9235 					{
9236 						jj = 255 * 255 + (*dest - 255) * k;
9237 						*dest++ = (jj + (jj >> 8) + 1) >> 8;
9238 					}
9239 				}
9240 			}
9241 			pixmap_put_rows(&p, buf, i, 1);
9242 		}
9243 		free(buf);
9244 	}
9245 
9246 	*(XID_type *)mf->m.buf = p.xid;
9247 	mf->top = sizeof(XID_type);
9248 	return (0);
9249 }
9250 
9251 #else /* Pixmap export fails by definition in absence of X */
9252 #define save_pixmap(A,B) (-1)
9253 #endif
9254 
load_pixmap(ls_settings * settings,memFILE * mf)9255 static int load_pixmap(ls_settings *settings, memFILE *mf)
9256 {
9257 	pixmap_info p;
9258 	int res = -1;
9259 
9260 	if (import_pixmap(&p, mf ? (void *)mf->m.buf : NULL)) // !mf == screenshot
9261 	{
9262 		settings->width = p.w;
9263 		settings->height = p.h;
9264 		settings->bpp = 3;
9265 		res = allocate_image(settings, CMASK_IMAGE);
9266 		if (!res) res = pixmap_get_rows(&p,
9267 			settings->img[CHN_IMAGE], 0, p.h) ? 1 : -1;
9268 		drop_pixmap(&p);
9269 	}
9270 	return (res);
9271 }
9272 
9273 /* Handle SVG import using gdk-pixbuf */
9274 
9275 #if (GDK_PIXBUF_MAJOR > 2) || ((GDK_PIXBUF_MAJOR == 2) && (GDK_PIXBUF_MINOR >= 4))
9276 
9277 #define MAY_HANDLE_SVG
9278 
9279 static int svg_check = -1;
9280 
svg_supported()9281 static int svg_supported()
9282 {
9283 	GSList *tmp, *ff;
9284 	int i, res = FALSE;
9285 
9286 	ff = gdk_pixbuf_get_formats();
9287 	for (tmp = ff; tmp; tmp = tmp->next)
9288 	{
9289 		gchar **mime = gdk_pixbuf_format_get_mime_types(tmp->data);
9290 
9291 		for (i = 0; mime[i]; i++)
9292 		{
9293 			res |= strstr(mime[i], "image/svg") == mime[i];
9294 		}
9295 		g_strfreev(mime);
9296 		if (res) break;
9297 	}
9298 	g_slist_free(ff);
9299 	return (res);
9300 }
9301 
load_svg(char * file_name,ls_settings * settings)9302 static int load_svg(char *file_name, ls_settings *settings)
9303 {
9304 	GdkPixbuf *pbuf;
9305 	GError *err = NULL;
9306 	guchar *src;
9307 	unsigned char *dest, *dsta;
9308 	int i, j, w, h, bpp, cmask, skip, res = -1;
9309 
9310 
9311 #if (GDK_PIXBUF_MAJOR == 2) && (GDK_PIXBUF_MINOR < 8)
9312 	/* 2.4 can constrain size only while preserving aspect ratio;
9313 	 * 2.6 can constrain size fully, but not partially */
9314 	if (settings->req_w && settings->req_h)
9315 		pbuf = gdk_pixbuf_new_from_file_at_scale(file_name,
9316 			settings->req_w, settings->req_h, FALSE, &err);
9317 	else pbuf = gdk_pixbuf_new_from_file(file_name, &err);
9318 #else
9319 	/* 2.8+ is full-featured */
9320 	pbuf = gdk_pixbuf_new_from_file_at_scale(file_name,
9321 		settings->req_w ? settings->req_w : -1,
9322 		settings->req_h ? settings->req_h : -1,
9323 		!(settings->req_w && settings->req_h), &err);
9324 #endif
9325 	if (!pbuf)
9326 	{
9327 		if ((err->domain == GDK_PIXBUF_ERROR) &&
9328 			(err->code == GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY))
9329 			res = FILE_MEM_ERROR;
9330 		g_error_free(err);
9331 		return (res);
9332 	}
9333 	/* Prevent images loading wrong in case gdk-pixbuf ever starts using
9334 	 * something other than 8-bit RGB/RGBA without me noticing - WJ */
9335 	if (gdk_pixbuf_get_bits_per_sample(pbuf) != 8) goto fail;
9336 
9337 	bpp = gdk_pixbuf_get_n_channels(pbuf);
9338 	if (bpp == 4) cmask = CMASK_RGBA;
9339 	else if (bpp == 3) cmask = CMASK_IMAGE;
9340 	else goto fail;
9341 	settings->width = w = gdk_pixbuf_get_width(pbuf);
9342 	settings->height = h = gdk_pixbuf_get_height(pbuf);
9343 	settings->bpp = 3;
9344 	if ((res = allocate_image(settings, cmask))) goto fail;
9345 
9346 	skip = gdk_pixbuf_get_rowstride(pbuf) - w * bpp;
9347 	src = gdk_pixbuf_get_pixels(pbuf);
9348 	dest = settings->img[CHN_IMAGE];
9349 	dsta = settings->img[CHN_ALPHA];
9350 	for (i = 0; i < h; i++ , src += skip)
9351 	for (j = 0; j < w; j++ , src += bpp , dest += 3)
9352 	{
9353 		dest[0] = src[0];
9354 		dest[1] = src[1];
9355 		dest[2] = src[2];
9356 		if (dsta) *dsta++ = src[3];
9357 	}
9358 	res = 1;
9359 
9360 	/* Delete all-set "alpha" */
9361 	delete_alpha(settings, 255);
9362 
9363 fail:	g_object_unref(pbuf);
9364 	return (res);
9365 }
9366 
9367 #endif
9368 
9369 /* Handle SVG import using rsvg-convert */
9370 
import_svg(char * file_name,ls_settings * settings)9371 static int import_svg(char *file_name, ls_settings *settings)
9372 {
9373 	da_settings ds;
9374 	char buf[PATHBUF];
9375 	int res = -1;
9376 
9377 	if (!get_tempname(buf, file_name, FT_PNG)) return (-1);
9378 	memset(&ds, 0, sizeof(ds));
9379 	ds.sname = file_name;
9380 	ds.dname = buf;
9381 	ds.width = settings->req_w;
9382 	ds.height = settings->req_h;
9383 	if (!run_def_action_x(DA_SVG_CONVERT, &ds))
9384 		res = load_png(buf, settings, NULL, FALSE);
9385 	unlink(buf);
9386 
9387 	/* Delete all-set "alpha" */
9388 	if (res == 1) delete_alpha(settings, 255);
9389 
9390 	return (res);
9391 }
9392 
9393 /* Handle textual palette file formats - GIMP's GPL and mtPaint's own TXT */
9394 
to_pal(png_color * c,int * rgb)9395 static void to_pal(png_color *c, int *rgb)
9396 {
9397 	c->red = rgb[0] < 0 ? 0 : rgb[0] > 255 ? 255 : rgb[0];
9398 	c->green = rgb[1] < 0 ? 0 : rgb[1] > 255 ? 255 : rgb[1];
9399 	c->blue = rgb[2] < 0 ? 0 : rgb[2] > 255 ? 255 : rgb[2];
9400 }
9401 
load_txtpal(char * file_name,ls_settings * settings)9402 static int load_txtpal(char *file_name, ls_settings *settings)
9403 {
9404 	char lbuf[4096];
9405 	FILE *fp;
9406 	png_color *c = settings->pal;
9407 	int i, rgb[3], n = 0, res = -1;
9408 
9409 
9410 	if (!(fp = fopen(file_name, "r"))) return (-1);
9411 	if (!fgets(lbuf, 4096, fp)) goto fail;
9412 	if (settings->ftype == FT_GPL)
9413 	{
9414 		if (strstr(lbuf, "GIMP Palette") != lbuf) goto fail;
9415 		while (fgets(lbuf, 4096, fp) && (n < 256))
9416 		{
9417 			/* Just ignore invalid/unknown lines */
9418 			if (sscanf(lbuf, "%d %d %d", rgb + 0, rgb + 1, rgb + 2) != 3)
9419 				continue;
9420 			to_pal(c++, rgb);
9421 			n++;
9422 		}
9423 	}
9424 	else
9425 	{
9426 		if (sscanf(lbuf, "%i", &n) != 1) goto fail;
9427 		/* No further validation of anything at all */
9428 		n = n < 2 ? 2 : n > 256 ? 256 : n;
9429 		for (i = 0; i < n; i++)
9430 		{
9431 			fscanf(fp, "%i,%i,%i\n", rgb + 0, rgb + 1, rgb + 2);
9432 			to_pal(c++, rgb);
9433 		}
9434 	}
9435 	settings->colors = n;
9436 	if (n > 0) res = 1;
9437 
9438 fail:	fclose(fp);
9439 	return (res);
9440 }
9441 
save_txtpal(char * file_name,ls_settings * settings)9442 static int save_txtpal(char *file_name, ls_settings *settings)
9443 {
9444 	FILE *fp;
9445 	char *tpl;
9446 	png_color *cp;
9447 	int i, l, n = settings->colors;
9448 
9449 	if ((fp = fopen(file_name, "w")) == NULL) return (-1);
9450 
9451 	if (settings->ftype == FT_GPL)	// .gpl file
9452 	{
9453 		tpl = extract_ident(file_name, &l);
9454 		if (!l) tpl = "mtPaint" , l = strlen("mtPaint");
9455 		fprintf(fp, "GIMP Palette\nName: %.*s\nColumns: 16\n#\n", l, tpl);
9456 		tpl = "%3i %3i %3i\tUntitled\n";
9457 	}
9458 	else // .txt file
9459 	{
9460 		fprintf(fp, "%i\n", n);
9461 		tpl = "%i,%i,%i\n";
9462 	}
9463 
9464 	cp = settings->pal;
9465 	for (i = 0; i < n; i++ , cp++)
9466 		fprintf(fp, tpl, cp->red, cp->green, cp->blue);
9467 
9468 	fclose(fp);
9469 	return (0);
9470 }
9471 
9472 /* Handle raw palette file formats - 6-bit PAL and 8-bit ACT */
9473 
load_rawpal(char * file_name,ls_settings * settings)9474 static int load_rawpal(char *file_name, ls_settings *settings)
9475 {
9476 	unsigned char buf[769], xlat[256], *tp;
9477 	FILE *fp;
9478 	char *stop;
9479 	int i, l, ftype;
9480 
9481 
9482 	memset(buf, 0, sizeof(buf));
9483 	if (!(fp = fopen(file_name, "rb"))) return (-1);
9484 	l = fread(buf, 1, 769, fp);
9485 	fclose(fp);
9486 	if (!l || (l > 768) || (l % 3)) return (-1); // Wrong size
9487 	l /= 3;
9488 
9489 	/* !!! Filetype in ls_settings is ignored */
9490 	ftype = FT_NONE;
9491 	if ((stop = strrchr(file_name, '.')))
9492 	{
9493 		if (!strcasecmp(stop + 1, "act"))
9494 		{
9495 			if (l != 256) return (-1);
9496 			ftype = FT_ACT;
9497 		}
9498 		else if (!strcasecmp(stop + 1, "pal"))
9499 			ftype = FT_PAL;
9500 	}
9501 	if (l < 256) ftype = FT_PAL;
9502 
9503 	if (ftype != FT_ACT) // Default to 6-bit
9504 	{
9505 		set_xlate(xlat, 6);
9506 		for (i = 64; i < 255; i++) xlat[i] = xlat[i - 64];
9507 	}
9508 	else set_xlate(xlat, 8); // 1:1
9509 
9510 	for (i = 0 , tp = buf; i < l; i++)
9511 	{
9512 		settings->pal[i].red = xlat[tp[0]];
9513 		settings->pal[i].green = xlat[tp[1]];
9514 		settings->pal[i].blue = xlat[tp[2]];
9515 		tp += 3;
9516 	}
9517 	settings->colors = l;
9518 
9519 	return (1);
9520 }
9521 
save_rawpal(char * file_name,ls_settings * settings)9522 static int save_rawpal(char *file_name, ls_settings *settings)
9523 {
9524 	FILE *fp;
9525 	unsigned char buf[768], xlat[256], *tp;
9526 	png_color *cp;
9527 	int i, n = settings->colors;
9528 
9529 	if (!(fp = fopen(file_name, "wb"))) return (-1);
9530 
9531 	memset(buf, 0, 768);
9532 	if (settings->ftype == FT_PAL) // 6-bit
9533 		for (i = 0; i < 256; i++)
9534 			xlat[i] = (63 * 2 * i + 255) / (255 * 2);
9535 	else for (i = 0; i < 256; i++) xlat[i] = i; // 8-bit ACT
9536 
9537 	cp = settings->pal;
9538 	for (i = 0 , tp = buf; i < n; i++ , cp++)
9539 	{
9540 		tp[0] = xlat[cp->red];
9541 		tp[1] = xlat[cp->green];
9542 		tp[2] = xlat[cp->blue];
9543 		tp += 3;
9544 	}
9545 	if (settings->ftype != FT_PAL) n = 256;
9546 	i = fwrite(buf, n * 3, 1, fp);
9547 	fclose(fp);
9548 
9549 	return (i ? 0 : -1);
9550 }
9551 
save_image_x(char * file_name,ls_settings * settings,memFILE * mf)9552 static int save_image_x(char *file_name, ls_settings *settings, memFILE *mf)
9553 {
9554 	ls_settings setw = *settings; // Make a copy to safely modify
9555 	png_color greypal[256];
9556 	int res;
9557 
9558 	/* Prepare to handle clipboard export */
9559 	if (setw.mode != FS_CLIPBOARD); // not export
9560 	else if (setw.ftype & FTM_EXTEND) setw.mode = FS_CLIP_FILE; // to mtPaint
9561 	else if (setw.img[CHN_SEL] && !setw.img[CHN_ALPHA])
9562 	{
9563 		/* Pass clipboard mask as alpha if there is no alpha already */
9564 		setw.img[CHN_ALPHA] = setw.img[CHN_SEL];
9565 		setw.img[CHN_SEL] = NULL;
9566 	}
9567 	setw.ftype &= FTM_FTYPE;
9568 
9569 	/* Be silent if only writing palette */
9570 	if (setw.mode == FS_PALETTE_SAVE) setw.silent = TRUE;
9571 
9572 	/* Provide a grayscale palette if needed */
9573 	if ((setw.bpp == 1) && !setw.pal)
9574 		mem_bw_pal(setw.pal = greypal, 0, 255);
9575 
9576 	/* Validate transparent color (for now, forbid out-of-palette RGB
9577 	 * transparency altogether) */
9578 	if (setw.colors && (setw.xpm_trans >= setw.colors))
9579 		setw.xpm_trans = setw.rgb_trans = -1;
9580 
9581 	switch (setw.ftype)
9582 	{
9583 	default:
9584 	case FT_PNG: res = save_png(file_name, &setw, mf); break;
9585 	case FT_GIF: res = save_gif(file_name, &setw); break;
9586 #ifdef U_JPEG
9587 	case FT_JPEG: res = save_jpeg(file_name, &setw); break;
9588 #endif
9589 #ifdef HANDLE_JP2
9590 	case FT_JP2:
9591 	case FT_J2K: res = save_jpeg2000(file_name, &setw); break;
9592 #endif
9593 #ifdef U_TIFF
9594 	case FT_TIFF: res = save_tiff(file_name, &setw, mf); break;
9595 #endif
9596 #ifdef U_WEBP
9597 	case FT_WEBP: res = save_webp(file_name, &setw); break;
9598 #endif
9599 	case FT_BMP: res = save_bmp(file_name, &setw, mf); break;
9600 	case FT_XPM: res = save_xpm(file_name, &setw); break;
9601 	case FT_XBM: res = save_xbm(file_name, &setw); break;
9602 	case FT_LSS: res = save_lss(file_name, &setw); break;
9603 	case FT_TGA: res = save_tga(file_name, &setw); break;
9604 	case FT_PCX: res = save_pcx(file_name, &setw); break;
9605 	case FT_LBM: res = save_lbm(file_name, &setw); break;
9606 	case FT_PBM: res = save_pbm(file_name, &setw); break;
9607 	case FT_PPM: res = save_ppm(file_name, &setw); break;
9608 	case FT_PAM: res = save_pam(file_name, &setw); break;
9609 	case FT_PMM: res = save_pmm(file_name, &setw, mf); break;
9610 	case FT_PIXMAP: res = save_pixmap(&setw, mf); break;
9611 	/* Palette files */
9612 	case FT_GPL:
9613 	case FT_TXT: res = save_txtpal(file_name, &setw); break;
9614 	case FT_PAL:
9615 	case FT_ACT: res = save_rawpal(file_name, &setw); break;
9616 	}
9617 
9618 	return (res);
9619 }
9620 
save_image(char * file_name,ls_settings * settings)9621 int save_image(char *file_name, ls_settings *settings)
9622 {
9623 	return (save_image_x(file_name, settings, NULL));
9624 }
9625 
save_mem_image(unsigned char ** buf,int * len,ls_settings * settings)9626 int save_mem_image(unsigned char **buf, int *len, ls_settings *settings)
9627 {
9628 	memFILE mf;
9629 	int res;
9630 
9631 	memset(&mf, 0, sizeof(mf));
9632 	if ((settings->ftype & FTM_FTYPE) == FT_PIXMAP)
9633 		mf.m.buf = malloc(sizeof(XID_type)); // Expect to know type here
9634 	else if (!(file_formats[settings->ftype & FTM_FTYPE].flags & FF_WMEM))
9635 		return (-1);
9636 	else mf.m.buf = malloc(mf.m.size = 0x4000 - 64);
9637 	/* Be silent when saving to memory */
9638 	settings->silent = TRUE;
9639 	res = save_image_x(NULL, settings, &mf);
9640 	if (res) free(mf.m.buf);
9641 	else *buf = mf.m.buf , *len = mf.top;
9642 	return (res);
9643 }
9644 
store_image_extras(image_info * image,image_state * state,ls_settings * settings)9645 static void store_image_extras(image_info *image, image_state *state,
9646 	ls_settings *settings)
9647 {
9648 #if U_LCMS
9649 	/* Apply ICC profile */
9650 	while (settings->icc_size > 0)
9651 	{
9652 		cmsHPROFILE from, to;
9653 		cmsHTRANSFORM how = NULL;
9654 		int l = settings->icc_size - sizeof(icHeader);
9655 		unsigned char *iccdata = settings->icc + sizeof(icHeader);
9656 
9657 		/* Do nothing if the profile seems to be the default sRGB one */
9658 		if ((l == 3016) && (hashf(HASHSEED, iccdata, l) == 0xBA0A8E52UL) &&
9659 			(hashf(HASH_RND(HASHSEED), iccdata, l) == 0x94C42C77UL)) break;
9660 
9661 		from = cmsOpenProfileFromMem((void *)settings->icc,
9662 			settings->icc_size);
9663 		to = cmsCreate_sRGBProfile();
9664 		if (from && (cmsGetColorSpace(from) == icSigRgbData))
9665 			how = cmsCreateTransform(from, TYPE_RGB_8,
9666 				to, TYPE_RGB_8, INTENT_PERCEPTUAL, 0);
9667 		if (how && (settings->bpp == 1)) /* For GIF: apply to palette */
9668 		{
9669 			unsigned char tm[256 * 3];
9670 			int l = settings->colors;
9671 
9672 			pal2rgb(tm, settings->pal, l, 0);
9673 			cmsDoTransform(how, tm, tm, l);
9674 			rgb2pal(settings->pal, tm, l);
9675 
9676 			cmsDeleteTransform(how);
9677 		}
9678 		else if (how)
9679 		{
9680 			unsigned char *img = settings->img[CHN_IMAGE];
9681 			size_t l = settings->width, sz = l * settings->height;
9682 			int i, j;
9683 
9684 			if (!settings->silent)
9685 				progress_init(_("Applying colour profile"), 1);
9686 			else if (sz < UINT_MAX) l = sz;
9687 			j = sz / l;
9688 			for (i = 0; i < j; i++ , img += l * 3)
9689 			{
9690 				if (!settings->silent && ((i * 20) % j >= j - 20))
9691 					if (progress_update((float)i / j)) break;
9692 				cmsDoTransform(how, img, img, l);
9693 			}
9694 			progress_end();
9695 			cmsDeleteTransform(how);
9696 		}
9697 		if (from) cmsCloseProfile(from);
9698 		cmsCloseProfile(to);
9699 		break;
9700 	}
9701 #endif
9702 // !!! Changing any values is frequently harmful in this mode, so don't do it
9703 	if (settings->mode == FS_CHANNEL_LOAD) return;
9704 
9705 	/* Stuff RGB transparency into color 255 */
9706 	map_rgb_trans(settings);
9707 
9708 	/* Accept vars which make sense */
9709 	state->xbm_hot_x = settings->hot_x;
9710 	state->xbm_hot_y = settings->hot_y;
9711 	if (settings->gif_delay > 0) preserved_gif_delay = settings->gif_delay;
9712 
9713 	/* Accept palette */
9714 	image->trans = settings->xpm_trans;
9715 	mem_pal_copy(image->pal, settings->pal);
9716 	image->cols = settings->colors;
9717 }
9718 
load_image_x(char * file_name,memFILE * mf,int mode,int ftype,int rw,int rh)9719 static int load_image_x(char *file_name, memFILE *mf, int mode, int ftype,
9720 	int rw, int rh)
9721 {
9722 	layer_image *lim = NULL;
9723 	png_color pal[256];
9724 	ls_settings settings;
9725 	int i, tr, res, res0, undo = ftype & FTM_UNDO;
9726 
9727 
9728 	/* Clipboard import - from mtPaint, or from something other? */
9729 	if ((mode == FS_CLIPBOARD) && (ftype & FTM_EXTEND)) mode = FS_CLIP_FILE;
9730 	ftype &= FTM_FTYPE;
9731 
9732 	/* Prepare layer slot */
9733 	if (mode == FS_LAYER_LOAD)
9734 	{
9735 		lim = layer_table[layers_total].image;
9736 		if (!lim) lim = layer_table[layers_total].image =
9737 			alloc_layer(0, 0, 1, 0, NULL);
9738 		else if (layers_total) mem_free_image(&lim->image_, FREE_IMAGE);
9739 		if (!lim) return (FILE_MEM_ERROR);
9740 	}
9741 
9742 	/* Fit scalable image into channel */
9743 	if (mode == FS_CHANNEL_LOAD) rw = mem_width , rh = mem_height;
9744 
9745 	init_ls_settings(&settings, NULL);
9746 	settings.req_w = rw;
9747 	settings.req_h = rh;
9748 	/* Preset delay to -1, to detect animations by its changing */
9749 	settings.gif_delay = -1;
9750 #ifdef U_LCMS
9751 	/* Set size to -1 when we don't want color profile */
9752 	if (!apply_icc || ((mode == FS_CHANNEL_LOAD) ? (MEM_BPP != 3) :
9753 		(mode != FS_PNG_LOAD) && (mode != FS_LAYER_LOAD)))
9754 		settings.icc_size = -1;
9755 #endif
9756 	/* 0th layer load is just an image load */
9757 	if ((mode == FS_LAYER_LOAD) && !layers_total) mode = FS_PNG_LOAD;
9758 	settings.mode = mode;
9759 	settings.ftype = ftype;
9760 	settings.pal = pal;
9761 	/* Clear hotspot & transparency */
9762 	settings.hot_x = settings.hot_y = -1;
9763 	settings.xpm_trans = settings.rgb_trans = -1;
9764 	/* Be silent if working from memory */
9765 	if (mf) settings.silent = TRUE;
9766 
9767 	/* !!! Use default palette - for now */
9768 	mem_pal_copy(pal, mem_pal_def);
9769 	settings.colors = mem_pal_def_i;
9770 
9771 	switch (ftype)
9772 	{
9773 	default:
9774 	case FT_PNG: res0 = load_png(file_name, &settings, mf, FALSE); break;
9775 	case FT_GIF: res0 = load_gif(file_name, &settings); break;
9776 #ifdef U_JPEG
9777 	case FT_JPEG: res0 = load_jpeg(file_name, &settings); break;
9778 #endif
9779 #ifdef HANDLE_JP2
9780 	case FT_JP2:
9781 	case FT_J2K: res0 = load_jpeg2000(file_name, &settings); break;
9782 #endif
9783 #ifdef U_TIFF
9784 	case FT_TIFF: res0 = load_tiff(file_name, &settings, mf); break;
9785 #endif
9786 #ifdef U_WEBP
9787 	case FT_WEBP: res0 = load_webp(file_name, &settings); break;
9788 #endif
9789 	case FT_BMP: res0 = load_bmp(file_name, &settings, mf); break;
9790 	case FT_XPM: res0 = load_xpm(file_name, &settings); break;
9791 	case FT_XBM: res0 = load_xbm(file_name, &settings); break;
9792 	case FT_LSS: res0 = load_lss(file_name, &settings); break;
9793 	case FT_TGA: res0 = load_tga(file_name, &settings); break;
9794 	case FT_PCX: res0 = load_pcx(file_name, &settings); break;
9795 	case FT_LBM: res0 = load_lbm(file_name, &settings); break;
9796 	case FT_PBM:
9797 	case FT_PGM:
9798 	case FT_PPM:
9799 	case FT_PAM: res0 = load_pnm(file_name, &settings); break;
9800 	case FT_PMM: res0 = load_pmm(file_name, &settings, mf); break;
9801 	case FT_PIXMAP: res0 = load_pixmap(&settings, mf); break;
9802 	case FT_SVG:
9803 #ifdef MAY_HANDLE_SVG
9804 		if (svg_check < 0) svg_check = svg_supported();
9805 		if (svg_check) res0 = load_svg(file_name, &settings);
9806 		else
9807 #endif
9808 		res0 = import_svg(file_name, &settings); break;
9809 	/* Palette files */
9810 	case FT_GPL:
9811 	case FT_TXT: res0 = load_txtpal(file_name, &settings); break;
9812 	case FT_PAL:
9813 	case FT_ACT: res0 = load_rawpal(file_name, &settings); break;
9814 	}
9815 
9816 	/* Consider animated GIF a success */
9817 	res = res0 == FILE_HAS_FRAMES ? 1 : res0;
9818 	/* Ignore frames beyond first if in-memory (imported clipboard) */
9819 	if (mf) res0 = res;
9820 
9821 	switch (mode)
9822 	{
9823 	case FS_PNG_LOAD: /* Image */
9824 		/* Success, or lib failure with single image - commit load */
9825 		if ((res == 1) || (!lim && (res == FILE_LIB_ERROR)))
9826 		{
9827 			if (!mem_img[CHN_IMAGE] || !undo)
9828 				mem_new(settings.width, settings.height,
9829 					settings.bpp, 0);
9830 			else undo_next_core(UC_DELETE, settings.width,
9831 				settings.height, settings.bpp, CMASK_ALL);
9832 			memcpy(mem_img, settings.img, sizeof(chanlist));
9833 			store_image_extras(&mem_image, &mem_state, &settings);
9834 			update_undo(&mem_image);
9835 			mem_undo_prepare();
9836 			if (lim) layer_copy_from_main(0);
9837 			/* Report whether the file is animated or multipage */
9838 			res = res0;
9839 			if ((res == FILE_HAS_FRAMES) &&
9840 				/* If file contains frame delay value... */
9841 				((settings.gif_delay >= 0) ||
9842 				/* ...or it cannot be multipage at all... */
9843 				!(file_formats[ftype].flags & FF_LAYER)))
9844 				res = FILE_HAS_ANIM; /* ...then it's animated */
9845 		}
9846 		/* Failure */
9847 		else
9848 		{
9849 			mem_free_chanlist(settings.img);
9850 			/* If loader managed to delete image before failing */
9851 			if (!mem_img[CHN_IMAGE]) create_default_image();
9852 		}
9853 		break;
9854 	case FS_CLIPBOARD: /* Imported clipboard */
9855 		if ((res == 1) && mem_clip_alpha && !mem_clip_mask)
9856 		{
9857 			/* "Alpha" likely means clipboard mask here */
9858 			mem_clip_mask = mem_clip_alpha;
9859 			mem_clip_alpha = NULL;
9860 			memcpy(settings.img, mem_clip.img, sizeof(chanlist));
9861 		}
9862 		/* Fallthrough */
9863 	case FS_CLIP_FILE: /* Clipboard */
9864 		/* Convert color transparency to alpha */
9865 		tr = settings.bpp == 3 ? settings.rgb_trans : settings.xpm_trans;
9866 		if ((res == 1) && (tr >= 0))
9867 		{
9868 			/* Add alpha channel if no alpha yet */
9869 			if (!settings.img[CHN_ALPHA])
9870 			{
9871 				i = settings.width * settings.height;
9872 				/* !!! Create committed */
9873 				mem_clip_alpha = malloc(i);
9874 				if (mem_clip_alpha)
9875 				{
9876 					settings.img[CHN_ALPHA] = mem_clip_alpha;
9877 					memset(mem_clip_alpha, 255, i);
9878 				}
9879 			}
9880 			if (!settings.img[CHN_ALPHA]) res = FILE_MEM_ERROR;
9881 			else mem_mask_colors(settings.img[CHN_ALPHA],
9882 				settings.img[CHN_IMAGE], 0, settings.width,
9883 				settings.height, settings.bpp, tr, tr);
9884 		}
9885 		/* Success - accept data */
9886 		if (res == 1); /* !!! Clipboard data committed already */
9887 		/* Failure needing rollback */
9888 		else if (settings.img[CHN_IMAGE])
9889 		{
9890 			/* !!! Too late to restore previous clipboard */
9891 			mem_free_image(&mem_clip, FREE_ALL);
9892 		}
9893 		break;
9894 	case FS_CHANNEL_LOAD:
9895 		/* Success - commit load */
9896 		if (res == 1)
9897 		{
9898 			/* Add frame & stuff data into it */
9899 			undo_next_core(UC_DELETE, mem_width, mem_height, mem_img_bpp,
9900 				CMASK_CURR);
9901 			mem_img[mem_channel] = settings.img[CHN_IMAGE];
9902 			update_undo(&mem_image);
9903 			if (mem_channel == CHN_IMAGE)
9904 				store_image_extras(&mem_image, &mem_state, &settings);
9905 			mem_undo_prepare();
9906 		}
9907 		/* Failure */
9908 		else free(settings.img[CHN_IMAGE]);
9909 		break;
9910 	case FS_LAYER_LOAD: /* Layer */
9911 		/* Success - commit load */
9912 		if (res == 1)
9913 		{
9914 			mem_alloc_image(0, &lim->image_, settings.width,
9915 				settings.height, settings.bpp, 0, NULL);
9916 			memcpy(lim->image_.img, settings.img, sizeof(chanlist));
9917 			store_image_extras(&lim->image_, &lim->state_, &settings);
9918 			update_undo(&lim->image_);
9919 		}
9920 		/* Failure */
9921 		else mem_free_chanlist(settings.img);
9922 		break;
9923 	case FS_PATTERN_LOAD:
9924 		/* Success - rebuild patterns */
9925 		if (res == 1) set_patterns(&settings);
9926 		free(settings.img[CHN_IMAGE]);
9927 		break;
9928 	case FS_PALETTE_LOAD:
9929 	case FS_PALETTE_DEF:
9930 		/* Drop image channels if any */
9931 		mem_free_chanlist(settings.img);
9932 		/* This "failure" in this context serves as shortcut */
9933 		if (res == EXPLODE_FAILED) res = 1;
9934 		/* In case of image format, retry as raw palette */
9935 		if ((res != 1) && (file_formats[ftype].flags & FF_IMAGE))
9936 			res = load_rawpal(file_name, &settings);
9937 		/* Utter failure - do nothing */
9938 		if ((res != 1) || (settings.colors <= 0));
9939 		/* Replace default palette */
9940 		else if (mode == FS_PALETTE_DEF)
9941 		{
9942 			mem_pal_copy(mem_pal_def, pal);
9943 			mem_pal_def_i = settings.colors;
9944 		}
9945 		/* Change current palette */
9946 		else
9947 		{
9948 			mem_undo_next(UNDO_PAL);
9949 			mem_pal_copy(mem_pal, pal);
9950 			mem_cols = settings.colors;
9951 		}
9952 		break;
9953 	}
9954 	free(settings.icc);
9955 	return (res);
9956 }
9957 
load_image(char * file_name,int mode,int ftype)9958 int load_image(char *file_name, int mode, int ftype)
9959 {
9960 	return (load_image_x(file_name, NULL, mode, ftype, 0, 0));
9961 }
9962 
load_mem_image(unsigned char * buf,int len,int mode,int ftype)9963 int load_mem_image(unsigned char *buf, int len, int mode, int ftype)
9964 {
9965 	memFILE mf;
9966 
9967 	if (((ftype & FTM_FTYPE) != FT_PIXMAP) /* Special case */ &&
9968 		!(file_formats[ftype & FTM_FTYPE].flags & FF_RMEM)) return (-1);
9969 	memset(&mf, 0, sizeof(mf));
9970 	mf.m.buf = buf; mf.top = mf.m.size = len;
9971 	return (load_image_x(NULL, &mf, mode, ftype, 0, 0));
9972 }
9973 
load_image_scale(char * file_name,int mode,int ftype,int w,int h)9974 int load_image_scale(char *file_name, int mode, int ftype, int w, int h)
9975 {
9976 	return (load_image_x(file_name, NULL, mode, ftype, w, h));
9977 }
9978 
9979 // !!! The only allowed modes for now are FS_LAYER_LOAD and FS_EXPLODE_FRAMES
9980 // !!! Load from memblock is not supported yet
load_frames_x(ani_settings * ani,int ani_mode,char * file_name,int mode,int ftype)9981 static int load_frames_x(ani_settings *ani, int ani_mode, char *file_name,
9982 	int mode, int ftype)
9983 {
9984 	png_color pal[256];
9985 
9986 
9987 	ftype &= FTM_FTYPE;
9988 	ani->mode = ani_mode;
9989 	init_ls_settings(&ani->settings, NULL);
9990 #ifdef U_LCMS
9991 	/* Set size to -1 when we don't want color profile */
9992 	/* if (!apply_icc) */ ani->settings.icc_size = -1; // !!! Disable for now
9993 #endif
9994 	ani->settings.mode = mode;
9995 	ani->settings.ftype = ftype;
9996 	ani->settings.pal = pal;
9997 	/* Clear hotspot & transparency */
9998 	ani->settings.hot_x = ani->settings.hot_y = -1;
9999 	ani->settings.xpm_trans = ani->settings.rgb_trans = -1;
10000 	/* No load progressbar when exploding frames */
10001 	if (mode == FS_EXPLODE_FRAMES) ani->settings.silent = TRUE;
10002 
10003 	/* !!! Use default palette - for now */
10004 	mem_pal_copy(pal, mem_pal_def);
10005 	ani->settings.colors = mem_pal_def_i;
10006 
10007 	switch (ftype)
10008 	{
10009 	case FT_PNG: return (load_apng_frames(file_name, ani));
10010 	case FT_GIF: return (load_gif_frames(file_name, ani));
10011 #ifdef U_TIFF
10012 	case FT_TIFF: return (load_tiff_frames(file_name, ani));
10013 #endif
10014 #ifdef U_WEBP
10015 	case FT_WEBP: return (load_webp_frames(file_name, ani));
10016 #endif
10017 	case FT_PBM:
10018 	case FT_PGM:
10019 	case FT_PPM:
10020 	case FT_PAM: return (load_pnm_frames(file_name, ani));
10021 	case FT_PMM: return (load_pmm_frames(file_name, ani, NULL));
10022 	}
10023 	return (-1);
10024 }
10025 
load_frameset(frameset * frames,int ani_mode,char * file_name,int mode,int ftype)10026 int load_frameset(frameset *frames, int ani_mode, char *file_name, int mode,
10027 	int ftype)
10028 {
10029 	ani_settings ani;
10030 	int res;
10031 
10032 
10033 	memset(&ani, 0, sizeof(ani_settings));
10034 	res = load_frames_x(&ani, ani_mode, file_name, mode, ftype);
10035 
10036 	/* Treat out-of-memory error as fatal, to avoid worse things later */
10037 	if ((res == FILE_MEM_ERROR) || !ani.fset.cnt)
10038 		mem_free_frames(&ani.fset);
10039 	/* Pass too-many-frames error along */
10040 	else if (res == FILE_TOO_LONG);
10041 	/* Consider all other errors partial failures */
10042 	else if (res != 1) res = FILE_LIB_ERROR;
10043 
10044 	/* Just pass the frameset to the outside, for now */
10045 	*frames = ani.fset;
10046 	return (res);
10047 }
10048 
10049 /* Write out the last frame to indexed sequence, and delete it */
write_out_frame(char * file_name,ani_settings * ani,ls_settings * f_set)10050 static int write_out_frame(char *file_name, ani_settings *ani, ls_settings *f_set)
10051 {
10052 	ls_settings w_set;
10053 	image_frame *frame = ani->fset.frames + ani->fset.cnt - 1;
10054 	char new_name[PATHBUF + 32], *tmp;
10055 	int n, deftype = ani->desttype, res;
10056 
10057 
10058 	/* Show progress, for unknown final count */
10059 	n = nextpow2(ani->cnt);
10060 	if (n < 16) n = 16;
10061 	progress_update((float)ani->cnt / n);
10062 
10063 	tmp = strrchr(file_name, DIR_SEP);
10064 	if (!tmp) tmp = file_name;
10065 	else tmp++;
10066 	file_in_dir(new_name, ani->destdir, tmp, PATHBUF);
10067 	tmp = new_name + strlen(new_name);
10068 	sprintf(tmp, ".%03d", ani->cnt);
10069 
10070 	if (f_set) w_set = *f_set;
10071 	else
10072 	{
10073 		init_ls_settings(&w_set, NULL);
10074 		memcpy(w_set.img, frame->img, sizeof(chanlist));
10075 		w_set.width = frame->width;
10076 		w_set.height = frame->height;
10077 		w_set.pal = frame->pal ? frame->pal : ani->fset.pal;
10078 		w_set.bpp = frame->bpp;
10079 		w_set.colors = frame->cols;
10080 		w_set.xpm_trans = frame->trans;
10081 	}
10082 	w_set.ftype = deftype;
10083 	w_set.silent = TRUE;
10084 	if (!(file_formats[deftype].flags & FF_SAVE_MASK_FOR(w_set)))
10085 	{
10086 		w_set.ftype = FT_PNG;
10087 		ani->miss++;
10088 	}
10089 	w_set.mode = ani->mode; // Only FS_EXPLODE_FRAMES for now
10090 
10091 	res = ani->error = save_image(new_name, &w_set);
10092 	if (!res) ani->cnt++;
10093 
10094 	if (f_set) // Delete
10095 	{
10096 		mem_free_chanlist(f_set->img);
10097 		memset(f_set->img, 0, sizeof(chanlist));
10098 	}
10099 	// Set for deletion
10100 	else frame->flags |= FM_NUKE;
10101 	return (res);
10102 }
10103 
warn_miss(int miss,int total,int ftype)10104 static void warn_miss(int miss, int total, int ftype)
10105 {
10106 	char *txt = g_strdup_printf(
10107 		__("%d out of %d frames could not be saved as %s - saved as PNG instead"),
10108 		miss, total, file_formats[ftype].name);
10109 	alert_box(_("Warning"), txt, "", NULL); // Not an error
10110 	g_free(txt);
10111 }
10112 
explode_frames(char * dest_path,int ani_mode,char * file_name,int ftype,int desttype)10113 int explode_frames(char *dest_path, int ani_mode, char *file_name, int ftype,
10114 	int desttype)
10115 {
10116 	ani_settings ani;
10117 	int res;
10118 
10119 
10120 	memset(&ani, 0, sizeof(ani_settings));
10121 	ani.desttype = desttype;
10122 	ani.destdir = dest_path;
10123 
10124 	progress_init(_("Explode frames"), 0);
10125 	progress_update(0.0);
10126 	res = load_frames_x(&ani, ani_mode, file_name, FS_EXPLODE_FRAMES, ftype);
10127 	progress_update(1.0);
10128 	if (res == 1); // Everything went OK
10129 	else if (res == FILE_MEM_ERROR); // Report memory problem
10130 	else if (ani.error) // Sequence write failure - soft or hard?
10131 		res = ani.cnt ? FILE_EXP_BREAK : EXPLODE_FAILED;
10132 	else if (ani.cnt) // Failed to read some middle frame
10133 		res = FILE_LIB_ERROR;
10134 	mem_free_frames(&ani.fset);
10135 	progress_end();
10136 
10137 	if (ani.miss && (res == 1))
10138 		warn_miss(ani.miss, ani.cnt, ani.desttype & FTM_FTYPE);
10139 
10140 	return (res);
10141 }
10142 
export_undo(char * file_name,ls_settings * settings)10143 int export_undo(char *file_name, ls_settings *settings)
10144 {
10145 	char new_name[PATHBUF + 32];
10146 	int start = mem_undo_done, res = 0, lenny, i, j;
10147 	int deftype = settings->ftype, miss = 0;
10148 
10149 	strncpy(new_name, file_name, PATHBUF);
10150 	lenny = strlen( file_name );
10151 
10152 	ls_init("UNDO", 1);
10153 	settings->silent = TRUE;
10154 
10155 	for (j = 0; j < 2; j++)
10156 	{
10157 		for (i = 1; i <= start + 1; i++)
10158 		{
10159 			if (!res && (!j ^ (settings->mode == FS_EXPORT_UNDO)))
10160 			{
10161 				progress_update((float)i / (start + 1));
10162 				settings->ftype = deftype;
10163 				if (!(file_formats[deftype].flags & FF_SAVE_MASK))
10164 				{
10165 					settings->ftype = FT_PNG;
10166 					miss++;
10167 				}
10168 				sprintf(new_name + lenny, "%03i.%s", i,
10169 					file_formats[settings->ftype].ext);
10170 				memcpy(settings->img, mem_img, sizeof(chanlist));
10171 				settings->pal = mem_pal;
10172 				settings->width = mem_width;
10173 				settings->height = mem_height;
10174 				settings->bpp = mem_img_bpp;
10175 				settings->colors = mem_cols;
10176 				res = save_image(new_name, settings);
10177 			}
10178 			if (!j) /* Goto first image */
10179 			{
10180 				if (mem_undo_done > 0) mem_do_undo(FALSE);
10181 			}
10182 			else if (mem_undo_done < start) mem_do_undo(TRUE);
10183 		}
10184 	}
10185 
10186 	progress_end();
10187 
10188 	if (miss && !res) warn_miss(miss, mem_undo_done, deftype);
10189 
10190 	return (res);
10191 }
10192 
export_ascii(char * file_name)10193 int export_ascii ( char *file_name )
10194 {
10195 	char ch[16] = " .,:;+=itIYVXRBM";
10196 	int i, j;
10197 	unsigned char pix;
10198 	FILE *fp;
10199 
10200 	if ((fp = fopen(file_name, "w")) == NULL) return -1;
10201 
10202 	for ( j=0; j<mem_height; j++ )
10203 	{
10204 		for ( i=0; i<mem_width; i++ )
10205 		{
10206 			pix = mem_img[CHN_IMAGE][ i + mem_width*j ];
10207 			fprintf(fp, "%c", ch[pix % 16]);
10208 		}
10209 		fprintf(fp, "\n");
10210 	}
10211 	fclose(fp);
10212 
10213 	return 0;
10214 }
10215 
do_detect_format(char * name,FILE * fp)10216 static int do_detect_format(char *name, FILE *fp)
10217 {
10218 	unsigned char buf[66], *stop;
10219 	int i;
10220 
10221 	i = fread(buf, 1, 64, fp);
10222 	buf[64] = '\0';
10223 
10224 	/* Check all unambiguous signatures */
10225 	if (!memcmp(buf, "\x89PNG", 4)) return (FT_PNG);
10226 	if (!memcmp(buf, "GIF8", 4)) return (FT_GIF);
10227 	if (!memcmp(buf, "\xFF\xD8", 2))
10228 #ifdef U_JPEG
10229 		return (FT_JPEG);
10230 #else
10231 		return (FT_NONE);
10232 #endif
10233 	if (!memcmp(buf, "\0\0\0\x0C\x6A\x50\x20\x20\x0D\x0A\x87\x0A", 12))
10234 #ifdef HANDLE_JP2
10235 		return (FT_JP2);
10236 #else
10237 		return (FT_NONE);
10238 #endif
10239 	if (!memcmp(buf, "\xFF\x4F", 2))
10240 #ifdef HANDLE_JP2
10241 		return (FT_J2K);
10242 #else
10243 		return (FT_NONE);
10244 #endif
10245 	if (!memcmp(buf, "II", 2) || !memcmp(buf, "MM", 2))
10246 #ifdef U_TIFF
10247 		return (FT_TIFF);
10248 #else
10249 		return (FT_NONE);
10250 #endif
10251 	if (!memcmp(buf, "RIFF", 4) && !memcmp(buf + 8, "WEBP", 4))
10252 #ifdef U_WEBP
10253 		return (FT_WEBP);
10254 #else
10255 		return (FT_NONE);
10256 #endif
10257 	if (!memcmp(buf, "FORM", 4) && (!memcmp(buf + 8, "ILBM", 4) ||
10258 		!memcmp(buf + 8, "PBM ", 4))) return (FT_LBM);
10259 	if (!memcmp(buf, "BM", 2) || !memcmp(buf, "BA", 2)) return (FT_BMP);
10260 
10261 	if (!memcmp(buf, "\x3D\xF3\x13\x14", 4)) return (FT_LSS);
10262 
10263 	if (!memcmp(buf, PMM_ID1, 12)) return (FT_PMM);
10264 
10265 	if (!memcmp(buf, "P7", 2)) return (FT_PAM);
10266 	if ((buf[0] == 'P') && (buf[1] >= '1') && (buf[1] <= '6'))
10267 	{
10268 		static const unsigned char pnms[3] = { FT_PBM, FT_PGM, FT_PPM };
10269 		return (pnms[(buf[1] - '1') % 3]);
10270 	}
10271 
10272 	if (!memcmp(buf, "GIMP Palette", strlen("GIMP Palette"))) return (FT_GPL);
10273 
10274 	/* Check layers signature and version */
10275 	if (!memcmp(buf, LAYERS_HEADER, strlen(LAYERS_HEADER)))
10276 	{
10277 		stop = strchr(buf, '\n');
10278 		if (!stop || (stop - buf > 32)) return (FT_NONE);
10279 		i = atoi(++stop);
10280 		if (i == 1) return (FT_LAYERS1);
10281 /* !!! Not implemented yet */
10282 //		if (i == 2) return (FT_LAYERS2);
10283 		return (FT_NONE);
10284 	}
10285 
10286 	/* Assume generic XML is SVG */
10287 	i = 0; sscanf(buf, " <?xml %n", &i);
10288 	if (!i) sscanf(buf, " <svg%n", &i);
10289 	if (!i) sscanf(buf, " <!DOCTYPE svg%n", &i);
10290 	if (i) return (FT_SVG);
10291 
10292 	/* Discern PCX from TGA */
10293 	while (buf[0] == 10)
10294 	{
10295 		if (buf[1] > 5) break;
10296 		if (buf[1] > 1) return (FT_PCX);
10297 		if (buf[2] != 1) break; // Uncompressed PCX is nonstandard
10298 		/* Ambiguity - look at name as a last resort
10299 		 * Bias to PCX - TGAs usually have 0th byte = 0 */
10300 		stop = strrchr(name, '.');
10301 		if (!stop) return (FT_PCX);
10302 		if (!strcasecmp(stop + 1, "tga")) break;
10303 		return (FT_PCX);
10304 	}
10305 
10306 	/* Check if this is TGA */
10307 	if ((buf[1] < 2) && (buf[2] < 12) && ((1 << buf[2]) & 0x0E0F))
10308 		return (FT_TGA);
10309 
10310 	/* Simple check for "txt" palette format */
10311 	if ((sscanf(buf, "%i", &i) == 1) && (i > 0) && (i <= 256)) return (FT_TXT);
10312 
10313 	/* Simple check for XPM */
10314 	stop = strstr(buf, "XPM");
10315 	if (stop)
10316 	{
10317 		i = stop - buf;
10318 		stop = strchr(buf, '\n');
10319 		if (!stop || (stop - buf > i)) return (FT_XPM);
10320 	}
10321 	/* Check possibility of XBM by absence of control chars */
10322 	for (i = 0; buf[i] && (buf[i] != '\n'); i++)
10323 	{
10324 		if (ISCNTRL(buf[i])) return (FT_NONE);
10325 	}
10326 	return (FT_XBM);
10327 }
10328 
detect_file_format(char * name,int need_palette)10329 int detect_file_format(char *name, int need_palette)
10330 {
10331 	FILE *fp;
10332 	int i, f;
10333 
10334 	if (!(fp = fopen(name, "rb"))) return (-1);
10335 	i = do_detect_format(name, fp);
10336 	f = file_formats[i].flags;
10337 	if (need_palette)
10338 	{
10339 		/* Check for PAL/ACT raw format */
10340 		if (!(f & (FF_16 | FF_256 | FF_PALETTE)))
10341 		{
10342 			f_long l;
10343 			fseek(fp, 0, SEEK_END);
10344 			l = ftell(fp);
10345 			i = (l > 0) && (l <= 768) && !(l % 3) ? FT_PAL : FT_NONE;
10346 		}
10347 	}
10348 	else if (!(f & (FF_IMAGE | FF_LAYER))) i = FT_NONE;
10349 	fclose(fp);
10350 	return (i);
10351 }
10352 
10353 // Can this file be opened for reading?
10354 
10355 /* 0 = readable, -1 = not exists, 1 = error, 2 = a directory */
valid_file(char * filename)10356 int valid_file(char *filename)
10357 {
10358 	FILE *fp = fopen(filename, "r");
10359 	if (!fp) return (errno == ENOENT ? -1 : 1);
10360 	else
10361 	{
10362 		struct stat buf;
10363 		int d = fstat(fileno(fp), &buf) ? 1 : S_ISDIR(buf.st_mode) ? 2 : 0;
10364 		fclose(fp);
10365 		return (d);
10366 	}
10367 }
10368