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; }
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); }
// 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); }
// 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_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; }
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; }
// A wrapper for de_bitmap_create() static struct deark_bitmap *bmp_bitmap_create(deark *c, lctx *d, int bypp) { struct deark_bitmap *img; img = de_bitmap_create(c, d->width, d->height, bypp); img->flipped = !d->top_down; if(d->xpelspermeter>0 && d->ypelspermeter>0) { img->density_code = DE_DENSITY_DPI; img->xdens = (double)d->xpelspermeter * 0.0254; img->ydens = (double)d->ypelspermeter * 0.0254; } return 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 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); }
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); }
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); } }
// 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; }
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); }