// 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)); }
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 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 wri_convert_image_pal4planar(deark *c, i64 fpos, i64 bytes_per_row_per_plane, de_bitmap *img) { const i64 nplanes = 4; i64 i, j, plane; i64 rowspan; u8 *rowbuf = NULL; static const u32 pal16[16] = { 0x000000,0x800000,0x008000,0x808000,0x000080,0x800080,0x008080,0x808080, 0xc0c0c0,0xff0000,0x00ff00,0xffff00,0x0000ff,0xff00ff,0x00ffff,0xffffff }; rowspan = bytes_per_row_per_plane * nplanes; rowbuf = de_malloc(c, rowspan); // The usual order seems to be // row0_plane0x1, row0_plane0x2, row0_plane0x4, row0_plane0x8, // row1_plane0x1, row1_plane0x2, row1_plane0x4, row1_plane0x8, // ... // But I have seen another, and I see no way to detect/support it. for(j=0; j<img->height; j++) { de_read(rowbuf, fpos+j*rowspan, rowspan); for(i=0; i<img->width; i++) { unsigned int palent = 0; u32 clr; for(plane=0; plane<nplanes; plane++) { unsigned int n = 0; i64 idx; idx = bytes_per_row_per_plane*plane + i/8; if(idx<rowspan) n = rowbuf[idx]; if(n & (1<<(7-i%8))) { palent |= (1<<plane); } } clr = DE_MAKE_OPAQUE(pal16[palent]); de_bitmap_setpixel_rgb(img, i, j, clr); } } de_free(c, rowbuf); }
static void read_paletted_image(deark *c, lctx *d, dbuf *unc_pixels, de_bitmap *img) { i64 i, j, plane; unsigned int n; u8 x; if(d->nplanes<1 || d->nplanes>8) return; for(j=0; j<d->h; j++) { for(i=0; i<d->w; i++) { n = 0; for(plane=0; plane<d->nplanes; plane++) { x = de_get_bits_symbol(unc_pixels, 1, j*d->rowspan_total + plane*d->rowspan_per_plane, i); if(x) n |= 1<<plane; } de_bitmap_setpixel_rgb(img, i, j, d->pal[n]); } } }
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"); } }
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); }