PSDTranslator: Add export to psd support (uncompressed only)

This commit is contained in:
Gerasim Troeglazov
2013-12-17 12:27:47 +00:00
parent cf9414ff69
commit 3459199e5d
5 changed files with 332 additions and 10 deletions
+2
View File
@@ -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
;
+74 -5
View File
@@ -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
{
+13 -5
View File
@@ -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;
+192
View File
@@ -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);
}
+51
View File
@@ -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 */