C++ Sample for TLPSDLD.DLL

///////// sample.cpp  version 100 ////////////////////////////////////////////////////
// By tail, May 11 2003
// This program requires tlpsdload.dll version 1.00 


#include "stdio.h"
#include < iostream >
#include < vector >
#include "tlpsd.h"

using namespace std;

#ifndef HEIGHT
#define HEIGHT(p) ((p)->bottom - (p)->top)
#endif
#ifndef WIDTH
#define WIDTH(p) ((p)->right - (p)->left)
#endif

TLPSDLOAD_GETVERSION    TlPsdLoad_GetVersion;
TLDSDLOAD_OPEN          TlPsdLoad_Open;
TLDSDLOAD_CLOSE         TlPsdLoad_Close = NULL;
TLDSDLOAD_GETLAYERCOUNT TlPsdLoad_GetLayerCount;
TLDSDLOAD_GETIMAGEINFO  TlPsdLoad_GetImageInfo;
TLDSDLOAD_GETIMAGE      TlPsdLoad_GetImage;
TLDSDLOAD_UNDERSCAN     TlPsdLoad_UnderScan;
TLDSDLOAD_MINIMIZE      TlPsdLoad_Minimize;

struct LAYER_IMAGE_ARRAY
{
    TLPSD_IMAGE_INFO   info;
    vector < RGBQUAD > image;
};

class CTestException
{
public:
    CTestException(int err){m_err = err;};
    int m_err;
};

void InitialLoadDll();
void InitialSaveDll();
void FreeDll();
void LoadAndSaveImage(LPCSTR lpszFileName, LPCSTR lpszPath);
bool GetMargedImage(vector < RGBQUAD >& image, TLPSD_IMAGE_INFO& info);
bool GetILayerImage(int index, LAYER_IMAGE_ARRAY& layer, RECT rcFrame);
void SaveBitmap  (LPCSTR lpszFileName, const LPVOID lpData, const RECT& rc);
void SaveCkissCel(LPCSTR lpszFileName, const LPVOID lpData, const RECT& rc);

HINSTANCE g_hLoadPsd = NULL;
HINSTANCE g_hSavePsd = NULL;
vector < RGBQUAD > g_merge_image;
TLPSD_IMAGE_INFO   g_marge_info;
vector < LAYER_IMAGE_ARRAY > g_layer;
// ======================================================
// INPUT
// xxx.exe c:\temp\sample.psd c:\temp\
// ------------------------------------------------------
int main(int argc, char *argv[])
{
    // Check arguments
    cout << endl;
    if(argc < 3){
        cout << "Bad argument"  << endl; 
        cout << "\t < executable file > < input filename >, < output path >" << endl;
        cout << "\t i.e.,  xxx.exe c:\\temp\\sample.psd c:\\temp\\ "         << endl;
        cout << "\t input filename : path to a loading psd file "            << endl;
        cout << "\t output path    : path to a directory for saving fies "   << endl;
        return 1;
    }
    cout << argv[1] << endl;
    cout << argv[2] << endl;

    try
    {
        cout << "--- Loading psd file ---" << endl;
        InitialLoadDll();
        cout << "Load Dll Version " << TlPsdLoad_GetVersion() << endl;
        LoadAndSaveImage(argv[1], argv[2]);

        FreeDll();
        getchar();
        return 0;
    }
    catch(const CTestException e)
    {
        cout << "Error: " << e.m_err << endl;
        if(TlPsdLoad_Close)
            TlPsdLoad_Close();
        FreeDll();
        return e.m_err;
    }
}

// ===================================================================================

void InitialLoadDll()
{
    if(!(g_hLoadPsd = ::LoadLibrary("tlpsdload.dll"))
            || !(TlPsdLoad_GetVersion    = (TLPSDLOAD_GETVERSION)   GetProcAddress(g_hLoadPsd, "TlPsdLoad_GetVersion"))
            || !(TlPsdLoad_Open          = (TLDSDLOAD_OPEN)         GetProcAddress(g_hLoadPsd, "TlPsdLoad_Open")) 
            || !(TlPsdLoad_Close         = (TLDSDLOAD_CLOSE)        GetProcAddress(g_hLoadPsd, "TlPsdLoad_Close"))
            || !(TlPsdLoad_GetLayerCount = (TLDSDLOAD_GETLAYERCOUNT)GetProcAddress(g_hLoadPsd, "TlPsdLoad_GetLayerCount"))
            || !(TlPsdLoad_GetImageInfo  = (TLDSDLOAD_GETIMAGEINFO) GetProcAddress(g_hLoadPsd, "TlPsdLoad_GetImageInfo"))
            || !(TlPsdLoad_GetImage      = (TLDSDLOAD_GETIMAGE)     GetProcAddress(g_hLoadPsd, "TlPsdLoad_GetImage")) 
            || !(TlPsdLoad_UnderScan     = (TLDSDLOAD_UNDERSCAN)    GetProcAddress(g_hLoadPsd, "TlPsdLoad_UnderScan"))
            || !(TlPsdLoad_Minimize      = (TLDSDLOAD_MINIMIZE)     GetProcAddress(g_hLoadPsd, "TlPsdLoad_Minimize")))
    {
        cout << "Error: InitialLoadDll()" << endl;
        throw CTestException(2);
    }
}

// ===================================================================================

void FreeDll()
{
    if(g_hLoadPsd)
        ::FreeLibrary(g_hLoadPsd);
    if(g_hSavePsd)
        ::FreeLibrary(g_hSavePsd);
}

// ===================================================================================

void LoadAndSaveImage(LPCSTR lpszFileName, LPCSTR lpszPath)
{
    int nErr;
    char szFileName[MAX_PATH];

    //===== Loading =====
    // Open, read and analyze the psd file. 
    // The file must be 8-bit deph and RGB mode. 
    if((nErr = TlPsdLoad_Open(lpszFileName, 2000, NULL))){
        cout << "Error: Can not open a file, " << lpszFileName << endl;
        throw CTestException(nErr);
    }
    //===== Loading a merged image =====
    g_marge_info.nIndex = -1;
    if(!GetMargedImage(g_merge_image, g_marge_info))
        cout << "Can not get the merged image. " << endl;
    //----- Saving the merged image as a bitmap file. -----
    sprintf(szFileName,  "%smerge.bmp", lpszPath);
    SaveBitmap(szFileName, &g_merge_image.at(0), g_marge_info.rcImage);
    //===== Loading layers =====
    int nSavedCount = 0;
    const int nCount = TlPsdLoad_GetLayerCount();
    if(nCount)
        g_layer.resize(nCount);
    for(int j = 0; j < nCount; j++){
        if(GetILayerImage(j, g_layer.at(j), g_marge_info.rcImage)){
            //----- Saving the layers as bitmap and CKiSS format files. -----
            sprintf(szFileName,  "%slayer%02d.bmp", lpszPath,    g_layer.at(j).info.nIndex);
            SaveBitmap(szFileName, &g_layer.at(j).  image.at(0), g_layer.at(j).info.rcImage);
            sprintf(szFileName,  "%slayer%02d.cel", lpszPath,    g_layer.at(j).info.nIndex);
            SaveCkissCel(szFileName, &g_layer.at(j).image.at(0), g_layer.at(j).info.rcImage);
            nSavedCount++;
        }
    }
    // Loading results
    cout << "The number of loaded layers of " << nCount      << endl;
    cout << "The number of saved layers of  " << nSavedCount << endl;

    TlPsdLoad_Close();
    cout << "--- End loading ---" << endl;
}

// ===================================================================================

bool GetMargedImage(vector < RGBQUAD >& image, TLPSD_IMAGE_INFO& info)
{
    if(TlPsdLoad_GetImageInfo(&info) != TLPSDERR_NO_ERROR)
        return false;

    int nSize = WIDTH(&info.rcImage) * HEIGHT(&info.rcImage);

    image.resize(nSize);

    if(TlPsdLoad_GetImage(info.nIndex, &image.at(0), nSize * sizeof(RGBQUAD), &info.rcImage))
        return false;

    return true;
}

// ===================================================================================

bool GetILayerImage(int index, LAYER_IMAGE_ARRAY& layer, RECT rcFrame)
{
    ZeroMemory(&layer.info, sizeof(TLPSD_IMAGE_INFO));
    layer.info.nIndex = index;

    if(TlPsdLoad_GetImageInfo(&layer.info) != TLPSDERR_NO_ERROR)
        return false;

    int nSize = WIDTH(&layer.info.rcImage) * HEIGHT(&layer.info.rcImage);
    if(nSize == 0)
        return false;    // Iamge data is nothing. 

    // Getting image data
    layer.image.resize(nSize);
    if(TlPsdLoad_GetImage(layer.info.nIndex, &layer.image.at(0), nSize * sizeof(RGBQUAD), &layer.info.rcImage))
        return false;

    // Trimming the image
    TlPsdLoad_UnderScan(&layer.image.at(0), &layer.info.rcImage, &rcFrame);
    TlPsdLoad_Minimize (&layer.image.at(0), &layer.info.rcImage);

    // Check the image size
    if(WIDTH(&layer.info.rcImage) == 0 || HEIGHT(&layer.info.rcImage) == 0){
        layer.image.clear();
        return false;
    }

    cout << "Layer " << layer.info.nIndex << "\t( " 
            << WIDTH(&layer.info.rcImage) << ", " << HEIGHT(&layer.info.rcImage) << ") " 
            << layer.info.nOpacity << " " << layer.info.szBlendMode
            << " " << layer.info.szName
            << endl;

    return true;
}

// ===================================================================================

void SaveBitmap(LPCSTR lpszFileName, const LPVOID lpData, const RECT& rc)
{
    BITMAPFILEHEADER bmfh = {0};
    BITMAPINFOHEADER bmih = {0};

    bmih.biSize      = sizeof(BITMAPINFOHEADER);
    bmih.biBitCount  = 0X20;
    bmih.biWidth     = WIDTH(&rc);
    bmih.biHeight    = HEIGHT(&rc);
    bmih.biSizeImage = bmih.biWidth * bmih.biHeight * sizeof(RGBQUAD);
    bmih.biPlanes    = 1;

    bmfh.bfType      = 'B' + ((WORD)'M' << 8); 
    bmfh.bfOffBits   = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
    bmfh.bfSize      = bmfh.bfOffBits + bmih.biSizeImage;

    FILE *stream = fopen(lpszFileName, "wb");
    if(!stream){
        cout << "Can not open " << lpszFileName << endl;
        return;
    }
    fwrite(&bmfh,  sizeof(BITMAPFILEHEADER), 1, stream);
    fwrite(&bmih,  sizeof(BITMAPINFOHEADER), 1, stream);
    fwrite(lpData, bmih.biSizeImage,         1, stream);
    fclose(stream);
}

// ===================================================================================

void SaveCkissCel(LPCSTR lpszFileName, const LPVOID lpData, const RECT& rc)
{
    char   id[]   = "KiSS";
    BYTE   marker = 0X21;
    BYTE   bits   = 0X20;
    WORD   pad    = 0;
    WORD   width  = (WORD)WIDTH (&rc);
    WORD   height = (WORD)HEIGHT(&rc);
    POINTS offset = {0, 0};
    DWORD  reserved [4] = {0};
    int    size  = width * height * sizeof(RGBQUAD);

    FILE *stream = fopen(lpszFileName, "wb");
    if(!stream){
        cout << "Can not open " << lpszFileName << endl;
        return;
    }
    fwrite(id,       4,                1, stream);
    fwrite(&marker,  sizeof(marker),   1, stream);
    fwrite(&bits,    sizeof(bits),     1, stream);
    fwrite(&pad,     sizeof(pad),      1, stream);
    fwrite(&width,   sizeof(width),    1, stream);
    fwrite(&height,  sizeof(height),   1, stream);
    fwrite(&offset,  sizeof(offset),   1, stream);
    fwrite(reserved, sizeof(reserved), 1, stream);
    fwrite(lpData,   size,             1, stream);
    fclose(stream);
}