Пример #1
0
struct dictentry *findbykey(psd_file_t f, int level, struct dictentry *parent,
							char *key, int len, int resetpos)
{
	struct dictentry *d;

	for(d = parent; d->key; ++d)
		if(KEYMATCH(key, d->key)){
			char *tagname = d->tag + (d->tag[0] == '-');
			//fprintf(stderr, "matched tag %s\n", d->tag);
			if(d->func)
				entertag(f, level, len, parent, d, resetpos);
			else{
				// there is no function to parse this block.
				// because tag is empty in this case, we only need to consider
				// parent's one-line-ness.
				if(xml){
					if(parent->tag[0] == '-')
						fprintf(xml, " <%s /> <!-- not parsed --> ", tagname);
					else
						fprintf(xml, "%s<%s /> <!-- not parsed -->\n", tabs(level), tagname);
				}
			}
			return d;
		}
	return NULL;
}
Пример #2
0
void layerblendmode(psd_file_t f, int level, int len, struct blend_mode_info *bm){
	struct dictentry *d;
	const char *indent = tabs(level);

	if(xml && KEYMATCH(bm->sig, "8BIM")){
		fprintf(xml, "%s<BLENDMODE OPACITY='%g' CLIPPING='%d'>\n",
				indent, bm->opacity/2.55, bm->clipping);
		findbykey(f, level+1, bmdict, bm->key, len, 1);
		if(bm->flags & 1) fprintf(xml, "%s\t<TRANSPARENCYPROTECTED />\n", indent);
		if(bm->flags & 2) fprintf(xml, "%s\t<HIDDEN />\n", indent);
		if((bm->flags & (8|16)) == (8|16))  // both bits set
			fprintf(xml, "%s\t<PIXELDATAIRRELEVANT />\n", indent);
		fprintf(xml, "%s</BLENDMODE>\n", indent);
	}
	if(!xml){
		d = findbykey(f, level+1, bmdict, bm->key, len, 1);
		VERBOSE("  blending mode: sig='%c%c%c%c' key='%c%c%c%c'(%s) opacity=%d(%d%%) clipping=%d(%s)\n\
    flags=%#x(transp_prot%s visible%s bit4valid%s pixel_data_irrelevant%s)\n",
				bm->sig[0],bm->sig[1],bm->sig[2],bm->sig[3],
				bm->key[0],bm->key[1],bm->key[2],bm->key[3],
				d ? d->desc : "???",
				bm->opacity, (bm->opacity*100+127)/255,
				bm->clipping, bm->clipping ? "non-base" : "base",
				bm->flags, BITSTR(bm->flags&1), BITSTR(bm->flags&2), BITSTR(bm->flags&8), BITSTR(bm->flags&16) );
	}
Пример #3
0
unsigned scan(unsigned char *addr, size_t len, int psd_version, struct layer_info *li)
{
	unsigned char *p = addr, *q;
	size_t i;
	int j, k;
	unsigned n = 0, ps_ptr_bytes = 2 << psd_version;
	struct dictentry *de;

	for(i = 0; i < len;)
	{
		if(KEYMATCH((char*)p+i, "8BIM")){
			i += 4;

			// found possible layer signature
			// check next 4 bytes for a known blend mode
			for(de = bmdict; de->key; ++de)
				if(!memcmp(de->key, (char*)p+i, 4)){
					// found a possible layer blendmode signature
					// try to guess number of channels
					for(j = 1; j < 64; ++j){
						q = p + i - 4 - j*(ps_ptr_bytes + 2) - 2;
						if(peek2B(q) == j){
							long t = peek4B(q-16), l = peek4B(q-12), b = peek4B(q-8), r = peek4B(q-4);
							// sanity check bounding box
							if(b >= t && r >= l){
								// sanity check channel ids
								for(k = 0; k < j; ++k){
									int chid = peek2B(q + 2 + k*(ps_ptr_bytes + 2));
									if(chid < -2 || chid >= j)
										break; // smells bad, give up
								}
								if(k == j){
									// channel ids were ok. could still be a valid guess...
									++n;
									if(li){
										li->filepos = q - p - 16;
										++li;
									}
									else
										VERBOSE("scavenge @ %8td : key: %c%c%c%c  could be %d channel layer: t = %ld, l = %ld, b = %ld, r = %ld\n",
											   q - p - 16,
											   de->key[0], de->key[1], de->key[2], de->key[3],
											   j,
											   t, l, b, r);
									break;
								}
							}
						}
					}

					break;
				}
		}else
			++i;
	}
	return n;
}
Пример #4
0
int is_resource(unsigned char *addr, size_t len, size_t offset)
{
	int namelen;
	long size;

	if(KEYMATCH(addr + offset, "8BIM")){
		offset += 4; // type
		offset += 2; // id
		namelen = addr[offset];
		offset += PAD2(1+namelen);
		size = peek4B(addr+offset);
		offset += 4;
		offset += PAD2(size); // skip resource block data
		return offset; // should be offset of next resource
	}
	return 0;
}
Пример #5
0
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;
}