int BDATreader::createTOC() { int res,laststate,n; long lastpos,p; datablockinfo db,saveddb; if(hasTOC) deleteTOC(); if(state>0) { laststate=state; lastpos=pos; saveddb=lastinfo; state=1;pos=8; FileSeek(f,pos,SEEK_SET); res=getnextblockinfo(db); while(res==0) { TOCN++; res=skipblock(); if(res==0) res=getnextblockinfo(db); } if(TOCN>0) { hasTOC=true; TOCpos=new long[TOCN]; TOCID=new unsigned int[TOCN]; TOCnames=new string[TOCN]; state=1;p=pos=8; FileSeek(f,pos,SEEK_SET); res=getnextblockinfo(db); n=0; while(res==0) { res=skipblock(); TOCpos[n]=p; TOCID[n]=lastinfo.ID; TOCnames[n]=lastinfo.name; p=pos; if(res==0) res=getnextblockinfo(db); n++; } } state=laststate; pos=lastpos; lastinfo=saveddb; FileSeek(f,pos,SEEK_SET); } else return -1; return 0; };
int BDATreader::printlist() { int res,laststate,n; long lastpos; string tname; datablockinfo db,saveddb; if(state>0) { laststate=state; lastpos=pos; saveddb=lastinfo; state=1;pos=8; FileSeek(f,pos,SEEK_SET); res=getnextblockinfo(db); printf("BDAT binary data file information:\n - name %s\n - size: %ld\n",filename.c_str(),size); n=1; while(res==0) { printf(" - data block %d\n - name: %s\n - ID: %d\n - type: (%08X) ",n,lastinfo.name.c_str(),lastinfo.ID,lastinfo.type); switch (lastinfo.type) { case DT_bit:tname="bits";break; case DT_byte:tname="byte";break; case DT_ubyte:tname="unsigned byte";break; case DT_word:tname="word/2-byte integer";break; case DT_uword:tname="unsigned word/2-byte integer";break; case DT_int:tname="int/4-byte integer";break; case DT_uint:tname="unsigned int/4-byte integer";break; case DT_long:tname="long int/8-byte integer";break; case DT_ulong:tname="unsigned long int/8-byte integer";break; case DT_single:tname="float/4-byte floating point number";break; case DT_double:tname="double/8-byte floating point number";break; case DT_quad:tname="quad/16-byte floating point number";break; case DT_csingle:tname="complex float/two 4-byte floating point numbers";break; case DT_cdouble:tname="complex double/two 8-byte floating point numbers";break; case DT_cquad:tname="complex quad/two 16-byte floating point number";break; case DT_user:tname="user defined format";break; default:tname="unknown";break; } printf("%s\n - records: %d\n - record size: %d bytes\n - data size: %d bytes\n",tname.c_str(),lastinfo.records,lastinfo.recordsize,lastinfo.records*lastinfo.recordsize); res=skipblock(); if(res==0) res=getnextblockinfo(db); n++; } state=laststate; pos=lastpos; lastinfo=saveddb; FileSeek(f,pos,SEEK_SET); } else return -1; //file needs to be open return 0; };
void readlayerinfo(psd_file_t f, struct psd_header *h, int i) { psd_bytes_t extralen, extrastart; int j, chid, namelen; char *chidstr, tmp[10]; struct layer_info *li = h->linfo + i; // process layer record li->top = get4B(f); li->left = get4B(f); li->bottom = get4B(f); li->right = get4B(f); li->channels = get2Bu(f); VERBOSE("\n"); UNQUIET(" layer %d: (%4d,%4d,%4d,%4d), %d channels (%4d rows x %4d cols)\n", i, li->top, li->left, li->bottom, li->right, li->channels, li->bottom-li->top, li->right-li->left); if( li->bottom < li->top || li->right < li->left || li->channels > 64 ) // sanity check { alwayswarn("### something's not right about that, trying to skip layer.\n"); fseeko(f, 6*li->channels+12, SEEK_CUR); skipblock(f, "layer info: extra data"); li->chan = NULL; li->chindex = NULL; li->nameno = li->name = li->unicode_name = NULL; } else { li->chan = checkmalloc(li->channels*sizeof(struct channel_info)); li->chindex = checkmalloc((li->channels+3)*sizeof(int)); li->chindex += 3; // so we can index array from [-3] (hackish) for(j = -3; j < li->channels; ++j) li->chindex[j] = -1; // fetch info on each of the layer's channels for(j = 0; j < li->channels; ++j){ li->chan[j].id = chid = get2B(f); li->chan[j].length = GETPSDBYTES(f); li->chan[j].rawpos = 0; li->chan[j].rowpos = NULL; li->chan[j].unzipdata = NULL; if(chid >= -3 && chid < li->channels) li->chindex[chid] = j; else warn_msg("unexpected channel id %d", chid); switch(chid){ case UMASK_CHAN_ID: chidstr = " (user layer mask)"; break; case LMASK_CHAN_ID: chidstr = " (layer mask)"; break; case TRANS_CHAN_ID: chidstr = " (transparency mask)"; break; default: if(h->mode != SCAVENGE_MODE && chid < (int)strlen(channelsuffixes[h->mode])) sprintf(chidstr = tmp, " (%c)", channelsuffixes[h->mode][chid]); // it's a mode-ish channel else chidstr = ""; // don't know } VERBOSE(" channel %2d: " LL_L("%7lld","%7ld") " bytes, id=%2d %s\n", j, li->chan[j].length, chid, chidstr); } fread(li->blend.sig, 1, 4, f); fread(li->blend.key, 1, 4, f); li->blend.opacity = fgetc(f); li->blend.clipping = fgetc(f); li->blend.flags = fgetc(f); fgetc(f); // padding // process layer's 'extra data' section extralen = get4B(f); extrastart = ftello(f); VERBOSE(" (extra data: " LL_L("%lld","%ld") " bytes @ " LL_L("%lld","%ld") ")\n", extralen, extrastart); // fetch layer mask data li->mask.size = get4B(f); if(li->mask.size >= 20){ off_t skip = li->mask.size; VERBOSE(" (has layer mask)\n"); li->mask.top = get4B(f); li->mask.left = get4B(f); li->mask.bottom = get4B(f); li->mask.right = get4B(f); li->mask.default_colour = fgetc(f); li->mask.flags = fgetc(f); skip -= 18; if(li->mask.size >= 36){ VERBOSE(" (has user layer mask)\n"); li->mask.real_flags = fgetc(f); li->mask.real_default_colour = fgetc(f); li->mask.real_top = get4B(f); li->mask.real_left = get4B(f); li->mask.real_bottom = get4B(f); li->mask.real_right = get4B(f); skip -= 18; } fseeko(f, skip, SEEK_CUR); // skip remainder }else VERBOSE(" (no layer mask)\n"); skipblock(f, "layer blending ranges"); // layer name li->nameno = checkmalloc(16); sprintf(li->nameno, "layer%d", i+1); namelen = fgetc(f); li->name = checkmalloc(PAD4(namelen+1)); fread(li->name, 1, PAD4(namelen+1)-1, f); li->name[namelen] = 0; if(namelen) UNQUIET(" name: \"%s\"\n", li->name); // process layer's 'additional info' li->additionalpos = ftello(f); li->additionallen = extrastart + extralen - li->additionalpos; // leave file positioned after extra data fseeko(f, extrastart + extralen, SEEK_SET); } }
int dopsd(psd_file_t f, char *psdpath, struct psd_header *h){ int result = 0; // file header fread(h->sig, 1, 4, f); h->version = get2Bu(f); get4B(f); get2B(f); // reserved[6]; h->channels = get2Bu(f); h->rows = get4B(f); h->cols = get4B(f); h->depth = get2Bu(f); h->mode = get2Bu(f); if(!feof(f) && KEYMATCH(h->sig, "8BPS")){ if(h->version == 1 #ifdef PSBSUPPORT || h->version == 2 #endif ){ openfiles(psdpath, h); if(listfile) fprintf(listfile, "-- PSD file: %s\n", psdpath); if(xml){ fputs("<PSD FILE='", xml); fputsxml(psdpath, xml); fprintf(xml, "' VERSION='%u' CHANNELS='%u' ROWS='%u' COLUMNS='%u' DEPTH='%u' MODE='%u'", h->version, h->channels, h->rows, h->cols, h->depth, h->mode); if(h->mode >= 0 && h->mode < 16) fprintf(xml, " MODENAME='%s'", mode_names[h->mode]); fputs(">\n", xml); } UNQUIET(" PS%c (version %u), %u channels, %u rows x %u cols, %u bit %s\n", h->version == 1 ? 'D' : 'B', h->version, h->channels, h->rows, h->cols, h->depth, h->mode >= 0 && h->mode < 16 ? mode_names[h->mode] : "???"); if(h->channels <= 0 || h->channels > 64 || h->rows <= 0 || h->cols <= 0 || h->depth <= 0 || h->depth > 32 || h->mode < 0) { alwayswarn("### something isn't right about that header, giving up now.\n"); } else{ h->colormodepos = ftello(f); if(h->mode == ModeDuotone) duotone_data(f, 1); else skipblock(f, "color mode data"); h->resourcepos = ftello(f); if(rsrc || resdump) doimageresources(f); else skipblock(f, "image resources"); dolayermaskinfo(f, h); h->layerdatapos = ftello(f); VERBOSE("## layer data begins @ " LL_L("%lld","%ld") "\n", h->layerdatapos); result = 1; } }else alwayswarn("# \"%s\": version %d not supported\n", psdpath, h->version); }else alwayswarn("# \"%s\": couldn't read header, or is not a PSD/PSB\n", psdpath); if(!result) alwayswarn("# Try --scavenge (and related options) to see if any layer data can be found.\n"); return result; }