PSDTranslator: Rework export module
This commit is contained in:
@@ -140,8 +140,10 @@ PSDTranslator::DerivedTranslate(BPositionIO *source,
|
|||||||
}
|
}
|
||||||
case 1:
|
case 1:
|
||||||
{
|
{
|
||||||
if (outType == PSD_IMAGE_FORMAT)
|
if (outType == PSD_IMAGE_FORMAT) {
|
||||||
return _TranslateFromBits(source, ioExtension, outType, target);
|
PSDWriter psdFile(source);
|
||||||
|
return psdFile.Encode(target);
|
||||||
|
}
|
||||||
return B_NO_TRANSLATOR;
|
return B_NO_TRANSLATOR;
|
||||||
}
|
}
|
||||||
default:
|
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
|
status_t
|
||||||
PSDTranslator::DerivedCanHandleImageSize(float width, float height) const
|
PSDTranslator::DerivedCanHandleImageSize(float width, float height) const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
#define DOCUMENT_COUNT "/documentCount"
|
#define DOCUMENT_COUNT "/documentCount"
|
||||||
#define DOCUMENT_INDEX "/documentIndex"
|
#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_IMAGE_FORMAT 'PSD '
|
||||||
|
|
||||||
#define PSD_IN_QUALITY 0.7
|
#define PSD_IN_QUALITY 0.7
|
||||||
@@ -53,9 +53,6 @@ class PSDTranslator : public BaseTranslator {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~PSDTranslator();
|
virtual ~PSDTranslator();
|
||||||
private:
|
|
||||||
status_t _TranslateFromBits(BPositionIO* stream,
|
|
||||||
BMessage* settings, uint32 outType, BPositionIO* target);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const char *kDocumentCount;
|
extern const char *kDocumentCount;
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ resource app_signature "application/x-vnd.Haiku-PSDTranslator";
|
|||||||
|
|
||||||
resource app_version {
|
resource app_version {
|
||||||
major = 1,
|
major = 1,
|
||||||
middle = 1,
|
middle = 2,
|
||||||
minor = 3,
|
minor = 1,
|
||||||
variety = 0,
|
variety = 0,
|
||||||
internal = 0,
|
internal = 0,
|
||||||
short_info = "1.1.3",
|
short_info = "1.2.1",
|
||||||
long_info = "Haiku PSDTranslator Add-Ons."
|
long_info = "Haiku PSDTranslator Add-Ons."
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,11 +8,39 @@
|
|||||||
|
|
||||||
#include "BaseTranslator.h"
|
#include "BaseTranslator.h"
|
||||||
#include "PSDWriter.h"
|
#include "PSDWriter.h"
|
||||||
|
#include "DataArray.h"
|
||||||
|
|
||||||
|
|
||||||
PSDWriter::PSDWriter(BPositionIO *stream)
|
PSDWriter::PSDWriter(BPositionIO *stream)
|
||||||
{
|
{
|
||||||
fStream = 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
|
bool
|
||||||
PSDWriter::EncodeFromRGBA(BPositionIO *target, uint8 *buff,
|
PSDWriter::IsReady(void)
|
||||||
int32 layers, int32 width, int32 height)
|
|
||||||
{
|
{
|
||||||
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();
|
void
|
||||||
_WriteUInt32ToStream(target, 0); // ImageResourceBlockSize = 0 for now
|
PSDWriter::SetCompression(int16 compression)
|
||||||
_WriteUInt32ToStream(target, 0x3842494D); // 8BIM
|
{
|
||||||
_WriteUInt16ToStream(target, 1005);
|
fCompression = compression;
|
||||||
_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);
|
|
||||||
|
|
||||||
// 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;
|
status_t
|
||||||
size_t lastPos = target->Position();
|
PSDWriter::Encode(BPositionIO *target)
|
||||||
target->Seek(sizePos, SEEK_SET);
|
{
|
||||||
_WriteUInt32ToStream(target, resBlockSize - sizeof(uint32));
|
if (!fReady)
|
||||||
target->Seek(lastPos, SEEK_SET);
|
return B_NO_TRANSLATOR;
|
||||||
|
|
||||||
sizePos = target->Position();
|
int32 channelSize = fWidth * fHeight;
|
||||||
_WriteUInt32ToStream(target, 0); // Layer & mask block size = 0
|
|
||||||
_WriteUInt32ToStream(target, 0); // Layer info block size = 0
|
|
||||||
|
|
||||||
_WriteUInt16ToStream(target, 1); // Layers count
|
fStream->Seek(fBitmapDataPos, SEEK_SET);
|
||||||
|
|
||||||
_WriteUInt32ToStream(target, 0); // Layer rect
|
BDataArray psdChannel[4];
|
||||||
_WriteUInt32ToStream(target, 0);
|
|
||||||
_WriteUInt32ToStream(target, height);
|
for (int i = 0; i < channelSize; i++) {
|
||||||
_WriteUInt32ToStream(target, width);
|
uint8 rgba[4];
|
||||||
|
fStream->Read(rgba, sizeof(uint32));
|
||||||
_WriteInt16ToStream(target, layers); // Layer Channels
|
psdChannel[0].Append((uint8)rgba[2]); // Red channel
|
||||||
|
psdChannel[1].Append((uint8)rgba[1]); // Green channel
|
||||||
for (int channels = 0; channels < 3; channels++) {
|
psdChannel[2].Append((uint8)rgba[0]); // Blue channel
|
||||||
_WriteInt16ToStream(target, channels); // Channel num
|
if (fChannels == 4)
|
||||||
_WriteUInt32ToStream(target, channelSize + 2); // Channel size
|
psdChannel[3].Append((uint8)rgba[3]); // Alpha channel
|
||||||
}
|
}
|
||||||
|
|
||||||
if (layers == 4) {
|
// PSD header
|
||||||
_WriteInt16ToStream(target, -1);
|
BDataArray psdHeader(64);
|
||||||
_WriteUInt32ToStream(target, channelSize + 2); // Alpha channel size
|
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
|
psdLayersSection << (uint8)15; // Layer name length
|
||||||
|
|
||||||
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
|
|
||||||
uint8 layerName[16] = {"Layer #1 "};
|
uint8 layerName[16] = {"Layer #1 "};
|
||||||
_WriteBlockToStream(target, layerName, 15); // Layer name
|
psdLayersSection.Append(layerName, 15); // Layer name
|
||||||
|
|
||||||
for (int dataChannel = 0; dataChannel < layers; dataChannel++) {
|
for (int dataChannel = 0; dataChannel < fChannels; dataChannel++) {
|
||||||
_WriteInt16ToStream(target, PSD_COMPRESSED_RAW); // Compression mode
|
psdLayersSection << fCompression; // Compression mode
|
||||||
_WriteBlockToStream(target, buff + dataChannel * channelSize,
|
psdLayersSection.Append(psdChannel[dataChannel].Buffer(),
|
||||||
channelSize); // Layer image data
|
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) {
|
// Merged layer
|
||||||
_WriteUInt8ToStream(target, 0);
|
_WriteUInt16ToStream(target, fCompression); // Compression mode
|
||||||
layerBlockSize++;
|
for (int dataChannel = 0; dataChannel < fChannels; dataChannel++)
|
||||||
}*/
|
psdChannel[dataChannel].WriteToStream(target);
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,8 +29,9 @@ public:
|
|||||||
PSDWriter(BPositionIO *stream);
|
PSDWriter(BPositionIO *stream);
|
||||||
~PSDWriter();
|
~PSDWriter();
|
||||||
|
|
||||||
status_t EncodeFromRGBA(BPositionIO *target, uint8 *buff,
|
bool IsReady(void);
|
||||||
int32 layers, int32 width, int32 height);
|
void SetCompression(int16 compression);
|
||||||
|
status_t Encode(BPositionIO *target);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _WriteInt32ToStream(BPositionIO *stream, int32);
|
void _WriteInt32ToStream(BPositionIO *stream, int32);
|
||||||
@@ -44,7 +45,17 @@ private:
|
|||||||
void _WriteBlockToStream(BPositionIO *stream,
|
void _WriteBlockToStream(BPositionIO *stream,
|
||||||
uint8 *block, size_t count);
|
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user