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_image_16_32bit(deark *c, lctx *d, dbuf *bits, de_int64 bits_offset) { struct deark_bitmap *img = NULL; de_int64 i, j; int has_transparency; de_uint32 v; de_int64 k; de_byte sm[4]; if(d->bitfields_type==BF_SEGMENT) { has_transparency = (d->bitfields_segment_len>=16 && d->bitfield[3].mask!=0); } else if(d->bitfields_type==BF_IN_HEADER) { has_transparency = (d->bitfield[3].mask!=0); } else { has_transparency = 0; } img = bmp_bitmap_create(c, d, has_transparency?4:3); for(j=0; j<d->height; j++) { for(i=0; i<d->width; i++) { if(d->bitcount==16) { v = (de_uint32)dbuf_getui16le(bits, bits_offset + j*d->rowspan + 2*i); } else { v = (de_uint32)dbuf_getui32le(bits, bits_offset + j*d->rowspan + 4*i); } for(k=0; k<4; k++) { if(d->bitfield[k].mask!=0) { sm[k] = (de_byte)(0.5 + d->bitfield[k].scale * (double)((v&d->bitfield[k].mask) >> d->bitfield[k].shift)); } else { if(k==3) sm[k] = 255; // Default alpha sample = opaque else sm[k] = 0; // Default other samples = 0 } } de_bitmap_setpixel_rgba(img, i, j, DE_MAKE_RGBA(sm[0], sm[1], sm[2], sm[3])); }
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); }
// Paint a character at the given index in the given font, to the given bitmap. void de_font_paint_character_idx(deark *c, de_bitmap *img, struct de_bitmap_font *font, i64 char_idx, i64 xpos, i64 ypos, u32 fgcol, u32 bgcol, unsigned int flags) { i64 i, j; i64 i_src; // -1 = No source position i64 j_src; u8 x; int fg; u32 clr; struct de_bitmap_font_char *ch; i64 num_x_pixels_to_paint; int vga9col_flag = 0; if(char_idx<0 || char_idx>=font->num_chars) return; ch = &font->char_array[char_idx]; if(!is_valid_char(ch)) return; if(ch->width > font->nominal_width) return; if(ch->height > font->nominal_height) return; num_x_pixels_to_paint = (i64)ch->extraspace_l + (i64)ch->width + (i64)ch->extraspace_r; if((flags&DE_PAINTFLAG_VGA9COL) && ch->width==8) { vga9col_flag = 1; num_x_pixels_to_paint = 9; } for(j=0; j<ch->height; j++) { j_src = j; if(flags&DE_PAINTFLAG_TOPHALF) { j_src = j/2; } else if(flags&DE_PAINTFLAG_BOTTOMHALF) { j_src = (ch->height+j)/2; } for(i=0; i<num_x_pixels_to_paint; i++) { i_src = i; if(flags&DE_PAINTFLAG_LEFTHALF) { i_src = i/2; } else if(flags&DE_PAINTFLAG_RIGHTHALF) { i_src = (num_x_pixels_to_paint+i)/2; } if(i_src==8 && vga9col_flag) { // Manufacture a column 8. if(ch->codepoint_nonunicode>=0xb0 && ch->codepoint_nonunicode<=0xdf) { i_src = 7; // Make this pixel a duplicate of the one in col #7. } else { i_src = -1; // Make this pixel a background pixel. } } i_src -= (i64)ch->extraspace_l; if(i_src>=0 && i_src<ch->width) { x = ch->bitmap[j_src*ch->rowspan + i_src/8]; fg = (x & (1<<(7-i_src%8))) ? 1 : 0; } else { fg = 0; } if(fg || !(flags&DE_PAINTFLAG_TRNSBKGD)) { clr = fg ? fgcol : bgcol; de_bitmap_setpixel_rgba(img, xpos+i, ypos+ch->v_offset+j, clr); } } } }