static void de_run_macpaint(deark *c, de_module_params *mparams) { lctx *d; de_int64 pos; const char *s; d = de_malloc(c, sizeof(lctx)); d->has_macbinary_header = -1; s = de_get_ext_option(c, "macpaint:macbinary"); if(s) d->has_macbinary_header = de_atoi(s); if(d->has_macbinary_header == -1) { int v512; int v640; de_dbg(c, "trying to determine if file has a MacBinary header\n"); v512 = valid_file_at(c, d, 0); v640 = valid_file_at(c, d, 128); if(v512 > v640) { de_dbg(c, "assuming it has no MacBinary header\n"); d->has_macbinary_header = 0; } else if(v640 > v512) { de_dbg(c, "assuming it has a MacBinary header\n"); d->has_macbinary_header = 1; } else if(v512 && v640) { de_warn(c, "Can't determine if this file has a MacBinary header. " "Try \"-opt macpaint:macbinary=0\".\n"); d->has_macbinary_header = 1; } else { de_warn(c, "This is probably not a MacPaint file.\n"); d->has_macbinary_header = 1; } } if(d->has_macbinary_header) de_declare_fmt(c, "MacPaint with MacBinary header"); else de_declare_fmt(c, "MacPaint without MacBinary header"); pos = d->has_macbinary_header ? 128 : 0; do_read_bitmap(c, d, pos); do_read_patterns(c, d, pos); de_free(c, d); }
static void do_opo_opa(deark *c, lctx *d) { de_int64 offset_2ndheader; de_int64 pos; de_int64 n; de_int64 len; de_declare_fmt(c, "Psion OPO/OPA"); // The second header marks the end of the embedded files section, I guess. offset_2ndheader = de_getui16le(18); de_dbg(c, "offset of second header: %d\n", (int)offset_2ndheader); pos = 20; // Read length of source filename n = (de_int64)de_getbyte(pos); pos++; pos+=n; while(pos<offset_2ndheader) { // Read length of this embedded file len = de_getui16le(pos); pos+=2; handle_embedded_file(c, d, pos, len); pos+=len; } }
// 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_img_app(deark *c, lctx *d) { de_int64 i; de_int64 offset; de_int64 len; de_declare_fmt(c, "Psion IMG/APP"); for(i=0; i<4; i++) { offset = de_getui16le(40 + 4*i); len = de_getui16le(40 + 4*i + 2); if(offset==0) break; handle_embedded_file(c, d, offset, len); } }
// To be called when we encounter a page that is not the first page of // its bitstream (or at EOF). static void declare_ogg_format(deark *c, lctx *d) { char tmps[80]; const char *name = NULL; if(d->format_declared) return; d->format_declared = 1; // There's no nice way, that I know of, to characterize the contents of an Ogg // file. But I think it's worth trying. if(d->bitstream_count<1) { // If there are zero streams : "other" } else if(d->found_ogm) { // else if there's an OGM stream of any kind... name="OGM"; } else if(d->found_skeleton) { // else If there's a Skeleton stream... name="Skeleton"; } else if(d->first_stream_type_valid && d->first_stream_sti && !d->has_unknown_or_multiple_stream_types) { // else if all streams are the same known type: that stream type name = d->first_stream_sti->name; } else if(d->found_theora && d->found_vorbis && !d->has_non_vorbis_non_theora_stream) { // else if there are Theora and Vorbis streams and nothing else... name="Theora+Vorbis"; } else if(d->found_theora) { // else if there's a Theora stream... name="Theora+other"; } // (else "other") de_snprintf(tmps, sizeof(tmps), "Ogg %s", name?name:"(other)"); de_declare_fmt(c, tmps); }
static int do_page(deark *c, lctx *d, int pagenum, de_int64 pos1) { struct page_ctx *pg = NULL; int retval = 0; pg = de_malloc(c, sizeof(struct page_ctx)); pg->fmt = identify_fmt(c, pos1); d->last_fmt = pg->fmt; pg->fmt_name = get_fmt_name(pg->fmt); if(pg->fmt==0) { de_err(c, "Not PNM/PAM format\n"); goto done; } if(pagenum==0) { de_declare_fmt(c, pg->fmt_name); } if(pg->fmt==FMT_PAM) { if(!read_pam_header(c, d, pg, pos1)) goto done; } else { if(!read_pnm_header(c, d, pg, pos1)) goto done; } if(!do_image(c, d, pg, pg->hdr_parse_pos)) { goto done; } d->last_bytesused = (pg->hdr_parse_pos + pg->image_data_len) - pos1; retval = 1; done: de_free(c, pg); return retval; }
static void de_run_tga(deark *c, de_module_params *mparams) { lctx *d = NULL; i64 pos; dbuf *unc_pixels = NULL; int saved_indent_level; i64 rowspan_tmp; de_dbg_indent_save(c, &saved_indent_level); d = de_malloc(c, sizeof(lctx)); detect_file_format(c, d); if(d->file_format==FMT_VST) { de_declare_fmt(c, "TrueVista"); } else { de_declare_fmt(c, "TGA"); } pos = 0; if(d->file_format==FMT_VST) { if(!do_read_vst_headers(c, d)) goto done; } else { if(!do_read_tga_headers(c, d)) goto done; } pos += 18; if(d->id_field_len>0) { de_dbg(c, "image ID at %d (len=%d)", (int)pos, (int)d->id_field_len); pos += d->id_field_len; } if(d->color_map_type!=0) { d->bytes_per_pal_entry = (d->cmap_depth+7)/8; d->pal_size_in_bytes = d->cmap_length * d->bytes_per_pal_entry; de_dbg(c, "color map at %d (%d colors, %d bytes)", (int)pos, (int)d->cmap_length, (int)d->pal_size_in_bytes); de_dbg_indent(c, 1); if(!do_read_palette(c, d, pos)) goto done; de_dbg_indent(c, -1); pos += d->pal_size_in_bytes; } de_dbg(c, "bitmap at %d", (int)pos); de_dbg_indent(c, 1); d->bytes_per_pixel = ((d->pixel_depth+7)/8); if(d->pixel_depth==1) { rowspan_tmp = (d->main_image.width+7)/8; } else { rowspan_tmp = d->main_image.width * d->bytes_per_pixel; } d->main_image.img_size_in_bytes = d->main_image.height * rowspan_tmp; if(d->color_type!=TGA_CLRTYPE_PALETTE && d->color_type!=TGA_CLRTYPE_TRUECOLOR && d->color_type!=TGA_CLRTYPE_GRAYSCALE) { de_err(c, "Unsupported color type (%d: %s)", (int)d->color_type, d->clrtype_name); goto done; } if( (d->color_type==TGA_CLRTYPE_PALETTE && d->pixel_depth==8) || (d->color_type==TGA_CLRTYPE_TRUECOLOR && d->pixel_depth==15) || (d->color_type==TGA_CLRTYPE_TRUECOLOR && d->pixel_depth==16) || (d->color_type==TGA_CLRTYPE_TRUECOLOR && d->pixel_depth==24) || (d->color_type==TGA_CLRTYPE_TRUECOLOR && d->pixel_depth==32) || (d->color_type==TGA_CLRTYPE_GRAYSCALE && d->pixel_depth==1) || (d->color_type==TGA_CLRTYPE_GRAYSCALE && d->pixel_depth==8) ) { ; } else { de_err(c, "Unsupported TGA image type (%s, depth=%d)", d->clrtype_name, (int)d->pixel_depth); goto done; } if(d->cmpr_type==TGA_CMPR_RLE) { if(d->pixel_depth<8) { de_err(c, "RLE compression not supported when depth (%d) is less than 8", (int)d->pixel_depth); goto done; } unc_pixels = dbuf_create_membuf(c, d->main_image.img_size_in_bytes, 1); if(!do_decode_rle(c, d, pos, unc_pixels)) goto done; } else if(d->cmpr_type==TGA_CMPR_NONE) { unc_pixels = dbuf_open_input_subfile(c->infile, pos, d->main_image.img_size_in_bytes); } else { de_err(c, "Unsupported compression type (%d, %s)", (int)d->cmpr_type, d->cmpr_name); goto done; } // Maybe scan the image, to help detect transparency. do_prescan_image(c, d, unc_pixels); if(d->pixel_depth==32) { de_dbg(c, "using alpha channel: %s", d->has_alpha_channel?"yes":"no"); } // TODO: 16-bit images could theoretically have a transparency bit, but I don't // know how to detect that. do_decode_image(c, d, &d->main_image, unc_pixels, NULL, 0); de_dbg_indent(c, -1); if(d->thumbnail_offset!=0) { do_decode_thumbnail(c, d); } done: dbuf_close(unc_pixels); de_dbg_indent_restore(c, saved_indent_level); de_free(c, d); }
static void de_run_alphabmp(deark *c, de_module_params *mparams) { unsigned int flags; lctx *d = NULL; i64 pos; i64 palsize; dbuf *unc_pixels = NULL; int saved_indent_level; de_dbg_indent_save(c, &saved_indent_level); d = de_malloc(c, sizeof(lctx)); de_declare_fmt(c, "Alpha Microsystems BMP"); pos = 10; de_dbg(c, "bitmap image definition block at %d", (int)pos); de_dbg_indent(c, 1); d->w = de_getu16le(pos); d->h = de_getu16le(pos+2); de_dbg_dimensions(c, d->w, d->h); if(!de_good_image_dimensions(c, d->w, d->h)) goto done; d->bpp = de_getu16le(pos+4); de_dbg(c, "bits/pixel: %d", (int)d->bpp); flags = (unsigned int)de_getu16le(pos+6); d->has_palette = flags & 0x01; d->palette_is_hls = (flags>>1) & 0x01; de_dbg(c, "has-palette: %d", (int)d->has_palette); if(d->has_palette) de_dbg(c, "palette-is-HLS: %d", (int)d->palette_is_hls); d->compression = de_getu16le(pos+8); de_dbg(c, "compression: %d", (int)d->compression); de_dbg_indent(c, -1); pos += 70; if(d->has_palette) { if(d->palette_is_hls && d->bpp<=8) { de_err(c, "HLS palettes are not supported"); goto done; } if(!do_read_palette(c, d, pos, &palsize)) goto done; pos += palsize; } else if(d->bpp<=8) { de_err(c, "Paletted images without an embedded palette are not supported"); goto done; } de_dbg(c, "bitmap at %d", (int)pos); de_dbg_indent(c, 1); if(d->compression) { unc_pixels = dbuf_create_membuf(c, 32768, 0); if(!do_uncompress_image(c, d, pos, unc_pixels)) goto done; } else { unc_pixels = dbuf_open_input_subfile(c->infile, pos, c->infile->len - pos); } if(d->bpp!=1 && d->bpp!=4 && d->bpp!=8 && d->bpp!=24) { de_err(c, "%d bits/pixel is not supported", (int)d->bpp); goto done; } do_bitmap(c, d, unc_pixels); de_dbg_indent(c, -1); done: de_dbg_indent_restore(c, saved_indent_level); dbuf_close(unc_pixels); de_free(c, d); }
static void de_run_png(deark *c, de_module_params *mparams) { lctx *d = NULL; i64 pos; i32 prev_chunk_id = 0; int suppress_idat_dbg = 0; d = de_malloc(c, sizeof(lctx)); de_dbg(c, "signature at %d", 0); de_dbg_indent(c, 1); d->fmt = do_identify_png_internal(c); switch(d->fmt) { case DE_PNGFMT_PNG: d->fmt_name = "PNG"; break; case DE_PNGFMT_JNG: d->fmt_name = "JNG"; break; case DE_PNGFMT_MNG: d->fmt_name = "MNG"; break; default: d->fmt_name = "?"; } de_dbg(c, "format: %s", d->fmt_name); if(d->fmt>0) { de_declare_fmt(c, d->fmt_name); } de_dbg_indent(c, -1); pos = 8; while(pos < c->infile->len) { struct de_fourcc chunk4cc; struct handler_params hp; u32 crc; char nbuf[80]; de_zeromem(&hp, sizeof(struct handler_params)); hp.dlen = de_getu32be(pos); if(pos + 8 + hp.dlen + 4 > c->infile->len) break; dbuf_read_fourcc(c->infile, pos+4, &chunk4cc, 4, 0x0); hp.cti = get_chunk_type_info(chunk4cc.id); if(chunk4cc.id==CODE_IDAT && suppress_idat_dbg) { ; } else if(chunk4cc.id==CODE_IDAT && prev_chunk_id==CODE_IDAT && c->debug_level<2) { de_dbg(c, "(more IDAT chunks follow)"); suppress_idat_dbg = 1; } else { if(hp.cti) { if(hp.cti->name) { de_snprintf(nbuf, sizeof(nbuf), " (%s)", hp.cti->name); } else { de_strlcpy(nbuf, "", sizeof(nbuf)); } } else { de_strlcpy(nbuf, " (?)", sizeof(nbuf)); } de_dbg(c, "chunk '%s'%s at %d dpos=%d dlen=%d", chunk4cc.id_dbgstr, nbuf, (int)pos, (int)(pos+8), (int)hp.dlen); if(chunk4cc.id!=CODE_IDAT) suppress_idat_dbg = 0; } pos += 8; de_dbg_indent(c, 1); hp.dpos = pos; hp.chunk4cc = &chunk4cc; if(hp.cti) { if(hp.cti->handler_fn) { hp.cti->handler_fn(c, d, &hp); } } else { if(c->debug_level>=2) { handler_hexdump(c, d, &hp); } } pos += hp.dlen; crc = (u32)de_getu32be(pos); de_dbg2(c, "crc32 (reported): 0x%08x", (unsigned int)crc); pos += 4; de_dbg_indent(c, -1); prev_chunk_id = chunk4cc.id; } de_free(c, d); }
static void de_run_gemraster(deark *c, de_module_params *mparams) { i64 ver; i64 ext_word0 = 0; lctx *d = NULL; int need_format_warning = 0; int saved_indent_level; de_dbg_indent_save(c, &saved_indent_level); d = de_malloc(c, sizeof(lctx)); de_dbg(c, "header (base part) at %d", 0); de_dbg_indent(c, 1); ver = de_getu16be(0); de_dbg(c, "version: %d", (int)ver); d->header_size_in_words = de_getu16be(2); d->header_size_in_bytes = d->header_size_in_words*2; de_dbg(c, "header size: %d words (%d bytes)", (int)d->header_size_in_words, (int)d->header_size_in_bytes); d->nplanes = de_getu16be(4); de_dbg(c, "planes: %d", (int)d->nplanes); if(d->header_size_in_words>=11) { d->is_ximg = !dbuf_memcmp(c->infile, 16, "XIMG", 4); } d->patlen = de_getu16be(6); de_dbg(c, "pattern def len: %d", (int)d->patlen); d->pixwidth = de_getu16be(8); d->pixheight = de_getu16be(10); de_dbg(c, "pixel size: %d"DE_CHAR_TIMES"%d microns", (int)d->pixwidth, (int)d->pixheight); d->w = de_getu16be(12); d->h = de_getu16be(14); de_dbg_dimensions(c, d->w, d->h); de_dbg_indent(c, -1); if(d->header_size_in_words>=9) { // This may help to detect the image format. ext_word0 = de_getu16be(16); } if(ver>2) { de_err(c, "This version of GEM Raster (%d) is not supported.", (int)ver); goto done; } if(d->is_ximg) { de_declare_fmt(c, "GEM VDI Bit Image, XIMG extension"); } else if(d->header_size_in_words==25 && d->patlen==2 && ext_word0==0x0080) { de_declare_fmt(c, "GEM VDI Bit Image, Hyperpaint extension"); } else if(d->header_size_in_words==8 && d->nplanes==1) { ; } else if(d->header_size_in_words==8 && (d->nplanes>=2 && d->nplanes<=8)) { need_format_warning = 1; } else if(d->header_size_in_words==9 && (d->nplanes>=1 && d->nplanes<=8)) { need_format_warning = 1; } else { if(d->header_size_in_words==27 && ext_word0==0x5354) { de_declare_fmt(c, "GEM VDI Bit Image, STTT extension"); } de_err(c, "This version of GEM Raster is not supported."); goto done; } if(need_format_warning) { de_warn(c, "This type of GEM Raster image is not very portable, and might " "not be handled correctly."); } if(!de_good_image_dimensions(c, d->w, d->h)) goto done; d->rowspan_per_plane = (d->w+7)/8; d->rowspan_total = d->rowspan_per_plane * d->nplanes; // If we haven't declared the format yet, do so. de_declare_fmt(c, "GEM VDI Bit Image"); if(d->is_ximg) { do_gem_ximg(c, d); } else if(d->header_size_in_words==25) { do_gem_ximg(c, d); } else { do_gem_img(c, d); } done: de_dbg_indent_restore(c, saved_indent_level); de_free(c, d); }