hrev46549 adds 1 changeset to branch 'master' old head: cf9414ff69f8823303ad5ac019f8336a73b94a93 new head: 3459199e5dd0e7fbf1c93fd1aa270ecb5d490fa1 overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=3459199+%5Ecf9414f ---------------------------------------------------------------------------- 3459199: PSDTranslator: Add export to psd support (uncompressed only) [ Gerasim Troeglazov <3dEyes@xxxxxxxxx> ] ---------------------------------------------------------------------------- Revision: hrev46549 Commit: 3459199e5dd0e7fbf1c93fd1aa270ecb5d490fa1 URL: http://cgit.haiku-os.org/haiku/commit/?id=3459199 Author: Gerasim Troeglazov <3dEyes@xxxxxxxxx> Date: Tue Dec 17 12:26:18 2013 UTC ---------------------------------------------------------------------------- 5 files changed, 332 insertions(+), 10 deletions(-) src/add-ons/translators/psd/Jamfile | 2 + src/add-ons/translators/psd/PSDTranslator.cpp | 79 ++++++++- src/add-ons/translators/psd/PSDTranslator.h | 18 +- src/add-ons/translators/psd/PSDWriter.cpp | 192 ++++++++++++++++++++++ src/add-ons/translators/psd/PSDWriter.h | 51 ++++++ ---------------------------------------------------------------------------- diff --git a/src/add-ons/translators/psd/Jamfile b/src/add-ons/translators/psd/Jamfile index 015236a..20dbc71 100644 --- a/src/add-ons/translators/psd/Jamfile +++ b/src/add-ons/translators/psd/Jamfile @@ -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 ; diff --git a/src/add-ons/translators/psd/PSDTranslator.cpp b/src/add-ons/translators/psd/PSDTranslator.cpp index 4f9f79a..de927bd 100644 --- a/src/add-ons/translators/psd/PSDTranslator.cpp +++ b/src/add-ons/translators/psd/PSDTranslator.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 { diff --git a/src/add-ons/translators/psd/PSDTranslator.h b/src/add-ons/translators/psd/PSDTranslator.h index 6b45838..a4f211f 100644 --- a/src/add-ons/translators/psd/PSDTranslator.h +++ b/src/add-ons/translators/psd/PSDTranslator.h @@ -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; diff --git a/src/add-ons/translators/psd/PSDWriter.cpp b/src/add-ons/translators/psd/PSDWriter.cpp new file mode 100644 index 0000000..e97c243 --- /dev/null +++ b/src/add-ons/translators/psd/PSDWriter.cpp @@ -0,0 +1,192 @@ +/* + * Copyright 2013, Gerasim Troeglazov, 3dEyes@xxxxxxxxx. 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); +} diff --git a/src/add-ons/translators/psd/PSDWriter.h b/src/add-ons/translators/psd/PSDWriter.h new file mode 100644 index 0000000..5f428c7 --- /dev/null +++ b/src/add-ons/translators/psd/PSDWriter.h @@ -0,0 +1,51 @@ +/* + * Copyright 2013, Gerasim Troeglazov, 3dEyes@xxxxxxxxx. 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 */