Esempio n. 1
0
static void do_read_bitmap(deark *c, lctx *d, de_int64 pos)
{
	de_int64 ver_num;
	dbuf *unc_pixels = NULL;

	ver_num = de_getui32be(pos);
	de_dbg(c, "version number: %u\n", (unsigned int)ver_num);
	if(ver_num!=0 && ver_num!=2 && ver_num!=3) {
		de_warn(c, "Unrecognized version number: %u\n", (unsigned int)ver_num);
	}

	pos += 512;

	unc_pixels = dbuf_create_membuf(c, MACPAINT_IMAGE_BYTES, 1);

	de_fmtutil_uncompress_packbits(c->infile, pos, c->infile->len - pos, unc_pixels, NULL);

	if(unc_pixels->len < MACPAINT_IMAGE_BYTES) {
		de_warn(c, "Image decompressed to %d bytes, expected %d.\n",
			(int)unc_pixels->len, (int)MACPAINT_IMAGE_BYTES);
	}

	de_convert_and_write_image_bilevel(unc_pixels, 0,
		MACPAINT_WIDTH, MACPAINT_HEIGHT, MACPAINT_WIDTH/8,
		DE_CVTF_WHITEISZERO, NULL, 0);

	dbuf_close(unc_pixels);
}
Esempio n. 2
0
static void de_run_macpaint(deark *c, de_module_params *mparams)
{
	lctx *d;
	de_int64 pos;
	const char *s;

	d = de_malloc(c, sizeof(lctx));

	d->has_macbinary_header = -1;

	s = de_get_ext_option(c, "macpaint:macbinary");
	if(s) d->has_macbinary_header = de_atoi(s);

	if(d->has_macbinary_header == -1) {
		int v512;
		int v640;
		de_dbg(c, "trying to determine if file has a MacBinary header\n");
		v512 = valid_file_at(c, d, 0);
		v640 = valid_file_at(c, d, 128);
		if(v512 > v640) {
			de_dbg(c, "assuming it has no MacBinary header\n");
			d->has_macbinary_header = 0;
		}
		else if(v640 > v512) {
			de_dbg(c, "assuming it has a MacBinary header\n");
			d->has_macbinary_header = 1;
		}
		else if(v512 && v640) {
			de_warn(c, "Can't determine if this file has a MacBinary header. "
				"Try \"-opt macpaint:macbinary=0\".\n");
			d->has_macbinary_header = 1;
		}
		else {
			de_warn(c, "This is probably not a MacPaint file.\n");
			d->has_macbinary_header = 1;
		}
	}

	if(d->has_macbinary_header)
		de_declare_fmt(c, "MacPaint with MacBinary header");
	else
		de_declare_fmt(c, "MacPaint without MacBinary header");

	pos = d->has_macbinary_header ? 128 : 0;

	do_read_bitmap(c, d, pos);

	do_read_patterns(c, d, pos);

	de_free(c, d);
}
Esempio n. 3
0
// Some OS/2v2 files exist with bad (3-bytes/color) palettes.
// Try to detect them.
static void do_os2v2_bad_palette(deark *c, lctx *d)
{
	de_int64 pal_space_avail;
	de_int64 pal_bytes_if_3bpc;
	de_int64 pal_bytes_if_4bpc;
	int nonzero_rsvd;
	int i;

	if(d->version!=DE_BMPVER_OS2V2) return;
	if(d->pal_entries<1) return;

	pal_space_avail = d->bits_offset - d->pal_pos;
	pal_bytes_if_4bpc = 4*d->pal_entries;
	pal_bytes_if_3bpc = 3*d->pal_entries;

	if(pal_space_avail>=pal_bytes_if_4bpc) return;
	if(pal_space_avail<pal_bytes_if_3bpc || pal_space_avail>(pal_bytes_if_3bpc+1)) return;

	// Look for nonzero 'reserved' bytes
	nonzero_rsvd = 0;
	for(i=0; i<pal_bytes_if_3bpc; i+=4) {
		if(de_getbyte(d->pal_pos + i + 3) != 0) {
			nonzero_rsvd = 1;
			break;
		}
	}
	if(!nonzero_rsvd) return;

	de_warn(c, "Assuming palette has 3 bytes per entry, instead of 4\n");
	d->bytes_per_pal_entry = 3;
}
Esempio n. 4
0
File: tga.c Progetto: jsummers/deark
static void do_read_developer_area(deark *c, lctx *d, i64 pos)
{
	i64 num_tags;
	i64 i;
	i64 tag_id, tag_data_pos, tag_data_size;

	de_dbg(c, "developer area at %d", (int)pos);
	if(pos > c->infile->len - 2) {
		de_warn(c, "Bad developer area offset: %u", (unsigned int)pos);
		return;
	}

	de_dbg_indent(c, 1);
	num_tags = de_getu16le(pos);
	de_dbg(c, "number of tags: %d", (int)num_tags);
	for(i=0; i<num_tags; i++) {
		if(i>=200) break;
		tag_id = de_getu16le(pos + 2 + 10*i);
		tag_data_pos = de_getu32le(pos + 2 + 10*i + 2);
		tag_data_size = de_getu32le(pos + 2 + 10*i + 6);
		de_dbg(c, "tag #%d: id=%d, pos=%d, size=%d", (int)i, (int)tag_id,
			(int)tag_data_pos, (int)tag_data_size);

		if(tag_id==20) {
			// Tag 20 seems to contain Photoshop resources, though this is unconfirmed.
			de_dbg_indent(c, 1);
			// TODO: We could retrieve the pixel density settings from the Photoshop data,
			// but it's not clear whether they are ever useful.
			de_fmtutil_handle_photoshop_rsrc(c, c->infile, tag_data_pos, tag_data_size, 0x0);
			de_dbg_indent(c, -1);
		}
	}
	de_dbg_indent(c, -1);
}
Esempio n. 5
0
static void de_run_t64(deark *c, de_module_params *mparams)
{
	lctx *d = NULL;
	de_int64 pos;
	de_int64 i;

	d = de_malloc(c, sizeof(lctx));

	pos = 32;
	d->version = de_getui16le(pos);
	de_dbg(c, "version: 0x%04x\n", (int)d->version);
	if(d->version!=0x100 && d->version!=0x101) {
		de_warn(c, "Unexpected version number. This might not be a T64 file.\n");
	}

	d->max_dir_entries = de_getui16le(pos+2);
	d->used_dir_entries = de_getui16le(pos+4);
	de_dbg(c, "max dir entries = %d, files = %d\n", (int)d->max_dir_entries, (int)d->used_dir_entries);

	pos += 32;
	for(i=0; i<d->max_dir_entries; i++) {
		do_dir_entry(c, d, i, pos+32*i);
	}

	de_free(c, d);
}
Esempio n. 6
0
static void do_psf2_header(deark *c, lctx *d)
{
	de_int64 pos = 0;

	de_dbg(c, "PFXv2 header at %d\n", (int)pos);
	de_dbg_indent(c, 1);

	d->psf2_version = (de_uint32)de_getui32le(pos+4);
	de_dbg(c, "PSFv2 version number: %d\n", (int)d->psf2_version);
	if(d->psf2_version!=0) {
		de_warn(c, "Unknown PSFv2 version number: %d\n", (int)d->psf2_version);
	}

	d->headersize = de_getui32le(pos+8);
	de_dbg(c, "header size: %d\n", (int)d->headersize);

	d->flags = (de_uint32)de_getui32le(pos+12);
	de_dbg(c, "flags: 0x%08x\n", (unsigned int)d->flags);
	de_dbg_indent(c, 1);
	d->has_unicode_table = (d->flags & 0x01) ? 1 : 0;
	de_dbg(c, "has Unicode table: %s\n", d->has_unicode_table?"yes":"no");
	de_dbg_indent(c, -1);

	d->num_glyphs = de_getui32le(pos+16);
	de_dbg(c, "number of glyphs: %d\n", (int)d->num_glyphs);

	d->bytes_per_glyph = de_getui32le(pos+20);
	de_dbg(c, "bytes per glyph: %d\n", (int)d->bytes_per_glyph);

	d->glyph_height = de_getui32le(pos+24);
	d->glyph_width = de_getui32le(pos+28);
	de_dbg(c, "glyph dimensions: %dx%d\n", (int)d->glyph_width, (int)d->glyph_height);

	de_dbg_indent(c, -1);
}
Esempio n. 7
0
static void do_psf1_unicode_table(deark *c, lctx *d, struct de_bitmap_font *font)
{
	de_int64 cur_idx;
	de_int64 pos;
	int got_cp;
	int found_fffe;
	de_int32 n;

	de_dbg(c, "Unicode table at %d\n", (int)d->unicode_table_pos);
	de_dbg_indent(c, 1);

	pos = d->unicode_table_pos;
	cur_idx = 0;
	got_cp = 0; // Have we set the codepoint for glyph[cur_idx]?
	found_fffe = 0;

	while(1) {
		if(cur_idx >= d->num_glyphs) break;
		if(pos+1 >= c->infile->len) break;
		n = (de_int32)de_getui16le(pos);
		pos+=2;

		if(n==0xffff) {
			if(!got_cp) {
				de_warn(c, "Missing codepoint for char #%d\n", (int)cur_idx);
			}
			cur_idx++;
			got_cp = 0;
			found_fffe = 0;
			continue;
		}
		else if(n==0xfffe) {
			found_fffe = 1;
		}

		if(found_fffe) {
			// Anything after 0xfffe is a multi-codepoint character, which we
			// don't support.
			continue;
		}

		if(!got_cp) {
			de_dbg2(c, "char[%d] = U+%04x\n", (int)cur_idx, (unsigned int)n);
			font->char_array[cur_idx].codepoint_unicode = n;
			got_cp = 1;
			continue;
		}

		// This is an "extra" codepoint for the current glyph.
		do_extra_codepoint(c, d, font, cur_idx, n);
	}

	font->has_unicode_codepoints = 1;
	font->prefer_unicode = 1;

	de_dbg_indent(c, -1);
}
Esempio n. 8
0
// 16-color 160x100 (maybe up to 160x102) mode.
// This is really a text mode, and can be processed by do_char() as well.
static int do_cga16(deark *c, lctx *d)
{
	de_bitmap *img = NULL;
	i64 max_possible_height;
	i64 i, j;
	int retval = 0;
	u8 charcode, colorcode;
	i64 src_rowspan;
	u8 color0, color1;
	int charwarning = 0;

	de_declare_fmt(c, "BSAVE-PC 16-color CGA pseudo-graphics");

	img = de_bitmap_create_noinit(c);
	img->width = get_width(c, d, 160);
	img->height = get_height(c, d, 100);

	img->bytes_per_pixel = 3;

	// Every pair of bytes codes for two pixels; i.e. one byte per pixel.
	src_rowspan = img->width;
	max_possible_height = (d->data_size+src_rowspan-1)/src_rowspan;
	if(img->height > max_possible_height)
		img->height = max_possible_height;

	if(img->height < 1) {
		de_err(c, "Not enough data for this format");
		goto done;
	}

	for(j=0; j<img->height; j++) {
		for(i=0; i<img->width; i+=2) {
			charcode = de_getbyte(BSAVE_HDRSIZE + j*src_rowspan + i);
			colorcode = de_getbyte(BSAVE_HDRSIZE + j*src_rowspan + i+1);

			if(charwarning==0 && charcode!=0xdd && charcode!=0xde) {
				// TODO: We could also handle space characters and full-block characters,
				// at least. But maybe not worth the trouble.
				de_warn(c, "Unexpected code found (0x%02x). Format may not be correct.", (int)charcode);
				charwarning=1;
			}

			if(charcode==0xde) {
				color0 = colorcode>>4;
				color1 = colorcode&0x0f;
			}
			else {
				color1 = colorcode>>4;
				color0 = colorcode&0x0f;
			}

			de_bitmap_setpixel_rgb(img, i+0, j, de_palette_pc16(color0));
			de_bitmap_setpixel_rgb(img, i+1, j, de_palette_pc16(color1));
		}
Esempio n. 9
0
static void read_palette_ximg(deark *c, lctx *d)
{
	i64 pal_entries_in_file;
	i64 pal_entries_to_read;
	i64 i;
	i64 cr1, cg1, cb1;
	u8 cr, cg, cb;
	int range_warned = 0;
	char tmps[64];

	pal_entries_in_file = (d->header_size_in_bytes-22)/3;
	if(pal_entries_in_file<1) return;
	if(d->nplanes<=8)
		pal_entries_to_read = (i64)(1<<((unsigned int)d->nplanes));
	else
		pal_entries_to_read = 0;
	if(pal_entries_to_read>pal_entries_in_file)
		pal_entries_to_read = pal_entries_in_file;
	if(pal_entries_to_read>256)
		pal_entries_to_read = 256;

	if(pal_entries_in_file<1) return;

	de_dbg(c, "palette at %d", 22);
	de_dbg_indent(c, 1);
	for(i=0; i<pal_entries_to_read; i++) {
		cr1 = de_getu16be(22 + 6*i);
		cg1 = de_getu16be(22 + 6*i + 2);
		cb1 = de_getu16be(22 + 6*i + 4);

		cr = de_scale_1000_to_255(cr1);
		cg = de_scale_1000_to_255(cg1);
		cb = de_scale_1000_to_255(cb1);

		d->pal[i] = DE_MAKE_RGB(cr, cg, cb);

		de_snprintf(tmps, sizeof(tmps), "(%4d,%4d,%4d) "DE_CHAR_RIGHTARROW" ",
			(int)cr1, (int)cg1, (int)cb1);
		de_dbg_pal_entry2(c, (int)i, d->pal[i], tmps, NULL, NULL);

		// TODO: Maybe some out-of-range colors have special meaning?
		if(!range_warned && (cr1>1000 || cg1>1000 || cb1>1000)) {
			de_warn(c, "Bad palette color #%d: is (%d,%d,%d), max=(1000,1000,1000).",
				(int)i, (int)cr1, (int)cg1, (int)cb1);
			range_warned=1;
		}
	}
	de_dbg_indent(c, -1);
}
Esempio n. 10
0
File: wri.c Progetto: jsummers/deark
static int do_picture_ole_static_rendition(deark *c, lctx *d, struct para_info *pinfo,
	int rendition_idx, i64 pos1, i64 *bytes_consumed)
{
	i64 pos = pos1;
	i64 stringlen;
	struct de_stringreaderdata *srd_typename = NULL;

	pos += 4; // 0x00000501
	pos += 4; // "type" (probably already read by caller)

	stringlen = de_getu32le_p(&pos);
	srd_typename = dbuf_read_string(c->infile, pos, stringlen, 260, DE_CONVFLAG_STOP_AT_NUL,
		DE_ENCODING_ASCII);
	de_dbg(c, "typename: \"%s\"", ucstring_getpsz(srd_typename->str));
	pos += stringlen;

	if(!de_strcmp(srd_typename->sz, "DIB")) {
		pos += 12;
		de_dbg_indent(c, 1);
		de_run_module_by_id_on_slice(c, "dib", NULL, c->infile, pos,
			pinfo->thisparapos+pinfo->thisparalen-pos);
		de_dbg_indent(c, -1);
	}
	else if(!de_strcmp(srd_typename->sz, "METAFILEPICT")) {
		i64 dlen;
		pos += 8; // ??
		dlen = de_getu32le_p(&pos);
		de_dbg(c, "metafile size: %d", (int)dlen); // Includes "mfp", apparently
		pos += 8; // "mfp" struct
		dbuf_create_file_from_slice(c->infile, pos, dlen-8, "wmf", NULL, 0);
	}
	else if(!de_strcmp(srd_typename->sz, "BITMAP")) {
		do_static_bitmap(c, d, pinfo, pos);
	}
	else {
		de_warn(c, "Static OLE picture type \"%s\" is not supported",
			ucstring_getpsz(srd_typename->str));
	}

	de_destroy_stringreaderdata(c, srd_typename);
	return 0;
}
Esempio n. 11
0
File: tga.c Progetto: jsummers/deark
static void do_decode_thumbnail(deark *c, lctx *d)
{
	dbuf *unc_pixels = NULL;
	i64 hdrsize = 2;

	de_dbg(c, "thumbnail image at %d", (int)d->thumbnail_offset);
	de_dbg_indent(c, 1);

	// The thumbnail image is supposed to use the same format as the main image,
	// except without compression. (And the dimensions are obviously different.)
	// Presumably this means the origin, palette, etc. will be the same.
	// But based on the few TGA thumbnails we've seen, nobody reads the spec, and
	// it's anybody's guess what format the thumbnail will use.

	// TGA 2.0 spec says the dimensions are one *byte* each.
	d->thumbnail_image.width = (i64)de_getbyte(d->thumbnail_offset);
	d->thumbnail_image.height = (i64)de_getbyte(d->thumbnail_offset+1);
	de_dbg(c, "thumbnail dimensions: %d"DE_CHAR_TIMES"%d", (int)d->thumbnail_image.width, (int)d->thumbnail_image.height);

	if(d->thumbnail_image.width!=0 && d->thumbnail_image.height==0) {
		de_warn(c, "Thumbnail image height is 0. Assuming the file incorrectly uses "
			"16-bit thumbnail dimensions, instead of 8.");
		d->thumbnail_image.width = de_getu16le(d->thumbnail_offset);
		d->thumbnail_image.height = de_getu16le(d->thumbnail_offset+2);
		de_dbg(c, "revised thumbnail dimensions: %d"DE_CHAR_TIMES"%d", (int)d->thumbnail_image.width, (int)d->thumbnail_image.height);
		hdrsize = 4;
	}
	if(!de_good_image_dimensions(c, d->thumbnail_image.width, d->thumbnail_image.height)) goto done;

	d->thumbnail_image.img_size_in_bytes = d->thumbnail_image.height * d->thumbnail_image.width * d->bytes_per_pixel;
	unc_pixels = dbuf_open_input_subfile(c->infile, d->thumbnail_offset+hdrsize, d->thumbnail_image.img_size_in_bytes);

	do_decode_image(c, d, &d->thumbnail_image, unc_pixels, "thumb", DE_CREATEFLAG_IS_AUX);

done:
	dbuf_close(unc_pixels);
	de_dbg_indent(c, -1);
}
Esempio n. 12
0
File: wri.c Progetto: jsummers/deark
static void wri_convert_image_pal8(deark *c, i64 fpos,
	i64 rowspan, de_bitmap *img)
{
	i64 i, j;
	int badcolorflag = 0;
	// Palette is from libwps (except I might have red/blue swapped it).
	// I haven't confirmed that it's correct.
	static const u32 pal_part1[8] = {
		0x000000,0x800000,0x008000,0x808000,0x000080,0x800080,0x008080,0xc0c0c0
	};
	static const u32 pal_part2[8] = {
		0x808080,0xff0000,0x00ff00,0xffff00,0x0000ff,0xff00ff,0x00ffff,0xffffff
	};

	for(j=0; j<img->height; j++) {
		for(i=0; i<img->width; i++) {
			unsigned int palent;
			u32 clr;

			palent = de_getbyte(fpos+j*rowspan+i);
			if(palent<8) {
				clr = pal_part1[palent];
			}
			else if(palent>=248) {
				clr = pal_part2[palent-248];
			}
			else {
				clr = DE_MAKE_RGB(254,palent,254); // Just an arbitrary color
				badcolorflag = 1;
			}
			de_bitmap_setpixel_rgb(img, i, j, clr);
		}
	}
	if(badcolorflag) {
		de_warn(c, "Image uses nonportable colors");
	}
}
Esempio n. 13
0
static void do_read_palette(deark *c, lctx *d)
{
	de_int64 pal_size_in_bytes;

	if(d->pal_entries<1) return;

	pal_size_in_bytes = d->pal_entries*d->bytes_per_pal_entry;
	if(d->pal_pos+pal_size_in_bytes > d->bits_offset) {
		de_warn(c, "Palette at %d (size %d) overlaps bitmap at %d\n",
			(int)d->pal_pos, (int)pal_size_in_bytes, (int)d->bits_offset);
		if(d->version==DE_BMPVER_OS2V2) {
			do_os2v2_bad_palette(c, d);
		}
	}

	de_dbg(c, "color table at %d, %d entries\n", (int)d->pal_pos, (int)d->pal_entries);

	de_dbg_indent(c, 1);
	de_read_palette_rgb(c->infile, d->pal_pos, d->pal_entries, d->bytes_per_pal_entry,
		d->pal, 256, DE_GETRGBFLAG_BGR);

	d->pal_is_grayscale = de_is_grayscale_palette(d->pal, d->pal_entries);
	de_dbg_indent(c, -1);
}
Esempio n. 14
0
void de_run(deark *c)
{
	dbuf *orig_ifile = NULL;
	dbuf *subfile = NULL;
	de_int64 subfile_size;
	struct deark_module_info *module_to_use = NULL;
	const char *friendly_infn;

	if(c->modhelp_req && c->input_format_req) {
		do_modhelp(c);
		goto done;
	}

	if(c->input_style==DE_INPUTSTYLE_STDIN) {
		friendly_infn = "[stdin]";
	}
	else {
		friendly_infn = c->input_filename;
	}

	if(!friendly_infn) {
		de_err(c, "Input file not set\n");
		de_fatalerror(c);
		return;
	}

	de_register_modules(c);

	if(c->input_format_req) {
		module_to_use = de_get_module_by_id(c, c->input_format_req);
		if(!module_to_use) {
			de_err(c, "Unknown module \"%s\"\n", c->input_format_req);
			goto done;
		}
	}

	if(c->slice_size_req_valid) {
		de_dbg(c, "Input file: %s[%d,%d]\n", friendly_infn,
			(int)c->slice_start_req, (int)c->slice_size_req);
	}
	else if(c->slice_start_req) {
		de_dbg(c, "Input file: %s[%d]\n", friendly_infn,
			(int)c->slice_start_req);
	}
	else {
		de_dbg(c, "Input file: %s\n", friendly_infn);
	}

	if(c->input_style==DE_INPUTSTYLE_STDIN) {
		orig_ifile = dbuf_open_input_stdin(c, c->input_filename);
	}
	else {
		orig_ifile = dbuf_open_input_file(c, c->input_filename);
	}
	if(!orig_ifile) {
		goto done;
	}

	c->infile = orig_ifile;

	// If we are only supposed to look at a segment of the original file,
	// do that by creating a child dbuf, using dbuf_open_input_subfile().
	if(c->slice_start_req>0 || c->slice_size_req_valid) {
		if(c->slice_size_req_valid)
			subfile_size = c->slice_size_req;
		else
			subfile_size = dbuf_get_length(c->infile) - c->slice_start_req;
		subfile = dbuf_open_input_subfile(c->infile, c->slice_start_req, subfile_size);
		c->infile = subfile;
	}

	if(!module_to_use) {
		module_to_use = detect_module_for_file(c);
	}

	if(!module_to_use) {
		if(c->infile->len==0)
			de_err(c, "Unknown or unsupported file format (empty file)\n");
		else
			de_err(c, "Unknown or unsupported file format\n");
		goto done;
	}

	de_msg(c, "Module: %s\n", module_to_use->id);
	if(module_to_use->flags&DE_MODFLAG_NONWORKING) {
		de_warn(c, "The %s module is considered to be incomplete, and may "
			"not work properly. Caveat emptor.\n",
			module_to_use->id);
	}
	de_dbg2(c, "file size: %" INT64_FMT "\n", c->infile->len);

	if(!de_run_module(c, module_to_use, NULL)) {
		goto done;
	}

	// The DE_MODFLAG_NOEXTRACT flag means the module is not expected to extract
	// any files.
	if(c->num_files_extracted==0 && c->error_count==0 &&
		!(module_to_use->flags&DE_MODFLAG_NOEXTRACT))
	{
		de_msg(c, "No files found to extract!\n");
	}

done:
	if(subfile) dbuf_close(subfile);
	if(orig_ifile) dbuf_close(orig_ifile);
}
Esempio n. 15
0
static void de_run_icns_pass(deark *c, lctx *d, int pass)
{
	de_int64 i;
	de_int64 segment_pos;
	struct page_ctx *pg = NULL;
	int image_count;

	segment_pos = 8;
	image_count = 0;

	while(1) {
		de_int64 segment_len;

		if(pg) { de_free(c, pg); pg=NULL; }

		if(segment_pos+8 > d->file_size) break;

		pg = de_malloc(c, sizeof(struct page_ctx));
		pg->image_num = image_count;

		dbuf_read_fourcc(c->infile, segment_pos, &pg->code4cc, 0);

		segment_len = de_getui32be(segment_pos+4);

		pg->image_pos = segment_pos + 8;
		pg->image_len = segment_len - 8;

		if(pass==2) {
			de_dbg(c, "image #%d, type '%s', at %d, size=%d\n", pg->image_num, pg->code4cc.id_printable,
				(int)pg->image_pos, (int)pg->image_len);
		}
		if(segment_len<8 || segment_pos+segment_len > d->file_size) {
			if(pass==2) {
				de_err(c, "Invalid length for segment '%s' (%u)\n", pg->code4cc.id_printable,
					(unsigned int)segment_len);
			}
			break;
		}

		if(pass==2) {
			// Find this type code in the image_type_info array
			pg->type_info = NULL;
			for(i=0; image_type_info_arr[i].code!=0; i++) {
				if(image_type_info_arr[i].code==pg->code4cc.id) {
					pg->type_info = &image_type_info_arr[i];
					break;
				}
			}
			if(!pg->type_info) {
				de_warn(c, "(Image #%d) Unknown image type '%s'\n", pg->image_num, pg->code4cc.id_printable);
			}
		}

		if(pass==1) {
			switch(pg->code4cc.id) {
			case 0x69636d23: // icm# 16x12x1
				d->mkpos_16_16_1 = pg->image_pos + (16*12)/8;
				break;
			case 0x69637323: // ics# 16x16x1
				d->mkpos_16_16_1 = pg->image_pos + 16*16/8;
				break;
			case 0x49434e23: // ICN# 32x32x1
				d->mkpos_32_32_1 = pg->image_pos + 32*32/8;
				break;
			case 0x69636823: // ich# 48x48x1
				d->mkpos_48_48_1 = pg->image_pos + 48*48/8;
				break;
			case 0x73386d6b: // s8mk 16x16x8
				d->mkpos_16_16_8 = pg->image_pos;
				break;
			case 0x6c386d6b: // l8mk 32x32x8
				d->mkpos_32_32_8 = pg->image_pos;
				break;
			case 0x68386d6b: // h8mk 48x48x8
				d->mkpos_48_48_8 = pg->image_pos;
				break;
			case 0x74386d6b: // t8mk 128x128x8
				d->mkpos_128_128_8 = pg->image_pos;
				break;
			}
		}
		else if(pass==2) {
			de_dbg_indent(c, 1);
			do_icon(c, d, pg);
			de_dbg_indent(c, -1);
		}

		image_count++;
		segment_pos += segment_len;
	}

	if(pg) de_free(c, pg);
}
Esempio n. 16
0
static void do_icon(deark *c, lctx *d, struct page_ctx *pg)
{
	de_int64 expected_image_size;
	int is_compressed;

	if(!pg->type_info) return; // Shouldn't happen.

	de_strlcpy(pg->filename_token, "", sizeof(pg->filename_token));

	if(pg->type_info->image_type==IMGTYPE_MASK) {
		de_dbg(c, "transparency mask\n");
		return;
	}

	if(pg->type_info->image_type==IMGTYPE_EMBEDDED_FILE) {
		de_snprintf(pg->filename_token, sizeof(pg->filename_token), "%dx%d",
			(int)pg->type_info->width, (int)pg->type_info->height);
		do_extract_png_or_jp2(c, d, pg);
		return;
	}

	if(pg->type_info->image_type!=IMGTYPE_IMAGE &&
		pg->type_info->image_type!=IMGTYPE_IMAGE_AND_MASK)
	{
		return;
	}

	// At this point we know it's a regular image (or an image+mask)

	// Note - This pg->rowspan is arguably incorrect for 24-bit images, since
	// rows aren't stored contiguously.
	pg->rowspan = ((pg->type_info->bpp * pg->type_info->width)+7)/8;

	expected_image_size = pg->rowspan * pg->type_info->height;
	if(pg->type_info->image_type==IMGTYPE_IMAGE_AND_MASK) {
		expected_image_size *= 2;
	}

	is_compressed = (pg->type_info->bpp==24) ? 1 : 0;

	if(!is_compressed) {
		if(pg->image_len < expected_image_size) {
			de_err(c, "(Image #%d) Premature end of image (expected %d bytes, found %d)\n",
				pg->image_num, (int)expected_image_size, (int)pg->image_len);
			return;
		}
		if(pg->image_len > expected_image_size) {
			de_warn(c, "(Image #%d) Extra image data found (expected %d bytes, found %d)\n",
				pg->image_num, (int)expected_image_size, (int)pg->image_len);
		}
	}

	find_mask(c, d, pg);

	de_snprintf(pg->filename_token, sizeof(pg->filename_token), "%dx%dx%d",
		(int)pg->type_info->width, (int)pg->type_info->height, (int)pg->type_info->bpp);

	de_dbg(c, "image dimensions: %dx%d, bpp: %d\n",
		pg->type_info->width, pg->type_info->height, pg->type_info->bpp);

	if(pg->type_info->bpp==1 || pg->type_info->bpp==4 || pg->type_info->bpp==8) {
		do_decode_1_4_8bit(c, d, pg);
		return;
	}
	else if(pg->type_info->bpp==24) {
		do_decode_24bit(c, d, pg);
		return;
	}

	de_warn(c, "(Image #%d) Image type '%s' is not supported\n", pg->image_num, pg->code4cc.id_printable);
}
Esempio n. 17
0
static int do_gzip_read_member(deark *c, lctx *d, i64 pos1, i64 *member_size)
{
	u8 b0, b1;
	i64 pos;
	i64 n;
	i64 foundpos;
	i64 string_len;
	i64 cmpr_data_len;
	i64 mod_time_unix;
	u32 crc_calculated;
	de_ucstring *member_name = NULL;
	int saved_indent_level;
	int ret;
	struct member_data *md = NULL;
	int retval = 0;

	md = de_malloc(c, sizeof(struct member_data));

	de_dbg_indent_save(c, &saved_indent_level);

	de_dbg(c, "gzip member at %d", (int)pos1);
	de_dbg_indent(c, 1);
	pos = pos1;

	b0 = de_getbyte(pos+0);
	b1 = de_getbyte(pos+1);
	if(b0!=0x1f || b1!=0x8b) {
		de_err(c, "Invalid gzip signature at %d. This is not a valid gzip file.",
			(int)pos1);
		goto done;
	}

	md->cmpr_code = de_getbyte(pos+2);
	if(md->cmpr_code!=0x08) {
		de_err(c, "Unsupported compression type (%d)", (int)md->cmpr_code);
		goto done;
	}

	md->flags = de_getbyte(pos+3);
	de_dbg(c, "flags: 0x%02x", (unsigned int)md->flags);
	pos += 4;

	mod_time_unix = de_getu32le(pos);
	de_unix_time_to_timestamp(mod_time_unix, &md->mod_time_ts, 0x1);
	if(md->mod_time_ts.is_valid) {
		char timestamp_buf[64];
		de_timestamp_to_string(&md->mod_time_ts, timestamp_buf, sizeof(timestamp_buf), 0);
		de_dbg(c, "mod time: %" I64_FMT " (%s)", mod_time_unix, timestamp_buf);
	}
	pos += 4;

	b0 = de_getbyte(pos++);
	de_dbg(c, "extra flags: 0x%02x", (unsigned int)b0);

	b0 = de_getbyte(pos++);
	de_dbg(c, "OS or filesystem: %d (%s)", (int)b0, get_os_name(b0));

	if(md->flags & GZIPFLAG_FEXTRA) {
		n = de_getu16le(pos); // XLEN
		// TODO: It might be interesting to dissect these extra fields, but it's
		// hard to find even a single file that uses them.
		de_dbg(c, "[extra fields at %d, dpos=%d, dlen=%d]",
			(int)pos, (int)(pos+2), (int)n);
		pos += 2;
		pos += n;
	}

	if(md->flags & GZIPFLAG_FNAME) {
		ret =  dbuf_search_byte(c->infile, 0x00, pos, c->infile->len - pos,
			&foundpos);
		if(!ret) {
			de_err(c, "Invalid NAME field");
			goto done;
		}

		string_len = foundpos - pos;

		member_name = ucstring_create(c);
#define DE_GZIP_MAX_FNLEN 300
		dbuf_read_to_ucstring_n(c->infile, pos, string_len, DE_GZIP_MAX_FNLEN,
			member_name, 0, DE_ENCODING_LATIN1);
		de_dbg(c, "file name at %d, len=%d: \"%s\"", (int)pos, (int)string_len,
			ucstring_getpsz_d(member_name));
		pos = foundpos + 1;
	}

	if(md->flags & GZIPFLAG_FCOMMENT) {
		ret =  dbuf_search_byte(c->infile, 0x00, pos, c->infile->len - pos,
			&foundpos);
		if(!ret) {
			de_err(c, "Invalid COMMENT field");
			goto done;
		}
		pos = foundpos + 1;
	}

	if(md->flags & GZIPFLAG_FHCRC) {
		md->crc16_reported = (u32)de_getu16le(pos);
		de_dbg(c, "crc16 (reported): 0x%04x", (unsigned int)md->crc16_reported);
		pos += 2;
	}

	de_dbg(c, "compressed blocks at %d", (int)pos);

	if(!d->output_file) {
		// Although any member can have a name and mod time, this metadata
		// is ignored for members after the first one.
		de_finfo *fi = NULL;

		fi = de_finfo_create(c);

		if(member_name && c->filenames_from_file) {
			de_finfo_set_name_from_ucstring(c, fi, member_name, 0);
			fi->original_filename_flag = 1;
		}

		if(md->mod_time_ts.is_valid) {
			fi->mod_time = md->mod_time_ts;
		}

		d->output_file = dbuf_create_output_file(c, member_name?NULL:"bin", fi, 0);

		de_finfo_destroy(c, fi);
	}

	d->output_file->writecallback_fn = our_writecallback;
	d->output_file->userdata = (void*)md;
	md->crco = d->crco;
	de_crcobj_reset(md->crco);

	ret = de_decompress_deflate(c->infile, pos, c->infile->len - pos, d->output_file,
		0, &cmpr_data_len, 0);

	crc_calculated = de_crcobj_getval(md->crco);
	d->output_file->writecallback_fn = NULL;
	d->output_file->userdata = NULL;

	if(!ret) goto done;
	pos += cmpr_data_len;

	de_dbg(c, "crc32 (calculated): 0x%08x", (unsigned int)crc_calculated);

	md->crc32_reported = (u32)de_getu32le(pos);
	de_dbg(c, "crc32 (reported)  : 0x%08x", (unsigned int)md->crc32_reported);
	pos += 4;

	if(crc_calculated != md->crc32_reported) {
		de_warn(c, "CRC check failed: Expected 0x%08x, got 0x%08x",
			(unsigned int)md->crc32_reported, (unsigned int)crc_calculated);
	}

	md->isize = de_getu32le(pos);
	de_dbg(c, "uncompressed size (mod 2^32): %u", (unsigned int)md->isize);
	pos += 4;

	retval = 1;

done:
	if(retval)
		*member_size = pos - pos1;
	else
		*member_size = 0;
	ucstring_destroy(member_name);
	de_free(c, md);
	de_dbg_indent_restore(c, saved_indent_level);
	return retval;
}
Esempio n. 18
0
File: tga.c Progetto: jsummers/deark
static void do_decode_image_default(deark *c, lctx *d, struct tgaimginfo *imginfo, dbuf *unc_pixels,
	de_finfo *fi, unsigned int createflags)
{
	de_bitmap *img = NULL;
	i64 i, j;
	u8 b;
	u32 clr;
	u8 a;
	i64 rowspan;
	int output_bypp;
	unsigned int getrgbflags;
	i64 interleave_stride;
	i64 interleave_pass;
	i64 cur_rownum; // 0-based, does not account for bottom-up orientation

	if(d->pixel_depth==1) {
		de_warn(c, "1-bit TGA images are not portable, and may not be decoded correctly");
		rowspan = (imginfo->width+7)/8;
	}
	else {
		rowspan = imginfo->width*d->bytes_per_pixel;
	}

	if(d->color_type==TGA_CLRTYPE_GRAYSCALE || d->pixel_depth==1)
		output_bypp=1;
	else
		output_bypp=3;

	if(d->has_alpha_channel)
		output_bypp++;

	if(d->file_format==FMT_VST)
		getrgbflags = 0;
	else
		getrgbflags = DE_GETRGBFLAG_BGR;

	img = de_bitmap_create(c, imginfo->width, imginfo->height, output_bypp);

	switch(d->interleave_mode) {
	case 1: interleave_stride = 2; break;
	case 2: interleave_stride = 4; break;
	default: interleave_stride = 1;
	}

	cur_rownum = 0;
	interleave_pass = 0;

	for(j=0; j<imginfo->height; j++) {
		i64 j_adj;

		if(d->top_down)
			j_adj = cur_rownum;
		else
			j_adj = imginfo->height-1-cur_rownum;

		// Update the row number for next time
		cur_rownum += interleave_stride;
		if(cur_rownum >= imginfo->height) {
			// Went past the end of the image; move back to near the start.
			interleave_pass++;
			cur_rownum = interleave_pass;
		}

		for(i=0; i<imginfo->width; i++) {
			i64 i_adj;

			if(d->right_to_left)
				i_adj = imginfo->width-1-i;
			else
				i_adj = i;

			if(d->pixel_depth==1) {
				de_convert_row_bilevel(unc_pixels, j*rowspan, img, j_adj, 0);
			}
			else if(d->color_type==TGA_CLRTYPE_TRUECOLOR && (d->pixel_depth==15 || d->pixel_depth==16)) {
				clr = (u32)dbuf_getu16le(unc_pixels, j*rowspan + i*d->bytes_per_pixel);
				clr = de_rgb555_to_888(clr);
				de_bitmap_setpixel_rgb(img, i_adj, j_adj, clr);
			}
			else if(d->color_type==TGA_CLRTYPE_TRUECOLOR) {
				clr = dbuf_getRGB(unc_pixels, j*rowspan + i*d->bytes_per_pixel, getrgbflags);
				if(d->has_alpha_channel) {
					a = dbuf_getbyte(unc_pixels, j*rowspan + i*d->bytes_per_pixel+3);
					de_bitmap_setpixel_rgba(img, i_adj, j_adj, DE_SET_ALPHA(clr, a));
				}
				else {
					de_bitmap_setpixel_rgb(img, i_adj, j_adj, clr);
				}
			}
			else if(d->color_type==TGA_CLRTYPE_GRAYSCALE) {
				b = dbuf_getbyte(unc_pixels, j*rowspan + i*d->bytes_per_pixel);
				de_bitmap_setpixel_gray(img, i_adj, j_adj, b);
			}
			else if(d->color_type==TGA_CLRTYPE_PALETTE) {
				b = dbuf_getbyte(unc_pixels, j*rowspan + i*d->bytes_per_pixel);
				de_bitmap_setpixel_rgb(img, i_adj, j_adj, d->pal[(unsigned int)b]);
			}
		}
	}

	de_bitmap_write_to_file_finfo(img, fi, createflags);

	de_bitmap_destroy(img);
}
Esempio n. 19
0
File: wri.c Progetto: jsummers/deark
// pos1 points to the ole_id field (should be 0x00000501).
// Caller must have looked ahead to check the type.
static int do_picture_ole_embedded_rendition(deark *c, lctx *d, struct para_info *pinfo,
	int rendition_idx, i64 pos1, i64 *bytes_consumed)
{
	i64 pos = pos1;
	i64 stringlen;
	i64 data_len;
	u8 buf[16];
	struct de_stringreaderdata *srd_typename = NULL;
	struct de_stringreaderdata *srd_filename = NULL;
	struct de_stringreaderdata *srd_params = NULL;

	pos += 4; // 0x00000501
	pos += 4; // "type" (probably already read by caller)

	stringlen = de_getu32le_p(&pos);
	srd_typename = dbuf_read_string(c->infile, pos, stringlen, 260, DE_CONVFLAG_STOP_AT_NUL,
		DE_ENCODING_ASCII);
	de_dbg(c, "typename: \"%s\"", ucstring_getpsz(srd_typename->str));
	pos += stringlen;

	stringlen = de_getu32le_p(&pos);
	srd_filename = dbuf_read_string(c->infile, pos, stringlen, 260, DE_CONVFLAG_STOP_AT_NUL,
		DE_ENCODING_ASCII);
	de_dbg(c, "filename: \"%s\"", ucstring_getpsz(srd_filename->str));
	pos += stringlen;

	stringlen = de_getu32le_p(&pos);
	srd_params = dbuf_read_string(c->infile, pos, stringlen, 260, DE_CONVFLAG_STOP_AT_NUL,
		DE_ENCODING_ASCII);
	de_dbg(c, "params: \"%s\"", ucstring_getpsz(srd_params->str));
	pos += stringlen;

	data_len = de_getu32le_p(&pos);
	de_dbg(c, "embedded ole rendition data: pos=%d, len=%d", (int)pos, (int)data_len);

	// TODO: I don't know the extent to which it's better to sniff the data, or
	// rely on the typename.
	de_read(buf, pos, sizeof(buf));

	if(!de_strcmp(srd_typename->sz, "CDraw") &&
		!de_memcmp(&buf[0], (const void*)"RIFF", 4) &&
		!de_memcmp(&buf[8], (const void*)"CDR", 3) )
	{
		// Looks like CorelDRAW
		dbuf_create_file_from_slice(c->infile, pos, data_len, "cdr", NULL, 0);
	}
	else if(buf[0]=='B' && buf[1]=='M') {
		// TODO: Detect true length of data
		dbuf_create_file_from_slice(c->infile, pos, data_len, "bmp", NULL, 0);
	}
	else {
		if(d->extract_ole) {
			extract_unknown_ole_obj(c, d, pos, data_len, srd_typename);
		}
		else {
			de_warn(c, "Unknown/unsupported type of OLE object (\"%s\") at %d",
				ucstring_getpsz(srd_typename->str), (int)pos1);
		}
	}

	pos += data_len;
	*bytes_consumed = pos - pos1;

	de_destroy_stringreaderdata(c, srd_typename);
	de_destroy_stringreaderdata(c, srd_filename);
	de_destroy_stringreaderdata(c, srd_params);
	return 1;
}
Esempio n. 20
0
File: tga.c Progetto: jsummers/deark
static void do_read_extension_area(deark *c, lctx *d, i64 pos)
{
	i64 ext_area_size;
	i64 k;
	int has_date;
	de_ucstring *s = NULL;
	i64 val[6];

	de_dbg(c, "extension area at %d", (int)pos);
	if(pos > c->infile->len - 2) {
		de_warn(c, "Bad extension area offset: %u", (unsigned int)pos);
		return;
	}

	de_dbg_indent(c, 1);

	s = ucstring_create(c);

	ext_area_size = de_getu16le(pos);
	de_dbg(c, "extension area size: %d", (int)ext_area_size);
	if(ext_area_size<495) goto done;

	d->has_extension_area = 1;

	ucstring_empty(s);
	dbuf_read_to_ucstring(c->infile, pos+2, 41, s, DE_CONVFLAG_STOP_AT_NUL, DE_ENCODING_ASCII);
	ucstring_strip_trailing_spaces(s);
	de_dbg(c, "author: \"%s\"", ucstring_getpsz_d(s));

	for(k=0; k<4; k++) {
		ucstring_empty(s);
		dbuf_read_to_ucstring(c->infile, pos+43+81*k, 81, s, DE_CONVFLAG_STOP_AT_NUL, DE_ENCODING_ASCII);
		ucstring_strip_trailing_spaces(s);
		de_dbg(c, "comment line %d: \"%s\"", (int)k, ucstring_getpsz_d(s));
	}

	// date/time: pos=367, size=12
	has_date = 0;
	for(k=0; k<6; k++) {
		val[k] = de_getu16le(pos+367+2*k);
		if(val[k]!=0) has_date = 1;
	}
	if(has_date) {
		char timestamp_buf[64];

		de_make_timestamp(&d->mod_time, val[2], val[0], val[1], val[3], val[4], val[5]);
		d->mod_time.tzcode = DE_TZCODE_LOCAL;
		de_timestamp_to_string(&d->mod_time, timestamp_buf, sizeof(timestamp_buf), 0);
		de_dbg(c, "timestamp: %s", timestamp_buf);
	}

	// Job name: pos=379, size=41 (not implemented)
	// Job time: pos=420, size=6 (not implemented)

	ucstring_empty(s);
	dbuf_read_to_ucstring(c->infile, pos+426, 41, s, DE_CONVFLAG_STOP_AT_NUL, DE_ENCODING_ASCII);
	ucstring_strip_trailing_spaces(s);
	de_dbg(c, "software id: \"%s\"", ucstring_getpsz_d(s));

	val[0] = de_getu16le(pos+467);
	val[1] = (i64)de_getbyte(pos+469);
	if(val[0]!=0 || val[1]!=32) {
		de_dbg(c, "software version: %u,%u,%u",
			(unsigned int)(val[0]/100), (unsigned int)(val[0]%100),
			(unsigned int)val[1]);
	}

	val[0] = de_getu32le(pos+470);
	if(val[0]!=0) {
		de_dbg(c, "background color: 0x%08x", (unsigned int)val[0]);
	}

	// TODO: Retain the aspect ratio. (Need sample files. Nobody seems to use this field.)
	d->aspect_ratio_num = de_getu16le(pos+474);
	d->aspect_ratio_den = de_getu16le(pos+476);
	if(d->aspect_ratio_den!=0) {
		de_dbg(c, "aspect ratio: %d/%d", (int)d->aspect_ratio_num, (int)d->aspect_ratio_den);
	}

	// Gamma: pos=478, size=4 (not implemented)
	// Color correction table offset: pos=482, size=4 (not implemented)

	d->thumbnail_offset = de_getu32le(pos+486);
	de_dbg(c, "thumbnail image offset: %d", (int)d->thumbnail_offset);

	val[0] = de_getu32le(pos+490);
	de_dbg(c, "scan line table offset: %"I64_FMT, val[0]);

	d->attributes_type = de_getbyte(pos+494);
	de_dbg(c, "attributes type: %d", (int)d->attributes_type);
	if(d->attributes_type==0 && d->num_attribute_bits!=0) {
		de_warn(c, "Incompatible \"number of attribute bits\" (%d) and \"attributes type\" "
			"(%d) fields. Transparency may not be handled correctly.",
			(int)d->num_attribute_bits, (int)d->attributes_type);
	}

done:
	de_dbg_indent(c, -1);
	ucstring_destroy(s);
}
Esempio n. 21
0
File: rpm.c Progetto: jsummers/deark
static void de_run_rpm(deark *c, de_module_params *mparams)
{
	lctx *d = NULL;
	i64 pos;
	u8 buf[8];
	const char *ext;
	i64 section_size = 0;
	de_finfo *fi = NULL;
	char filename[128];

	d = de_malloc(c, sizeof(lctx));

	if(!do_lead_section(c, d)) {
		goto done;
	}

	pos = 96;

	if(!do_header_structure(c, d, 1, pos, &section_size)) {
		goto done;
	}
	pos += section_size;

	// Header structures are 8-byte aligned. The first one always starts at
	// offset 96, so we don't have to worry about it. But we need to make
	// sure the second one is aligned.
	pos = ((pos + 7)/8)*8;

	if(!do_header_structure(c, d, 0, pos, &section_size)) {
		goto done;
	}
	pos += section_size;

	de_dbg(c, "data pos: %d", (int)pos);
	if(pos > c->infile->len) goto done;

	// There is usually a tag that indicates the compression format, but we
	// primarily figure out the format by sniffing its magic number, on the
	// theory that that's more reliable.

	// TODO: I think it's also theoretically possible that it could use an archive
	// format other than cpio.

	de_read(buf, pos, 8);

	if(buf[0]==0x1f && buf[1]==0x8b) {
		ext = "cpio.gz";
	}
	else if(buf[0]==0x42 && buf[1]==0x5a && buf[2]==0x68) {
		ext = "cpio.bz2";
	}
	else if(buf[0]==0xfd && buf[1]==0x37 && buf[2]==0x7a) {
		ext = "cpio.xz";
	}
	else if(d->cmpr_type==DE_RPM_CMPR_LZMA || buf[0]==0x5d) {
		ext = "cpio.lzma";
	}
	else {
		de_warn(c, "Unidentified compression or archive format");
		ext = "cpio.bin";
	}

	if(d->name_srd && c->filenames_from_file) {
		const char *version2 = "x";
		const char *release2 = "x";

		if(d->version_srd) version2 = d->version_srd->sz;
		if(d->release_srd) release2 = d->release_srd->sz;

		fi = de_finfo_create(c);
		de_snprintf(filename, sizeof(filename), "%s-%s.%s",
			d->name_srd->sz, version2, release2);
		de_finfo_set_name_from_sz(c, fi, filename, 0, DE_ENCODING_ASCII);
	}

	dbuf_create_file_from_slice(c->infile, pos, c->infile->len - pos, ext, fi, 0);

done:
	de_finfo_destroy(c, fi);
	if(d) {
		de_destroy_stringreaderdata(c, d->name_srd);
		de_destroy_stringreaderdata(c, d->release_srd);
		de_destroy_stringreaderdata(c, d->version_srd);
		de_free(c, d);
	}
}
Esempio n. 22
0
File: tga.c Progetto: jsummers/deark
// TGA transparency is kind of a mess. Multiple ways of labeling it, some of
// which are ambiguous... Files that have inconsistent labels... Files that
// claim to have transparency but don't, or that claim not to but do...
static void do_prescan_image(deark *c, lctx *d, dbuf *unc_pixels)
{
	i64 num_pixels;
	i64 i;
	u8 b[4];
	int has_alpha_0 = 0;
	int has_alpha_partial = 0;
	int has_alpha_255 = 0;

	if(d->pixel_depth!=32 || d->color_type!=TGA_CLRTYPE_TRUECOLOR) {
		return;
	}

	if(d->num_attribute_bits!=0 && d->num_attribute_bits!=8) {
		de_warn(c, "%d-bit attribute channel not supported. Transparency disabled.",
			(int)d->num_attribute_bits);
		return;
	}

	if(d->has_extension_area) {
		if(d->attributes_type==0) {
			// attributes_type==0 technically also means there is no transparency,
			// but this cannot be trusted.
			;
		}
		if(d->attributes_type==1 || d->attributes_type==2) {
			// Indicates that attribute data can be ignored.
			return;
		}
		else if(d->attributes_type==3 && d->num_attribute_bits==8) {
			// Alpha channel seems to be labeled correctly.
			// Trust it, and don't scan the image.
			d->has_alpha_channel = 1;
			return;
		}
		else if(d->attributes_type==4) {
			// Sigh. The spec shows that Field 24 (Attributes Type) == 4 is for
			// pre-multiplied alpha. Then the discussion section says that
			// Field *23* ("Attributes Type") == *3* is for premultiplied alpha.
			// I have to guess that the "23" and "3" are clerical errors, but that
			// doesn't do me much good unless all TGA developers made the same guess.
			de_warn(c, "Pre-multiplied alpha is not supported. Disabling transparency.");
			return;
		}
	}

	de_dbg(c, "pre-scanning image");

	num_pixels = d->main_image.width * d->main_image.height;
	for(i=0; i<num_pixels; i++) {
		// TODO: This may run a lot slower than it ought to.
		dbuf_read(unc_pixels, b, i*4, 4);
		// BGRA order
		if(b[3]==0x00) {
			has_alpha_0 = 1;
		}
		else if(b[3]==0xff) {
			has_alpha_255 = 1;
		}
		else {
			has_alpha_partial = 1;
			break;
		}
		if(has_alpha_0 && has_alpha_255) {
			break;
		}
	}
	// Note that the has_alpha_* variables may not all be accurate at this point,
	// because we stop scanning when we have the info we need.

	if(has_alpha_partial || (has_alpha_0 && has_alpha_255)) {
		if(d->num_attribute_bits==0) {
			de_warn(c, "Detected likely alpha channel. Enabling transparency, even though "
				"the image is labeled as non-transparent.");
		}
		d->has_alpha_channel = 1;
		return;
	}
	else if(has_alpha_0) { // All 0x00
		if(d->num_attribute_bits!=0) {
			de_warn(c, "Non-visible image detected. Disabling transparency.");
		}
		else {
			de_dbg(c, "potential alpha channel ignored: all 0 bits");
		}
		return;
	}
	else { // All 0xff
		de_dbg(c, "potential alpha channel is moot: all 1 bits");
		return;
	}
}
Esempio n. 23
0
// Gathers information about a DIB.
// If DE_BMPINFO_HAS_FILEHEADER flag is set, pos points to the BITMAPFILEHEADER.
// Otherwise, it points to the BITMAPINFOHEADER.
// Caller allocates bi.
// Returns 0 if BMP is invalid.
int de_fmtutil_get_bmpinfo(deark *c, dbuf *f, struct de_bmpinfo *bi, i64 pos,
	i64 len, unsigned int flags)
{
	i64 fhs; // file header size
	i64 bmih_pos;
	struct de_fourcc cmpr4cc;
	char cmprname_dbgstr[80];

	de_zeromem(bi, sizeof(struct de_bmpinfo));
	de_zeromem(&cmpr4cc, sizeof(struct de_fourcc));

	fhs = (flags & DE_BMPINFO_HAS_FILEHEADER) ? 14 : 0;

	if(fhs+len < 16) return 0;

	if(fhs) {
		if(flags & DE_BMPINFO_HAS_HOTSPOT) {
			bi->hotspot_x = dbuf_getu16le(f, pos+6);
			bi->hotspot_y = dbuf_getu16le(f, pos+8);
			de_dbg(c, "hotspot: (%d,%d)", (int)bi->hotspot_x, (int)bi->hotspot_y);
		}

		bi->bitsoffset = dbuf_getu32le(f, pos+10);
		de_dbg(c, "bits offset: %d", (int)bi->bitsoffset);
	}

	bmih_pos = pos + fhs;

	bi->infohdrsize = dbuf_getu32le(f, bmih_pos);

	if(bi->infohdrsize==0x474e5089 && (flags & DE_BMPINFO_ICO_FORMAT)) {
		// We don't examine PNG-formatted icons, but we can identify them.
		bi->infohdrsize = 0;
		bi->file_format = DE_BMPINFO_FMT_PNG;
		return 1;
	}

	de_dbg(c, "info header size: %d", (int)bi->infohdrsize);

	if(bi->infohdrsize==12) {
		bi->bytes_per_pal_entry = 3;
		bi->width = dbuf_getu16le(f, bmih_pos+4);
		bi->height = dbuf_getu16le(f, bmih_pos+6);
		bi->bitcount = dbuf_getu16le(f, bmih_pos+10);
	}
	else if(bi->infohdrsize>=16 && bi->infohdrsize<=124) {
		bi->bytes_per_pal_entry = 4;
		bi->width = dbuf_getu32le(f, bmih_pos+4);
		bi->height = dbuf_geti32le(f, bmih_pos+8);
		if(bi->height<0) {
			bi->is_topdown = 1;
			bi->height = -bi->height;
		}
		bi->bitcount = dbuf_getu16le(f, bmih_pos+14);
		if(bi->infohdrsize>=20) {
			bi->compression_field = (u32)dbuf_getu32le(f, bmih_pos+16);
			if(flags & DE_BMPINFO_CMPR_IS_4CC) {
				dbuf_read_fourcc(f, bmih_pos+16, &cmpr4cc, 4, 0x0);
			}
		}
		if(bi->infohdrsize>=24) {
			bi->sizeImage_field = dbuf_getu32le(f, bmih_pos+20);
		}
		if(bi->infohdrsize>=36) {
			bi->pal_entries = dbuf_getu32le(f, bmih_pos+32);
		}
	}
	else {
		return 0;
	}

	if(flags & DE_BMPINFO_ICO_FORMAT) bi->height /= 2;

	if(bi->bitcount>=1 && bi->bitcount<=8) {
		if(bi->pal_entries==0) {
			bi->pal_entries = (i64)(1<<(unsigned int)bi->bitcount);
		}
		// I think the NumColors field (in icons) is supposed to be the maximum number of
		// colors implied by the bit depth, not the number of colors in the palette.
		bi->num_colors = (i64)(1<<(unsigned int)bi->bitcount);
	}
	else {
		// An arbitrary value. All that matters is that it's >=256.
		bi->num_colors = 16777216;
	}

	de_dbg_dimensions(c, bi->width, bi->height);
	de_dbg(c, "bit count: %d", (int)bi->bitcount);

	if((flags & DE_BMPINFO_CMPR_IS_4CC) && (bi->compression_field>0xffff)) {
		de_snprintf(cmprname_dbgstr, sizeof(cmprname_dbgstr), "'%s'", cmpr4cc.id_dbgstr);
	}
	else {
		de_fmtutil_get_bmp_compression_name(bi->compression_field,
			cmprname_dbgstr, sizeof(cmprname_dbgstr), 0);
	}
	de_dbg(c, "compression: %u (%s)", (unsigned int)bi->compression_field, cmprname_dbgstr);

	if(bi->sizeImage_field!=0) {
		de_dbg(c, "sizeImage: %u", (unsigned int)bi->sizeImage_field);
	}

	de_dbg(c, "palette entries: %u", (unsigned int)bi->pal_entries);
	if(bi->pal_entries>256 && bi->bitcount>8) {
		de_warn(c, "Ignoring bad palette size (%u entries)", (unsigned int)bi->pal_entries);
		bi->pal_entries = 0;
	}

	bi->pal_bytes = bi->bytes_per_pal_entry*bi->pal_entries;
	bi->size_of_headers_and_pal = fhs + bi->infohdrsize + bi->pal_bytes;

	// FIXME: cmpr type 3 doesn't always mean BITFIELDS
	if(bi->compression_field==3) {
		bi->size_of_headers_and_pal += 12; // BITFIELDS
	}

	bi->is_compressed = !((bi->compression_field==0) ||
		(bi->compression_field==3 && bi->bitcount>1));

	if(!de_good_image_dimensions(c, bi->width, bi->height)) {
		return 0;
	}

	// TODO: This needs work, to decide how to handle compressed images.
	// TODO: What about BI_BITFIELDS images?
	if(bi->compression_field==0) {
		// Try to figure out the true size of the resource, minus any padding.

		bi->rowspan = ((bi->bitcount*bi->width +31)/32)*4;
		bi->foreground_size = bi->rowspan * bi->height;
		de_dbg(c, "foreground size: %d", (int)bi->foreground_size);

		if(flags & DE_BMPINFO_ICO_FORMAT) {
			bi->mask_rowspan = ((bi->width +31)/32)*4;
			bi->mask_size = bi->mask_rowspan * bi->height;
			de_dbg(c, "mask size: %d", (int)bi->mask_size);
		}
		else {
			bi->mask_size = 0;
		}

		bi->total_size = bi->size_of_headers_and_pal + bi->foreground_size + bi->mask_size;
	}
	else {
		// Don't try to figure out the true size of compressed or other unusual images.
		bi->total_size = len;
	}

	return 1;
}
Esempio n. 24
0
static int do_read_header(deark *c, lctx *d)
{
	de_int64 dfType;
	de_int64 dfPixWidth;
	de_int64 dfPixHeight;
	de_int64 dfMaxWidth;
	int is_vector = 0;
	int retval = 0;

	d->fnt_version = de_getui16le(0);
	de_dbg(c, "dfVersion: 0x%04x\n", (int)d->fnt_version);

	if(d->fnt_version==0x0300)
		d->hdrsize = 148;
	else
		d->hdrsize = 118;

	dfType = de_getui16le(66);
	de_dbg(c, "dfType: 0x%04x\n", (int)dfType);
	is_vector = (dfType&0x1)?1:0;
	de_dbg(c, "Font type: %s\n", is_vector?"vector":"bitmap");

	d->dfPoints = de_getui16le(68);
	de_dbg(c, "dfPoints: %d\n", (int)d->dfPoints);

	dfPixWidth = de_getui16le(86);
	de_dbg(c, "dfPixWidth: %d\n", (int)dfPixWidth);
	dfPixHeight = de_getui16le(88);
	de_dbg(c, "dfPixHeight: %d\n", (int)dfPixHeight);

	d->dfCharSet = de_getbyte(85);
	de_dbg(c, "charset: 0x%02x\n", (int)d->dfCharSet);
	if(d->dfCharSet==0x00) { // "ANSI"
		d->encoding = DE_ENCODING_WINDOWS1252; // Guess
	}
	else if(d->dfCharSet==0xff) { // "OEM"
		d->encoding = DE_ENCODING_CP437_G; // Guess
	}
	else {
		d->encoding = DE_ENCODING_UNKNOWN;
	}

	dfMaxWidth = de_getui16le(93);
	de_dbg(c, "dfMaxWidth: %d\n", (int)dfMaxWidth);

	if(dfPixWidth!=dfMaxWidth && dfPixWidth!=0) {
		de_warn(c, "dfMaxWidth (%d) does not equal dfPixWidth (%d)\n",
			(int)dfMaxWidth, (int)dfPixWidth);
	}

	d->first_char = de_getbyte(95);
	d->last_char = de_getbyte(96);
	de_dbg(c, "first char: %d, last char: %d\n", (int)d->first_char, (int)d->last_char);

	if(is_vector) {
		de_err(c, "This is a vector font. Not supported.\n");
		goto done;
	}

	// Apparently, the first 117 bytes (through the dfBitsOffset field) are
	// common to all versions
	if(d->fnt_version<0x0200) {
		de_err(c, "This version of FNT is not supported\n");
		goto done;
	}

	if(d->fnt_version >= 0x0200) {
		d->dfFace = de_getui32le(105);
	}

	// There is an extra character at the end of the table that is an
	// "absolute-space" character, and is guaranteed to be blank.
	d->num_chars_stored = (de_int64)d->last_char - d->first_char + 1 + 1;

	if(d->fnt_version==0x0300) {
		d->char_entry_size = 6;
	}
	else {
		d->char_entry_size = 4;
	}

	d->char_table_size = d->char_entry_size * d->num_chars_stored;
	de_dbg(c, "character index at %d, size %d, %d bytes/entry\n", (int)d->hdrsize,
		(int)d->char_table_size, (int)d->char_entry_size);

	do_prescan_chars(c, d);
	if(d->detected_max_width<1) goto done;
	d->nominal_char_width = d->detected_max_width;

	d->char_height = dfPixHeight;

	retval = 1;
done:
	return retval;
}
Esempio n. 25
0
static void de_run_gemraster(deark *c, de_module_params *mparams)
{
	i64 ver;
	i64 ext_word0 = 0;
	lctx *d = NULL;
	int need_format_warning = 0;
	int saved_indent_level;

	de_dbg_indent_save(c, &saved_indent_level);
	d = de_malloc(c, sizeof(lctx));

	de_dbg(c, "header (base part) at %d", 0);
	de_dbg_indent(c, 1);
	ver = de_getu16be(0);
	de_dbg(c, "version: %d", (int)ver);
	d->header_size_in_words = de_getu16be(2);
	d->header_size_in_bytes = d->header_size_in_words*2;
	de_dbg(c, "header size: %d words (%d bytes)", (int)d->header_size_in_words,
		(int)d->header_size_in_bytes);
	d->nplanes = de_getu16be(4);
	de_dbg(c, "planes: %d", (int)d->nplanes);

	if(d->header_size_in_words>=11) {
		d->is_ximg = !dbuf_memcmp(c->infile, 16, "XIMG", 4);
	}

	d->patlen = de_getu16be(6);
	de_dbg(c, "pattern def len: %d", (int)d->patlen);
	d->pixwidth = de_getu16be(8);
	d->pixheight = de_getu16be(10);
	de_dbg(c, "pixel size: %d"DE_CHAR_TIMES"%d microns", (int)d->pixwidth, (int)d->pixheight);
	d->w = de_getu16be(12);
	d->h = de_getu16be(14);
	de_dbg_dimensions(c, d->w, d->h);
	de_dbg_indent(c, -1);

	if(d->header_size_in_words>=9) {
		// This may help to detect the image format.
		ext_word0 = de_getu16be(16);
	}

	if(ver>2) {
		de_err(c, "This version of GEM Raster (%d) is not supported.", (int)ver);
		goto done;
	}

	if(d->is_ximg) {
		de_declare_fmt(c, "GEM VDI Bit Image, XIMG extension");
	}
	else if(d->header_size_in_words==25 && d->patlen==2 && ext_word0==0x0080) {
		de_declare_fmt(c, "GEM VDI Bit Image, Hyperpaint extension");
	}
	else if(d->header_size_in_words==8 && d->nplanes==1) {
		;
	}
	else if(d->header_size_in_words==8 && (d->nplanes>=2 && d->nplanes<=8)) {
		need_format_warning = 1;
	}
	else if(d->header_size_in_words==9 && (d->nplanes>=1 && d->nplanes<=8)) {
		need_format_warning = 1;
	}
	else {
		if(d->header_size_in_words==27 && ext_word0==0x5354) {
			de_declare_fmt(c, "GEM VDI Bit Image, STTT extension");
		}
		de_err(c, "This version of GEM Raster is not supported.");
		goto done;
	}

	if(need_format_warning) {
		de_warn(c, "This type of GEM Raster image is not very portable, and might "
			"not be handled correctly.");
	}

	if(!de_good_image_dimensions(c, d->w, d->h)) goto done;

	d->rowspan_per_plane = (d->w+7)/8;
	d->rowspan_total = d->rowspan_per_plane * d->nplanes;

	// If we haven't declared the format yet, do so.
	de_declare_fmt(c, "GEM VDI Bit Image");

	if(d->is_ximg) {
		do_gem_ximg(c, d);
	}
	else if(d->header_size_in_words==25) {
		do_gem_ximg(c, d);
	}
	else {
		do_gem_img(c, d);
	}

done:
	de_dbg_indent_restore(c, saved_indent_level);
	de_free(c, d);
}
Esempio n. 26
0
static int do_dataset(deark *c, lctx *d, de_int64 ds_idx, de_int64 pos1,
	de_int64 *bytes_consumed)
{
	de_byte b;
	de_byte recnum, dsnum;
	int retval = 0;
	de_int64 pos = pos1;
	de_int64 dflen;
	de_int64 dflen_bytes_consumed;
	struct ds_info dsi;
	int ds_known;

	*bytes_consumed = 0;

	b = de_getbyte(pos);
	if(b!=0x1c) {
		if(b==0x00 && ds_idx>0) {
			// Extraneous padding at the end of data?
			de_warn(c, "Expected %d bytes of IPTC data, only found %d\n",
				(int)c->infile->len, (int)pos);
		}
		else {
			de_err(c, "Bad IPTC tag marker (0x%02x) at %d\n", (int)b, (int)pos);
		}
		goto done;
	}
	pos++;

	recnum = de_getbyte(pos++);
	dsnum = de_getbyte(pos++);

	ds_known = lookup_ds_info(recnum, dsnum, &dsi);

	if(!read_dflen(c, c->infile, pos, &dflen, &dflen_bytes_consumed)) goto done;
	pos += dflen_bytes_consumed;

	de_dbg(c, "IPTC dataset %d:%02d (%s) dpos=%" INT64_FMT " dlen=%" INT64_FMT "\n",
		(int)recnum, (int)dsnum, dsi.dsname, pos, dflen);

	// Decode the value
	de_dbg_indent(c, 1);

	if(dsi.hfn) {
		dsi.hfn(c, d, &dsi, pos, dflen);
	}
	else if(dsi.flags&0x1) {
		handle_text(c, d, &dsi, pos, dflen);
	}
	else if(dsi.recnum==2 && !ds_known) {
		// Unknown record-2 datasets often contain readable text.
		handle_text(c, d, &dsi, pos, dflen);
	}
	pos += dflen;

	de_dbg_indent(c, -1);
	//

	*bytes_consumed = pos - pos1;
	retval = 1;
done:
	return retval;
}
Esempio n. 27
0
static void do_psf2_unicode_table(deark *c, lctx *d, struct de_bitmap_font *font)
{
	de_int64 cur_idx;
	de_int64 pos;
	int ret;
	de_int64 foundpos;
	de_int64 char_data_len;
	de_byte char_data_buf[200];
	de_int32 ch;
	de_int64 utf8len;

	de_dbg(c, "Unicode table at %d\n", (int)d->unicode_table_pos);
	de_dbg_indent(c, 1);

	pos = d->unicode_table_pos;
	cur_idx = 0;
	while(1) {
		de_int64 pos_in_char_data;
		de_int64 cp_idx;

		if(cur_idx >= d->num_glyphs) break;
		if(pos >= c->infile->len) break;

		// Figure out the size of the data for this glyph
		ret = dbuf_search_byte(c->infile, 0xff, pos,
			c->infile->len - pos, &foundpos);
		if(!ret) break;
		char_data_len = foundpos - pos;
		if(char_data_len<0) char_data_len=0;
		else if(char_data_len>(de_int64)sizeof(char_data_buf)) char_data_len=(de_int64)sizeof(char_data_buf);

		// Read all the data for this glyph
		de_read(char_data_buf, pos, char_data_len);

		// Read the codepoints for this glyph
		cp_idx = 0;
		pos_in_char_data = 0;
		while(1) {
			if(pos_in_char_data >= char_data_len) break;

			ret = de_utf8_to_uchar(&char_data_buf[pos_in_char_data], char_data_len-pos_in_char_data,
				&ch, &utf8len);
			if(!ret) {
				// If there are any multi-codepoint aliases for this glyph, we
				// expect de_utf8_to_uchar() to fail when it hits the 0xfe byte.
				// So, this is not necessarily an error.
				break;
			}

			if(cp_idx==0) {
				// This is the primary Unicode codepoint for this glyph
				de_dbg2(c, "char[%d] = U+%04x\n", (int)cur_idx, (unsigned int)ch);
				font->char_array[cur_idx].codepoint_unicode = ch;
			}
			else {
				do_extra_codepoint(c, d, font, cur_idx, ch);
			}

			cp_idx++;
			pos_in_char_data += utf8len;
		}

		if(cp_idx==0) {
			de_warn(c, "Missing codepoint for char #%d\n", (int)cur_idx);
		}

		// Advance to the next glyph
		pos = foundpos+1;
		cur_idx++;
	}

	font->has_unicode_codepoints = 1;
	font->prefer_unicode = 1;

	de_dbg_indent(c, -1);
}
Esempio n. 28
0
File: png.c Progetto: jsummers/deark
static void handler_text(deark *c, lctx *d, struct handler_params *hp)
{
	i64 pos;
	i64 endpos;
	i64 field_bytes_consumed;
	int is_compressed = 0;
	int encoding;
	int ret;
	struct text_chunk_ctx tcc;

	de_zeromem(&tcc, sizeof(struct text_chunk_ctx));

	endpos = hp->dpos+hp->dlen;
	pos = hp->dpos;

	// Keyword
	ret = do_text_field(c, d, &tcc, FIELD_KEYWORD, pos, endpos-pos,
		1, 0, DE_ENCODING_LATIN1, &field_bytes_consumed);
	if(!ret) goto done;
	pos += field_bytes_consumed;
	pos += 1;

	// Compression flag
	if(hp->chunk4cc->id==CODE_iTXt) {
		is_compressed = (int)de_getbyte(pos++);
		de_dbg(c, "compression flag: %d", (int)is_compressed);
	}
	else if(hp->chunk4cc->id==CODE_zTXt) {
		is_compressed = 1;
	}

	// Compression method
	if(hp->chunk4cc->id==CODE_zTXt || hp->chunk4cc->id==CODE_iTXt) {
		u8 cmpr_method;
		cmpr_method = de_getbyte(pos++);
		if(is_compressed && cmpr_method!=0) {
			de_warn(c, "Unsupported text compression type: %d", (int)cmpr_method);
			goto done;
		}
	}

	if(hp->chunk4cc->id==CODE_iTXt) {
		// Language tag
		ret = do_text_field(c, d, &tcc, FIELD_LANG, pos, endpos-pos,
			1, 0, DE_ENCODING_ASCII, &field_bytes_consumed);
		if(!ret) goto done;
		pos += field_bytes_consumed;
		pos += 1;

		// Translated keyword
		ret = do_text_field(c, d, &tcc, FIELD_XKEYWORD, pos, endpos-pos,
			1, 0, DE_ENCODING_UTF8, &field_bytes_consumed);
		if(!ret) goto done;
		pos += field_bytes_consumed;
		pos += 1;
	}

	if(hp->chunk4cc->id==CODE_iTXt)
		encoding = DE_ENCODING_UTF8;
	else
		encoding = DE_ENCODING_LATIN1;

	do_text_field(c, d, &tcc, FIELD_MAIN, pos, endpos-pos,
		0, is_compressed, encoding, &field_bytes_consumed);

done:
	;
}