#pragma once
#ifndef PSD_INCLUDED
#define PSD_INCLUDED
#include "psdutils.h"
#include "timage_io.h"
#define REF_LAYER_BY_NAME
class TRasterImageP;
#undef DVAPI
#undef DVVAR
#ifdef TNZCORE_EXPORTS
#define DVAPI DV_EXPORT_API
#define DVVAR DV_EXPORT_VAR
#else
#define DVAPI DV_IMPORT_API
#define DVVAR DV_IMPORT_VAR
#endif
// Photoshop's mode
#define ModeBitmap 0
#define ModeGrayScale 1
#define ModeIndexedColor 2
#define ModeRGBColor 3
#define ModeCMYKColor 4
#define ModeHSLColor 5
#define ModeHSBColor 6
#define ModeMultichannel 7
#define ModeDuotone 8
#define ModeLabColor 9
#define ModeGray16 10
#define ModeRGB48 11
#define ModeLab48 12
#define ModeCMYK64 13
#define ModeDeepMultichannel 14
#define ModeDuotone16 15
struct TPSDLayerMaskInfo {
psdByte size;
long top;
long left;
long bottom;
long right;
char default_colour;
char flags;
psdPixel rows, cols;
};
struct TPSDBlendModeInfo {
char sig[4];
char key[4];
unsigned char opacity;
unsigned char clipping;
unsigned char flags;
};
struct TPSDLayerInfo {
long top;
long left;
long bottom;
long right;
short channels;
TPSDChannelInfo *chan;
int *chindex;
unsigned long layerId;
unsigned long protect;
unsigned long section;
unsigned long foreignEffectID;
unsigned long layerVersion;
int blendClipping;
int blendInterior;
int knockout;
int transparencyShapes;
int layerMaskAsGlobalMask;
int vectorMaskAsGlobalMask;
TPSDBlendModeInfo blend;
TPSDLayerMaskInfo mask;
double referencePointX;
double referencePointY;
char *name;
char *nameno; // "layerNr"
char *unicodeName;
char *layerNameSource;
psdByte additionalpos;
psdByte additionallen;
psdByte filepos; //
psdByte startDataPos; // Posizione di inizio dati all'interno del file
psdByte dataLength; // lunghezza dati
// LAYER EFFECTS
unsigned long int *fxCommonStateVersion;
int fxCommonStateVisible;
unsigned long int fxShadowVersion;
float fxShadowBlur;
float fxShadowIntensity;
float fxShadowAngle;
float fxShadowDistance;
//my tags
bool isFolder;
};
struct TPSDHeaderInfo {
char sig[4];
short version;
char reserved[6];
short channels;
long rows;
long cols;
short depth;
short mode;
double vres; // image resource. Vertical resolution
double hres; // image resource. Horizontal resolution
psdByte colormodepos;
int layersCount;
int mergedalpha;
bool linfoBlockEmpty;
TPSDLayerInfo *linfo; // array of layer info
psdByte lmistart, lmilen; // set by doLayerAndMaskInfo()
psdByte layerDataPos; //set by doInfo
};
struct dictentry {
int id;
const char *key, *tag, *desc;
void (*func)(FILE *f, struct dictentry *dict, TPSDLayerInfo *li);
};
// PSD LIB
// Restituisce eccezioni
class DVAPI TPSDReader
{
TFilePath m_path;
FILE *m_file;
int m_lx, m_ly;
TPSDHeaderInfo m_headerInfo;
int m_layerId;
int m_shrinkX;
int m_shrinkY;
TRect m_region;
public:
TPSDReader(const TFilePath &path);
~TPSDReader();
TImageReaderP getFrameReader(TFilePath path);
TPSDHeaderInfo getPSDHeaderInfo();
void load(TRasterImageP &rasP, int layerId);
TDimension getSize() const { return TDimension(m_lx, m_ly); }
TPSDLayerInfo *getLayerInfo(int index);
int getLayerInfoIndexById(int layerId);
void setShrink(int shrink)
{
m_shrinkX = shrink;
m_shrinkY = shrink;
}
void setShrink(int shrinkX, int shrinkY)
{
m_shrinkX = shrinkX;
m_shrinkY = shrinkY;
}
void setRegion(TRect region) { m_region = region; }
int getShrinkX() { return m_shrinkX; }
int getShrinkY() { return m_shrinkY; }
TRect getRegion() { return m_region; }
private:
std::map<int, TRect> m_layersSavebox;
bool doInfo();
bool doHeaderInfo();
bool doColorModeData();
bool doImageResources();
bool doLayerAndMaskInfo();
bool doLayersInfo();
bool readLayerInfo(int index);
//void doImage(unsigned char *rasP, TPSDLayerInfo *li);
void doImage(TRasterP &rasP, int layerId);
void readImageData(TRasterP &rasP, TPSDLayerInfo *li, TPSDChannelInfo *chan,
int chancount, psdPixel rows, psdPixel cols);
int m_error;
TThread::Mutex m_mutex;
int openFile();
void doExtraData(TPSDLayerInfo *li, psdByte length);
int sigkeyblock(FILE *f, struct dictentry *dict, TPSDLayerInfo *li);
struct dictentry *findbykey(FILE *f, struct dictentry *parent, char *key, TPSDLayerInfo *li);
};
// converts psd layers structure into toonz level structure according to path
class DVAPI TPSDParser
{
class Level
{
public:
Level(std::string nm = "Unknown", int lid = 0, bool is_folder = false) : name(nm),
layerId(lid),
folder(is_folder)
{
}
void addFrame(int layerId, bool isFolder = false) { framesId.push_back(Frame(layerId, isFolder)); }
int getFrameCount() { return (int)framesId.size(); }
std::string getName() { return name; }
int getLayerId() { return layerId; }
void setName(std::string nname) { name = nname; }
void setLayerId(int nlayerId) { layerId = nlayerId; }
int getFrameId(int index)
{
assert(index >= 0 && index < (int)framesId.size());
return framesId[index].layerId;
}
// return true if frame is a subfolder
bool isSubFolder(int frameIndex)
{
assert(frameIndex >= 0 && frameIndex < (int)framesId.size());
return framesId[frameIndex].isFolder;
}
// return true if the level is built from a psd folder
bool isFolder() { return folder; }
private:
struct Frame {
int layerId; // psd layerId
bool isFolder;
Frame(int layId, bool folder) : layerId(layId), isFolder(folder)
{
}
};
std::string name; // psd name
int layerId; // psd layer id
std::vector<Frame> framesId; // array of layer ID as frame
bool folder;
};
TFilePath m_path;
std::vector<Level> m_levels; // layers id
TPSDReader *m_psdreader; //lib
public:
// path define levels construction method
// if path = :
// filename.psd flat image so LevelsCount = 1;
// filename#LAYERID.psd each psd layer as a tlevel
// filename#LAYERID#frames.psd each psd layer as a frame so there is only one tlevel with 1 or more frames;
// filename#LAYERID#folder.psd each psd layer is a tlevel and
// each folder is a tlevel such as the psd layers
// contained into folder are frames of tlevel
// LAYERID(Integer) is psd layerId
TPSDParser(const TFilePath &path);
~TPSDParser();
int getLevelsCount() { return (int)m_levels.size(); }
// load a psd layer
// if layerId == 0 load flat image
void load(TRasterImageP &rasP, int layerId = 0);
// Returns psd layerID
int getLevelId(int index)
{
assert(index >= 0 && index < (int)m_levels.size());
return m_levels[index].getLayerId();
}
bool isFolder(int levelIndex)
{
assert(levelIndex >= 0 && levelIndex < (int)m_levels.size());
return m_levels[levelIndex].isFolder();
}
int getLevelIndexById(int levelId);
// Returns layerID by name. Note that the layer name is not unique, so it return the first layer id found.
int getLevelIdByName(std::string levelName);
int getFrameId(int layerId, int frameIndex) { return m_levels[getLevelIndexById(layerId)].getFrameId(frameIndex); }
int getFramesCount(int levelId);
bool isSubFolder(int levelIndex, int frameIndex)
{
assert(levelIndex >= 0 && levelIndex < (int)m_levels.size());
return m_levels[levelIndex].isSubFolder(frameIndex);
}
std::string getLevelName(int levelId);
// Returns level name.
// If there are 2 or more level with the same name then
// returns levelname, levelname__2, etc
std::string getLevelNameWithCounter(int levelId);
private:
void doLevels(); // do m_levels
};
#endif //TIIO_PSD_H