// 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); }
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); }
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); }
// 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); }
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; }
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); }
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); }
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); }
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; }
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); }