static void do_uncompress_24(deark *c, lctx *d, struct page_ctx *pg, dbuf *unc_pixels, de_int64 skip) { de_int64 pos; de_byte b; de_int64 count; de_byte n; pos = pg->image_pos; if(skip) pos+=4; while(1) { if(pos >= pg->image_pos + pg->image_len) break; b = de_getbyte(pos); pos++; if(b>=128) { // Compressed run count = (de_int64)b - 125; n = de_getbyte(pos); pos++; dbuf_write_run(unc_pixels, n, count); } else { // An uncompressed run count = 1 + (de_int64)b; dbuf_copy(c->infile, pos, count, unc_pixels); pos += count; } } }
static void do_dir_entry(deark *c, lctx *d, de_int64 entry_num, de_int64 pos) { de_byte filetype_c64s; de_byte filetype; filetype_c64s = de_getbyte(pos); if(filetype_c64s==0) { de_dbg2(c, "unused entry #%d at %d\n", (int)entry_num, (int)pos); return; } de_dbg(c, "entry #%d at %d\n", (int)entry_num, (int)pos); de_dbg_indent(c, 1); filetype = de_getbyte(pos+1); de_dbg(c, "c64s filetype=%d, filetype=0x%02x\n", (int)filetype_c64s, (int)filetype); if(filetype==0x00) { de_err(c, "Unsupported file type (0x%02x)\n", (int)filetype); } else { do_extract_file(c, d, pos, filetype_c64s, filetype); } de_dbg_indent(c, -1); }
static void do_psf1_header(deark *c, lctx *d) { de_int64 pos = 0; de_dbg(c, "PFXv1 header at %d\n", (int)pos); de_dbg_indent(c, 1); d->headersize = 4; d->mode = de_getbyte(2); de_dbg(c, "mode: 0x%02x\n", (unsigned int)d->mode); de_dbg_indent(c, 1); d->num_glyphs = (d->mode & 0x01) ? 512 : 256; de_dbg(c, "number of glyphs: %d\n", (int)d->num_glyphs); d->has_unicode_table = (d->mode & 0x02) ? 1 : 0; de_dbg(c, "has Unicode table: %s\n", d->has_unicode_table?"yes":"no"); de_dbg_indent(c, -1); d->bytes_per_glyph = (de_int64)de_getbyte(3); d->glyph_height = d->bytes_per_glyph; d->glyph_width = 8; de_dbg(c, "glyph dimensions: %dx%d\n", (int)d->glyph_width, (int)d->glyph_height); de_dbg_indent(c, -1); }
static void handler_IHDR(deark *c, lctx *d, struct handler_params *hp) { i64 w, h; u8 n; const char *name; if(hp->dlen<13) return; w = de_getu32be(hp->dpos); h = de_getu32be(hp->dpos+4); de_dbg_dimensions(c, w, h); n = de_getbyte(hp->dpos+8); de_dbg(c, "depth: %d bits/sample", (int)n); d->color_type = de_getbyte(hp->dpos+9); switch(d->color_type) { case 0: name="grayscale"; break; case 2: name="truecolor"; break; case 3: name="palette"; break; case 4: name="grayscale+alpha"; break; case 6: name="truecolor+alpha"; break; default: name="?"; } de_dbg(c, "color type: %d (%s)", (int)d->color_type, name); n = de_getbyte(hp->dpos+12); de_dbg(c, "interlaced: %d", (int)n); }
// 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 handler_sPLT(deark *c, lctx *d, struct handler_params *hp) { struct de_stringreaderdata *srd = NULL; i64 pos = hp->dpos; i64 nbytes_to_scan; u8 depth; i64 nentries; i64 stride; i64 i; nbytes_to_scan = hp->dlen; if(nbytes_to_scan>80) nbytes_to_scan=80; srd = dbuf_read_string(c->infile, pos, nbytes_to_scan, 79, DE_CONVFLAG_STOP_AT_NUL, DE_ENCODING_LATIN1); if(!srd->found_nul) goto done; de_dbg(c, "palette name: \"%s\"", ucstring_getpsz(srd->str)); pos += srd->bytes_consumed; if(pos >= hp->dpos+hp->dlen) goto done; depth = de_getbyte(pos++); de_dbg(c, "depth: %d", (int)depth); if(depth!=8 && depth!=16) goto done; stride = (depth==8) ? 6 : 10; nentries = (hp->dpos+hp->dlen-pos)/stride; de_dbg(c, "number of entries: %d", (int)nentries); if(c->debug_level<2) goto done; for(i=0; i<nentries; i++) { unsigned int cr, cg, cb, ca, cf; if(depth==8) { cr = (unsigned int)de_getbyte(pos); cg = (unsigned int)de_getbyte(pos+1); cb = (unsigned int)de_getbyte(pos+2); ca = (unsigned int)de_getbyte(pos+3); cf = (unsigned int)de_getu16be(pos+4); de_dbg2(c, "pal[%3d] = (%3u,%3u,%3u,A=%u) F=%u", (int)i, cr, cg, cb, ca, cf); } else { cr = (unsigned int)de_getu16be(pos); cg = (unsigned int)de_getu16be(pos+2); cb = (unsigned int)de_getu16be(pos+4); ca = (unsigned int)de_getu16be(pos+6); cf = (unsigned int)de_getu16be(pos+8); de_dbg2(c, "pal[%3d] = (%5u,%5u,%5u,A=%u) F=%u", (int)i, cr, cg, cb, ca, cf); } pos += stride; } done: de_destroy_stringreaderdata(c, srd); }
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; }
// This .vst (TrueVista) decoder is based on guesswork, on the limited information // in the TGA spec, and on the behavior of XnView. It may not be correct. static int do_read_vst_headers(deark *c, lctx *d) { int retval = 0; de_dbg(c, "header at %d", 0); de_dbg_indent(c, 1); d->id_field_len = (i64)de_getbyte(0); if(d->id_field_len==0) { // ??? XnView seems to do something like this. d->id_field_len=18; } d->cmpr_type = TGA_CMPR_NONE; d->cmpr_name = "none"; d->main_image.width = de_getu16le(12); d->main_image.height = de_getu16le(14); de_dbg_dimensions(c, d->main_image.width, d->main_image.height); d->pixel_depth = (i64)de_getbyte(16); de_dbg(c, "pixel depth: %d", (int)d->pixel_depth); if(d->pixel_depth==8) { d->color_map_type = 1; d->color_type = TGA_CLRTYPE_PALETTE; d->clrtype_name = "palette"; } else { d->color_type = TGA_CLRTYPE_TRUECOLOR; d->clrtype_name = "truecolor"; } if(d->color_type==TGA_CLRTYPE_PALETTE) { d->cmap_start = 0; d->cmap_length = 256; d->cmap_depth = 24; } do_read_image_descriptor(c, d); de_dbg_indent(c, -1); if(!de_good_image_dimensions(c, d->main_image.width, d->main_image.height)) goto done; retval = 1; done: return retval; }
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; }
// Some OS/2v2 files exist with bad (3-bytes/color) palettes. // Try to detect them. static void do_os2v2_bad_palette(deark *c, lctx *d) { de_int64 pal_space_avail; de_int64 pal_bytes_if_3bpc; de_int64 pal_bytes_if_4bpc; int nonzero_rsvd; int i; if(d->version!=DE_BMPVER_OS2V2) return; if(d->pal_entries<1) return; pal_space_avail = d->bits_offset - d->pal_pos; pal_bytes_if_4bpc = 4*d->pal_entries; pal_bytes_if_3bpc = 3*d->pal_entries; if(pal_space_avail>=pal_bytes_if_4bpc) return; if(pal_space_avail<pal_bytes_if_3bpc || pal_space_avail>(pal_bytes_if_3bpc+1)) return; // Look for nonzero 'reserved' bytes nonzero_rsvd = 0; for(i=0; i<pal_bytes_if_3bpc; i+=4) { if(de_getbyte(d->pal_pos + i + 3) != 0) { nonzero_rsvd = 1; break; } } if(!nonzero_rsvd) return; de_warn(c, "Assuming palette has 3 bytes per entry, instead of 4\n"); d->bytes_per_pal_entry = 3; }
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; } }
static void de_run_cardfile(deark *c, de_module_params *mparams) { lctx *d = NULL; de_byte b; de_int64 pos; de_int64 n; d = de_malloc(c, sizeof(lctx)); pos = 0; b = de_getbyte(pos); if(b=='R') d->fmt=DE_CRDFMT_RRG; else d->fmt=DE_CRDFMT_MGC; if(d->fmt==DE_CRDFMT_RRG) { de_err(c, "CardFile RRG format is not supported\n"); goto done; } pos+=3; d->numcards = de_getui16le(pos); de_dbg(c, "number of cards: %d\n", (int)d->numcards); pos+=2; for(n=0; n<d->numcards; n++) { do_card_index(c, d, n, pos); pos+=52; } done: de_free(c, d); }
static void do_extract_file(deark *c, lctx *d, de_int64 dir_pos, de_byte filetype_c64s, de_byte filetype) { de_int64 load_addr; de_int64 end_addr; de_int64 offset; dbuf *f = NULL; de_int64 payload_size; // = file_size-2 de_ucstring *fname = NULL; de_int64 fname_len; de_int64 i; de_int64 fnpos; de_finfo *fi = NULL; load_addr = de_getui16le(dir_pos+2); end_addr = de_getui16le(dir_pos+4); offset = de_getui32le(dir_pos+8); de_dbg(c, "load_addr=%d end_addr=%d offset=%d\n", (int)load_addr, (int)end_addr, (int)offset); // File name at pos+16 fnpos = dir_pos+16; // Find the length of the (space-padded) filename. fname_len = 0; for(i=15; i>=0; i--) { if(de_getbyte(fnpos+i)!=' ') { fname_len = i+1; break; } } de_dbg2(c, "filename length: %d\n", (int)fname_len); fname = ucstring_create(c); dbuf_read_to_ucstring(c->infile, fnpos, fname_len, fname, 0, DE_ENCODING_PETSCII); de_dbg(c, "filename: \"%s\"\n", ucstring_get_printable_sz(fname)); ucstring_append_sz(fname, ".prg", DE_ENCODING_ASCII); fi = de_finfo_create(c); de_finfo_set_name_from_ucstring(c, fi, fname); fi->original_filename_flag = 1; payload_size = end_addr - load_addr; if(payload_size < 0) { // TODO: Try to support files that don't have end_addr set properly. de_err(c, "This type of T64 file is not supported.\n"); goto done; } f = dbuf_create_output_file(c, NULL, fi, 0); dbuf_copy(c->infile, dir_pos+2, 2, f); dbuf_copy(c->infile, offset, payload_size, f); done: dbuf_close(f); de_finfo_destroy(c, fi); ucstring_destroy(fname); }
static int do_decode_rle(deark *c, lctx *d, i64 pos1, dbuf *unc_pixels) { u8 b; i64 count; i64 k; u8 buf[8]; i64 pos = pos1; while(1) { if(pos >= c->infile->len) break; if(unc_pixels->len >= d->main_image.img_size_in_bytes) break; b = de_getbyte(pos); pos++; if(b & 0x80) { // RLE block count = (i64)(b - 0x80) + 1; de_read(buf, pos, d->bytes_per_pixel); pos += d->bytes_per_pixel; for(k=0; k<count; k++) { dbuf_write(unc_pixels, buf, d->bytes_per_pixel); } } else { // uncompressed block count = (i64)(b) + 1; dbuf_copy(c->infile, pos, count * d->bytes_per_pixel, unc_pixels); pos += count * d->bytes_per_pixel; } } de_dbg(c, "decompressed %d bytes to %d bytes", (int)(pos-pos1), (int)unc_pixels->len); return 1; }
static void handler_orNT(deark *c, lctx *d, struct handler_params *hp) { u8 n; if(hp->dlen!=1) return; n = de_getbyte(hp->dpos); de_dbg(c, "orientation: %d (%s)", (int)n, de_fmtutil_tiff_orientation_name((i64)n)); }
static void handler_tRNS(deark *c, lctx *d, struct handler_params *hp) { i64 r, g, b; if(d->color_type==0) { if(hp->dlen<2) return; r = de_getu16be(hp->dpos); de_dbg(c, "transparent color gray shade: %d", (int)r); } else if(d->color_type==2) { if(hp->dlen<6) return; r = de_getu16be(hp->dpos); g = de_getu16be(hp->dpos+2); b = de_getu16be(hp->dpos+4); de_dbg(c, "transparent color: (%d,%d,%d)", (int)r, (int)g, (int)b); } else if(d->color_type==3) { i64 i; u8 a; de_dbg(c, "number of alpha values: %d", (int)hp->dlen); if(c->debug_level<2) return; for(i=0; i<hp->dlen && i<256; i++) { a = de_getbyte(hp->dpos+i); de_dbg2(c, "alpha[%3d] = %d", (int)i, (int)a); } } }
static int de_identify_wad(deark *c) { if(!dbuf_memcmp(c->infile, 1, "WAD", 3)) { u8 b0; b0 = de_getbyte(0); if(b0=='I' || b0=='P') return 80; } return 0; }
static int de_identify_iptc(deark *c) { de_byte b; // First byte of each dataset is 0x1c. if(de_getbyte(0)!=0x1c) return 0; // Check the record number. Record numbers 1-9 are known. b = de_getbyte(1); if(b<1 || b>15) return 0; // This is not meant to imply that .iptc is an official file extension for // IPTC data. It's just that it's used by Deark when extracting IPTC data // to a file. if(!de_input_file_has_ext(c, "iptc")) return 0; return 60; }
static void de_run_psf(deark *c, de_module_params *mparams) { lctx *d = NULL; de_byte b; const char *s; d = de_malloc(c, sizeof(lctx)); s = de_get_ext_option(c, "font:noaliases"); if(s) d->read_extra_codepoints = 0; else d->read_extra_codepoints = 1; b = de_getbyte(0); if(b==0x36) { d->version=1; } else if(b==0x72) { d->version=2; } else { de_err(c, "Not a PSF file\n"); goto done; } de_dbg(c, "PSF version: %d\n", (int)d->version); if(d->version==2) do_psf2_header(c, d); else do_psf1_header(c, d); d->font_data_size = d->bytes_per_glyph * d->num_glyphs; if(d->has_unicode_table) { d->unicode_table_pos = d->headersize + d->font_data_size; if(d->unicode_table_pos >= c->infile->len) { d->has_unicode_table = 0; } } if((d->headersize+d->font_data_size > c->infile->len) || d->bytes_per_glyph<1 || d->glyph_width<1 || d->glyph_width>256 || d->glyph_height<1 || d->glyph_height>256 || d->num_glyphs<1 || d->num_glyphs>2000000) { de_err(c, "Invalid or unsupported PSF file\n"); goto done; } do_glyphs(c, d); done: de_free(c, d); }
static void handler_tIME(deark *c, lctx *d, struct handler_params *hp) { i64 yr; u8 mo, da, hr, mi, se; struct de_timestamp ts; char timestamp_buf[64]; yr = de_getu16be(hp->dpos); mo = de_getbyte(hp->dpos+2); da = de_getbyte(hp->dpos+3); hr = de_getbyte(hp->dpos+4); mi = de_getbyte(hp->dpos+5); se = de_getbyte(hp->dpos+6); de_make_timestamp(&ts, yr, mo, da, hr, mi, se); ts.tzcode = DE_TZCODE_UTC; de_timestamp_to_string(&ts, timestamp_buf, sizeof(timestamp_buf), 0); de_dbg(c, "mod time: %s", timestamp_buf); }
static int do_lead_section(deark *c, lctx *d) { int retval = 0; de_dbg(c, "lead section at %d", 0); de_dbg_indent(c, 1); d->ver_major = de_getbyte(4); d->ver_minor = de_getbyte(5); de_dbg(c, "RPM format version: %d.%d", (int)d->ver_major, (int)d->ver_minor); if(d->ver_major < 3) { de_err(c, "Unsupported RPM version (%d.%d)", (int)d->ver_major, (int)d->ver_minor); goto done; } retval = 1; done: de_dbg_indent(c, -1); return retval; }
static int read_pam_header(deark *c, lctx *d, struct page_ctx *pg, de_int64 pos1) { int ret; de_int64 pos = pos1; int retval = 0; char linebuf[200]; char token1buf[200]; //char token2buf[200]; de_dbg(c, "header at %d\n", (int)pos1); de_dbg_indent(c, 1); de_err(c, "PAM format not supported\n"); goto done; pos += 3; // Skip "P7\n" while(1) { de_int64 content_len; de_int64 total_len; de_int64 curpos; //ret = dbuf_find_line(c->infile, pos, // &content_len, &total_len); ret = read_pam_header_line(c, d, pg, pos, &content_len, &total_len, linebuf, sizeof(linebuf)); if(!ret) { de_err(c, "Invalid PAM header\n"); break; } if(content_len>0 && (de_getbyte(pos)=='#')) { // comment line pos += total_len; continue; } curpos = 0; if(!read_next_pam_token(c, d, pg, linebuf, token1buf, sizeof(token1buf), &curpos)) goto done; if(!de_strcmp(token1buf,"ENDHDR")) { break; } pos += total_len; continue; } retval = 1; done: de_dbg_indent(c, -1); return retval; }
static void do_decode_thumbnail(deark *c, lctx *d) { dbuf *unc_pixels = NULL; i64 hdrsize = 2; de_dbg(c, "thumbnail image at %d", (int)d->thumbnail_offset); de_dbg_indent(c, 1); // The thumbnail image is supposed to use the same format as the main image, // except without compression. (And the dimensions are obviously different.) // Presumably this means the origin, palette, etc. will be the same. // But based on the few TGA thumbnails we've seen, nobody reads the spec, and // it's anybody's guess what format the thumbnail will use. // TGA 2.0 spec says the dimensions are one *byte* each. d->thumbnail_image.width = (i64)de_getbyte(d->thumbnail_offset); d->thumbnail_image.height = (i64)de_getbyte(d->thumbnail_offset+1); de_dbg(c, "thumbnail dimensions: %d"DE_CHAR_TIMES"%d", (int)d->thumbnail_image.width, (int)d->thumbnail_image.height); if(d->thumbnail_image.width!=0 && d->thumbnail_image.height==0) { de_warn(c, "Thumbnail image height is 0. Assuming the file incorrectly uses " "16-bit thumbnail dimensions, instead of 8."); d->thumbnail_image.width = de_getu16le(d->thumbnail_offset); d->thumbnail_image.height = de_getu16le(d->thumbnail_offset+2); de_dbg(c, "revised thumbnail dimensions: %d"DE_CHAR_TIMES"%d", (int)d->thumbnail_image.width, (int)d->thumbnail_image.height); hdrsize = 4; } if(!de_good_image_dimensions(c, d->thumbnail_image.width, d->thumbnail_image.height)) goto done; d->thumbnail_image.img_size_in_bytes = d->thumbnail_image.height * d->thumbnail_image.width * d->bytes_per_pixel; unc_pixels = dbuf_open_input_subfile(c->infile, d->thumbnail_offset+hdrsize, d->thumbnail_image.img_size_in_bytes); do_decode_image(c, d, &d->thumbnail_image, unc_pixels, "thumb", DE_CREATEFLAG_IS_AUX); done: dbuf_close(unc_pixels); de_dbg_indent(c, -1); }
// Print an element ID number, in the format used by the Matroska spec. static void print_encoded_id(deark *c, lctx *d, i64 pos, i64 len) { de_ucstring *s = NULL; i64 i; if(len>8) return; s = ucstring_create(c); for(i=0; i<len; i++) { ucstring_printf(s, DE_ENCODING_UTF8, "[%02x]", (unsigned int)de_getbyte(pos+i)); } de_dbg(c, "encoded id: %s", ucstring_getpsz_d(s)); ucstring_destroy(s); }
static void do_para_fprop(deark *c, lctx *d, struct para_info *pinfo, i64 bfprop, u8 is_dup) { i64 fprop_dlen = 0; // bfprop is a pointer into the 123 bytes of data starting // at pos+4. The maximum sensible value is at most 122. if(bfprop<=122) { // It appears that the length prefix does not include itself, // contrary to what one source says. fprop_dlen = (i64)de_getbyte(pinfo->bfprop_offset); if(!is_dup) de_dbg(c, "fprop dlen: %d", (int)fprop_dlen); } if(fprop_dlen>=2) { pinfo->justification = de_getbyte(pinfo->bfprop_offset + 1 + 1) & 0x03; if(!is_dup && pinfo->justification!=0) { de_dbg(c, "justification: %d", (int)pinfo->justification); } } if(fprop_dlen>=17) { pinfo->papflags = de_getbyte(pinfo->bfprop_offset + 1 + 16); if(!is_dup) { de_ucstring *flagstr = ucstring_create(c); if(pinfo->papflags&0x06) { ucstring_append_flags_item(flagstr, (pinfo->papflags&0x01)?"footer":"header"); ucstring_append_flags_item(flagstr, (pinfo->papflags&0x08)?"print on first page": "do not print on first page"); } if(pinfo->papflags&0x10) ucstring_append_flags_item(flagstr, "picture"); de_dbg(c, "paragraph flags: 0x%02x (%s)", (unsigned int)pinfo->papflags, ucstring_getpsz(flagstr)); ucstring_destroy(flagstr); } } }
static void do_vorbis_page(deark *c, lctx *d, struct page_info *pgi, struct stream_info *si) { u8 firstbyte; if(pgi->is_first_page) { // The first Ogg page of a bitstream usually contains enough data to be // useful. So, we'll try to process it directly, without reconstructing // the codec bitstream. do_vorbis_id_header(c, d, pgi, si); } // We want to save a copy of the Comment and Setup header data, // but not the Identification header which is handled elsewhere. if(si->stream_state!=0) { // We've already handled the Comment & Setup headers. goto done; } if(pgi->dlen<1) goto done; firstbyte = de_getbyte(pgi->dpos); if(si->page_count==0 || pgi->page_seq_num==0 || (pgi->hdr_type&0x02)) { // This appears to be the Identification header page. Skip it. goto done; } if(pgi->page_seq_num>=1 && (firstbyte&0x01)) { // This appears to be one of the pages we care about. // Save its data for later. if(!si->header_stream) { si->header_stream = dbuf_create_membuf(c, 1048576, 1); } dbuf_copy(c->infile, pgi->dpos, pgi->dlen, si->header_stream); } else if((firstbyte&0x01)==0) { // Reached the end of headers (by encountering a non-header page). // (There is required to be an Ogg page break immediately after the // Vorbis headers, so the start of the first data *page* must correspond // to the start of the first data *packet*. A Vorbis data packet always // begins with a byte whose low bit is 0.) do_theora_vorbis_after_headers(c, d, si); } done: ; }
static void handler_sRGB(deark *c, lctx *d, struct handler_params *hp) { u8 intent; const char *name; if(hp->dlen<1) return; intent = de_getbyte(hp->dpos); switch(intent) { case 0: name="perceptual"; break; case 1: name="relative"; break; case 2: name="saturation"; break; case 3: name="absolute"; break; default: name="?"; } de_dbg(c, "rendering intent: %d (%s)", (int)intent, name); }
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 handler_pHYs(deark *c, lctx *d, struct handler_params *hp) { i64 dx, dy; u8 u; const char *name; dx = de_getu32be(hp->dpos); dy = de_getu32be(hp->dpos+4); de_dbg(c, "density: %d"DE_CHAR_TIMES"%d", (int)dx, (int)dy); u = de_getbyte(hp->dpos+8); switch(u) { case 0: name="unspecified"; break; case 1: name="per meter"; break; default: name="?"; } de_dbg(c, "units: %d (%s)", (int)u, name); }
static int read_next_token(deark *c, lctx *d, struct page_ctx *pg, char *tokenbuf, size_t tokenbuflen) { de_byte b; size_t token_len = 0; int in_comment = 0; token_len = 0; while(1) { if(pg->hdr_parse_pos >= c->infile->len) return 0; if(token_len >= tokenbuflen) { return 0; // Token too long. } b = de_getbyte(pg->hdr_parse_pos++); if(in_comment) { if(b==10 || b==13) { in_comment = 0; } continue; } else if(b=='#') { in_comment = 1; continue; } else if(is_pnm_whitespace(b)) { if(token_len>0) { tokenbuf[token_len] = '\0'; return 1; } else { continue; // Skip leading whitespace. } } else { // Append the character to the token. tokenbuf[token_len] = (char)b; token_len++; } } return 0; }