Campbell Barton d869b5
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
Toshihiro Shimizu 890ddd
#define _CRT_SECURE_NO_DEPRECATE 1
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "zlib.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "psdutils.h"
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void readrow(FILE *psd, TPSDChannelInfo *chan,
Shinya Kitaoka 120a6e
             psdPixel row,             // row index
Shinya Kitaoka 120a6e
             unsigned char *inbuffer,  // dest buffer for the uncompressed row
Shinya Kitaoka 120a6e
             unsigned char *
Shinya Kitaoka 120a6e
                 tmpbuffer)  // temp rlebuffer for compressed data, 2xrb in size
Toshihiro Shimizu 890ddd
{
Shinya Kitaoka 120a6e
  psdPixel n = 0, rlebytes;
Shinya Kitaoka 120a6e
  psdByte pos;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int seekres = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  switch (chan->comptype) {
Shinya Kitaoka 120a6e
  case RAWDATA: /* uncompressed */
Shinya Kitaoka 120a6e
    pos                  = chan->filepos + chan->rowbytes * row;
Shinya Kitaoka 120a6e
    seekres              = fseek(psd, pos, SEEK_SET);
Shinya Kitaoka 120a6e
    if (seekres != -1) n = fread(inbuffer, 1, chan->rowbytes, psd);
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case RLECOMP:
Shinya Kitaoka 120a6e
    pos     = chan->rowpos[row];
Shinya Kitaoka 120a6e
    seekres = fseek(psd, pos, SEEK_SET);
Shinya Kitaoka 120a6e
    if (seekres != -1) {
Shinya Kitaoka 120a6e
      rlebytes = fread(tmpbuffer, 1, chan->rowpos[row + 1] - pos, psd);
Shinya Kitaoka 120a6e
      n        = unpackrow(inbuffer, tmpbuffer, chan->rowbytes, rlebytes);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case ZIPWITHPREDICTION:
Shinya Kitaoka 120a6e
  case ZIPWITHOUTPREDICTION:
Shinya Kitaoka 120a6e
    memcpy(inbuffer, chan->unzipdata + chan->rowbytes * row, chan->rowbytes);
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  // if we don't recognise the compression type, skip the row
Shinya Kitaoka 120a6e
  // FIXME: or would it be better to use the last valid type seen?
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //	if(seekres == -1)
Shinya Kitaoka 120a6e
  //	alwayswarn("# can't seek to " LL_L("%lld\n","%ld\n"), pos);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (n < chan->rowbytes) {
Shinya Kitaoka 120a6e
    // warn("row data short (wanted %d, got %d bytes)", chan->rowbytes, n);
Shinya Kitaoka 120a6e
    // zero out unwritten part of row
Shinya Kitaoka 120a6e
    memset(inbuffer + n, 0, chan->rowbytes - n);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int unpackrow(unsigned char *out, unsigned char *in, psdPixel outlen,
Shinya Kitaoka 120a6e
              psdPixel inlen) {
Shinya Kitaoka 120a6e
  psdPixel i, len;
Shinya Kitaoka 120a6e
  int val;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (i = 0; inlen > 1 && i < outlen;) {
Shinya Kitaoka 120a6e
    len = *in++;
Shinya Kitaoka 120a6e
    --inlen;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (len == 128) /* ignore RLE flag value */
Shinya Kitaoka 120a6e
      ;
Shinya Kitaoka 120a6e
    else {
Shinya Kitaoka 120a6e
      if (len > 128) {
Shinya Kitaoka 120a6e
        len = 1 + 256 - len;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        val = *in++;
Shinya Kitaoka 120a6e
        --inlen;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        if ((i + len) <= outlen)
Shinya Kitaoka 120a6e
          memset(out, val, len);
Shinya Kitaoka 120a6e
        else {
Shinya Kitaoka 120a6e
          memset(out, val, outlen - i);  // fill to complete row
Shinya Kitaoka 120a6e
          len = 0;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        ++len;
Shinya Kitaoka 120a6e
        if ((i + len) <= outlen) {
Shinya Kitaoka 120a6e
          if (len > inlen) break;
Shinya Kitaoka 120a6e
          memcpy(out, in, len);
Shinya Kitaoka 120a6e
          in += len;
Shinya Kitaoka 120a6e
          inlen -= len;
Shinya Kitaoka 120a6e
        } else {
Shinya Kitaoka 120a6e
          memcpy(out, in, outlen - i);  // copy to complete row
Shinya Kitaoka 120a6e
          len = 0;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      out += len;
Shinya Kitaoka 120a6e
      i += len;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (i < outlen) {
Shinya Kitaoka 120a6e
    // WARNING: not enough RLE data for row;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return i;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void skipBlock(FILE *f) {
Shinya Kitaoka 120a6e
  psdByte n = read4Bytes(f);
Shinya Kitaoka 120a6e
  if (n) {
Shinya Kitaoka 120a6e
    fseek(f, n, SEEK_CUR);
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Read 2byte unsigned binary value.
Toshihiro Shimizu 890ddd
// BigEndian.
Shinya Kitaoka 120a6e
unsigned read2UBytes(FILE *f) {
Shinya Kitaoka 120a6e
  unsigned n = fgetc(f) << 8;
Shinya Kitaoka 120a6e
  return n |= fgetc(f);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
// Read 2byte binary value
Toshihiro Shimizu 890ddd
// BigEndian.
Shinya Kitaoka 120a6e
int read2Bytes(FILE *f) {
Shinya Kitaoka 120a6e
  unsigned n = fgetc(f) << 8;
Shinya Kitaoka 120a6e
  n |= fgetc(f);
Shinya Kitaoka 120a6e
  return n < 0x8000 ? n : n - 0x10000;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Read 4byte signed binary value.
Toshihiro Shimizu 890ddd
// BigEndian.
Shinya Kitaoka 120a6e
long read4Bytes(FILE *f) {
Shinya Kitaoka 120a6e
  long n = fgetc(f) << 24;
Shinya Kitaoka 120a6e
  n |= fgetc(f) << 16;
Shinya Kitaoka 120a6e
  n |= fgetc(f) << 8;
Shinya Kitaoka 120a6e
  return n | fgetc(f);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void *mymalloc(long n) {
Shinya Kitaoka 120a6e
  void *p = malloc(n);
Shinya Kitaoka 120a6e
  if (p)
Shinya Kitaoka 120a6e
    return p;
Shinya Kitaoka 120a6e
  else {
Shinya Kitaoka 120a6e
    // ALLOCATION ERROR
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return NULL;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// ZIP COMPRESSION
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// ZIP WITHOUT PREDICTION
Toshihiro Shimizu 890ddd
// If no error returns 1 else returns 0
Toshihiro Shimizu 890ddd
int psdUnzipWithoutPrediction(unsigned char *src_buf, int src_len,
Shinya Kitaoka 120a6e
                              unsigned char *dst_buf, int dst_len) {
Shinya Kitaoka 120a6e
  z_stream stream;
Shinya Kitaoka 120a6e
  int state;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  memset(&stream, 0, sizeof(z_stream));
Shinya Kitaoka 120a6e
  stream.data_type = Z_BINARY;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  stream.next_in   = (Bytef *)src_buf;
Shinya Kitaoka 120a6e
  stream.avail_in  = src_len;
Shinya Kitaoka 120a6e
  stream.next_out  = (Bytef *)dst_buf;
Shinya Kitaoka 120a6e
  stream.avail_out = dst_len;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (inflateInit(&stream) != Z_OK) return 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  do {
Shinya Kitaoka 120a6e
    state = inflate(&stream, Z_PARTIAL_FLUSH);
Shinya Kitaoka 120a6e
    if (state == Z_STREAM_END) break;
Shinya Kitaoka 120a6e
    if (state == Z_DATA_ERROR || state != Z_OK) break;
Shinya Kitaoka 120a6e
  } while (stream.avail_out > 0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (state != Z_STREAM_END && state != Z_OK) return 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return 1;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// ZIP WITH PREDICTION
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int psdUnzipWithPrediction(unsigned char *src_buf, int src_len,
Shinya Kitaoka 120a6e
                           unsigned char *dst_buf, int dst_len, int row_size,
Shinya Kitaoka 120a6e
                           int color_depth) {
Shinya Kitaoka 120a6e
  int status;
Shinya Kitaoka 120a6e
  int len;
Shinya Kitaoka 120a6e
  unsigned char *buf;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  status = psdUnzipWithoutPrediction(src_buf, src_len, dst_buf, dst_len);
Shinya Kitaoka 120a6e
  if (!status) return status;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  buf = dst_buf;
Shinya Kitaoka 120a6e
  do {
Shinya Kitaoka 120a6e
    len = row_size;
Shinya Kitaoka 120a6e
    if (color_depth == 16) {
Shinya Kitaoka 120a6e
      while (--len) {
Shinya Kitaoka 120a6e
        buf[2] += buf[0] + ((buf[1] + buf[3]) >> 8);
Shinya Kitaoka 120a6e
        buf[3] += buf[1];
Shinya Kitaoka 120a6e
        buf += 2;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      buf += 2;
Shinya Kitaoka 120a6e
      dst_len -= row_size * 2;
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      while (--len) {
Shinya Kitaoka 120a6e
        *(buf + 1) += *buf;
Shinya Kitaoka 120a6e
        buf++;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      buf++;
Shinya Kitaoka 120a6e
      dst_len -= row_size;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } while (dst_len > 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return 1;
Toshihiro Shimizu 890ddd
}