PSDTranslator: Add export to psd support (uncompressed only)
This commit is contained in:
@@ -13,6 +13,7 @@ for architectureObject in [ MultiArchSubDirSetup ] {
|
||||
PSDTranslatorApp.cpp
|
||||
PSDTranslator.cpp
|
||||
PSDLoader.cpp
|
||||
PSDWriter.cpp
|
||||
ConfigView.cpp
|
||||
: be translation
|
||||
[ MultiArchDefaultGristFiles libtranslatorsutils.a ]
|
||||
@@ -28,5 +29,6 @@ DoCatalogs PSDTranslator :
|
||||
PSDTranslatorApp.cpp
|
||||
PSDTranslator.cpp
|
||||
PSDLoader.cpp
|
||||
PSDWriter.cpp
|
||||
ConfigView.cpp
|
||||
;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "ConfigView.h"
|
||||
#include "PSDTranslator.h"
|
||||
#include "PSDLoader.h"
|
||||
#include "PSDWriter.h"
|
||||
|
||||
const char *kDocumentCount = "/documentCount";
|
||||
const char *kDocumentIndex = "/documentIndex";
|
||||
@@ -20,13 +21,21 @@ const char *kDocumentIndex = "/documentIndex";
|
||||
|
||||
static const translation_format sInputFormats[] = {
|
||||
{
|
||||
B_TRANSLATOR_BITMAP,
|
||||
B_TRANSLATOR_BITMAP,
|
||||
BITS_IN_QUALITY,
|
||||
BITS_IN_CAPABILITY,
|
||||
"image/x-be-bitmap",
|
||||
"Be Bitmap Format (PSDTranslator)"
|
||||
},
|
||||
{
|
||||
PSD_IMAGE_FORMAT,
|
||||
B_TRANSLATOR_BITMAP,
|
||||
PSD_IN_QUALITY,
|
||||
PSD_IN_CAPABILITY,
|
||||
kPSDMimeType,
|
||||
kPSDName
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
static const translation_format sOutputFormats[] = {
|
||||
@@ -38,6 +47,14 @@ static const translation_format sOutputFormats[] = {
|
||||
"image/x-be-bitmap",
|
||||
"Be Bitmap Format (PSDTranslator)"
|
||||
},
|
||||
{
|
||||
PSD_IMAGE_FORMAT,
|
||||
B_TRANSLATOR_BITMAP,
|
||||
PSD_OUT_QUALITY,
|
||||
PSD_OUT_CAPABILITY,
|
||||
kPSDMimeType,
|
||||
kPSDName
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -46,8 +63,10 @@ static const TranSetting sDefaultSettings[] = {
|
||||
{B_TRANSLATOR_EXT_DATA_ONLY, TRAN_SETTING_BOOL, false}
|
||||
};
|
||||
|
||||
const uint32 kNumInputFormats = 1;
|
||||
const uint32 kNumOutputFormats = 1;
|
||||
const uint32 kNumInputFormats = sizeof(sInputFormats)
|
||||
/ sizeof(translation_format);
|
||||
const uint32 kNumOutputFormats = sizeof(sOutputFormats)
|
||||
/ sizeof(translation_format);
|
||||
const uint32 kNumDefaultSettings = sizeof(sDefaultSettings)
|
||||
/ sizeof(TranSetting);
|
||||
|
||||
@@ -102,7 +121,8 @@ PSDTranslator::DerivedTranslate(BPositionIO *source,
|
||||
const translator_info *info, BMessage *ioExtension,
|
||||
uint32 outType, BPositionIO *target, int32 baseType)
|
||||
{
|
||||
if (outType != B_TRANSLATOR_BITMAP)
|
||||
if (outType != B_TRANSLATOR_BITMAP
|
||||
&& outType != PSD_IMAGE_FORMAT)
|
||||
return B_NO_TRANSLATOR;
|
||||
|
||||
switch (baseType) {
|
||||
@@ -117,13 +137,62 @@ PSDTranslator::DerivedTranslate(BPositionIO *source,
|
||||
|
||||
return psdFile.Decode(target);
|
||||
}
|
||||
|
||||
case 1:
|
||||
{
|
||||
if (outType == PSD_IMAGE_FORMAT)
|
||||
return _TranslateFromBits(source, ioExtension, outType, target);
|
||||
return B_NO_TRANSLATOR;
|
||||
}
|
||||
default:
|
||||
return B_NO_TRANSLATOR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
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,13 +21,18 @@
|
||||
#define DOCUMENT_COUNT "/documentCount"
|
||||
#define DOCUMENT_INDEX "/documentIndex"
|
||||
|
||||
#define PSD_TRANSLATOR_VERSION B_TRANSLATION_MAKE_VERSION(1, 1, 3)
|
||||
#define PSD_TRANSLATOR_VERSION B_TRANSLATION_MAKE_VERSION(1, 2, 0)
|
||||
#define PSD_IMAGE_FORMAT 'PSD '
|
||||
|
||||
#define PSD_IN_QUALITY 0.5
|
||||
#define PSD_IN_CAPABILITY 0.5
|
||||
#define BITS_OUT_QUALITY 1
|
||||
#define BITS_OUT_CAPABILITY 0.9
|
||||
#define PSD_IN_QUALITY 0.7
|
||||
#define PSD_IN_CAPABILITY 0.6
|
||||
#define PSD_OUT_QUALITY 0.5
|
||||
#define PSD_OUT_CAPABILITY 0.6
|
||||
|
||||
#define BITS_IN_QUALITY 0.7
|
||||
#define BITS_IN_CAPABILITY 0.6
|
||||
#define BITS_OUT_QUALITY 0.7
|
||||
#define BITS_OUT_CAPABILITY 0.6
|
||||
|
||||
class PSDTranslator : public BaseTranslator {
|
||||
public:
|
||||
@@ -48,6 +53,9 @@ class PSDTranslator : public BaseTranslator {
|
||||
|
||||
protected:
|
||||
virtual ~PSDTranslator();
|
||||
private:
|
||||
status_t _TranslateFromBits(BPositionIO* stream,
|
||||
BMessage* settings, uint32 outType, BPositionIO* target);
|
||||
};
|
||||
|
||||
extern const char *kDocumentCount;
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Copyright 2013, Gerasim Troeglazov, [email protected]. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <File.h>
|
||||
|
||||
#include "BaseTranslator.h"
|
||||
#include "PSDWriter.h"
|
||||
|
||||
|
||||
PSDWriter::PSDWriter(BPositionIO *stream)
|
||||
{
|
||||
fStream = stream;
|
||||
}
|
||||
|
||||
|
||||
PSDWriter::~PSDWriter()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PSDWriter::EncodeFromRGBA(BPositionIO *target, uint8 *buff,
|
||||
int32 layers, int32 width, int32 height)
|
||||
{
|
||||
int32 channelSize = width * height;
|
||||
|
||||
_WriteUInt32ToStream(target, 0x38425053); // 8BPS
|
||||
_WriteUInt16ToStream(target, 1); // Version = 1
|
||||
_WriteFillBlockToStream(target, 0, 6); // reserved
|
||||
_WriteInt16ToStream(target, layers); // Channels = 4
|
||||
_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);
|
||||
|
||||
// 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);
|
||||
|
||||
sizePos = target->Position();
|
||||
_WriteUInt32ToStream(target, 0); // Layer & mask block size = 0
|
||||
_WriteUInt32ToStream(target, 0); // Layer info block size = 0
|
||||
|
||||
_WriteUInt16ToStream(target, 1); // Layers count
|
||||
|
||||
_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); // Layer data size
|
||||
}
|
||||
|
||||
if (layers == 4) {
|
||||
uint8 resBlock2[2] = {0xFF, 0xFF};
|
||||
_WriteBlockToStream(target, resBlock2, 2);
|
||||
_WriteUInt32ToStream(target, channelSize + 2); // Alpha layer data size
|
||||
}
|
||||
|
||||
_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, 4 + 4 + 16); // Extra data length
|
||||
_WriteUInt32ToStream(target, 0); // Mask info
|
||||
_WriteUInt32ToStream(target, 0);
|
||||
|
||||
_WriteUInt8ToStream(target, 15); // Layer name length
|
||||
uint8 layerName[16] = {"Layer #1 "};
|
||||
_WriteBlockToStream(target, 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
|
||||
}
|
||||
|
||||
uint32 layerBlockSize = target->Position() - sizePos;
|
||||
|
||||
/* 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);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PSDWriter::_WriteInt32ToStream(BPositionIO *stream, int32 val)
|
||||
{
|
||||
val = B_HOST_TO_BENDIAN_INT32(val);
|
||||
stream->Write(&val, sizeof(int32));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PSDWriter::_WriteUInt32ToStream(BPositionIO *stream, uint32 val)
|
||||
{
|
||||
val = B_HOST_TO_BENDIAN_INT32(val);
|
||||
stream->Write(&val, sizeof(uint32));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PSDWriter::_WriteInt16ToStream(BPositionIO *stream, int16 val)
|
||||
{
|
||||
val = B_HOST_TO_BENDIAN_INT16(val);
|
||||
stream->Write(&val, sizeof(int16));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PSDWriter::_WriteUInt16ToStream(BPositionIO *stream, uint16 val)
|
||||
{
|
||||
val = B_HOST_TO_BENDIAN_INT16(val);
|
||||
stream->Write(&val, sizeof(int16));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PSDWriter::_WriteInt8ToStream(BPositionIO *stream, int8 val)
|
||||
{
|
||||
stream->Write(&val, sizeof(int8));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PSDWriter::_WriteUInt8ToStream(BPositionIO *stream, uint8 val)
|
||||
{
|
||||
stream->Write(&val, sizeof(uint8));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PSDWriter::_WriteFillBlockToStream(BPositionIO *stream,
|
||||
uint8 val, size_t count)
|
||||
{
|
||||
for (size_t i = 0; i < count; i++)
|
||||
stream->Write(&val, sizeof(uint8));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PSDWriter::_WriteBlockToStream(BPositionIO *stream,
|
||||
uint8 *val, size_t count)
|
||||
{
|
||||
stream->Write(val, count);
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2013, Gerasim Troeglazov, [email protected]. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PSD_WRITER_H
|
||||
#define PSD_WRITER_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <Translator.h>
|
||||
#include <TranslatorFormats.h>
|
||||
#include <TranslationDefs.h>
|
||||
#include <GraphicsDefs.h>
|
||||
#include <InterfaceDefs.h>
|
||||
#include <String.h>
|
||||
#include <DataIO.h>
|
||||
#include <File.h>
|
||||
#include <ByteOrder.h>
|
||||
#include <List.h>
|
||||
|
||||
#include "PSDLoader.h"
|
||||
|
||||
class PSDWriter {
|
||||
public:
|
||||
PSDWriter(BPositionIO *stream);
|
||||
~PSDWriter();
|
||||
|
||||
status_t EncodeFromRGBA(BPositionIO *target, uint8 *buff,
|
||||
int32 layers, int32 width, int32 height);
|
||||
|
||||
private:
|
||||
void _WriteInt32ToStream(BPositionIO *stream, int32);
|
||||
void _WriteUInt32ToStream(BPositionIO *stream, uint32);
|
||||
void _WriteInt16ToStream(BPositionIO *stream, int16);
|
||||
void _WriteUInt16ToStream(BPositionIO *stream, uint16);
|
||||
void _WriteInt8ToStream(BPositionIO *stream, int8);
|
||||
void _WriteUInt8ToStream(BPositionIO *stream, uint8);
|
||||
void _WriteFillBlockToStream(BPositionIO *stream,
|
||||
uint8 val, size_t count);
|
||||
void _WriteBlockToStream(BPositionIO *stream,
|
||||
uint8 *block, size_t count);
|
||||
|
||||
BPositionIO *fStream;
|
||||
};
|
||||
|
||||
|
||||
#endif /* PSD_WRITER_H */
|
||||
Reference in New Issue
Block a user