/* 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 "dbg.h" #include #include /* The Run Length Encoding (RLE) scheme used in the PSP file format ...the first byte encountered in the compressed stream is a byte that represents a Òrun countÓ. While decompressing, if this run count is greater than 128, then 128 should be subtracted from the Òrun count.Ó This calculated run count (run count Ð 128) indicates the number of times the next byte in the compressed stream should be repeated in the decompressed stream. If the Òrun countÓ read from compressed stream is less than 128, then it indicates the number of following bytes (in the compressed stream) that should be copied as-is from the compressed stream to the decompressed stream. The compressed stream is comprised of these RLE Òpackets,Ó each containing a Òrun countÓ and data associated with that run count. */ /* note that flag bytes of 128 are not generated. */ long rle_compress(unsigned char *src, unsigned char *dst, long len){ unsigned char *q, *run; int n, maxrun; for(run = src, q = dst; len > 0; run += n, len -= n){ maxrun = len < RLE_MAXRUN ? len : RLE_MAXRUN; #if 0 /* trivial uncompressed RLE - for testing only! */ *q++ = n = maxrun; /* flag byte */ memcpy(q, run, n); /* verbatim run */ q += n; #else if(len >= 3 && run[1]==run[0] && run[2]==run[0]){ //dbg("duplicate run"); // we know that the first three bytes are equal, so skip them for(n = 3; n < maxrun && run[n]==run[0];) ++n; *q++ = 128+n; /* flag byte */ *q++ = run[0]; /* the duplicated value */ }else{ //dbg("verbatim run"); // shortest possible verbatim run is 1 for(n = 1; n < maxrun; ++n) if(n <= len-3 && run[n+1]==run[n] && run[n+2]==run[n]) break; // repeated 3 times: end verbatim run *q++ = n; /* flag byte */ memcpy(q, run, n); /* verbatim run */ q += n; } #endif //sprintf(s,"n = %d",n);dbg(s); } return q-dst; } void rle_expand(unsigned char *indata, long bytesin, unsigned char *outdata, long bytesout){ int len; unsigned char *p, *q; for(p = indata, q=outdata; p < (indata+bytesin) && q < (outdata+bytesout);){ len = *p++; if(len > 128){ len -= 128; memset(q, *p++, len); }else{ memcpy(q, p, len); p += len; } q += len; } #if 0 /* decompressed output can overflow the output buffer by as much as RLE_MAXRUN bytes */ if(q > outdata+bytesout) DPRINTF("**** RLE: output overflowed by %d bytes", q-(outdata+bytesout)); #endif }