Example #1
0
static void do_bitmap(deark *c, lctx *d, dbuf *unc_pixels)
{
	i64 i, j;
	i64 rowspan;
	u32 clr;
	de_bitmap *img = NULL;
	u8 b;

	rowspan = (d->w * d->bpp +7)/8;

	img = de_bitmap_create(c, d->w, d->h, 3);

	for(j=0; j<d->h; j++) {
		for(i=0; i<d->w; i++) {
			if(d->bpp<=8) {
				b = de_get_bits_symbol(unc_pixels, d->bpp, j*rowspan, i);
				clr = d->pal[(unsigned int)b];
			}
			else {
				clr = dbuf_getRGB(unc_pixels, j*rowspan + i*3, 0);
			}
			de_bitmap_setpixel_rgb(img, i, j, clr);
		}
	}

	de_bitmap_write_to_file(img, NULL, 0);

	de_bitmap_destroy(img);
}
Example #2
0
// Rasterized caption
static void handle_2_125(deark *c, lctx *d, const struct ds_info *dsi,
	de_int64 pos, de_int64 len)
{
	dbuf *unc_pixels = NULL;
	struct deark_bitmap *img = NULL;
	de_int64 i, j;
	de_byte b;
	de_int64 rowspan;
	de_int64 width, height;

	// I can't find any examples of this field, so this may not be correct.
	// The format seems to be well-documented, though the pixels are in an
	// unusual order.

	unc_pixels = dbuf_open_input_subfile(c->infile, pos, len);
	width = 460;
	height = 128;
	img = de_bitmap_create(c, width, height, 1);
	rowspan = height/8;

	for(j=0; j<width; j++) {
		for(i=0; i<height; i++) {
			b = de_get_bits_symbol(unc_pixels, 1, rowspan*j, i);
			de_bitmap_setpixel_gray(img, j, (height-1-i), b?0:255);
		}
	}

	de_bitmap_write_to_file(img, "caption", DE_CREATEFLAG_IS_AUX);
	de_bitmap_destroy(img);
	dbuf_close(unc_pixels);
}
Example #3
0
static int do_image_pbm_ascii(deark *c, lctx *d, struct page_ctx *pg, de_int64 pos1)
{
	struct deark_bitmap *img = NULL;
	de_int64 xpos, ypos;
	de_int64 pos = pos1;
	de_byte b;
	de_byte v;

	img = de_bitmap_create(c, pg->width, pg->height, 1);

	xpos=0; ypos=0;
	while(1) {
		if(pos >= c->infile->len) break; // end of file
		if(ypos==(pg->height-1) && xpos>=pg->width) break; // end of image
		if(ypos>=pg->height) break;

		b = de_getbyte(pos++);
		if(b=='1') v=0;
		else if(b=='0') v=255;
		else continue;

		de_bitmap_setpixel_gray(img, xpos, ypos, v);
		xpos++;
		if(xpos>=pg->width) {
			ypos++;
			xpos=0;
		}
	}

	de_bitmap_write_to_file_finfo(img, NULL, 0);
	de_bitmap_destroy(img);
	return 1;
}
Example #4
0
static void do_image_paletted(deark *c, lctx *d, dbuf *bits, de_int64 bits_offset)
{
	struct deark_bitmap *img = NULL;

	img = bmp_bitmap_create(c, d, d->pal_is_grayscale?1:3);
	de_convert_image_paletted(bits, bits_offset,
		d->bitcount, d->rowspan, d->pal, img, 0);
	de_bitmap_write_to_file(img, NULL, 0);
	de_bitmap_destroy(img);
}
Example #5
0
// Some MacPaint files contain a collection of brush patterns.
// Essentially, MacPaint saves workspace settings inside image files.
// (But these patterns are the only setting.)
static void do_read_patterns(deark *c, lctx *d, de_int64 pos)
{
	de_int64 cell;
	de_int64 i, j;
	de_byte x;
	const de_int64 dispwidth = 19;
	const de_int64 dispheight = 17;
	de_int64 xpos, ypos;
	int is_blank;
	struct deark_bitmap *pat = NULL;
	de_uint32 patcrc;
	const char *patsetname;

	pos += 4;

	patcrc = x_dbuf_crc32(c->infile, pos, 38*8);
	patsetname = get_pattern_set_info(patcrc, &is_blank);
	de_dbg(c, "brush patterns crc: 0x%08x (%s)\n", (unsigned int)patcrc, patsetname);

	if(c->extract_level<2) {
		goto done;
	}

	if(is_blank) {
		de_dbg(c, "brush patterns are blank: not extracting\n");
		goto done;
	}

	pat = de_bitmap_create(c, (dispwidth+1)*19+1, (dispheight+1)*2+1, 1);

	for(cell=0; cell<38; cell++) {
		xpos = (dispwidth+1)*(cell%19)+1;
		ypos = (dispheight+1)*(cell/19)+1;

		for(j=0; j<dispheight; j++) {
			for(i=0; i<dispwidth; i++) {
				// TODO: Figure out the proper "brush origin" of these patterns.
				// Some of them may be shifted differently than MacPaint displays them.
				x = de_get_bits_symbol(c->infile, 1, pos+cell*8+j%8, i%8);

				// 0 = white. Only need to set the white pixels, since they start out
				// black.
				if(x==0) {
					de_bitmap_setpixel_gray(pat, xpos+i, ypos+j, 255);
				}
			}
		}
	}

	de_bitmap_write_to_file(pat, "pat", DE_CREATEFLAG_IS_AUX);

done:
	de_bitmap_destroy(pat);
}
Example #6
0
static int do_gem_img(deark *c, lctx *d)
{
	dbuf *unc_pixels = NULL;
	de_bitmap *img = NULL;
	de_finfo *fi = NULL;
	int is_color = 0;
	i64 k;

	if(d->header_size_in_words==9 && (d->nplanes==3 || d->nplanes==4)) {
		i64 x;
		x = de_getu16be(8*2);
		if(x==0) {
			is_color = 1;
		}
	}

	de_dbg(c, "image at %d", (int)d->header_size_in_bytes);

	unc_pixels = dbuf_create_membuf(c, d->rowspan_total*d->h, 0);

	uncompress_pixels(c, d, unc_pixels, d->header_size_in_bytes, c->infile->len-d->header_size_in_bytes);

	img = de_bitmap_create(c, d->w, d->h, is_color?3:1);

	fi = de_finfo_create(c);
	set_density(c, d, fi);

	if(d->nplanes==1) {
		de_convert_image_bilevel(unc_pixels, 0, d->rowspan_per_plane, img, DE_CVTF_WHITEISZERO);
	}
	else if(is_color && d->nplanes==3) {
		for(k=0; k<8; k++) {
			d->pal[k] = pal3bit[k];
		}
		read_paletted_image(c, d, unc_pixels, img);
	}
	else if(is_color && d->nplanes==4) {
		for(k=0; k<16; k++) {
			d->pal[k] = pal4bit[k];
		}
		read_paletted_image(c, d, unc_pixels, img);
	}
	else {
		de_make_grayscale_palette(d->pal, ((i64)1)<<((unsigned int)d->nplanes), 1);
		read_paletted_image(c, d, unc_pixels, img);
	}

	de_bitmap_write_to_file_finfo(img, fi, 0);

	de_bitmap_destroy(img);
	de_finfo_destroy(c, fi);
	dbuf_close(unc_pixels);
	return 1;
}
Example #7
0
static int do_image_pgm_ppm_binary(deark *c, lctx *d, struct page_ctx *pg, de_int64 pos1)
{
	struct deark_bitmap *img = NULL;
	de_int64 rowspan;
	de_int64 nsamples; // For both input and output
	de_int64 bytes_per_sample;
	de_int64 i, j, k;
	de_int64 pos = pos1;
	unsigned int samp_ori[3];
	de_byte samp_adj[3];

	if(fmt_is_ppm(pg->fmt)) nsamples=3;
	else nsamples=1;

	if(pg->maxval<=255) bytes_per_sample=1;
	else bytes_per_sample=2;

	rowspan = pg->width * nsamples * bytes_per_sample;
	pg->image_data_len = rowspan * pg->height;

	img = de_bitmap_create(c, pg->width, pg->height, (int)nsamples);

	for(j=0; j<pg->height; j++) {
		for(i=0; i<pg->width; i++) {
			for(k=0; k<nsamples; k++) {
				if(bytes_per_sample==1) {
					samp_ori[k] = de_getbyte(pos++);
				}
				else {
					samp_ori[k] = (unsigned int)de_getbyte(pos++) << 8 ;
					samp_ori[k] |= (unsigned int)de_getbyte(pos++);
				}

				samp_adj[k] = de_scale_n_to_255(pg->maxval, samp_ori[k]);
			}

			if(nsamples==1) {
				de_bitmap_setpixel_gray(img, i, j, samp_adj[0]);
			}
			else {
				de_uint32 clr;
				clr = DE_MAKE_RGB(samp_adj[0], samp_adj[1], samp_adj[2]);
				de_bitmap_setpixel_rgb(img, i, j, clr);
			}
		}
	}

	de_bitmap_write_to_file(img, NULL, 0);

	de_bitmap_destroy(img);
	return 1;
}
Example #8
0
static void do_image_24bit(deark *c, lctx *d, dbuf *bits, de_int64 bits_offset)
{
	struct deark_bitmap *img = NULL;
	de_int64 i, j;
	de_uint32 clr;

	img = bmp_bitmap_create(c, d, 3);
	for(j=0; j<d->height; j++) {
		for(i=0; i<d->width; i++) {
			clr = dbuf_getRGB(bits, bits_offset + j*d->rowspan + 3*i, DE_GETRGBFLAG_BGR);
			de_bitmap_setpixel_rgb(img, i, j, clr);
		}
	}
	de_bitmap_write_to_file(img, NULL, 0);
	de_bitmap_destroy(img);
}
Example #9
0
static void do_decode_24bit(deark *c, lctx *d, struct page_ctx *pg)
{
	dbuf *unc_pixels = NULL;
	struct deark_bitmap *img = NULL;
	de_int64 i, j;
	de_byte cr, cg, cb, ca;
	de_int64 w, h;
	de_int64 skip;

	w = pg->type_info->width;
	h = pg->type_info->height;

	// TODO: Try to support uncompressed 24-bit images, assuming they exist.

	// Apparently, some 'it32' icons begin with four extra 0x00 bytes.
	// Skip over the first four bytes if they are 0x00.
	// (I don't know the reason for these bytes, but this is the same
	// logic libicns uses.)
	skip = 0;
	if(pg->code4cc.id==0x69743332) { // 'it32' (128x128)
		if(!dbuf_memcmp(c->infile, pg->image_pos, "\0\0\0\0", 4)) {
			skip = 4;
		}
	}

	unc_pixels = dbuf_create_membuf(c, w*h*3, 1);
	do_uncompress_24(c, d, pg, unc_pixels, skip);

	img = de_bitmap_create(c, w, h, 4);

	for(j=0; j<pg->type_info->height; j++) {
		for(i=0; i<pg->type_info->width; i++) {
			cr = dbuf_getbyte(unc_pixels, j*w + i);
			cg = dbuf_getbyte(unc_pixels, (h+j)*w + i);
			cb = dbuf_getbyte(unc_pixels, (2*h+j)*w + i);
			if(pg->mask_pos)
				ca = de_getbyte(pg->mask_pos + j*w + i);
			else
				ca = 0xff;
			de_bitmap_setpixel_rgba(img, i, j, DE_MAKE_RGBA(cr,cg,cb,ca));
		}
	}

	de_bitmap_write_to_file(img, pg->filename_token, 0);
	de_bitmap_destroy(img);
	if(unc_pixels) dbuf_close(unc_pixels);
}
Example #10
0
static void do_decode_1_4_8bit(deark *c, lctx *d, struct page_ctx *pg)
{
	struct deark_bitmap *img = NULL;
	de_int64 i, j;
	de_byte a, b;
	de_byte x;
	de_int32 fgcol;

	img = de_bitmap_create(c, pg->type_info->width, pg->type_info->height, 4);

	for(j=0; j<pg->type_info->height; j++) {
		for(i=0; i<pg->type_info->width; i++) {
			// Foreground
			b = de_get_bits_symbol(c->infile, pg->type_info->bpp, pg->image_pos + pg->rowspan*j, i);

			if(pg->type_info->bpp==8) {
				fgcol = getpal256((int)b);
			}
			else if(pg->type_info->bpp==4) {
				fgcol = pal16[(unsigned int)b];
			}
			else {
				fgcol = b ? 0x0000000 : 0xffffff;
			}

			// Opacity
			if(pg->mask_pos) {
				x = de_get_bits_symbol(c->infile, 1, pg->mask_pos + pg->mask_rowspan*j, i);
				a = x ? 0xff : 0x00;
			}
			else {
				a = 0xff;
			}
			de_bitmap_setpixel_rgba(img, i, j, DE_SET_ALPHA(fgcol, a));
		}
	}

	de_bitmap_write_to_file(img, pg->filename_token, 0);
	de_bitmap_destroy(img);
}
Example #11
0
File: tga.c Project: 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);
}
Example #12
0
static void do_card_index(deark *c, lctx *d, de_int64 cardnum, de_int64 pos)
{
	de_int64 datapos;
	de_int64 bitmap_len;
	de_int64 w, h;
	de_int64 src_rowspan;
	de_int64 text_len;
	de_int64 text_pos;
	struct deark_bitmap *img = NULL;
	de_finfo *fi_bitmap = NULL;
	de_finfo *fi_text = NULL;
	const char *cardtype;
	de_ucstring *name = NULL;
	int saved_indent_level;

	de_dbg_indent_save(c, &saved_indent_level);

	datapos = de_getui32le(pos+6);
	de_dbg(c, "card #%d at %d, dpos=%d\n", (int)cardnum, (int)pos, (int)datapos);
	de_dbg_indent(c, 1);

	if(datapos>=c->infile->len) goto done;
	bitmap_len = de_getui16le(datapos);
	de_dbg(c, "bitmap length: %d\n", (int)bitmap_len);

	if(bitmap_len==0) {
		text_len = de_getui16le(datapos+2);
		text_pos = datapos+4;
	}
	else {
		text_len = de_getui16le(datapos + bitmap_len + 10);
		text_pos = datapos + bitmap_len + 10;
	}
	de_dbg(c, "text length: %d\n", (int)text_len);

	if(bitmap_len==0 && text_len==0) {
		cardtype = "empty";
	}
	else if(bitmap_len==0) {
		cardtype = "text-only";
	}
	else if(text_len==0) {
		cardtype = "graphics-only";
	}
	else {
		cardtype = "graphics+text";
	}
	de_dbg(c, "card type: %s\n", cardtype);

	if(bitmap_len==0 && text_len==0) {
		goto done;
	}

	name = ucstring_create(c);
	dbuf_read_to_ucstring(c->infile, pos+11, 40, name, DE_CONVFLAG_STOP_AT_NUL, DE_ENCODING_ASCII);
	de_dbg(c, "name: \"%s\"\n", ucstring_get_printable_sz(name));

	// Text

	if(text_len!=0 && c->extract_level>=2) {
		fi_text = de_finfo_create(c);
		if(c->filenames_from_file)
			de_finfo_set_name_from_ucstring(c, fi_text, name);

		do_text_data(c, d, fi_text, text_pos, text_len);
	}

	// Bitmap

	if(bitmap_len==0) goto done;

	fi_bitmap = de_finfo_create(c);
	if(c->filenames_from_file)
		de_finfo_set_name_from_ucstring(c, fi_bitmap, name);

	w = de_getui16le(datapos+2);
	h = de_getui16le(datapos+4);
	de_dbg(c, "bitmap dimensions: %dx%d\n", (int)w, (int)h);

	img = de_bitmap_create(c, w, h, 1);
	src_rowspan = ((w+15)/16)*2;

	de_convert_and_write_image_bilevel(c->infile, datapos+10,
		w, h, src_rowspan, 0, fi_bitmap, 0);

done:
	ucstring_destroy(name);
	de_bitmap_destroy(img);
	de_finfo_destroy(c, fi_bitmap);
	de_finfo_destroy(c, fi_text);
	de_dbg_indent_restore(c, saved_indent_level);
}
Example #13
0
void de_font_bitmap_font_to_image(deark *c, struct de_bitmap_font *font1, de_finfo *fi,
	unsigned int createflags)
{
	struct font_render_ctx *fctx = NULL;
	i64 i, j, k;
	de_bitmap *img = NULL;
	i64 xpos, ypos;
	i64 img_leftmargin, img_topmargin;
	i64 img_rightmargin, img_bottommargin;
	i64 img_vpixelsperchar;
	i64 img_width, img_height;
	i64 num_table_rows_to_display;
	i64 num_table_rows_total;
	i64 last_valid_row;
	struct de_bitmap_font *dfont = NULL;
	i64 chars_per_row = 32;
	const char *s;
	struct row_info_struct *row_info = NULL;
	struct col_info_struct *col_info = NULL;
	int unicode_req = 0;
	i64 label_stride;
	i64 rownum, colnum;
	i64 curpos;
	unsigned int dnflags;

	fctx = de_malloc(c, sizeof(struct font_render_ctx));
	fctx->font = font1;

	if(fctx->font->num_chars<1) goto done;
	if(fctx->font->num_chars>17*65536) goto done;
	if(fctx->font->nominal_width>512 || fctx->font->nominal_height>512) {
		de_err(c, "Font size too big (%d"DE_CHAR_TIMES"%d). Not supported.",
			(int)fctx->font->nominal_width, (int)fctx->font->nominal_height);
		goto done;
	}

	// -1 = "no preference"
	unicode_req = de_get_ext_option_bool(c, "font:tounicode", -1);

	if(unicode_req==0 &&
		(fctx->font->has_nonunicode_codepoints || !fctx->font->has_unicode_codepoints))
	{
		; // Render as nonunicode.
	}
	else if(fctx->font->has_unicode_codepoints &&
		(unicode_req>0 || fctx->font->prefer_unicode || !fctx->font->has_nonunicode_codepoints))
	{
		fctx->render_as_unicode = 1;
	}

	s = de_get_ext_option(c, "font:charsperrow");
	if(s) {
		chars_per_row = de_atoi64(s);
		if(chars_per_row<1) chars_per_row=1;
	}

	dfont = make_digit_font(c);

	fctx->codepoint_tmp = de_mallocarray(c, fctx->font->num_chars, sizeof(i32));
	fixup_codepoints(c, fctx);

	get_min_max_codepoint(fctx);
	if(fctx->num_valid_chars<1) goto done;
	num_table_rows_total = fctx->max_codepoint/chars_per_row+1;

	// TODO: Clean up these margin calculations, and make it more general.
	if(fctx->render_as_unicode) {
		img_leftmargin = dfont->nominal_width * 5 + 6;
	}
	else {
		if(fctx->max_codepoint >= 1000)
			img_leftmargin = dfont->nominal_width * 5 + 6;
		else
			img_leftmargin = dfont->nominal_width * 3 + 6;
	}
	img_topmargin = dfont->nominal_height + 6;
	img_rightmargin = 1;
	img_bottommargin = 1;

	// Scan the characters, and record relevant information.
	row_info = de_mallocarray(c, num_table_rows_total, sizeof(struct row_info_struct));
	col_info = de_mallocarray(c, chars_per_row, sizeof(struct col_info_struct));
	for(i=0; i<chars_per_row; i++) {
#define MIN_CHAR_CELL_WIDTH 5
		col_info[i].display_width = MIN_CHAR_CELL_WIDTH;
	}

	for(k=0; k<fctx->font->num_chars; k++) {
		i64 char_display_width;

		if(fctx->codepoint_tmp[k] == DE_CODEPOINT_INVALID) continue;
		if(!is_valid_char(&fctx->font->char_array[k])) continue;
		rownum = fctx->codepoint_tmp[k] / chars_per_row;
		colnum = fctx->codepoint_tmp[k] % chars_per_row;
		if(rownum<0 || rownum>=num_table_rows_total) {
			de_err(c, "internal: bad rownum");
			de_fatalerror(c);
		}

		// Remember that there is at least one valid character in this character's row.
		row_info[rownum].is_visible = 1;

		// Track the maximum width of any character in this character's column.
		char_display_width = (i64)(fctx->font->char_array[k].width +
				(int)fctx->font->char_array[k].extraspace_l +
				(int)fctx->font->char_array[k].extraspace_r);
		if(char_display_width > col_info[colnum].display_width) {
			col_info[colnum].display_width = char_display_width;
		}
	}

	img_vpixelsperchar = fctx->font->nominal_height + 1;

	// Figure out how many rows are used, and where to draw them.
	num_table_rows_to_display = 0;
	last_valid_row = -1;
	curpos = img_topmargin;
	for(j=0; j<num_table_rows_total; j++) {
		if(!row_info[j].is_visible) continue;

		// If we skipped one or more rows, leave some extra vertical space.
		if(num_table_rows_to_display>0 && !row_info[j-1].is_visible) curpos+=3;

		last_valid_row = j;
		row_info[j].display_pos = curpos;
		curpos += img_vpixelsperchar;
		num_table_rows_to_display++;
	}
	if(num_table_rows_to_display<1) goto done;

	// Figure out the positions of the columns.
	curpos = img_leftmargin;
	for(i=0; i<chars_per_row; i++) {
		col_info[i].display_pos = curpos;
		curpos += col_info[i].display_width + 1;
	}

	img_width = col_info[chars_per_row-1].display_pos +
		col_info[chars_per_row-1].display_width + img_rightmargin;
	img_height = row_info[last_valid_row].display_pos +
		img_vpixelsperchar -1 + img_bottommargin;

	img = de_bitmap_create(c, img_width, img_height, 1);

	// Clear the image
	for(j=0; j<img->height; j++) {
		for(i=0; i<img->width; i++) {
			de_bitmap_setpixel_gray(img, i, j, 128);
		}
	}

	// Draw/clear the cell backgrounds
	for(j=0; j<num_table_rows_total; j++) {
		if(!row_info[j].is_visible) continue;
		ypos = row_info[j].display_pos;

		for(i=0; i<chars_per_row; i++) {
			i64 ii, jj;

			xpos = col_info[i].display_pos;
			for(jj=0; jj<img_vpixelsperchar-1; jj++) {
				for(ii=0; ii<col_info[i].display_width; ii++) {
					de_bitmap_setpixel_gray(img, xpos+ii, ypos+jj, (ii/2+jj/2)%2 ? 176 : 192);
				}
			}
		}
	}

	// Draw the labels in the top margin.

	// TODO: Better label spacing logic.
	if(fctx->font->nominal_width <= 12)
		label_stride = 2;
	else
		label_stride = 1;

	for(i=0; i<chars_per_row; i++) {
		if(i%label_stride != 0) continue;
		xpos = col_info[i].display_pos + col_info[i].display_width/2;
		ypos = img_topmargin - 3;

		dnflags = DNFLAG_HCENTER;
		if(fctx->render_as_unicode) dnflags |= DNFLAG_HEX;

		draw_number(c, img, dfont, i, xpos, ypos, dnflags);
	}

	// Draw the labels in the left margin.
	for(j=0; j<num_table_rows_total; j++) {
		if(!row_info[j].is_visible) continue;
		xpos = img_leftmargin - 3;
		ypos = row_info[j].display_pos + (img_vpixelsperchar + dfont->nominal_height + 1)/2;

		dnflags = 0;
		if(fctx->render_as_unicode) dnflags |= DNFLAG_HEX | DNFLAG_LEADING_ZEROES;

		draw_number(c, img, dfont, j*chars_per_row, xpos, ypos, dnflags);
	}

	// Render the glyphs.
	for(k=0; k<fctx->font->num_chars; k++) {
		if(fctx->codepoint_tmp[k] == DE_CODEPOINT_INVALID) continue;
		if(!is_valid_char(&fctx->font->char_array[k])) continue;

		rownum = fctx->codepoint_tmp[k] / chars_per_row;
		colnum = fctx->codepoint_tmp[k] % chars_per_row;
		if(rownum<0 || rownum>=num_table_rows_total) {
			de_err(c, "internal: bad rownum");
			de_fatalerror(c);
		}

		xpos = col_info[colnum].display_pos;
		ypos = row_info[rownum].display_pos;

		de_font_paint_character_idx(c, img, fctx->font, k, xpos, ypos,
			DE_STOCKCOLOR_BLACK, DE_STOCKCOLOR_WHITE, 0);
	}

	de_bitmap_write_to_file_finfo(img, fi, createflags);

done:
	if(dfont) {
		de_free(c, dfont->char_array);
		de_destroy_bitmap_font(c, dfont);
	}
	de_bitmap_destroy(img);
	de_free(c, row_info);
	de_free(c, col_info);
	if(fctx) {
		de_free(c, fctx->codepoint_tmp);
		de_free(c, fctx);
	}
}
Example #14
0
// XIMG and similar formats.
// TODO: Should this function be merged with do_gem_img()?
static int do_gem_ximg(deark *c, lctx *d)
{
	dbuf *unc_pixels = NULL;
	de_bitmap *img = NULL;
	de_finfo *fi = NULL;
	int retval = 0;
	int saved_indent_level;

	de_dbg_indent_save(c, &saved_indent_level);

	de_dbg(c, "header (continued) at %d", 8*2);
	de_dbg_indent(c, 1);

	if((d->nplanes>=1 && d->nplanes<=8) /* || d->nplanes==24 */) {
		;
	}
	else {
		if(d->is_ximg)
			de_err(c, "%d-plane XIMG images are not supported", (int)d->nplanes);
		else
			de_err(c, "This type of %d-plane image is not supported", (int)d->nplanes);
		goto done;
	}

	if(d->header_size_in_words==25 && !d->is_ximg) {
		i64 pal_pos = d->header_size_in_bytes-32;
		de_dbg(c, "palette at %d", (int)pal_pos);
		de_dbg_indent(c, 1);
		de_fmtutil_read_atari_palette(c, c->infile, pal_pos,
			d->pal, 16, ((i64)1)<<d->nplanes, 0);
		de_dbg_indent(c, -1);
	}
	else {
		read_palette_ximg(c, d);
	}

	if(d->nplanes==1 && d->pal[0]==d->pal[1]) {
		de_dbg(c, "Palette doesn't seem to be present. Using a default palette.");
		d->pal[0] = DE_STOCKCOLOR_WHITE;
		d->pal[1] = DE_STOCKCOLOR_BLACK;
	}

	de_dbg_indent(c, -1);

	de_dbg(c, "image at %d", (int)d->header_size_in_bytes);

	unc_pixels = dbuf_create_membuf(c, d->rowspan_total*d->h, 0);
	uncompress_pixels(c, d, unc_pixels, d->header_size_in_bytes, c->infile->len-d->header_size_in_bytes);

	img = de_bitmap_create(c, d->w, d->h, 3);

	fi = de_finfo_create(c);
	set_density(c, d, fi);

	if(d->nplanes>8) {
		read_rgb_image(c, d, unc_pixels, img);
	}
	else {
		read_paletted_image(c, d, unc_pixels, img);
	}

	de_bitmap_write_to_file_finfo(img, fi, 0);

	retval = 1;

done:
	de_bitmap_destroy(img);
	de_finfo_destroy(c, fi);
	dbuf_close(unc_pixels);
	de_dbg_indent_restore(c, saved_indent_level);
	return retval;
}
Example #15
0
static int do_image_pgm_ppm_ascii(deark *c, lctx *d, struct page_ctx *pg, de_int64 pos1)
{
	struct deark_bitmap *img = NULL;
	de_int64 nsamples; // For both input and output
	de_int64 pos = pos1;
	de_int64 xpos, ypos, sampidx;
	char samplebuf[32];
	size_t samplebuf_used;
	de_byte b;

	if(fmt_is_ppm(pg->fmt)) nsamples=3;
	else nsamples=1;

	img = de_bitmap_create(c, pg->width, pg->height, (int)nsamples);

	xpos=0; ypos=0;
	sampidx=0;
	samplebuf_used=0;

	while(1) {
		if(pos >= c->infile->len) break; // end of file
		if(ypos==(pg->height-1) && xpos>=pg->width) break; // end of image
		if(ypos>=pg->height) break;

		b = de_getbyte(pos++);
		if(is_pnm_whitespace(b)) {
			if(samplebuf_used>0) {
				de_int64 v;
				de_byte v_adj;

				// Completed a sample
				samplebuf[samplebuf_used] = '\0'; // NUL terminate for de_atoi64()
				v = de_atoi64((const char*)samplebuf);
				v_adj = de_scale_n_to_255(pg->maxval, v);
				samplebuf_used = 0;

				if(nsamples>1) {
					de_bitmap_setsample(img, xpos, ypos, sampidx, v_adj);
				}
				else {
					de_bitmap_setpixel_gray(img, xpos, ypos, v_adj);
				}

				sampidx++;
				if(sampidx>=nsamples) {
					sampidx=0;
					xpos++;
					if(xpos>=pg->width) {
						xpos=0;
						ypos++;
					}
				}

			}
			else { // Skip extra whitespace
				continue;
			}
		}
		else {
			// Non-whitespace. Save for later.
			if(samplebuf_used < sizeof(samplebuf_used)-1) {
				samplebuf[samplebuf_used++] = b;
			}
		}
	}
	de_bitmap_write_to_file(img, NULL, 0);

	de_bitmap_destroy(img);
	return 1;
}
Example #16
0
File: wri.c Project: jsummers/deark
static void do_static_bitmap(deark *c, lctx *d, struct para_info *pinfo, i64 pos1)
{
	i64 dlen;
	i64 pos = pos1;
	unsigned int bmType;
	i64 bmWidth, bmHeight;
	i64 bmPlanes;
	i64 bmBitsPixel;
	i64 bytes_per_row_per_plane;
	i64 src_realbitsperpixel;
	de_bitmap *img = NULL;

	pos += 8; // ??
	dlen = de_getu32le_p(&pos);
	de_dbg(c, "bitmap size: %d", (int)dlen);

	bmType = (unsigned int)de_getu16le_p(&pos);
	de_dbg(c, "bmType: %u", bmType);

	bmWidth = de_getu16le_p(&pos);
	bmHeight = de_getu16le_p(&pos);
	de_dbg_dimensions(c, bmWidth, bmHeight);

	bytes_per_row_per_plane = de_getu16le_p(&pos);
	de_dbg(c, "bytes/row: %d", (int)bytes_per_row_per_plane);

	bmPlanes = (i64)de_getbyte_p(&pos);
	de_dbg(c, "planes: %d", (int)bmPlanes);

	bmBitsPixel = (i64)de_getbyte_p(&pos);
	de_dbg(c, "bmBitsPixel: %d", (int)bmBitsPixel);

	pos += 4; // Placeholder for a pointer?

	if((bmBitsPixel==1 && bmPlanes==1) ||
		(bmBitsPixel==1 && bmPlanes==4) ||
		(bmBitsPixel==8 && bmPlanes==1))
	{
		;
	}
	else {
		de_err(c, "This type of static OLE bitmap is not supported "
			"(bmBitsPixel=%d, planes=%d)", (int)bmBitsPixel, (int)bmPlanes);
		goto done;
	}

	src_realbitsperpixel = bmBitsPixel * bmPlanes;
	if(!de_good_image_dimensions(c, bmWidth, bmHeight)) goto done;
	img = de_bitmap_create(c, bmWidth, bmHeight, (src_realbitsperpixel==1)?1:3);

	if(bmBitsPixel==1 && bmPlanes==1) {
		de_convert_image_bilevel(c->infile, pos, bytes_per_row_per_plane, img, 0);
	}
	else if(bmBitsPixel==1 || bmPlanes==4) {
		wri_convert_image_pal4planar(c, pos, bytes_per_row_per_plane, img);
	}
	else if(bmBitsPixel==8 || bmPlanes==1) {
		wri_convert_image_pal8(c, pos, bytes_per_row_per_plane, img);
	}

	de_bitmap_write_to_file(img, NULL, 0);

done:
	de_bitmap_destroy(img);
}