[haiku-commits] haiku: hrev46549 - src/add-ons/translators/psd

  • From: Gerasim Troeglazov <3deyes@xxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Tue, 17 Dec 2013 13:29:07 +0100 (CET)

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 */


Other related posts: