/* This file is part of PSPFormat, a File Format plugin for Adobe Photoshop Copyright (C) 2003-7 Toby Thain, toby@telegraphics.com.au This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* PSP File Format Specification is Copyright (C) 2000 Jasc Software, Inc. See http://www.jasc.com/specs/psp.asp */ #include "psp.h" #include OSErr readrectL(FILEREF r, RECT *pr){ OSErr e; (e = read4L(r, &pr->left)) || (e = read4L(r, &pr->top)) || (e = read4L(r, &pr->right)) || (e = read4L(r, &pr->bottom)) ; return e; } OSErr writerectL(FILEREF r, RECT *pr){ OSErr e; (e = write4L(r, pr->left)) || (e = write4L(r, pr->top)) || (e = write4L(r, pr->right)) || (e = write4L(r, pr->bottom)) ; return e; } OSErr readvarstr(FILEREF r, char *p, int max){ OSErr e; short n; FILECOUNT count; if( !(e = read2L(r, &n)) ){ --max; count = n < max ? n : max; p[count] = 0; if(!(e = FSREAD(r, &count, p)) && count != n) e = SETFPOS(r, fsFromMark, n - count); } return e; } OSErr writevarstr(FILEREF r, char *p){ OSErr e; FILECOUNT count = strlen(p); if( !(e = write2L(r, count)) ) e = FSWRITE(r, &count, p); return e; } OSErr skip(FILEREF r, long n){ return SETFPOS(r, fsFromMark, n); } OSErr psp_read_file_header(FILEREF r, PSP_file_header *h){ OSErr e; FILECOUNT count = PSP_SIG_LENGTH; (e = FSREAD(r, &count, h->signature)) || (e = read2L(r, (short*)&h->major_version)) || (e = read2L(r, (short*)&h->minor_version)) ; return e; } OSErr psp_write_file_header(FILEREF r, PSP_file_header *h){ OSErr e; FILECOUNT count = PSP_SIG_LENGTH; (e = FSWRITE(r, &count, h->signature)) || (e = write2L(r, h->major_version)) || (e = write2L(r, h->minor_version)) ; return e; } OSErr psp_read_block_header(FILEREF r, int vers, PSP_block_header *bh){ OSErr e; FILECOUNT count = 4; (e = FSREAD(r, &count, bh->header_id)) || (e = read2L(r, (short*)&bh->block_id)) || ( vers <= PSP_SPEC5 ? (e = read4L(r, (long*)&bh->initial_len)) : (bh->initial_len = 0) ) || (e = read4L(r, (long*)&bh->block_len)) ; return e; } OSErr psp_write_block_header(FILEREF r, int vers, PSP_block_header *bh){ OSErr e; FILECOUNT count = 4; (e = FSWRITE(r, &count, bh->header_id)) || (e = write2L(r, bh->block_id)) || ( vers <= PSP_SPEC5 ? (e = write4L(r, bh->initial_len)) : 0 ) || (e = write4L(r, bh->block_len)) ; return e; } OSErr write_block(FILEREF f, int vers, WORD block_id, DWORD initial_len, DWORD block_len){ PSP_block_header bh; strcpy(bh.header_id, PSP_BLOCK_ID); bh.block_id = block_id; /* initial_len, only used in v5 spec, is size of first chunk (after header) only */ bh.initial_len = initial_len; /* block_len is total size of all enclosed chunks and blocks */ bh.block_len = block_len; return psp_write_block_header(f, vers, &bh); } OSErr psp_read_image_attr_chunk(FILEREF r, int vers, PSP_image_attr_chunk *c){ OSErr e; ( vers > PSP_SPEC5 ? (e = read4L(r, (long*)&c->chunk_size)) : (c->chunk_size = 0) ) || (e = read4L(r, &c->image_width)) || (e = read4L(r, &c->image_height)) || (e = readdoubleL(r, &c->resolution)) || (e = read1 (r, &c->res_metric)) || (e = read2L(r, (short*)&c->comp_type)) || (e = read2L(r, (short*)&c->bit_depth)) || (e = read2L(r, (short*)&c->plane_count)) || (e = read4L(r, (long*)&c->colour_count)) || (e = read1 (r, &c->greyscale_flag)) || (e = read4L(r, (long*)&c->total_size)) || (e = read4L(r, &c->active_layer)) || (e = read2L(r, (short*)&c->layer_count)) || ( vers > PSP_SPEC5 ? (e = read4L(r, (long*)&c->graphic_contents)) : (c->graphic_contents = 0) ) || ( vers > PSP_SPEC5 ? (e = skip(r, c->chunk_size-46)) : noErr ) ; return e; } OSErr psp_write_image_attr_chunk(FILEREF r, int vers, PSP_image_attr_chunk *c){ OSErr e; ( vers > PSP_SPEC5 ? (e = write4L(r, c->chunk_size)) : 0 ) || (e = write4L(r, c->image_width)) || (e = write4L(r, c->image_height)) || (e = writedoubleL(r, c->resolution)) || (e = write1 (r, c->res_metric)) || (e = write2L(r, c->comp_type)) || (e = write2L(r, c->bit_depth)) || (e = write2L(r, c->plane_count)) || (e = write4L(r, c->colour_count)) || (e = write1 (r, c->greyscale_flag)) || (e = write4L(r, c->total_size)) || (e = write4L(r, c->active_layer)) || (e = write2L(r, c->layer_count)) || ( vers > PSP_SPEC5 ? (e = write4L(r, c->graphic_contents)) : 0 ) ; return e; } OSErr psp5_read_thumbnail_attr_chunk(FILEREF r, PSP5_thumbnail_attr_chunk *c){ OSErr e; (e = read4L(r, &c->width)) || (e = read4L(r, &c->height)) || (e = read2L(r, (short*)&c->bit_depth)) || (e = read2L(r, (short*)&c->comp_type)) || (e = read2L(r, (short*)&c->plane_count)) || (e = read4L(r, (long*)&c->colour_count)) || (e = read4L(r, (long*)&c->palette_entry_count)) || (e = read2L(r, (short*)&c->channel_count)) ; return e; } OSErr psp7_read_layer_bitmap_chunk(FILEREF r, PSP7_layer_bitmap_chunk *c){ OSErr e; (e = read4L(r, (long*)&c->chunk_size)) || (e = read2L(r, (short*)&c->bitmap_count)) || (e = read2L(r, (short*)&c->channel_count)) || (e = skip(r, c->chunk_size-8)) ; return e; } OSErr psp7_write_layer_bitmap_chunk(FILEREF r, PSP7_layer_bitmap_chunk *c){ OSErr e; (e = write4L(r, c->chunk_size)) || (e = write2L(r, c->bitmap_count)) || (e = write2L(r, c->channel_count)) ; return e; } OSErr psp_read_layer_info_chunk(FILEREF r, int vers, PSP_layer_info_chunk *c){ FILEPOS pos; FILECOUNT count1 = PSP_LAYER_NAME_MAX, count2 = PSP_BLEND_RANGE_BYTES; OSErr e; GETFPOS(r, &pos); ( vers > PSP_SPEC5 ? (e = read4L(r, (long*)&c->chunk_size)) : (c->chunk_size = 0) ) || (e = vers > PSP_SPEC5 ? readvarstr(r, c->name, PSP_LAYER_NAME_MAX) : FSREAD(r, &count1, c->name) ) || (e = read1 (r, &c->type)) || (e = readrectL(r, &c->image_rect)) || (e = readrectL(r, &c->saved_rect)) || (e = read1 (r, &c->opacity)) || (e = read1 (r, &c->blending_mode)) || (e = read1 (r, &c->flags)) || (e = read1 (r, &c->transparency_flags)) || (e = read1 (r, &c->link_group_id)) || (e = readrectL(r, &c->mask_rect)) || (e = readrectL(r, &c->saved_mask_rect)) || (e = read1 (r, &c->mask_linked)) || (e = read1 (r, &c->mask_disabled)) || (e = read1 (r, &c->invert_mask_on_blend)) || (e = read2L(r, (short*)&c->blend_range_count)) || (e = FSREAD(r, &count2, &c->blend_range_data)) || ( vers <= PSP_SPEC5 ? (e = read2L(r, (short*)&c->bitmap_count)) : (c->bitmap_count = 0) ) || ( vers <= PSP_SPEC5 ? (e = read2L(r, (short*)&c->channel_count)) : (c->channel_count = 0) ) || ( vers > PSP_SPEC5 ? (e = SETFPOS(r, fsFromStart, pos+c->chunk_size)) : noErr ) ; return e; } OSErr psp_write_layer_info_chunk(FILEREF r, int vers, PSP_layer_info_chunk *c){ FILECOUNT count1 = PSP_LAYER_NAME_MAX, count2 = PSP_BLEND_RANGE_BYTES; OSErr e; ( vers > PSP_SPEC5 ? (e = write4L(r, c->chunk_size)) : 0 ) || (e = vers > PSP_SPEC5 ? writevarstr(r, c->name) : FSWRITE(r, &count1, c->name) ) || (e = write1 (r, c->type)) || (e = writerectL(r, &c->image_rect)) || (e = writerectL(r, &c->saved_rect)) || (e = write1 (r, c->opacity)) || (e = write1 (r, c->blending_mode)) || (e = write1 (r, c->flags)) || (e = write1 (r, c->transparency_flags)) || (e = write1 (r, c->link_group_id)) || (e = writerectL(r, &c->mask_rect)) || (e = writerectL(r, &c->saved_mask_rect)) || (e = write1 (r, c->mask_linked)) || (e = write1 (r, c->mask_disabled)) || (e = write1 (r, c->invert_mask_on_blend)) || (e = write2L(r, c->blend_range_count)) || (e = FSWRITE(r, &count2, &c->blend_range_data)) || ( vers <= PSP_SPEC5 ? (e = write2L(r, c->bitmap_count)) : 0 ) || ( vers <= PSP_SPEC5 ? (e = write2L(r, c->channel_count)) : 0 ) ; return e; } OSErr psp_read_channel_info_chunk(FILEREF r, int vers, PSP_channel_info_chunk *c){ OSErr e; ( vers > PSP_SPEC5 ? (e = read4L(r, (long*)&c->chunk_size)) : (c->chunk_size = 0) ) || (e = read4L(r, (long*)&c->comp_length)) || (e = read4L(r, (long*)&c->uncomp_length)) || (e = read2L(r, (short*)&c->bitmap_type)) || (e = read2L(r, (short*)&c->channel_type)) || ( vers > PSP_SPEC5 ? (e = skip(r, c->chunk_size-16)) : noErr ) ; return e; } OSErr psp_write_channel_info_chunk(FILEREF r, int vers, PSP_channel_info_chunk *c){ OSErr e; ( vers > PSP_SPEC5 ? (e = write4L(r, c->chunk_size)) : 0 ) || (e = write4L(r, c->comp_length)) || (e = write4L(r, c->uncomp_length)) || (e = write2L(r, c->bitmap_type)) || (e = write2L(r, c->channel_type)) ; return e; } OSErr psp_read_palette_info_chunk(FILEREF r, int vers, PSP_palette_info_chunk *c){ OSErr e; ( vers > PSP_SPEC5 ? (e = read4L(r, (long*)&c->chunk_size)) : (c->chunk_size = 0) ) || (e = read4L(r, (long*)&c->entry_count)) || ( vers > PSP_SPEC5 ? (e = skip(r, c->chunk_size-8)) : noErr ) ; return e; } OSErr psp_write_palette_info_chunk(FILEREF r, int vers, PSP_palette_info_chunk *c){ OSErr e; ( vers > PSP_SPEC5 ? (e = write4L(r, c->chunk_size)) : 0 ) || (e = write4L(r, c->entry_count)) ; return e; } OSErr psp_read_alpha_bank_info_chunk(FILEREF r, int vers, PSP_alpha_bank_info_chunk *c){ OSErr e; ( vers > PSP_SPEC5 ? (e = read4L(r, (long*)&c->chunk_size)) : (c->chunk_size = 0) ) || (e = read2L(r, (short*)&c->alpha_count)) || ( vers > PSP_SPEC5 ? (e = skip(r, c->chunk_size-6)) : noErr ) ; return e; } OSErr psp_write_alpha_bank_info_chunk(FILEREF r, int vers, PSP_alpha_bank_info_chunk *c){ OSErr e; ( vers > PSP_SPEC5 ? (e = write4L(r, c->chunk_size)) : 0 ) || (e = write2L(r, c->alpha_count)) ; return e; } OSErr psp_read_alpha_channel_info_chunk(FILEREF r, int vers, PSP_alpha_channel_info_chunk *c){ FILEPOS pos; FILECOUNT count1 = PSP_LAYER_NAME_MAX; OSErr e; GETFPOS(r, &pos); ( vers > PSP_SPEC5 ? (e = read4L(r, (long*)&c->chunk_size)) : (c->chunk_size = 0) ) || (e = vers > PSP_SPEC5 ? readvarstr(r, c->name, PSP_LAYER_NAME_MAX) : FSREAD(r, &count1, c->name) ) || (e = readrectL(r, &c->alpha_rect)) || (e = readrectL(r, &c->saved_rect)) || ( vers <= PSP_SPEC5 ? (e = read2L(r, (short*)&c->bitmap_count)) : (c->bitmap_count = 0) ) || ( vers <= PSP_SPEC5 ? (e = read2L(r, (short*)&c->channel_count)) : (c->channel_count = 0) ) || ( vers > PSP_SPEC5 ? (e = SETFPOS(r, fsFromStart, pos+c->chunk_size)) : noErr ) ; return e; } OSErr psp_write_alpha_channel_info_chunk(FILEREF r, int vers, PSP_alpha_channel_info_chunk *c){ FILEPOS pos; FILECOUNT count1 = PSP_LAYER_NAME_MAX; OSErr e; GETFPOS(r, &pos); ( vers > PSP_SPEC5 ? (e = write4L(r, c->chunk_size)) : 0 ) || (e = vers > PSP_SPEC5 ? writevarstr(r, c->name) : FSWRITE(r, &count1, c->name) ) || (e = writerectL(r, &c->alpha_rect)) || (e = writerectL(r, &c->saved_rect)) || ( vers <= PSP_SPEC5 ? (e = write2L(r, c->bitmap_count)) : 0 ) || ( vers <= PSP_SPEC5 ? (e = write2L(r, c->channel_count)) : 0 ) ; return e; } OSErr psp7_read_alpha_channel_chunk(FILEREF r, PSP7_alpha_channel_chunk *c){ OSErr e; (e = read4L(r, (long*)&c->chunk_size)) || (e = read2L(r, (short*)&c->bitmap_count)) || (e = read2L(r, (short*)&c->channel_count)) || (e = skip(r, c->chunk_size-8)); ; return e; } OSErr psp7_write_alpha_channel_chunk(FILEREF r, PSP7_alpha_channel_chunk *c){ OSErr e; (e = write4L(r, c->chunk_size)) || (e = write2L(r, c->bitmap_count)) || (e = write2L(r, c->channel_count)) ; return e; }