ciderpress/reformat/PrintShop.cpp

212 lines
6.7 KiB
C++

/*
* CiderPress
* Copyright (C) 2007 by faddenSoft, LLC. All Rights Reserved.
* See the file LICENSE for distribution terms.
*/
/*
* Reformat Print Shop graphics.
*
* The "image editor" in Print Shop GS shows a nearly square image. It looks
* like it doubles with width and triples the height, resulting in a
* 176x156 image. We could do that here, but that would make it harder to
* manipulate the basic pixels if a different aspect ratio were desired.
* (May want to make that an option someday.)
*/
#include "StdAfx.h"
#include "PrintShop.h"
/*
* Decide whether or not we want to handle this file.
*/
void ReformatPrintShop::Examine(ReformatHolder* pHolder)
{
ReformatHolder::ReformatApplies applies = ReformatHolder::kApplicNot;
long fileType = pHolder->GetFileType();
long auxType = pHolder->GetAuxType();
long length = pHolder->GetSourceLen(ReformatHolder::kPartData);
bool relaxed;
relaxed = pHolder->GetOption(ReformatHolder::kOptRelaxGfxTypeCheck) != 0;
if (length == 576 && fileType == kTypeBIN) {
/* PrintShop monochrome */
if (auxType == 0x4800 || auxType == 0x5800 ||
auxType == 0x6800 || auxType == 0x7800)
applies = ReformatHolder::kApplicYes;
else
applies = ReformatHolder::kApplicMaybe; // below monitor listing
} else if (length == 1716) {
/* PrintShop GS color */
if (fileType == 0xf8) {
if (auxType == 0xc323)
applies = ReformatHolder::kApplicYes;
else
applies = ReformatHolder::kApplicProbably;
} else if (fileType == kTypeBIN && relaxed)
applies = ReformatHolder::kApplicMaybe;
} else if (length == 572) {
/* PrintShop GS monochrome */
if (fileType == 0xf8 && auxType == 0xc313)
applies = ReformatHolder::kApplicYes;
}
pHolder->SetApplic(ReformatHolder::kReformatPrintShop, applies,
ReformatHolder::kApplicNot, ReformatHolder::kApplicNot);
}
/*
* Convert Print Shop clip art into a DIB.
*/
int ReformatPrintShop::Process(const ReformatHolder* pHolder,
ReformatHolder::ReformatID id, ReformatHolder::ReformatPart part,
ReformatOutput* pOutput)
{
MyDIBitmap* pDib = NULL;
const uint8_t* srcBuf = pHolder->GetSourceBuf(part);
long srcLen = pHolder->GetSourceLen(part);
if (srcLen == 572 || srcLen == 576) {
pDib = ConvertBW(srcBuf);
} else if (srcLen == 1716) {
pDib = ConvertColor(srcBuf);
} else {
LOGI("PS shouldn't be here (len=%ld)", srcLen);
return -1;
}
if (pDib == NULL) {
LOGI("DIB creation failed");
return -1;
}
SetResultBuffer(pOutput, pDib);
return 0;
}
/*
* Convert a B&W "classic" Print Shop graphic.
*
* This does a "straight" conversion without half-pixel shifting
* or other monkey business.
*
* The file is a linear 1-bit 88x52 image, with four extra bytes of data
* at the end.
*/
MyDIBitmap* ReformatPrintShop::ConvertBW(const uint8_t* srcBuf)
{
MyDIBitmap* pDib = new MyDIBitmap;
uint8_t* outBuf;
uint8_t* ptr;
int pitch;
int x, y;
if (pDib == NULL)
return NULL;
RGBQUAD colorConv[2];
colorConv[0].rgbRed = colorConv[0].rgbGreen = colorConv[0].rgbBlue = 255;
colorConv[1].rgbRed = colorConv[1].rgbGreen = colorConv[1].rgbBlue = 0;
colorConv[0].rgbReserved = colorConv[1].rgbReserved = 0;
outBuf = (uint8_t*) pDib->Create(kWidth, kHeight, 1, 2);
if (outBuf == NULL) {
delete pDib;
pDib = NULL;
goto bail;
}
pDib->SetColorTable(colorConv);
pitch = pDib->GetPitch();
/* build it in standard upside-down Windows format */
for (y = kHeight-1; y >= 0; y--) {
ptr = outBuf + y * pitch;
for (x = 0; x < kWidth/8; x++)
*ptr++ = *srcBuf++;
}
bail:
return pDib;
}
/*
* The format is similar to the B&W version, but instead of one bitmap
* there are three. They're sorta-kinda CMY:
*
* >[...] There are 3 bit maps for the graphic. The
* >first is yellow, the second is magenta and the third is cyan. The other
* >colors are from combinations. Yellow and magenta is orange. Yellow and cyan
* >is green. Magenta and cyan are purple. All three is black.
*
* It appears, based on running Print Shop GS in an emulator, that "cyan"
* is actually 100% blue and "magenta" is 100% red. The values in the color
* table below come from a screen capture of KEGS.
*/
MyDIBitmap* ReformatPrintShop::ConvertColor(const uint8_t* srcBuf)
{
MyDIBitmap* pDib = new MyDIBitmap;
uint8_t* outBuf;
uint8_t* ptr;
uint8_t outVal;
uint16_t yellow, magenta, cyan;
int pitch;
int x, y, bit;
static const RGBQUAD kColorConv[8] = {
/* blue, green, red, reserved YMC */
{ 0xff, 0xff, 0xff }, // 000 white
{ 0xff, 0x00, 0x00 }, // 001 cyan (blue)
{ 0x00, 0x00, 0xff }, // 010 magenta (red)
{ 0xcc, 0x00, 0xcc }, // 011 purple
{ 0x00, 0xff, 0xff }, // 100 yellow
{ 0x00, 0xff, 0x00 }, // 101 green
{ 0x00, 0x66, 0xff }, // 110 orange
{ 0x00, 0x00, 0x00 }, // 111 black
};
if (pDib == NULL)
return NULL;
outBuf = (uint8_t*) pDib->Create(kWidth, kHeight, 4, 8);
if (outBuf == NULL) {
delete pDib;
pDib = NULL;
goto bail;
}
pDib->SetColorTable(kColorConv);
pitch = pDib->GetPitch();
/*
* Build it in standard upside-down Windows format.
*
* We pre-shift the yellow/magenta/cyan values into offsetting positions
* to save ourselves a shift each time through the loop.
*/
for (y = kHeight-1; y >= 0; y--) {
ptr = outBuf + y * pitch;
for (x = 0; x < kWidth/8; x++) {
yellow = *srcBuf << 2;
magenta = *(srcBuf + (kWidth/8)*kHeight) << 1;
cyan = *(srcBuf + (kWidth/8)*kHeight *2);
/* each 3-bit combo turns into a 4-bit index, 2 per output byte */
for (bit = 0; bit < 4; bit++) {
outVal = ((yellow & 0x200) | (magenta & 0x100) | (cyan & 0x80)) >> 3;
yellow <<= 1;
magenta <<= 1;
cyan <<= 1;
outVal |= ((yellow & 0x200) | (magenta & 0x100) | (cyan & 0x80)) >> 7;
yellow <<= 1;
magenta <<= 1;
cyan <<= 1;
*ptr++ = outVal;
}
srcBuf++;
}
}
bail:
return pDib;
}