PSDTranslator: Rework export module

This commit is contained in:
Gerasim Troeglazov 2013-12-19 10:37:09 +00:00
parent e3ec312ebf
commit 7983058de3
5 changed files with 153 additions and 141 deletions

View File

@ -140,8 +140,10 @@ PSDTranslator::DerivedTranslate(BPositionIO *source,
}
case 1:
{
if (outType == PSD_IMAGE_FORMAT)
return _TranslateFromBits(source, ioExtension, outType, target);
if (outType == PSD_IMAGE_FORMAT) {
PSDWriter psdFile(source);
return psdFile.Encode(target);
}
return B_NO_TRANSLATOR;
}
default:
@ -150,50 +152,6 @@ PSDTranslator::DerivedTranslate(BPositionIO *source,
}
status_t
PSDTranslator::_TranslateFromBits(BPositionIO* stream,
BMessage* ioExtension, uint32 outType,
BPositionIO* target)
{
TranslatorBitmap bitsHeader;
status_t result;
result = identify_bits_header(stream, NULL, &bitsHeader);
if (result != B_OK)
return result;
if (bitsHeader.colors != B_RGB32
&& bitsHeader.colors != B_RGBA32) {
return B_NO_TRANSLATOR;
}
uint32 width = bitsHeader.bounds.IntegerWidth() + 1;
uint32 height = bitsHeader.bounds.IntegerHeight() + 1;
int32 layerSize = height * width;
int32 layersCount = bitsHeader.colors == B_RGB32 ? 3 : 4;
uint8 *buff = new uint8[layerSize * layersCount];
uint8 *ptr = buff;
for (int i = 0; i < layerSize; i++) {
uint8 rgba[4];
stream->Read(rgba, sizeof(uint32));
ptr[i] = rgba[2];
ptr[i+layerSize] = rgba[1];
ptr[i+layerSize+layerSize] = rgba[0];
if (layersCount == 4)
ptr[i+layerSize+layerSize+layerSize] = rgba[3];
}
PSDWriter psdFile(stream);
psdFile.EncodeFromRGBA(target, buff, layersCount, width, height);
delete buff;
return B_OK;
}
status_t
PSDTranslator::DerivedCanHandleImageSize(float width, float height) const
{

View File

@ -21,7 +21,7 @@
#define DOCUMENT_COUNT "/documentCount"
#define DOCUMENT_INDEX "/documentIndex"
#define PSD_TRANSLATOR_VERSION B_TRANSLATION_MAKE_VERSION(1, 2, 0)
#define PSD_TRANSLATOR_VERSION B_TRANSLATION_MAKE_VERSION(1, 2, 1)
#define PSD_IMAGE_FORMAT 'PSD '
#define PSD_IN_QUALITY 0.7
@ -53,9 +53,6 @@ class PSDTranslator : public BaseTranslator {
protected:
virtual ~PSDTranslator();
private:
status_t _TranslateFromBits(BPositionIO* stream,
BMessage* settings, uint32 outType, BPositionIO* target);
};
extern const char *kDocumentCount;

View File

@ -6,10 +6,10 @@ resource app_signature "application/x-vnd.Haiku-PSDTranslator";
resource app_version {
major = 1,
middle = 1,
minor = 3,
middle = 2,
minor = 1,
variety = 0,
internal = 0,
short_info = "1.1.3",
short_info = "1.2.1",
long_info = "Haiku PSDTranslator Add-Ons."
};

View File

@ -8,11 +8,39 @@
#include "BaseTranslator.h"
#include "PSDWriter.h"
#include "DataArray.h"
PSDWriter::PSDWriter(BPositionIO *stream)
{
fStream = stream;
fReady = false;
TranslatorBitmap header;
stream->Seek(0, SEEK_SET);
status_t err = stream->Read(&header, sizeof(TranslatorBitmap));
if (err < B_OK)
return;
else if (err < (int)sizeof(TranslatorBitmap))
return;
fBitmapDataPos = stream->Position();
BRect bounds;
bounds.left = B_BENDIAN_TO_HOST_FLOAT(header.bounds.left);
bounds.top = B_BENDIAN_TO_HOST_FLOAT(header.bounds.top);
bounds.right = B_BENDIAN_TO_HOST_FLOAT(header.bounds.right);
bounds.bottom = B_BENDIAN_TO_HOST_FLOAT(header.bounds.bottom);
fInRowBytes = B_BENDIAN_TO_HOST_INT32(header.rowBytes);
fColorSpace = (color_space)B_BENDIAN_TO_HOST_INT32(header.colors);
fChannels = fColorSpace == B_RGB32 ? 3 : 4;
fWidth = bounds.IntegerWidth() + 1;
fHeight = bounds.IntegerHeight() + 1;
fCompression = PSD_COMPRESSED_RAW;
fReady = true;
}
@ -21,108 +49,126 @@ PSDWriter::~PSDWriter()
}
status_t
PSDWriter::EncodeFromRGBA(BPositionIO *target, uint8 *buff,
int32 layers, int32 width, int32 height)
bool
PSDWriter::IsReady(void)
{
int32 channelSize = width * height;
return fReady;
}
_WriteUInt32ToStream(target, 0x38425053); // 8BPS
_WriteUInt16ToStream(target, 1); // Version = 1
_WriteFillBlockToStream(target, 0, 6); // reserved
_WriteInt16ToStream(target, layers); // Channels
_WriteInt32ToStream(target, height); // Height
_WriteInt32ToStream(target, width); // Width
_WriteInt16ToStream(target, 8); // Depth = 8
_WriteInt16ToStream(target, PSD_COLOR_MODE_RGB); // ColorMode
_WriteUInt32ToStream(target, 0); // ColorModeBlockSize = 0
size_t sizePos = target->Position();
_WriteUInt32ToStream(target, 0); // ImageResourceBlockSize = 0 for now
_WriteUInt32ToStream(target, 0x3842494D); // 8BIM
_WriteUInt16ToStream(target, 1005);
_WriteUInt16ToStream(target, 0);
_WriteUInt32ToStream(target, 16);
uint8 resBlock[16] = {0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01};
_WriteBlockToStream(target, resBlock, 16);
void
PSDWriter::SetCompression(int16 compression)
{
fCompression = compression;
}
// current layer info
_WriteUInt32ToStream(target, 0x3842494D); // 8BIM
_WriteUInt16ToStream(target, 1024);
_WriteUInt16ToStream(target, 0);
_WriteUInt32ToStream(target, 2);
_WriteUInt16ToStream(target, 0); // Set current layer to 0
int32 resBlockSize = target->Position() - sizePos;
size_t lastPos = target->Position();
target->Seek(sizePos, SEEK_SET);
_WriteUInt32ToStream(target, resBlockSize - sizeof(uint32));
target->Seek(lastPos, SEEK_SET);
status_t
PSDWriter::Encode(BPositionIO *target)
{
if (!fReady)
return B_NO_TRANSLATOR;
sizePos = target->Position();
_WriteUInt32ToStream(target, 0); // Layer & mask block size = 0
_WriteUInt32ToStream(target, 0); // Layer info block size = 0
int32 channelSize = fWidth * fHeight;
_WriteUInt16ToStream(target, 1); // Layers count
fStream->Seek(fBitmapDataPos, SEEK_SET);
_WriteUInt32ToStream(target, 0); // Layer rect
_WriteUInt32ToStream(target, 0);
_WriteUInt32ToStream(target, height);
_WriteUInt32ToStream(target, width);
_WriteInt16ToStream(target, layers); // Layer Channels
for (int channels = 0; channels < 3; channels++) {
_WriteInt16ToStream(target, channels); // Channel num
_WriteUInt32ToStream(target, channelSize + 2); // Channel size
BDataArray psdChannel[4];
for (int i = 0; i < channelSize; i++) {
uint8 rgba[4];
fStream->Read(rgba, sizeof(uint32));
psdChannel[0].Append((uint8)rgba[2]); // Red channel
psdChannel[1].Append((uint8)rgba[1]); // Green channel
psdChannel[2].Append((uint8)rgba[0]); // Blue channel
if (fChannels == 4)
psdChannel[3].Append((uint8)rgba[3]); // Alpha channel
}
if (layers == 4) {
_WriteInt16ToStream(target, -1);
_WriteUInt32ToStream(target, channelSize + 2); // Alpha channel size
// PSD header
BDataArray psdHeader(64);
psdHeader << "8BPS"; // Signature
psdHeader << (uint16)1; // Version = 1
psdHeader.Repeat(0, 6); // Reserved
psdHeader << fChannels; // Channels
psdHeader << fHeight << fWidth; // Image size
psdHeader << (int16)8; // Depth
psdHeader << (int16)PSD_COLOR_MODE_RGB; // ColorMode
// Color mode section
BDataArray psdColorModeSection(16);
psdColorModeSection << (uint32)0;
// Image resource section
BDataArray psdImageResourceSection(64);
psdImageResourceSection << "8BIM"; // Block signature
psdImageResourceSection << (uint16)1005;
psdImageResourceSection << (uint16)0;
psdImageResourceSection << (uint32)16;
uint8 resBlock[16] = {0x00, 0x48, 0x00, 0x00,
0x00, 0x01, 0x00, 0x01,
0x00, 0x48, 0x00, 0x00,
0x00, 0x01, 0x00, 0x01};
psdImageResourceSection.Append(resBlock, 16);
// Current layer info
psdImageResourceSection << "8BIM"; // Block signature
psdImageResourceSection << (uint16)1024;
psdImageResourceSection << (uint16)0;
psdImageResourceSection << (uint32)2;
psdImageResourceSection << (uint16)0; // Set current layer to 0
// Layer & mask section
BDataArray psdLayersSection;
psdLayersSection << (uint16)1; // Layers count
psdLayersSection << (uint32)0; // Layer rect
psdLayersSection << (uint32)0;
psdLayersSection << (uint32)fHeight;
psdLayersSection << (uint32)fWidth;
psdLayersSection << (uint16)fChannels;
for (int dataChannel = 0; dataChannel < 3; dataChannel++) {
psdLayersSection << (int16)dataChannel; // Channel num
psdLayersSection << (uint32)(psdChannel[dataChannel].Length() + 2);
}
if (fChannels == 4) {
psdLayersSection << (int16)-1; // Alpha channel id (-1)
psdLayersSection << (uint32)(psdChannel[4].Length() + 2);
}
psdLayersSection << "8BIM";
psdLayersSection << "norm"; // Blend mode = norm
psdLayersSection << (uint8)255; // Opacity
psdLayersSection << (uint8)0; // Clipping
psdLayersSection << (uint8)1; // Flags
psdLayersSection << (uint8)0; // Flags
psdLayersSection << (uint32)24; // Extra data length
psdLayersSection << (uint32)0; // Mask info
psdLayersSection << (uint32)0;
_WriteUInt32ToStream(target, 0x3842494D); // 8BIM
uint8 blendModeKey[4] = {'n','o','r','m'};
_WriteBlockToStream(target, blendModeKey, 4); // Blend mode norm
_WriteUInt8ToStream(target, 255); // Alpha
_WriteUInt8ToStream(target, 0); // Clipping
_WriteUInt8ToStream(target, 1); // Flags
_WriteUInt8ToStream(target, 0); // Flags
_WriteUInt32ToStream(target, 24); // Extra data length
_WriteUInt32ToStream(target, 0); // Mask info
_WriteUInt32ToStream(target, 0);
_WriteUInt8ToStream(target, 15); // Layer name length
psdLayersSection << (uint8)15; // Layer name length
uint8 layerName[16] = {"Layer #1 "};
_WriteBlockToStream(target, layerName, 15); // Layer name
psdLayersSection.Append(layerName, 15); // Layer name
for (int dataChannel = 0; dataChannel < layers; dataChannel++) {
_WriteInt16ToStream(target, PSD_COMPRESSED_RAW); // Compression mode
_WriteBlockToStream(target, buff + dataChannel * channelSize,
channelSize); // Layer image data
for (int dataChannel = 0; dataChannel < fChannels; dataChannel++) {
psdLayersSection << fCompression; // Compression mode
psdLayersSection.Append(psdChannel[dataChannel].Buffer(),
psdChannel[dataChannel].Length()); // Layer image data
}
psdHeader.WriteToStream(target);
psdColorModeSection.WriteToStream(target);
_WriteUInt32ToStream(target, psdImageResourceSection.Length());
psdImageResourceSection.WriteToStream(target);
uint32 layerBlockSize = target->Position() - sizePos;
_WriteUInt32ToStream(target, psdLayersSection.Length() + 4);
_WriteUInt32ToStream(target, psdLayersSection.Length());
psdLayersSection.WriteToStream(target);
/* if (layerBlockSize % 2 != 0) {
_WriteUInt8ToStream(target, 0);
layerBlockSize++;
}*/
lastPos = target->Position();
target->Seek(sizePos, SEEK_SET);
_WriteUInt32ToStream(target, layerBlockSize - 4);
_WriteUInt32ToStream(target, layerBlockSize - 8);
target->Seek(lastPos, SEEK_SET);
_WriteUInt16ToStream(target, PSD_COMPRESSED_RAW); // Compression mode
_WriteBlockToStream(target, buff, channelSize * layers);
// Merged layer
_WriteUInt16ToStream(target, fCompression); // Compression mode
for (int dataChannel = 0; dataChannel < fChannels; dataChannel++)
psdChannel[dataChannel].WriteToStream(target);
return B_OK;
}

View File

@ -29,8 +29,9 @@ public:
PSDWriter(BPositionIO *stream);
~PSDWriter();
status_t EncodeFromRGBA(BPositionIO *target, uint8 *buff,
int32 layers, int32 width, int32 height);
bool IsReady(void);
void SetCompression(int16 compression);
status_t Encode(BPositionIO *target);
private:
void _WriteInt32ToStream(BPositionIO *stream, int32);
@ -44,7 +45,17 @@ private:
void _WriteBlockToStream(BPositionIO *stream,
uint8 *block, size_t count);
BPositionIO *fStream;
BPositionIO *fStream;
size_t fBitmapDataPos;
color_space fColorSpace;
int32 fInRowBytes;
int16 fChannels;
int32 fWidth;
int32 fHeight;
int16 fCompression;
bool fReady;
};