PSDTranslator: Rework export module
This commit is contained in:
parent
e3ec312ebf
commit
7983058de3
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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."
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue