Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
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 "psd.h"
Toshihiro Shimizu 890ddd
#include "trasterimage.h"
Toshihiro Shimizu 890ddd
#include "trop.h"
Toshihiro Shimizu 890ddd
#include "tpixelutils.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Shinya Kitaoka 120a6e
  The entire content of this file is ridden with LEAKS. A bug has been filed,
Shinya Kitaoka 120a6e
  will hopefully
Toshihiro Shimizu 890ddd
  be dealt with ASAP.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  L'intero contenuto del file e' pieno di LEAK. Ho inserito la cosa in Bugilla e
Shinya Kitaoka 120a6e
  non ho potuto
Shinya Kitaoka 120a6e
  fare altro sotto rilascio. Non solo, il codice dei distruttori e' SBAGLIATO -
Shinya Kitaoka 120a6e
  l'ho esplicitamente
Toshihiro Shimizu 890ddd
  disabilitato, tanto non era chiamato cmq.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  E' da rifare usando SMART POINTERS (boost::scoped_ptr<> o tcg::unique_ptr<>, o
Toshihiro Shimizu 890ddd
  std::unique_ptr<> se facciamo l'upgrade del compilatore).
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  Da osservare che anche il campo FILE in TPSDReader leaka se viene sganciata
Shinya Kitaoka 120a6e
  un'eccezione...
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#define LEVEL_NAME_INDEX_SEP "@"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----forward declarations
Toshihiro Shimizu 890ddd
std::string buildErrorString(int error);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void readChannel(FILE *f, TPSDLayerInfo *li, TPSDChannelInfo *chan,
Shinya Kitaoka 120a6e
                 int channels, TPSDHeaderInfo *h);
Toshihiro Shimizu 890ddd
void readLongData(FILE *f, struct dictentry *parent, TPSDLayerInfo *li);
Toshihiro Shimizu 890ddd
void readByteData(FILE *f, struct dictentry *parent, TPSDLayerInfo *li);
Toshihiro Shimizu 890ddd
void readKey(FILE *f, struct dictentry *parent, TPSDLayerInfo *li);
Toshihiro Shimizu 890ddd
void readLayer16(FILE *f, struct dictentry *parent, TPSDLayerInfo *li);
Toshihiro Shimizu 890ddd
//----end forward declarations
Toshihiro Shimizu 890ddd
Campbell Barton 8c6c57
static char swapByte(unsigned char src) {
Shinya Kitaoka 120a6e
  unsigned char out = 0;
Shinya Kitaoka 120a6e
  for (int i = 0; i < 8; ++i) {
Shinya Kitaoka 120a6e
    out = out << 1;
Shinya Kitaoka 120a6e
    out |= (src & 1);
Shinya Kitaoka 120a6e
    src = src >> 1;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return out;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TPSDReader::TPSDReader(const TFilePath &path)
Shinya Kitaoka 120a6e
    : m_shrinkX(1), m_shrinkY(1), m_region(TRect()) {
Shinya Kitaoka 120a6e
  m_layerId    = 0;
Shinya Kitaoka 120a6e
  QString name = path.getName().c_str();
Shinya Kitaoka 120a6e
  name.append(path.getDottedType().c_str());
Shinya Kitaoka 120a6e
  int sepPos = name.indexOf("#");
Shinya Kitaoka 120a6e
  int dotPos = name.indexOf(".", sepPos);
Shinya Kitaoka 120a6e
  name.remove(sepPos, dotPos - sepPos);
Shinya Kitaoka 120a6e
  m_path = path.getParentDir() + TFilePath(name.toStdString());
Shinya Kitaoka 120a6e
  // m_path = path;
Shinya Kitaoka 120a6e
  QMutexLocker sl(&m_mutex);
Shinya Kitaoka 120a6e
  openFile();
Shinya Kitaoka 120a6e
  if (!doInfo()) {
Shinya Kitaoka 120a6e
    fclose(m_file);
Shinya Kitaoka 120a6e
    throw TImageException(m_path, "Do PSD INFO ERROR");
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  fclose(m_file);
Toshihiro Shimizu 890ddd
}
Shinya Kitaoka 120a6e
TPSDReader::~TPSDReader() {
Shinya Kitaoka 120a6e
  /*for(int i=0; i
Shinya Kitaoka 120a6e
free(m_headerInfo.linfo + i);*/
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // NO - L'istruzione sopra e' SBAGLIATA, si tratta di uno pseudo-array
Shinya Kitaoka 120a6e
  // allocato in blocco
Shinya Kitaoka 120a6e
  // con una SINGOLA malloc() - quindi deve dovrebbe essere deallocato con una
Shinya Kitaoka 120a6e
  // SINGOLA free().
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Se fino ad ora funzionava e' perche' questa funzione NON VENIVA MAI
Shinya Kitaoka 120a6e
  // CHIAMATA -
Shinya Kitaoka 120a6e
  // LEAKAVA TUTTO.
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Non solo, ma il CONTENUTO delle singole strutture - tra cui altri array -
Shinya Kitaoka 120a6e
  // non viene
Shinya Kitaoka 120a6e
  // deallocato. Non ho idea se sia garantito che venga deallocato prima di
Shinya Kitaoka 120a6e
  // arrivare qui,
Shinya Kitaoka 120a6e
  // ma NON E' AFFATTO SICURO.
Toshihiro Shimizu 890ddd
}
Shinya Kitaoka 120a6e
int TPSDReader::openFile() {
Shinya Kitaoka 120a6e
  m_file = fopen(m_path, "rb");
Shinya Kitaoka 120a6e
  if (!m_file) throw TImageException(m_path, buildErrorString(2));
Shinya Kitaoka 120a6e
  return 0;
Toshihiro Shimizu 890ddd
}
Shinya Kitaoka 120a6e
bool TPSDReader::doInfo() {
Shinya Kitaoka 120a6e
  // Read Header Block
Shinya Kitaoka 120a6e
  if (!doHeaderInfo()) return false;
Shinya Kitaoka 120a6e
  // Read Color Mode Data Block
Shinya Kitaoka 120a6e
  if (!doColorModeData()) return false;
Shinya Kitaoka 120a6e
  // Read Image Resources Block
Shinya Kitaoka 120a6e
  if (!doImageResources()) return false;
Shinya Kitaoka 120a6e
  // Read Layer Info Block (Layers Number and merged alpha)
Shinya Kitaoka 120a6e
  if (!doLayerAndMaskInfo()) return false;
Shinya Kitaoka 120a6e
  // Read Layers and Mask Information Block
Shinya Kitaoka 120a6e
  // if(!doLayersInfo()) return false;
Shinya Kitaoka 120a6e
  m_headerInfo.layerDataPos = ftell(m_file);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_headerInfo.layersCount == 0)  // tento con extra data
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    fseek(m_file, m_headerInfo.layerDataPos, SEEK_SET);
Shinya Kitaoka 120a6e
    skipBlock(m_file);  // skip global layer mask info
Shinya Kitaoka 120a6e
    psdByte currentPos = ftell(m_file);
Shinya Kitaoka 120a6e
    psdByte len        = m_headerInfo.lmistart + m_headerInfo.lmilen -
Shinya Kitaoka 120a6e
                  currentPos;  // 4 = bytes skipped by global layer mask info
Shinya Kitaoka 120a6e
    doExtraData(NULL, len);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
// Read Header Block
Shinya Kitaoka 120a6e
bool TPSDReader::doHeaderInfo() {
Shinya Kitaoka 120a6e
  fread(m_headerInfo.sig, 1, 4, m_file);
Shinya Kitaoka 120a6e
  m_headerInfo.version = read2UBytes(m_file);
Shinya Kitaoka 120a6e
  read4Bytes(m_file);
Shinya Kitaoka 120a6e
  read2Bytes(m_file);  // reserved[6];
Shinya Kitaoka 120a6e
  m_headerInfo.channels = read2UBytes(m_file);
Shinya Kitaoka 120a6e
  m_headerInfo.rows     = read4Bytes(m_file);
Shinya Kitaoka 120a6e
  m_headerInfo.cols     = read4Bytes(m_file);
Shinya Kitaoka 120a6e
  m_headerInfo.depth    = read2UBytes(m_file);
Shinya Kitaoka 120a6e
  m_headerInfo.mode     = read2UBytes(m_file);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!feof(m_file) && !memcmp(m_headerInfo.sig, "8BPS", 4)) {
Shinya Kitaoka 120a6e
    if (m_headerInfo.version == 1) {
Shinya Kitaoka 120a6e
      if (m_headerInfo.channels <= 0 || m_headerInfo.channels > 64 ||
Shinya Kitaoka 120a6e
          m_headerInfo.rows <= 0 || m_headerInfo.cols <= 0 ||
Shinya Kitaoka 120a6e
          m_headerInfo.depth < 0 || m_headerInfo.depth > 32 ||
Shinya Kitaoka 120a6e
          m_headerInfo.mode < 0) {
Shinya Kitaoka 120a6e
        throw TImageException(m_path, "Reading PSD Header Info error");
Shinya Kitaoka 120a6e
        return false;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      throw TImageException(m_path, "PSD Version not supported");
Shinya Kitaoka 120a6e
      return false;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    throw TImageException(m_path, "Cannot read Header");
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
// Read Color Mode Data Block
Shinya Kitaoka 120a6e
bool TPSDReader::doColorModeData() {
Shinya Kitaoka 120a6e
  m_headerInfo.colormodepos = ftell(m_file);
Shinya Kitaoka 120a6e
  skipBlock(m_file);  // skip "color mode data"
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
// Read Image Resources Block
Shinya Kitaoka 120a6e
bool TPSDReader::doImageResources() {
Shinya Kitaoka 120a6e
  // skipBlock(m_file); //skip "image resources"
Shinya Kitaoka 120a6e
  long len = read4Bytes(m_file);  // lunghezza del blocco Image resources
Shinya Kitaoka 120a6e
  while (len > 0) {
Shinya Kitaoka 120a6e
    char type[4], name[0x100];
Shinya Kitaoka 120a6e
    int id, namelen;
Shinya Kitaoka 120a6e
    long size;
Shinya Kitaoka 120a6e
    fread(type, 1, 4, m_file);
Shinya Kitaoka 120a6e
    id      = read2Bytes(m_file);
Shinya Kitaoka 120a6e
    namelen = fgetc(m_file);
Shinya Kitaoka 120a6e
    fread(name, 1, NEXT2(1 + namelen) - 1, m_file);
Shinya Kitaoka 120a6e
    name[namelen] = 0;
Shinya Kitaoka 120a6e
    size          = read4Bytes(m_file);
Shinya Kitaoka 120a6e
    if (id == 1005)  // ResolutionInfo
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      psdByte savepos = ftell(m_file);
Shinya Kitaoka 120a6e
      long hres, vres;
Shinya Kitaoka 120a6e
      double hresd, vresd;
Shinya Kitaoka 120a6e
      hresd = FIXDPI(hres = read4Bytes(m_file));
Shinya Kitaoka 120a6e
      read2Bytes(m_file);
Shinya Kitaoka 120a6e
      read2Bytes(m_file);
Shinya Kitaoka 120a6e
      vresd = FIXDPI(vres = read4Bytes(m_file));
Shinya Kitaoka 120a6e
      m_headerInfo.vres = vresd;
Shinya Kitaoka 120a6e
      m_headerInfo.hres = hresd;
Shinya Kitaoka 120a6e
      fseek(m_file, savepos, SEEK_SET);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    len -= 4 + 2 + NEXT2(1 + namelen) + 4 + NEXT2(size);
Shinya Kitaoka 120a6e
    fseek(m_file, NEXT2(size), SEEK_CUR);  // skip resource block data
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (len != 0) return false;
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
// Read Layer Info Block (Layers Number and merged alpha)
Shinya Kitaoka 120a6e
bool TPSDReader::doLayerAndMaskInfo() {
Shinya Kitaoka 120a6e
  psdByte layerlen;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_headerInfo.layersCount = 0;
Shinya Kitaoka 120a6e
  m_headerInfo.lmilen      = read4Bytes(m_file);
Shinya Kitaoka 120a6e
  m_headerInfo.lmistart    = ftell(m_file);
Shinya Kitaoka 120a6e
  if (m_headerInfo.lmilen) {
Shinya Kitaoka 120a6e
    // process layer info section
Shinya Kitaoka 120a6e
    layerlen                     = read4Bytes(m_file);
Shinya Kitaoka 120a6e
    m_headerInfo.linfoBlockEmpty = false;
Shinya Kitaoka 120a6e
    m_headerInfo.mergedalpha     = 0;
Shinya Kitaoka 120a6e
    if (layerlen) {
Shinya Kitaoka 120a6e
      doLayersInfo();
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      // WARNING: layer info section empty
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    // WARNING: layer & mask info section empty
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Read Layers Information Block
Toshihiro Shimizu 890ddd
// It is called by doLayerAndMaskInfo()
Shinya Kitaoka 120a6e
bool TPSDReader::doLayersInfo() {
Shinya Kitaoka 120a6e
  m_headerInfo.layersCount     = read2Bytes(m_file);
Shinya Kitaoka 120a6e
  m_headerInfo.linfoBlockEmpty = false;
Shinya Kitaoka 120a6e
  m_headerInfo.mergedalpha     = m_headerInfo.layersCount < 0;
Shinya Kitaoka 120a6e
  if (m_headerInfo.mergedalpha > 0) {
Shinya Kitaoka 120a6e
    m_headerInfo.layersCount = -m_headerInfo.layersCount;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (!m_headerInfo.linfoBlockEmpty) {
Shinya Kitaoka 120a6e
    m_headerInfo.linfo = (TPSDLayerInfo *)mymalloc(
Shinya Kitaoka 120a6e
        m_headerInfo.layersCount * sizeof(struct TPSDLayerInfo));
Shinya Kitaoka 120a6e
    int i = 0;
Shinya Kitaoka 120a6e
    for (i = 0; i < m_headerInfo.layersCount; i++) {
Shinya Kitaoka 120a6e
      readLayerInfo(i);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Shinya Kitaoka 120a6e
bool TPSDReader::readLayerInfo(int i) {
Shinya Kitaoka 120a6e
  psdByte chlen, extralen, extrastart;
Shinya Kitaoka 120a6e
  int j, chid, namelen;
Shinya Kitaoka 120a6e
  TPSDLayerInfo *li = m_headerInfo.linfo + i;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // process layer record
Shinya Kitaoka 120a6e
  li->top      = read4Bytes(m_file);
Shinya Kitaoka 120a6e
  li->left     = read4Bytes(m_file);
Shinya Kitaoka 120a6e
  li->bottom   = read4Bytes(m_file);
Shinya Kitaoka 120a6e
  li->right    = read4Bytes(m_file);
Shinya Kitaoka 120a6e
  li->channels = read2UBytes(m_file);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (li->bottom < li->top || li->right < li->left ||
Shinya Kitaoka 120a6e
      li->channels > 64)  // sanity ck
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    // qualcosa รจ andato storto, skippo il livello
Shinya Kitaoka 120a6e
    fseek(m_file, 6 * li->channels + 12, SEEK_CUR);
Shinya Kitaoka 120a6e
    skipBlock(m_file);  // skip  "layer info: extra data";
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    li->chan = (TPSDChannelInfo *)mymalloc(li->channels *
Shinya Kitaoka 120a6e
                                           sizeof(struct TPSDChannelInfo));
Shinya Kitaoka 120a6e
    li->chindex = (int *)mymalloc((li->channels + 2) * sizeof(int));
Shinya Kitaoka 120a6e
    li->chindex += 2;  //
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    for (j = -2; j < li->channels; ++j) li->chindex[j] = -1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // fetch info on each of the layer's channels
Shinya Kitaoka 120a6e
    for (j = 0; j < li->channels; ++j) {
Shinya Kitaoka 120a6e
      chid = li->chan[j].id = read2Bytes(m_file);
Shinya Kitaoka 120a6e
      chlen = li->chan[j].length = read4Bytes(m_file);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (chid >= -2 && chid < li->channels)
Shinya Kitaoka 120a6e
        li->chindex[chid] = j;
Shinya Kitaoka 120a6e
      else {
Shinya Kitaoka 120a6e
        // WARNING: unexpected channel id
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    fread(li->blend.sig, 1, 4, m_file);
Shinya Kitaoka 120a6e
    fread(li->blend.key, 1, 4, m_file);
Shinya Kitaoka 120a6e
    li->blend.opacity  = fgetc(m_file);
Shinya Kitaoka 120a6e
    li->blend.clipping = fgetc(m_file);
Shinya Kitaoka 120a6e
    li->blend.flags    = fgetc(m_file);
Shinya Kitaoka 120a6e
    fgetc(m_file);  // padding
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    extralen   = read4Bytes(m_file);
Shinya Kitaoka 120a6e
    extrastart = ftell(m_file);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // layer mask data
Shinya Kitaoka 120a6e
    if ((li->mask.size = read4Bytes(m_file))) {
Shinya Kitaoka 120a6e
      li->mask.top            = read4Bytes(m_file);
Shinya Kitaoka 120a6e
      li->mask.left           = read4Bytes(m_file);
Shinya Kitaoka 120a6e
      li->mask.bottom         = read4Bytes(m_file);
Shinya Kitaoka 120a6e
      li->mask.right          = read4Bytes(m_file);
Shinya Kitaoka 120a6e
      li->mask.default_colour = fgetc(m_file);
Shinya Kitaoka 120a6e
      li->mask.flags          = fgetc(m_file);
Shinya Kitaoka 120a6e
      fseek(m_file, li->mask.size - 18, SEEK_CUR);  // skip remainder
Shinya Kitaoka 120a6e
      li->mask.rows = li->mask.bottom - li->mask.top;
Shinya Kitaoka 120a6e
      li->mask.cols = li->mask.right - li->mask.left;
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      // no layer mask data
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    skipBlock(m_file);  // skip "layer blending ranges";
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // layer name
Shinya Kitaoka 120a6e
    li->nameno = (char *)malloc(16);
Rozhuk Ivan 823a31
    snprintf(li->nameno, 16, "layer%d", i + 1);
Shinya Kitaoka 120a6e
    namelen  = fgetc(m_file);
Shinya Kitaoka 120a6e
    li->name = (char *)mymalloc(NEXT4(namelen + 1));
Shinya Kitaoka 120a6e
    fread(li->name, 1, NEXT4(namelen + 1) - 1, m_file);
Shinya Kitaoka 120a6e
    li->name[namelen] = 0;
Shinya Kitaoka 120a6e
    if (namelen) {
Shinya Kitaoka 120a6e
      if (li->name[0] == '.') li->name[0] = '_';
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // process layer's 'additional info'
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    li->additionalpos = ftell(m_file);
Shinya Kitaoka 120a6e
    li->additionallen = extrastart + extralen - li->additionalpos;
Shinya Kitaoka 120a6e
    doExtraData(li, li->additionallen);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // leave file positioned at end of layer's data
Shinya Kitaoka 120a6e
    fseek(m_file, extrastart + extralen, SEEK_SET);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TPSDReader::doImage(TRasterP &rasP, int layerId) {
Shinya Kitaoka 120a6e
  m_layerId         = layerId;
Shinya Kitaoka 120a6e
  int layerIndex    = getLayerInfoIndexById(layerId);
Shinya Kitaoka 120a6e
  TPSDLayerInfo *li = getLayerInfo(layerIndex);
Shinya Kitaoka 120a6e
  psdByte imageDataEnd;
Shinya Kitaoka 120a6e
  // retrieve start data pos
Shinya Kitaoka 120a6e
  psdByte startPos = ftell(m_file);
Shinya Kitaoka 120a6e
  if (m_headerInfo.layersCount > 0) {
Shinya Kitaoka 120a6e
    struct TPSDLayerInfo *lilast =
Shinya Kitaoka 120a6e
        &m_headerInfo.linfo[m_headerInfo.layersCount - 1];
Shinya Kitaoka 120a6e
    startPos = lilast->additionalpos + lilast->additionallen;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (layerIndex > 0) {
Shinya Kitaoka 120a6e
    for (int j = 0; j < layerIndex; j++) {
Shinya Kitaoka 120a6e
      struct TPSDLayerInfo *liprev = &m_headerInfo.linfo[j];
Shinya Kitaoka 120a6e
      for (int ch = 0; ch < liprev->channels; ch++) {
Shinya Kitaoka 120a6e
        startPos += liprev->chan[ch].length;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  fseek(m_file, startPos, SEEK_SET);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  long pixw    = li ? li->right - li->left : m_headerInfo.cols;
Shinya Kitaoka 120a6e
  long pixh    = li ? li->bottom - li->top : m_headerInfo.rows;
Shinya Kitaoka 120a6e
  int channels = li ? li->channels : m_headerInfo.channels;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (li == NULL)
Shinya Kitaoka 120a6e
    fseek(m_file, m_headerInfo.lmistart + m_headerInfo.lmilen, SEEK_SET);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  psdPixel rows = pixh;
Shinya Kitaoka 120a6e
  psdPixel cols = pixw;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int ch = 0;
Shinya Kitaoka 120a6e
  psdByte **rowpos;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  rowpos = (psdByte **)mymalloc(channels * sizeof(psdByte *));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (ch = 0; ch < channels; ++ch) {
Shinya Kitaoka 120a6e
    psdPixel chrows =
Shinya Kitaoka 120a6e
        li && !m_headerInfo.linfoBlockEmpty && li->chan[ch].id == -2
Shinya Kitaoka 120a6e
            ? li->mask.rows
Shinya Kitaoka 120a6e
            : rows;
Shinya Kitaoka 120a6e
    rowpos[ch] = (psdByte *)mymalloc((chrows + 1) * sizeof(psdByte));
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int tnzchannels = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int depth = m_headerInfo.depth;
Shinya Kitaoka 120a6e
  switch (m_headerInfo.mode) {
Shinya Kitaoka 120a6e
  // default: // multichannel, cmyk, lab etc
Shinya Kitaoka 120a6e
  //	split = 1;
Shinya Kitaoka 120a6e
  case ModeBitmap:
Shinya Kitaoka 120a6e
  case ModeGrayScale:
Shinya Kitaoka 120a6e
  case ModeGray16:
Shinya Kitaoka 120a6e
  case ModeDuotone:
Shinya Kitaoka 120a6e
  case ModeDuotone16:
Shinya Kitaoka 120a6e
    tnzchannels = 1;
Shinya Kitaoka 120a6e
    // check if there is an alpha channel, or if merged data has alpha
Shinya Kitaoka 120a6e
    if (li ? li->chindex[-1] != -1 : channels > 1 && m_headerInfo.mergedalpha) {
Shinya Kitaoka 120a6e
      tnzchannels = 2;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case ModeIndexedColor:
Shinya Kitaoka 120a6e
    tnzchannels = 1;
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case ModeRGBColor:
Shinya Kitaoka 120a6e
  case ModeRGB48:
Shinya Kitaoka 120a6e
    tnzchannels = 3;
Shinya Kitaoka 120a6e
    if (li ? li->chindex[-1] != -1 : channels > 3 && m_headerInfo.mergedalpha) {
Shinya Kitaoka 120a6e
      tnzchannels = 4;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  default:
Shinya Kitaoka 120a6e
    tnzchannels = channels;
Shinya Kitaoka 120a6e
    // assert(0);
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!li || m_headerInfo.linfoBlockEmpty) {  // merged channel
Shinya Kitaoka 120a6e
    TPSDChannelInfo *mergedChans =
Shinya Kitaoka 120a6e
        (TPSDChannelInfo *)mymalloc(channels * sizeof(struct TPSDChannelInfo));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    readChannel(m_file, NULL, mergedChans, channels, &m_headerInfo);
Shinya Kitaoka 120a6e
    imageDataEnd = ftell(m_file);
Shinya Kitaoka 120a6e
    readImageData(rasP, NULL, mergedChans, tnzchannels, rows, cols);
Shinya Kitaoka 120a6e
    free(mergedChans);
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    for (ch = 0; ch < channels; ++ch) {
Shinya Kitaoka 120a6e
      readChannel(m_file, li, li->chan + ch, 1, &m_headerInfo);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    imageDataEnd = ftell(m_file);
Shinya Kitaoka 120a6e
    readImageData(rasP, li, li->chan, tnzchannels, rows, cols);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  fseek(m_file, imageDataEnd, SEEK_SET);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (ch = 0; ch < channels; ++ch) free(rowpos[ch]);
Shinya Kitaoka 120a6e
  free(rowpos);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TPSDReader::load(TRasterImageP &img, int layerId) {
Shinya Kitaoka 120a6e
  QMutexLocker sl(&m_mutex);
Shinya Kitaoka 120a6e
  TPSDLayerInfo *li = NULL;
Shinya Kitaoka 120a6e
  int layerIndex    = 0;
Shinya Kitaoka 120a6e
  if (layerId > 0) {
Shinya Kitaoka 120a6e
    layerIndex = getLayerInfoIndexById(layerId);
Shinya Kitaoka 120a6e
    li         = getLayerInfo(layerIndex);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (layerId < 0) throw TImageException(m_path, "Layer ID not exists");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_headerInfo.mode == 4 || m_headerInfo.depth == 32) {
Shinya Kitaoka 120a6e
    img = TRasterImageP();
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  try {
Shinya Kitaoka 120a6e
    TRasterP rasP;
Shinya Kitaoka 120a6e
    openFile();
Shinya Kitaoka 120a6e
    doImage(rasP, layerId);
Shinya Kitaoka 120a6e
    fclose(m_file);
Shinya Kitaoka 120a6e
    /*
Shinya Kitaoka 120a6e
    // do savebox
Shinya Kitaoka 120a6e
    long sbx0 = li ? li->left : 0;
Shinya Kitaoka 120a6e
    long sby0 = li ? m_headerInfo.rows-li->bottom : 0;
Shinya Kitaoka 120a6e
    long sbx1 = li ? li->right - 1 : m_headerInfo.cols - 1;
Shinya Kitaoka 120a6e
    long sby1 = li ? m_headerInfo.rows - li->top - 1 : m_headerInfo.rows - 1;
Shinya Kitaoka 120a6e
    TRect layerSaveBox;
Shinya Kitaoka 120a6e
    layerSaveBox = TRect(sbx0,sby0,sbx1,sby1);
Shinya Kitaoka 120a6e
    TRect imageRect = TRect(0,0,m_headerInfo.cols-1,m_headerInfo.rows-1);
Shinya Kitaoka 120a6e
    // E' possibile che il layer sia in parte o tutto al di fuori della'immagine
Shinya Kitaoka 120a6e
    // in questo caso considero solo la parte visibile, cioรจ che rientra
Shinya Kitaoka 120a6e
    nell'immagine.
Shinya Kitaoka 120a6e
    // Se รจ tutta fuori restutuisco TRasterImageP()
Shinya Kitaoka 120a6e
    layerSaveBox *= imageRect;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if(layerSaveBox== TRect()) {
Shinya Kitaoka 120a6e
            img = TRasterImageP();
Shinya Kitaoka 120a6e
            return;
Shinya Kitaoka 120a6e
    }			 */
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (!rasP) {
Shinya Kitaoka 120a6e
      img = TRasterImageP();
Shinya Kitaoka 120a6e
      return;
Shinya Kitaoka 120a6e
    }  // Happens if layer image has 0 rows and (or?)
Shinya Kitaoka 120a6e
    // cols (dont ask me why, but I've seen it)
Shinya Kitaoka 120a6e
    TRect layerSaveBox = m_layersSavebox[layerId];
Shinya Kitaoka 120a6e
    TRect savebox(layerSaveBox);
Shinya Kitaoka 120a6e
    TDimension imgSize(rasP->getLx(), rasP->getLy());
Shinya Kitaoka 120a6e
    assert(TRect(imgSize).contains(savebox));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (TRasterGR8P ras = rasP) {
Shinya Kitaoka 120a6e
      TPixelGR8 bgColor;
Shinya Kitaoka 120a6e
      ras->fillOutside(savebox, bgColor);
Shinya Kitaoka 120a6e
      img = TRasterImageP(ras);
Shinya Kitaoka 120a6e
    } else if (TRaster32P ras = rasP) {
Shinya Kitaoka 120a6e
      TPixel32 bgColor(0, 0, 0, 0);
Shinya Kitaoka 120a6e
      if (savebox != TRect())
Shinya Kitaoka 120a6e
        ras->fillOutside(savebox, bgColor);
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        ras->fill(bgColor);
Shinya Kitaoka 120a6e
      img = TRasterImageP(ras);
Shinya Kitaoka 120a6e
    } else if ((TRaster64P)rasP) {
Shinya Kitaoka 120a6e
      TRaster32P raux(rasP->getLx(), rasP->getLy());
Shinya Kitaoka 120a6e
      TRop::convert(raux, rasP);
Shinya Kitaoka 120a6e
      TPixel32 bgColor(0, 0, 0, 0);
Shinya Kitaoka 120a6e
      raux->fillOutside(savebox, bgColor);
Shinya Kitaoka 120a6e
      img = TRasterImageP(raux);
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      throw TImageException(m_path, "Invalid Raster");
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    img->setDpi(m_headerInfo.hres, m_headerInfo.vres);
Shinya Kitaoka 120a6e
    img->setSavebox(savebox);
Shinya Kitaoka 120a6e
  } catch (...) {
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int TPSDReader::getLayerInfoIndexById(int layerId) {
Shinya Kitaoka 120a6e
  int layerIndex = -1;
Shinya Kitaoka 120a6e
  for (int i = 0; i < m_headerInfo.layersCount; i++) {
Shinya Kitaoka 120a6e
    TPSDLayerInfo *litemp = m_headerInfo.linfo + i;
Shinya Kitaoka 120a6e
    if (litemp->layerId == layerId) {
Shinya Kitaoka 120a6e
      layerIndex = i;
Shinya Kitaoka 120a6e
      break;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (layerIndex < 0 && layerId != 0)
Shinya Kitaoka 120a6e
    throw TImageException(m_path, "Layer ID not exists");
Shinya Kitaoka 120a6e
  return layerIndex;
Toshihiro Shimizu 890ddd
}
Shinya Kitaoka 120a6e
TPSDLayerInfo *TPSDReader::getLayerInfo(int index) {
Shinya Kitaoka 120a6e
  if (index < 0 || index >= m_headerInfo.layersCount) return NULL;
Shinya Kitaoka 120a6e
  return m_headerInfo.linfo + index;
Toshihiro Shimizu 890ddd
}
Shinya Kitaoka 120a6e
TPSDHeaderInfo TPSDReader::getPSDHeaderInfo() { return m_headerInfo; }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
void TPSDReader::readImageData(TRasterP &rasP, TPSDLayerInfo *li,
Shinya Kitaoka 120a6e
                               TPSDChannelInfo *chan, int chancount,
Shinya Kitaoka 120a6e
                               psdPixel rows, psdPixel cols) {
Shinya Kitaoka 120a6e
  int channels = li ? li->channels : m_headerInfo.channels;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  short depth = m_headerInfo.depth;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  psdByte savepos = ftell(m_file);
Shinya Kitaoka 120a6e
  if (rows == 0 || cols == 0) return;
Shinya Kitaoka 120a6e
  psdPixel j;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  unsigned char *inrows[4], *rledata;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int ch, map[4];
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  rledata = (unsigned char *)mymalloc(chan->rowbytes * 2);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (ch = 0; ch < chancount; ++ch) {
Shinya Kitaoka 120a6e
    inrows[ch] = (unsigned char *)mymalloc(chan->rowbytes);
Shinya Kitaoka 120a6e
    map[ch]    = li && chancount > 1 ? li->chindex[ch] : ch;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // find the alpha channel, if needed
Shinya Kitaoka 120a6e
  if (li && (chancount == 2 || chancount == 4)) {  // grey+alpha
Shinya Kitaoka 120a6e
    if (li->chindex[-1] == -1) {
Shinya Kitaoka 120a6e
      // WARNING no alpha found?;
Shinya Kitaoka 120a6e
    } else
Shinya Kitaoka 120a6e
      map[chancount - 1] = li->chindex[-1];
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // region dimensions with shrink
Shinya Kitaoka 120a6e
  // x0 e x1 non tengono conto dello shrink.
Shinya Kitaoka 120a6e
  int x0 = 0;
Shinya Kitaoka 120a6e
  int x1 = m_headerInfo.cols - 1;
Shinya Kitaoka 120a6e
  int y0 = 0;
Shinya Kitaoka 120a6e
  int y1 = m_headerInfo.rows - 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!m_region.isEmpty()) {
Shinya Kitaoka 120a6e
    x0 = m_region.getP00().x;
Shinya Kitaoka 120a6e
    // se x0 รจ fuori dalle dimensioni dell'immagine ritorna un'immagine vuota
Shinya Kitaoka 120a6e
    if (x0 >= m_headerInfo.cols) {
Shinya Kitaoka 120a6e
      free(rledata);
Shinya Kitaoka 120a6e
      return;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    x1 = x0 + m_region.getLx() - 1;
Shinya Kitaoka 120a6e
    // controllo che x1 rimanga all'interno dell'immagine
Shinya Kitaoka 120a6e
    if (x1 >= m_headerInfo.cols) x1 = m_headerInfo.cols - 1;
Shinya Kitaoka 120a6e
    y0                              = m_region.getP00().y;
Shinya Kitaoka 120a6e
    // se y0 รจ fuori dalle dimensioni dell'immagine ritorna un'immagine vuota
Shinya Kitaoka 120a6e
    if (y0 >= m_headerInfo.rows) {
Shinya Kitaoka 120a6e
      free(rledata);
Shinya Kitaoka 120a6e
      return;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    y1 = y0 + m_region.getLy() - 1;
Shinya Kitaoka 120a6e
    // controllo che y1 rimanga all'interno dell'immagine
Shinya Kitaoka 120a6e
    if (y1 >= m_headerInfo.rows) y1 = m_headerInfo.rows - 1;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (m_shrinkX > x1 - x0) m_shrinkX = x1 - x0;
Shinya Kitaoka 120a6e
  if (m_shrinkY > y1 - y0) m_shrinkY = y1 - y0;
Shinya Kitaoka 120a6e
  assert(m_shrinkX > 0 && m_shrinkY > 0);
Shinya Kitaoka 120a6e
  if (m_shrinkX > 1) {
Shinya Kitaoka 120a6e
    x1 -= (x1 - x0) % m_shrinkX;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (m_shrinkY > 1) {
Shinya Kitaoka 120a6e
    y1 -= (y1 - y0) % m_shrinkY;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  assert(x0 <= x1 && y0 <= y1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TDimension imgSize((x1 - x0) / m_shrinkX + 1, (y1 - y0) / m_shrinkY + 1);
Shinya Kitaoka 120a6e
  if (depth == 1 && chancount == 1) {
Shinya Kitaoka 120a6e
    rasP = TRasterGR8P(imgSize);
Shinya Kitaoka 120a6e
  } else if (depth == 8 && chancount > 1) {
Shinya Kitaoka 120a6e
    rasP = TRaster32P(imgSize);
Shinya Kitaoka 120a6e
  } else if (m_headerInfo.depth == 8 && chancount == 1) {
Shinya Kitaoka 120a6e
    rasP = TRasterGR8P(imgSize);
Shinya Kitaoka 120a6e
  } else if (m_headerInfo.depth == 16 && chancount == 1 &&
Shinya Kitaoka 120a6e
             m_headerInfo.mergedalpha) {
Shinya Kitaoka 120a6e
    rasP = TRasterGR8P(imgSize);
Shinya Kitaoka 120a6e
  } else if (m_headerInfo.depth == 16) {
Shinya Kitaoka 120a6e
    rasP = TRaster64P(imgSize);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // do savebox
Shinya Kitaoka 120a6e
  // calcolo la savebox in coordinate dell'immagine
Shinya Kitaoka 120a6e
  long sbx0 = li ? li->left - x0 : 0;
Shinya Kitaoka 120a6e
  long sby0 = li ? m_headerInfo.rows - li->bottom - y0 : 0;
Shinya Kitaoka 120a6e
  long sbx1 = li ? li->right - 1 - x0 : x1 - x0;
Shinya Kitaoka 120a6e
  long sby1 = li ? m_headerInfo.rows - li->top - 1 - y0 : y1 - y0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRect layerSaveBox;
Shinya Kitaoka 120a6e
  layerSaveBox = TRect(sbx0, sby0, sbx1, sby1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRect imageRect;
Shinya Kitaoka 120a6e
  if (!m_region.isEmpty())
Shinya Kitaoka 120a6e
    imageRect = TRect(0, 0, m_region.getLx() - 1, m_region.getLy() - 1);
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    imageRect = TRect(0, 0, m_headerInfo.cols - 1, m_headerInfo.rows - 1);
Shinya Kitaoka 120a6e
  // E' possibile che il layer sia in parte o tutto al di fuori della'immagine
Shinya Kitaoka 120a6e
  // in questo caso considero solo la parte visibile, cioรจ che rientra
Shinya Kitaoka 120a6e
  // nell'immagine.
Shinya Kitaoka 120a6e
  // Se รจ tutta fuori restutuisco TRasterImageP()
Shinya Kitaoka 120a6e
  layerSaveBox *= imageRect;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (layerSaveBox == TRect() || layerSaveBox.isEmpty()) {
Shinya Kitaoka 120a6e
    free(rledata);
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  // Estraggo da rasP solo il rettangolo che si interseca con il livello
Shinya Kitaoka 120a6e
  // corrente
Shinya Kitaoka 120a6e
  // stando attento a prendere i pixel giusti.
Shinya Kitaoka 120a6e
  int firstXPixIndexOfLayer = layerSaveBox.getP00().x - 1 + m_shrinkX -
Shinya Kitaoka 120a6e
                              (abs(layerSaveBox.getP00().x - 1) % m_shrinkX);
Shinya Kitaoka 120a6e
  int lrx0                  = firstXPixIndexOfLayer / m_shrinkX;
Shinya Kitaoka 120a6e
  int firstLineIndexOfLayer = layerSaveBox.getP00().y - 1 + m_shrinkY -
Shinya Kitaoka 120a6e
                              (abs(layerSaveBox.getP00().y - 1) % m_shrinkY);
Shinya Kitaoka 120a6e
  int lry0 = firstLineIndexOfLayer / m_shrinkY;
Shinya Kitaoka 120a6e
  int lrx1 =
Shinya Kitaoka 120a6e
      (layerSaveBox.getP11().x - abs(layerSaveBox.getP11().x % m_shrinkX)) /
Shinya Kitaoka 120a6e
      m_shrinkX;
Shinya Kitaoka 120a6e
  int lry1 =
Shinya Kitaoka 120a6e
      (layerSaveBox.getP11().y - abs(layerSaveBox.getP11().y % m_shrinkY)) /
Shinya Kitaoka 120a6e
      m_shrinkY;
Shinya Kitaoka 120a6e
  TRect layerSaveBox2 = TRect(lrx0, lry0, lrx1, lry1);
Shinya Kitaoka 120a6e
  if (layerSaveBox2.isEmpty()) return;
Shinya Kitaoka 120a6e
  assert(TRect(imgSize).contains(layerSaveBox2));
Shinya Kitaoka 120a6e
  if (li)
Shinya Kitaoka 120a6e
    m_layersSavebox[li->layerId] = layerSaveBox2;
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    m_layersSavebox[0] = layerSaveBox2;
Shinya Kitaoka 120a6e
  TRasterP smallRas    = rasP->extract(layerSaveBox2);
Shinya Kitaoka 120a6e
  assert(smallRas);
Shinya Kitaoka 120a6e
  if (!smallRas) return;
Shinya Kitaoka 120a6e
  // Trovo l'indice di colonna del primo pixel del livello che deve essere letto
Shinya Kitaoka 120a6e
  // L'indice รจ riferito al livello.
Shinya Kitaoka 120a6e
  int colOffset = firstXPixIndexOfLayer - layerSaveBox.getP00().x;
Shinya Kitaoka 120a6e
  assert(colOffset >= 0);
Shinya Kitaoka 120a6e
  // Trovo l'indice della prima riga del livello che deve essere letta
Shinya Kitaoka 120a6e
  // L'indice รจ riferito al livello.
Shinya Kitaoka 120a6e
  // Nota che nel file photoshop le righe sono memorizzate dall'ultima alla
Shinya Kitaoka 120a6e
  // prima.
Rozhuk Ivan 823a31
  int rowOffset = std::abs(sby1) % m_shrinkY;
Shinya Kitaoka 120a6e
  int rowCount  = rowOffset;
Shinya Kitaoka 120a6e
  // if(m_shrinkY==3) rowCount--;
Shinya Kitaoka 120a6e
  for (j = 0; j < smallRas->getLy(); j++) {
Shinya Kitaoka 120a6e
    for (ch = 0; ch < chancount; ++ch) {
Shinya Kitaoka 120a6e
      /* get row data */
Shinya Kitaoka 120a6e
      if (map[ch] < 0 || map[ch] > chancount) {
Shinya Kitaoka 120a6e
        // warn("bad map[%d]=%d, skipping a channel", i, map[i]);
Shinya Kitaoka 120a6e
        memset(inrows[ch], 0, chan->rowbytes);  // zero out the row
Shinya Kitaoka 120a6e
      } else
Shinya Kitaoka 120a6e
        readrow(m_file, chan + map[ch], rowCount, inrows[ch], rledata);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    // se la riga corrente non rientra nell'immagine salto la copia
Shinya Kitaoka 120a6e
    if (sby1 - rowCount < 0 || sby1 - rowCount > m_headerInfo.rows - 1) {
Shinya Kitaoka 120a6e
      rowCount += m_shrinkY;
Shinya Kitaoka 120a6e
      continue;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if (depth == 1 && chancount == 1) {
Shinya Kitaoka 120a6e
      if (!(layerSaveBox.getP00().x - sbx0 >= 0 &&
Shinya Kitaoka 120a6e
            layerSaveBox.getP00().x - sbx0 + smallRas->getLx() / 8 - 1 <
Shinya Kitaoka 120a6e
                chan->rowbytes))
Shinya Kitaoka 120a6e
        throw TImageException(
Shinya Kitaoka 120a6e
            m_path, "Unable to read image with this depth and channels values");
Shinya Kitaoka 120a6e
      smallRas->lock();
Shinya Kitaoka 120a6e
      unsigned char *rawdata =
Shinya Kitaoka 120a6e
          (unsigned char *)smallRas->getRawData(0, smallRas->getLy() - j - 1);
Shinya Kitaoka 120a6e
      TPixelGR8 *pix = (TPixelGR8 *)rawdata;
Shinya Kitaoka 120a6e
      int colCount   = colOffset;
Shinya Kitaoka 120a6e
      for (int k = 0; k < smallRas->getLx(); k += 8) {
Shinya Kitaoka 120a6e
        char value = ~inrows[0][layerSaveBox.getP00().x - sbx0 + colCount];
Shinya Kitaoka 120a6e
        pix[k].setValue(value);
Shinya Kitaoka 120a6e
        pix[k + 1].setValue(value);
Shinya Kitaoka 120a6e
        pix[k + 2].setValue(value);
Shinya Kitaoka 120a6e
        pix[k + 3].setValue(value);
Shinya Kitaoka 120a6e
        pix[k + 4].setValue(value);
Shinya Kitaoka 120a6e
        pix[k + 5].setValue(value);
Shinya Kitaoka 120a6e
        pix[k + 6].setValue(value);
Shinya Kitaoka 120a6e
        pix[k + 7].setValue(value);
Shinya Kitaoka 120a6e
        colCount += m_shrinkX;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      smallRas->unlock();
Shinya Kitaoka 120a6e
    } else if (depth == 8 && chancount > 1) {
Shinya Kitaoka 120a6e
      if (!(layerSaveBox.getP00().x - sbx0 >= 0 &&
Shinya Kitaoka 120a6e
            layerSaveBox.getP00().x - sbx0 + smallRas->getLx() - 1 <
Shinya Kitaoka 120a6e
                chan->rowbytes))
Shinya Kitaoka 120a6e
        throw TImageException(
Shinya Kitaoka 120a6e
            m_path, "Unable to read image with this depth and channels values");
Shinya Kitaoka 120a6e
      smallRas->lock();
Shinya Kitaoka 120a6e
      unsigned char *rawdata =
Shinya Kitaoka 120a6e
          (unsigned char *)smallRas->getRawData(0, smallRas->getLy() - j - 1);
Shinya Kitaoka 120a6e
      TPixel32 *pix = (TPixel32 *)rawdata;
Shinya Kitaoka 120a6e
      int colCount  = colOffset;
Shinya Kitaoka 120a6e
      for (int k = 0; k < smallRas->getLx(); k++) {
Shinya Kitaoka 120a6e
        if (chancount >= 3) {
Shinya Kitaoka 120a6e
          pix[k].r = inrows[0][layerSaveBox.getP00().x - sbx0 + colCount];
Shinya Kitaoka 120a6e
          pix[k].g = inrows[1][layerSaveBox.getP00().x - sbx0 + colCount];
Shinya Kitaoka 120a6e
          pix[k].b = inrows[2][layerSaveBox.getP00().x - sbx0 + colCount];
Shinya Kitaoka 120a6e
          if (chancount == 4)  // RGB + alpha
Shinya Kitaoka 120a6e
            pix[k].m = inrows[3][layerSaveBox.getP00().x - sbx0 + colCount];
Shinya Kitaoka 120a6e
          else
Shinya Kitaoka 120a6e
            pix[k].m = 255;
Shinya Kitaoka 120a6e
        } else if (chancount <= 2)  // gray + alpha
Shinya Kitaoka 120a6e
        {
Shinya Kitaoka 120a6e
          pix[k].r = inrows[0][layerSaveBox.getP00().x - sbx0 + colCount];
Shinya Kitaoka 120a6e
          pix[k].g = inrows[0][layerSaveBox.getP00().x - sbx0 + colCount];
Shinya Kitaoka 120a6e
          pix[k].b = inrows[0][layerSaveBox.getP00().x - sbx0 + colCount];
Shinya Kitaoka 120a6e
          if (chancount == 2)
Shinya Kitaoka 120a6e
            pix[k].m = inrows[1][layerSaveBox.getP00().x - sbx0 + colCount];
Shinya Kitaoka 120a6e
          else
Shinya Kitaoka 120a6e
            pix[k].m = 255;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        colCount += m_shrinkX;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      smallRas->unlock();
Shinya Kitaoka 120a6e
    } else if (m_headerInfo.depth == 8 && chancount == 1) {
Shinya Kitaoka 120a6e
      if (!(layerSaveBox.getP00().x - sbx0 >= 0 &&
Shinya Kitaoka 120a6e
            layerSaveBox.getP00().x - sbx0 + smallRas->getLx() - 1 <
Shinya Kitaoka 120a6e
                chan->rowbytes))
Shinya Kitaoka 120a6e
        throw TImageException(
Shinya Kitaoka 120a6e
            m_path, "Unable to read image with this depth and channels values");
Shinya Kitaoka 120a6e
      smallRas->lock();
Shinya Kitaoka 120a6e
      unsigned char *rawdata =
Shinya Kitaoka 120a6e
          (unsigned char *)smallRas->getRawData(0, smallRas->getLy() - j - 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      TPixelGR8 *pix = (TPixelGR8 *)rawdata;
Shinya Kitaoka 120a6e
      int colCount   = colOffset;
Shinya Kitaoka 120a6e
      for (int k = 0; k < smallRas->getLx(); k++) {
Shinya Kitaoka 120a6e
        pix[k].setValue(inrows[0][layerSaveBox.getP00().x - sbx0 + colCount]);
Shinya Kitaoka 120a6e
        colCount += m_shrinkX;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      smallRas->unlock();
Shinya Kitaoka 120a6e
    } else if (m_headerInfo.depth == 16 && chancount == 1 &&
Shinya Kitaoka 120a6e
               m_headerInfo.mergedalpha)  // mergedChannels
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      if (!(layerSaveBox.getP00().x - sbx0 >= 0 &&
Shinya Kitaoka 120a6e
            layerSaveBox.getP00().x - sbx0 + smallRas->getLx() - 1 <
Shinya Kitaoka 120a6e
                chan->rowbytes))
Shinya Kitaoka 120a6e
        throw TImageException(
Shinya Kitaoka 120a6e
            m_path, "Unable to read image with this depth and channels values");
Shinya Kitaoka 120a6e
      smallRas->lock();
Shinya Kitaoka 120a6e
      unsigned char *rawdata =
Shinya Kitaoka 120a6e
          (unsigned char *)smallRas->getRawData(0, smallRas->getLy() - j - 1);
Shinya Kitaoka 120a6e
      TPixelGR8 *pix = (TPixelGR8 *)rawdata;
Shinya Kitaoka 120a6e
      int colCount   = colOffset;
Shinya Kitaoka 120a6e
      for (int k = 0; k < smallRas->getLx(); k++) {
Shinya Kitaoka 120a6e
        pix[k].setValue(inrows[0][layerSaveBox.getP00().x - sbx0 + colCount]);
Shinya Kitaoka 120a6e
        colCount += m_shrinkX;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      smallRas->unlock();
Shinya Kitaoka 120a6e
    } else if (m_headerInfo.depth == 16) {
Shinya Kitaoka 120a6e
      if (!(layerSaveBox.getP00().x - sbx0 >= 0 &&
Shinya Kitaoka 120a6e
            layerSaveBox.getP00().x - sbx0 + smallRas->getLx() - 1 <
Shinya Kitaoka 120a6e
                chan->rowbytes))
Shinya Kitaoka 120a6e
        throw TImageException(
Shinya Kitaoka 120a6e
            m_path, "Unable to read image with this depth and channels values");
Shinya Kitaoka 120a6e
      smallRas->lock();
Shinya Kitaoka 120a6e
      unsigned short *rawdata =
Shinya Kitaoka 120a6e
          (unsigned short *)smallRas->getRawData(0, smallRas->getLy() - j - 1);
Shinya Kitaoka 120a6e
      TPixel64 *pix = (TPixel64 *)rawdata;
Shinya Kitaoka 120a6e
      int colCount  = colOffset;
Shinya Kitaoka 120a6e
      for (int k = 0; k < smallRas->getLx(); k++) {
Shinya Kitaoka 120a6e
        if (chancount >= 3) {
Shinya Kitaoka 120a6e
          pix[k].r = swapShort(
Shinya Kitaoka 120a6e
              ((psdUint16 *)
Shinya Kitaoka 120a6e
                   inrows[0])[layerSaveBox.getP00().x - sbx0 + colCount]);
Shinya Kitaoka 120a6e
          pix[k].g = swapShort(
Shinya Kitaoka 120a6e
              ((psdUint16 *)
Shinya Kitaoka 120a6e
                   inrows[1])[layerSaveBox.getP00().x - sbx0 + colCount]);
Shinya Kitaoka 120a6e
          pix[k].b = swapShort(
Shinya Kitaoka 120a6e
              ((psdUint16 *)
Shinya Kitaoka 120a6e
                   inrows[2])[layerSaveBox.getP00().x - sbx0 + colCount]);
Shinya Kitaoka 120a6e
        } else if (chancount <= 2) {
Shinya Kitaoka 120a6e
          pix[k].r = swapShort(
Shinya Kitaoka 120a6e
              ((psdUint16 *)
Shinya Kitaoka 120a6e
                   inrows[0])[layerSaveBox.getP00().x - sbx0 + colCount]);
Shinya Kitaoka 120a6e
          pix[k].g = swapShort(
Shinya Kitaoka 120a6e
              ((psdUint16 *)
Shinya Kitaoka 120a6e
                   inrows[0])[layerSaveBox.getP00().x - sbx0 + colCount]);
Shinya Kitaoka 120a6e
          pix[k].b = swapShort(
Shinya Kitaoka 120a6e
              ((psdUint16 *)
Shinya Kitaoka 120a6e
                   inrows[0])[layerSaveBox.getP00().x - sbx0 + colCount]);
Shinya Kitaoka 120a6e
          if (chancount == 2)
Shinya Kitaoka 120a6e
            pix[k].m = swapShort(
Shinya Kitaoka 120a6e
                ((psdUint16 *)
Shinya Kitaoka 120a6e
                     inrows[1])[layerSaveBox.getP00().x - sbx0 + colCount]);
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        if (chancount == 4) {
Shinya Kitaoka 120a6e
          pix[k].m = swapShort(
Shinya Kitaoka 120a6e
              ((psdUint16 *)
Shinya Kitaoka 120a6e
                   inrows[3])[layerSaveBox.getP00().x - sbx0 + colCount]);
Shinya Kitaoka 120a6e
        } else
Shinya Kitaoka 120a6e
          pix[k].m = 0xffff;
Shinya Kitaoka 120a6e
        colCount += m_shrinkX;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      smallRas->unlock();
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      throw TImageException(
Shinya Kitaoka 120a6e
          m_path, "Unable to read image with this depth and channels values");
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    rowCount += m_shrinkY;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  fseek(m_file, savepos, SEEK_SET);  // restoring filepos
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  free(rledata);
Shinya Kitaoka 120a6e
  for (ch = 0; ch < chancount; ++ch) free(inrows[ch]);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TPSDReader::doExtraData(TPSDLayerInfo *li, psdByte length) {
Shinya Kitaoka 120a6e
  static struct dictentry extradict[] = {
Shinya Kitaoka 120a6e
      // v4.0
Shinya Kitaoka 120a6e
      {0, "levl", "LEVELS", "Levels", NULL /*adj_levels*/},
Shinya Kitaoka 120a6e
      {0, "curv", "CURVES", "Curves", NULL /*adj_curves*/},
Shinya Kitaoka 120a6e
      {0, "brit", "BRIGHTNESSCONTRAST", "Brightness/contrast", NULL},
Shinya Kitaoka 120a6e
      {0, "blnc", "COLORBALANCE", "Color balance", NULL},
Shinya Kitaoka 120a6e
      {0, "hue ", "HUESATURATION4", "Old Hue/saturation, Photoshop 4.0",
Shinya Kitaoka 120a6e
       NULL /*adj_huesat4*/},
Shinya Kitaoka 120a6e
      {0, "hue2", "HUESATURATION5", "New Hue/saturation, Photoshop 5.0",
Shinya Kitaoka 120a6e
       NULL /*adj_huesat5*/},
Shinya Kitaoka 120a6e
      {0, "selc", "SELECTIVECOLOR", "Selective color", NULL /*adj_selcol*/},
Shinya Kitaoka 120a6e
      {0, "thrs", "THRESHOLD", "Threshold", NULL},
Shinya Kitaoka 120a6e
      {0, "nvrt", "INVERT", "Invert", NULL},
Shinya Kitaoka 120a6e
      {0, "post", "POSTERIZE", "Posterize", NULL},
Shinya Kitaoka 120a6e
      // v5.0
Shinya Kitaoka 120a6e
      {0, "lrFX", "EFFECT", "Effects layer", NULL /*ed_layereffects*/},
Shinya Kitaoka 120a6e
      {0, "tySh", "TYPETOOL5", "Type tool (5.0)", NULL /*ed_typetool*/},
Shinya Kitaoka 120a6e
      {0, "luni", "-UNICODENAME", "Unicode layer name",
Shinya Kitaoka 120a6e
       NULL /*ed_unicodename*/},
Shinya Kitaoka 120a6e
      {0, "lyid", "-LAYERID", "Layer ID",
Shinya Kitaoka 120a6e
       readLongData},  // '-' prefix means keep tag value on one line
Shinya Kitaoka 120a6e
      // v6.0
Shinya Kitaoka 120a6e
      {0, "lfx2", "OBJECTEFFECT", "Object based effects layer",
Shinya Kitaoka 120a6e
       NULL /*ed_objecteffects*/},
Shinya Kitaoka 120a6e
      {0, "Patt", "PATTERN", "Pattern", NULL},
Shinya Kitaoka 120a6e
      {0, "Pat2", "PATTERNCS", "Pattern (CS)", NULL},
Shinya Kitaoka 120a6e
      {0, "Anno", "ANNOTATION", "Annotation", NULL /*ed_annotation*/},
Shinya Kitaoka 120a6e
      {0, "clbl", "-BLENDCLIPPING", "Blend clipping", readByteData},
Shinya Kitaoka 120a6e
      {0, "infx", "-BLENDINTERIOR", "Blend interior", readByteData},
Shinya Kitaoka 120a6e
      {0, "knko", "-KNOCKOUT", "Knockout", readByteData},
Shinya Kitaoka 120a6e
      {0, "lspf", "-PROTECTED", "Protected", readLongData},
Shinya Kitaoka 120a6e
      {0, "lclr", "SHEETCOLOR", "Sheet color", NULL},
Shinya Kitaoka 120a6e
      {0, "fxrp", "-REFERENCEPOINT", "Reference point",
Shinya Kitaoka 120a6e
       NULL /*ed_referencepoint*/},
Shinya Kitaoka 120a6e
      {0, "grdm", "GRADIENT", "Gradient", NULL},
Shinya Kitaoka 120a6e
      {0, "lsct", "-SECTION", "Section divider", readLongData},  // CS doc
Shinya Kitaoka 120a6e
      {0, "SoCo", "SOLIDCOLORSHEET", "Solid color sheet",
Shinya Kitaoka 120a6e
       NULL /*ed_versdesc*/},  // CS doc
Shinya Kitaoka 120a6e
      {0, "PtFl", "PATTERNFILL", "Pattern fill",
Shinya Kitaoka 120a6e
       NULL /*ed_versdesc*/},  // CS doc
Shinya Kitaoka 120a6e
      {0, "GdFl", "GRADIENTFILL", "Gradient fill",
Shinya Kitaoka 120a6e
       NULL /*ed_versdesc*/},                          // CS doc
Shinya Kitaoka 120a6e
      {0, "vmsk", "VECTORMASK", "Vector mask", NULL},  // CS doc
Shinya Kitaoka 120a6e
      {0, "TySh", "TYPETOOL6", "Type tool (6.0)",
Shinya Kitaoka 120a6e
       NULL /*ed_typetool*/},  // CS doc
Shinya Kitaoka 120a6e
      {0, "ffxi", "-FOREIGNEFFECTID", "Foreign effect ID",
Shinya Kitaoka 120a6e
       readLongData},  // CS doc (this is probably a key too, who knows)
Shinya Kitaoka 120a6e
      {0, "lnsr", "-LAYERNAMESOURCE", "Layer name source",
Shinya Kitaoka 120a6e
       readKey},  // CS doc (who knew this was a signature? docs fail again -
Shinya Kitaoka 120a6e
                  // and what do the values mean?)
Shinya Kitaoka 120a6e
      {0, "shpa", "PATTERNDATA", "Pattern data", NULL},  // CS doc
Shinya Kitaoka 120a6e
      {0, "shmd", "METADATASETTING", "Metadata setting",
Shinya Kitaoka 120a6e
       NULL /*ed_metadata*/},  // CS doc
Shinya Kitaoka 120a6e
      {0, "brst", "BLENDINGRESTRICTIONS", "Channel blending restrictions",
Shinya Kitaoka 120a6e
       NULL},  // CS doc
Shinya Kitaoka 120a6e
      // v7.0
Shinya Kitaoka 120a6e
      {0, "lyvr", "-LAYERVERSION", "Layer version", readLongData},  // CS doc
Shinya Kitaoka 120a6e
      {0, "tsly", "-TRANSPARENCYSHAPES", "Transparency shapes layer",
Shinya Kitaoka 120a6e
       readByteData},  // CS doc
Shinya Kitaoka 120a6e
      {0, "lmgm", "-LAYERMASKASGLOBALMASK", "Layer mask as global mask",
Shinya Kitaoka 120a6e
       readByteData},  // CS doc
Shinya Kitaoka 120a6e
      {0, "vmgm", "-VECTORMASKASGLOBALMASK", "Vector mask as global mask",
Shinya Kitaoka 120a6e
       readByteData},  // CS doc
Shinya Kitaoka 120a6e
      // CS
Shinya Kitaoka 120a6e
      {0, "mixr", "CHANNELMIXER", "Channel mixer", NULL},  // CS doc
Shinya Kitaoka 120a6e
      {0, "phfl", "PHOTOFILTER", "Photo Filter", NULL},    // CS doc
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      {0, "Lr16", "LAYER16", "Layer 16", readLayer16},
Shinya Kitaoka 120a6e
      {0, NULL, NULL, NULL, NULL}};
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  while (length >= 12) {
Shinya Kitaoka 120a6e
    psdByte block = sigkeyblock(m_file, extradict, li);
Shinya Kitaoka 120a6e
    if (!block) {
Shinya Kitaoka 120a6e
      // warn("bad signature in layer's extra data, skipping the rest");
Shinya Kitaoka 120a6e
      break;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    length -= block;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
struct dictentry *TPSDReader::findbykey(FILE *f, struct dictentry *parent,
Shinya Kitaoka 120a6e
                                        char *key, TPSDLayerInfo *li) {
Shinya Kitaoka 120a6e
  struct dictentry *d;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (d = parent; d->key; ++d)
Shinya Kitaoka 120a6e
    if (!memcmp(key, d->key, 4)) {
Shinya Kitaoka 120a6e
      // char *tagname = d->tag + (d->tag[0] == '-');
Shinya Kitaoka 120a6e
      // fprintf(stderr, "matched tag %s\n", d->tag);
Shinya Kitaoka 120a6e
      if (d->func) {
Shinya Kitaoka 120a6e
        psdByte savepos = ftell(f);
Shinya Kitaoka 120a6e
        // int oneline = d->tag[0] == '-';
Shinya Kitaoka 120a6e
        // char *tagname = d->tag + oneline;
Shinya Kitaoka 120a6e
        if (memcmp(key, "Lr16", 4) == 0) {
Shinya Kitaoka 120a6e
          doLayersInfo();
Shinya Kitaoka 120a6e
        } else
Shinya Kitaoka 120a6e
          d->func(f, d, li);  // parse contents of this datum
Shinya Kitaoka 120a6e
        fseek(f, savepos, SEEK_SET);
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        // there is no function to parse this block.
Shinya Kitaoka 120a6e
        // because tag is empty in this case, we only need to consider
Shinya Kitaoka 120a6e
        // parent's one-line-ness.
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      return d;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  return NULL;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int TPSDReader::sigkeyblock(FILE *f, struct dictentry *dict,
Shinya Kitaoka 120a6e
                            TPSDLayerInfo *li) {
Shinya Kitaoka 120a6e
  char sig[4], key[4];
Shinya Kitaoka 120a6e
  long len;
Shinya Kitaoka 120a6e
  struct dictentry *d;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  fread(sig, 1, 4, f);
Shinya Kitaoka 120a6e
  fread(key, 1, 4, f);
Shinya Kitaoka 120a6e
  len = read4Bytes(f);
Shinya Kitaoka 120a6e
  if (!memcmp(sig, "8BIM", 4)) {
Shinya Kitaoka 120a6e
    if (dict && (d = findbykey(f, dict, key, li)) && !d->func) {
Shinya Kitaoka 120a6e
      // there is no function to parse this block
Shinya Kitaoka 120a6e
      // UNQUIET("    (data: %s)\n", d->desc);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    fseek(f, len, SEEK_CUR);
Shinya Kitaoka 120a6e
    return len + 12;  // return number of bytes consumed
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return 0;  // bad signature
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------- Utility functions
Shinya Kitaoka 120a6e
std::string buildErrorString(int error) {
Shinya Kitaoka 120a6e
  std::string message = "";
Shinya Kitaoka 120a6e
  switch (error) {
Shinya Kitaoka 120a6e
  case 0:
Shinya Kitaoka 120a6e
    message = "NO Error Found";
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case 1:
Shinya Kitaoka 120a6e
    message = "Reading File Error";
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case 2:
Shinya Kitaoka 120a6e
    message = "Opening File Error";
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  default:
Shinya Kitaoka 120a6e
    message = "Unknown Error";
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return message;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void readChannel(FILE *f, TPSDLayerInfo *li,
Shinya Kitaoka 120a6e
                 TPSDChannelInfo *chan,  // channel info array
Shinya Kitaoka 120a6e
                 int channels, TPSDHeaderInfo *h) {
Shinya Kitaoka 120a6e
  int comp, ch;
Shinya Kitaoka 120a6e
  psdByte pos, chpos, rb;
Shinya Kitaoka 120a6e
  unsigned char *zipdata;
Shinya Kitaoka 120a6e
  psdPixel count, last, j;
Shinya Kitaoka 120a6e
  chpos = ftell(f);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (li) {
Shinya Kitaoka 120a6e
    // If this is a layer mask, the pixel size is a special case
Shinya Kitaoka 120a6e
    if (chan->id == -2) {
Shinya Kitaoka 120a6e
      chan->rows = li->mask.rows;
Shinya Kitaoka 120a6e
      chan->cols = li->mask.cols;
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      // channel has dimensions of the layer
Shinya Kitaoka 120a6e
      chan->rows = li->bottom - li->top;
Shinya Kitaoka 120a6e
      chan->cols = li->right - li->left;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    // merged image, has dimensions of PSD
Shinya Kitaoka 120a6e
    chan->rows = h->rows;
Shinya Kitaoka 120a6e
    chan->cols = h->cols;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Compute image row bytes
Shinya Kitaoka 120a6e
  rb = ((long)chan->cols * h->depth + 7) / 8;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Read compression type
Shinya Kitaoka 120a6e
  comp = read2UBytes(f);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Prepare compressed data for later access:
Shinya Kitaoka 120a6e
  pos = chpos + 2;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // skip rle counts, leave pos pointing to first compressed image row
Shinya Kitaoka 120a6e
  if (comp == RLECOMP) pos += (channels * chan->rows) << h->version;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (ch = 0; ch < channels; ++ch) {
Shinya Kitaoka 120a6e
    if (!li) chan[ch].id = ch;
Shinya Kitaoka 120a6e
    chan[ch].rowbytes    = rb;
Shinya Kitaoka 120a6e
    chan[ch].comptype    = comp;
Shinya Kitaoka 120a6e
    chan[ch].rows        = chan->rows;
Shinya Kitaoka 120a6e
    chan[ch].cols        = chan->cols;
Shinya Kitaoka 120a6e
    chan[ch].filepos     = pos;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (!chan->rows) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // For RLE, we read the row count array and compute file positions.
Shinya Kitaoka 120a6e
    // For ZIP, read and decompress whole channel.
Shinya Kitaoka 120a6e
    switch (comp) {
Shinya Kitaoka 120a6e
    case RAWDATA:
Shinya Kitaoka 120a6e
      pos += chan->rowbytes * chan->rows;
Shinya Kitaoka 120a6e
      break;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    case RLECOMP:
Shinya Kitaoka 120a6e
      /* accumulate RLE counts, to make array of row start positions */
Shinya Kitaoka 120a6e
      chan[ch].rowpos =
Shinya Kitaoka 120a6e
          (psdByte *)mymalloc((chan[ch].rows + 1) * sizeof(psdByte));
Shinya Kitaoka 120a6e
      last = chan[ch].rowbytes;
Shinya Kitaoka 120a6e
      for (j = 0; j < chan[ch].rows && !feof(f); ++j) {
Shinya Kitaoka 120a6e
        count = h->version == 1 ? read2UBytes(f) : (unsigned long)read4Bytes(f);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        if (count > 2 * chan[ch].rowbytes)  // this would be impossible
Shinya Kitaoka 120a6e
          count = last;                     // make a guess, to help recover
Shinya Kitaoka 120a6e
        last    = count;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        chan[ch].rowpos[j] = pos;
Shinya Kitaoka 120a6e
        pos += count;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      if (j < chan[ch].rows) {
Shinya Kitaoka 120a6e
        // fatal error couldn't read RLE counts
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      chan[ch].rowpos[j] = pos; /* = end of last row */
Shinya Kitaoka 120a6e
      break;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    case ZIPWITHOUTPREDICTION:
Shinya Kitaoka 120a6e
    case ZIPWITHPREDICTION:
Shinya Kitaoka 120a6e
      if (li) {
Shinya Kitaoka 120a6e
        pos += chan->length - 2;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        zipdata = (unsigned char *)mymalloc(chan->length);
Shinya Kitaoka 120a6e
        count   = fread(zipdata, 1, chan->length - 2, f);
Shinya Kitaoka 120a6e
        // if(count < chan->length - 2)
Shinya Kitaoka 120a6e
        //	alwayswarn("ZIP data short: wanted %d bytes, got %d",
Shinya Kitaoka 38fd86
        // chan->length, count);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        chan->unzipdata =
Shinya Kitaoka 120a6e
            (unsigned char *)mymalloc(chan->rows * chan->rowbytes);
Shinya Kitaoka 120a6e
        if (comp == ZIPWITHOUTPREDICTION)
Shinya Kitaoka 120a6e
          psdUnzipWithoutPrediction(zipdata, count, chan->unzipdata,
Shinya Kitaoka 120a6e
                                    chan->rows * chan->rowbytes);
Shinya Kitaoka 120a6e
        else
Shinya Kitaoka 120a6e
          psdUnzipWithPrediction(zipdata, count, chan->unzipdata,
Shinya Kitaoka 120a6e
                                 chan->rows * chan->rowbytes, chan->cols,
Shinya Kitaoka 120a6e
                                 h->depth);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        free(zipdata);
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        // WARNING cannot process ZIP compression outside layer
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      break;
Shinya Kitaoka 120a6e
    default: {
Shinya Kitaoka 120a6e
      // BAD COMPRESSION TYPE
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
      if (li) fseek(f, chan->length - 2, SEEK_CUR);
Shinya Kitaoka 120a6e
      break;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // if(li && pos != chpos + chan->length)
Shinya Kitaoka 120a6e
  //	alwayswarn("# channel data is %ld bytes, but length = %ld\n",
Shinya Kitaoka 120a6e
  //			   pos - chpos, chan->length);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // set at the end of channel's data
Shinya Kitaoka 120a6e
  fseek(f, pos, SEEK_SET);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void readLongData(FILE *f, struct dictentry *parent, TPSDLayerInfo *li) {
Shinya Kitaoka 120a6e
  unsigned long id = read4Bytes(f);
Shinya Kitaoka 120a6e
  if (strcmp(parent->key, "lyid") == 0)
Shinya Kitaoka 120a6e
    li->layerId = id;
Shinya Kitaoka 120a6e
  else if (strcmp(parent->key, "lspf") == 0)
Shinya Kitaoka 120a6e
    li->protect = id;
Shinya Kitaoka 120a6e
  else if (strcmp(parent->key, "lsct") == 0)
Shinya Kitaoka 120a6e
    li->section = id;
Shinya Kitaoka 120a6e
  else if (strcmp(parent->key, "ffxi") == 0)
Shinya Kitaoka 120a6e
    li->foreignEffectID = id;
Shinya Kitaoka 120a6e
  else if (strcmp(parent->key, "lyvr") == 0)
Shinya Kitaoka 120a6e
    li->layerVersion = id;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void readByteData(FILE *f, struct dictentry *parent, TPSDLayerInfo *li) {
Shinya Kitaoka 120a6e
  int id = fgetc(f);
Shinya Kitaoka 120a6e
  if (strcmp(parent->key, "clbl") == 0)
Shinya Kitaoka 120a6e
    li->blendClipping = id;
Shinya Kitaoka 120a6e
  else if (strcmp(parent->key, "infx") == 0)
Shinya Kitaoka 120a6e
    li->blendInterior = id;
Shinya Kitaoka 120a6e
  else if (strcmp(parent->key, "knko") == 0)
Shinya Kitaoka 120a6e
    li->knockout = id;
Shinya Kitaoka 120a6e
  else if (strcmp(parent->key, "tsly") == 0)
Shinya Kitaoka 120a6e
    li->transparencyShapes = id;
Shinya Kitaoka 120a6e
  else if (strcmp(parent->key, "lmgm") == 0)
Shinya Kitaoka 120a6e
    li->layerMaskAsGlobalMask = id;
Shinya Kitaoka 120a6e
  else if (strcmp(parent->key, "vmgm") == 0)
Shinya Kitaoka 120a6e
    li->vectorMaskAsGlobalMask = id;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void readKey(FILE *f, struct dictentry *parent, TPSDLayerInfo *li) {
Shinya Kitaoka 120a6e
  static char key[5];
Shinya Kitaoka 120a6e
  if (fread(key, 1, 4, f) == 4)
Shinya Kitaoka 120a6e
    key[4] = 0;
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    key[0] = 0;  // or return NULL?
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (strcmp(parent->key, "lnsr") == 0) li->layerNameSource = key;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void readLayer16(FILE *f, struct dictentry *parent, TPSDLayerInfo *li) {
Shinya Kitaoka 120a6e
  // struct psd_header h2 = *psd_header; // a kind of 'nested' set of layers;
Shinya Kitaoka 120a6e
  // don't alter main PSD header
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // overwrite main PSD header, mainly because of the 'merged alpha' flag
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // I *think* they mean us to respect the one in Lr16 because in my test data,
Shinya Kitaoka 120a6e
  // the main layer count is zero, so cannot convey this information.
Shinya Kitaoka 120a6e
  // dolayerinfo(f, psd_header);
Shinya Kitaoka 120a6e
  // processlayers(f, psd_header);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//---------------------------- END Utility functions
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TPSD PARSER
Shinya Kitaoka 120a6e
TPSDParser::TPSDParser(const TFilePath &path) {
Shinya Kitaoka 120a6e
  m_path       = path;
Shinya Kitaoka 120a6e
  QString name = path.getName().c_str();
Shinya Kitaoka 120a6e
  name.append(path.getDottedType().c_str());
Shinya Kitaoka 120a6e
  int sepPos = name.indexOf("#");
Shinya Kitaoka 120a6e
  int dotPos = name.indexOf(".", sepPos);
Shinya Kitaoka 120a6e
  name.remove(sepPos, dotPos - sepPos);
Shinya Kitaoka 120a6e
  TFilePath psdpath = m_path.getParentDir() + TFilePath(name.toStdString());
Shinya Kitaoka 120a6e
  m_psdreader       = new TPSDReader(psdpath);
Shinya Kitaoka 120a6e
  doLevels();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TPSDParser::~TPSDParser() { delete m_psdreader; }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
void TPSDParser::doLevels() {
Shinya Kitaoka 120a6e
  QString path     = m_path.getName().c_str();
Shinya Kitaoka 120a6e
  QStringList list = path.split("#");
Shinya Kitaoka 120a6e
  m_levels.clear();
Shinya Kitaoka 120a6e
  if (list.size() > 1) {
Shinya Kitaoka 120a6e
    TPSDHeaderInfo psdheader = m_psdreader->getPSDHeaderInfo();
Shinya Kitaoka 120a6e
    if (list.contains("frames") && list.at(0) != "frames") {
Shinya Kitaoka 120a6e
      int firstLayerId = 0;
Shinya Kitaoka 120a6e
      Level level;
Shinya Kitaoka 120a6e
      for (int i = 0; i < psdheader.layersCount; i++) {
Shinya Kitaoka 120a6e
        TPSDLayerInfo *li = m_psdreader->getLayerInfo(i);
Shinya Kitaoka 120a6e
        long width        = li->right - li->left;
Shinya Kitaoka 120a6e
        long height       = li->bottom - li->top;
Shinya Kitaoka 120a6e
        if (width > 0 && height > 0) {
Shinya Kitaoka 120a6e
          assert(li->layerId >= 0);
Shinya Kitaoka 120a6e
          if (i == 0) firstLayerId = li->layerId;
Shinya Kitaoka 120a6e
          level.addFrame(li->layerId);
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      // non ha importanza quale layerId assegno, l'importante รจ che esista
Shinya Kitaoka 120a6e
      level.setLayerId(0);
Shinya Kitaoka 120a6e
      if (psdheader.layersCount == 0)
Shinya Kitaoka 120a6e
        level.addFrame(firstLayerId);  // succede nel caso in cui la psd non ha
Shinya Kitaoka 120a6e
                                       // blocco layerInfo
Shinya Kitaoka 120a6e
      m_levels.push_back(level);
Shinya Kitaoka 120a6e
    } else if (list.size() == 3) {
Shinya Kitaoka 120a6e
      if (list.at(2) == "group") {
Shinya Kitaoka 120a6e
        int folderTagOpen = 0;
Shinya Kitaoka 120a6e
        int scavenge      = 0;
Shinya Kitaoka 120a6e
        for (int i = 0; i < psdheader.layersCount; i++) {
Shinya Kitaoka 120a6e
          TPSDLayerInfo *li = m_psdreader->getLayerInfo(i);
Shinya Kitaoka 120a6e
          long width        = li->right - li->left;
Shinya Kitaoka 120a6e
          long height       = li->bottom - li->top;
Shinya Kitaoka 120a6e
          if (width > 0 && height > 0 && folderTagOpen == 0) {
Shinya Kitaoka 120a6e
            assert(li->layerId >= 0);
Shinya Kitaoka 120a6e
            Level level(li->name, li->layerId);
Shinya Kitaoka 120a6e
            level.addFrame(li->layerId);
Shinya Kitaoka 120a6e
            m_levels.push_back(level);
Shinya Kitaoka 120a6e
            scavenge = 0;
Shinya Kitaoka 120a6e
          } else {
Shinya Kitaoka 120a6e
            if (width != 0 && height != 0) {
Shinya Kitaoka 120a6e
              m_levels[m_levels.size() - 1 - (scavenge - folderTagOpen)]
Shinya Kitaoka 120a6e
                  .addFrame(li->layerId);
Shinya Kitaoka 120a6e
            } else {
Shinya Kitaoka 120a6e
              if (strcmp(li->name, "") == 0 ||
Shinya Kitaoka 120a6e
                  strcmp(li->name, "") == 0) {
Shinya Kitaoka 120a6e
                assert(li->layerId >= 0);
Shinya Kitaoka 120a6e
                Level level(li->name, li->layerId, true);
Shinya Kitaoka 120a6e
                m_levels.push_back(level);
Shinya Kitaoka 120a6e
                folderTagOpen++;
Shinya Kitaoka 120a6e
                scavenge = folderTagOpen;
Shinya Kitaoka 120a6e
              } else if (li->section > 0 &&
Shinya Kitaoka 120a6e
                         li->section <= 3)  // vedi specifiche psd
Shinya Kitaoka 120a6e
              {
Shinya Kitaoka 120a6e
                assert(li->layerId >= 0);
Shinya Kitaoka 120a6e
                m_levels[m_levels.size() - 1 - (scavenge - folderTagOpen)]
Shinya Kitaoka 120a6e
                    .setName(li->name);
Shinya Kitaoka 120a6e
                m_levels[m_levels.size() - 1 - (scavenge - folderTagOpen)]
Shinya Kitaoka 120a6e
                    .setLayerId(li->layerId);
Shinya Kitaoka 120a6e
                folderTagOpen--;
Shinya Kitaoka 120a6e
                if (folderTagOpen > 0)
Shinya Kitaoka 120a6e
                  m_levels[m_levels.size() - 1 - (scavenge - folderTagOpen)]
Shinya Kitaoka 120a6e
                      .addFrame(li->layerId, true);
Shinya Kitaoka 120a6e
              }
Shinya Kitaoka 120a6e
            }
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        if (psdheader.layersCount ==
Shinya Kitaoka 120a6e
            0)  // succede nel caso in cui la psd non ha blocco layerInfo
Shinya Kitaoka 120a6e
        {
Shinya Kitaoka 120a6e
          Level level;
Shinya Kitaoka 120a6e
          level.setLayerId(0);
Shinya Kitaoka 120a6e
          level.addFrame(0);
Shinya Kitaoka 120a6e
          m_levels.push_back(level);
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      } else
Shinya Kitaoka 120a6e
        throw TImageException(m_path, "PSD code name error");
Shinya Kitaoka 120a6e
    } else if (list.size() == 2)  // each psd layer is a tlevel
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      TPSDHeaderInfo psdheader = m_psdreader->getPSDHeaderInfo();
Shinya Kitaoka 120a6e
      for (int i = 0; i < psdheader.layersCount; i++) {
Shinya Kitaoka 120a6e
        TPSDLayerInfo *li = m_psdreader->getLayerInfo(i);
Shinya Kitaoka 120a6e
        long width        = li->right - li->left;
Shinya Kitaoka 120a6e
        long height       = li->bottom - li->top;
Shinya Kitaoka 120a6e
        if (width > 0 && height > 0) {
Shinya Kitaoka 120a6e
          assert(li->layerId >= 0);
Shinya Kitaoka 120a6e
          Level level(li->name, li->layerId);
Shinya Kitaoka 120a6e
          level.addFrame(li->layerId);
Shinya Kitaoka 120a6e
          m_levels.push_back(level);
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      if (psdheader.layersCount ==
Shinya Kitaoka 120a6e
          0)  // succede nel caso in cui la psd non ha blocco layerInfo
Shinya Kitaoka 120a6e
      {
Shinya Kitaoka 120a6e
        Level level;
Shinya Kitaoka 120a6e
        level.setLayerId(0);
Shinya Kitaoka 120a6e
        level.addFrame(0);
Shinya Kitaoka 120a6e
        m_levels.push_back(level);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else
Shinya Kitaoka 120a6e
      throw TImageException(m_path, "PSD code name error");
Shinya Kitaoka 120a6e
  } else  // list.size()==1. float
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    Level level;
Shinya Kitaoka 120a6e
    level.setName(m_path.getName());
Shinya Kitaoka 120a6e
    level.addFrame(0);
Shinya Kitaoka 120a6e
    m_levels.push_back(level);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TPSDParser::load(TRasterImageP &rasP, int layerId) {
Shinya Kitaoka 120a6e
  m_psdreader->load(rasP, layerId);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int TPSDParser::getLevelIndexById(int layerId) {
Shinya Kitaoka 120a6e
  int layerIndex = -1;
Shinya Kitaoka 120a6e
  for (int i = 0; i < (int)m_levels.size(); i++) {
Shinya Kitaoka 120a6e
    if (m_levels[i].getLayerId() == layerId) {
Shinya Kitaoka 120a6e
      layerIndex = i;
Shinya Kitaoka 120a6e
      break;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (layerId == 0 && layerIndex < 0) layerIndex = 0;
Shinya Kitaoka 120a6e
  if (layerIndex < 0 && layerId != 0)
Shinya Kitaoka 120a6e
    throw TImageException(m_path, "Layer ID not exists");
Shinya Kitaoka 120a6e
  return layerIndex;
Toshihiro Shimizu 890ddd
}
Shinya Kitaoka 120a6e
int TPSDParser::getLevelIdByName(std::string levelName) {
Shinya Kitaoka 120a6e
  int pos     = levelName.find_last_of(LEVEL_NAME_INDEX_SEP);
Shinya Kitaoka 120a6e
  int counter = 0;
Shinya Kitaoka 120a6e
  if (pos != std::string::npos) {
Shinya Kitaoka 120a6e
    counter   = atoi(levelName.substr(pos + 1).c_str());
Shinya Kitaoka 120a6e
    levelName = levelName.substr(0, pos);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  int lyid           = -1;
Shinya Kitaoka 120a6e
  int levelNameCount = 0;
Shinya Kitaoka 120a6e
  for (int i = 0; i < (int)m_levels.size(); i++) {
Shinya Kitaoka 120a6e
    if (m_levels[i].getName() == levelName) {
Shinya Kitaoka 120a6e
      lyid = m_levels[i].getLayerId();
Shinya Kitaoka 120a6e
      if (counter == levelNameCount) break;
Shinya Kitaoka 120a6e
      levelNameCount++;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (lyid == 0 && lyid < 0) lyid = 0;
Shinya Kitaoka 120a6e
  if (lyid < 0 && lyid != 0)
Shinya Kitaoka 120a6e
    throw TImageException(m_path, "Layer ID not exists");
Shinya Kitaoka 120a6e
  return lyid;
Toshihiro Shimizu 890ddd
}
Shinya Kitaoka 120a6e
int TPSDParser::getFramesCount(int levelId) {
Shinya Kitaoka 120a6e
  int levelIndex = getLevelIndexById(levelId);
Shinya Kitaoka 120a6e
  assert(levelIndex >= 0 && levelIndex < (int)m_levels.size());
Shinya Kitaoka 120a6e
  return m_levels[levelIndex].getFrameCount();
Toshihiro Shimizu 890ddd
}
Shinya Kitaoka 120a6e
std::string TPSDParser::getLevelName(int levelId) {
Shinya Kitaoka 120a6e
  int levelIndex = getLevelIndexById(levelId);
Shinya Kitaoka 120a6e
  assert(levelIndex >= 0 && levelIndex < (int)m_levels.size());
Shinya Kitaoka 120a6e
  return m_levels[levelIndex].getName();
Toshihiro Shimizu 890ddd
}
Shinya Kitaoka 120a6e
std::string TPSDParser::getLevelNameWithCounter(int levelId) {
Shinya Kitaoka 120a6e
  std::string levelName = getLevelName(levelId);
Shinya Kitaoka 120a6e
  int count             = 0;
Shinya Kitaoka 120a6e
  for (int i = 0; i < (int)m_levels.size(); i++) {
Shinya Kitaoka 120a6e
    if (m_levels[i].getName() == levelName) {
Shinya Kitaoka 120a6e
      if (m_levels[i].getLayerId() == levelId) {
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      count++;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (count > 0) {
Shinya Kitaoka 120a6e
    levelName.append(LEVEL_NAME_INDEX_SEP);
Shinya Kitaoka 120a6e
    std::string c = QString::number(count).toStdString();
Shinya Kitaoka 120a6e
    levelName.append(c);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return levelName;
Toshihiro Shimizu 890ddd
}