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

  • From: Gerasim Troeglazov <3deyes@xxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Thu, 19 Dec 2013 13:25:10 +0100 (CET)

hrev46565 adds 3 changesets to branch 'master'
old head: bd50e8aedbea52e02a35cd1070eff0e597126ced
new head: 5a65c29781873d0e3b18ec9bc15f30623d8a6f08
overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=5a65c29+%5Ebd50e8a

----------------------------------------------------------------------------

e3ec312: PSDTranslator: Implemented DataArray class for export improvements

7983058: PSDTranslator: Rework export module

5a65c29: PSDTranslator: Add RLE compression method for export

                                   [ Gerasim Troeglazov <3dEyes@xxxxxxxxx> ]

----------------------------------------------------------------------------

8 files changed, 549 insertions(+), 147 deletions(-)
src/add-ons/translators/psd/DataArray.cpp      | 216 +++++++++++++
src/add-ons/translators/psd/DataArray.h        |  61 ++++
src/add-ons/translators/psd/Jamfile            |   2 +
src/add-ons/translators/psd/PSDTranslator.cpp  |  51 +---
src/add-ons/translators/psd/PSDTranslator.h    |   5 +-
src/add-ons/translators/psd/PSDTranslator.rdef |   6 +-
src/add-ons/translators/psd/PSDWriter.cpp      | 335 +++++++++++++++------
src/add-ons/translators/psd/PSDWriter.h        |  20 +-

############################################################################

Commit:      e3ec312ebf6ad6343d7477963cf5e3edd4b41deb
URL:         http://cgit.haiku-os.org/haiku/commit/?id=e3ec312
Author:      Gerasim Troeglazov <3dEyes@xxxxxxxxx>
Date:        Thu Dec 19 09:11:26 2013 UTC

PSDTranslator: Implemented DataArray class for export improvements

----------------------------------------------------------------------------

diff --git a/src/add-ons/translators/psd/DataArray.cpp 
b/src/add-ons/translators/psd/DataArray.cpp
new file mode 100644
index 0000000..e3dd21b
--- /dev/null
+++ b/src/add-ons/translators/psd/DataArray.cpp
@@ -0,0 +1,216 @@
+/*
+ * Copyright 2013, Gerasim Troeglazov, 3dEyes@xxxxxxxxx. All rights reserved.
+ * Distributed under the terms of the MIT License.
+ */
+
+#include "DataArray.h"
+
+
+BDataArray::BDataArray(int32 blockSize)
+{
+       fBlockSize = blockSize;
+       fData = (uint8*)malloc(blockSize);
+       fAllocatedDataSize = blockSize;
+       fDataSize = 0;
+}
+
+
+BDataArray::~BDataArray()
+{
+       free(fData);
+}
+
+
+status_t
+BDataArray::_ReallocArrayFor(int32 size)
+{
+       if (fDataSize + size > fAllocatedDataSize) {
+               int32 blocks = ((fDataSize + size) / fBlockSize) + 1;
+               uint8 *newData = (uint8*)realloc(fData, blocks * fBlockSize);
+               if (newData != NULL) {
+                       fData = newData;
+                       fAllocatedDataSize = blocks * fBlockSize;
+               }
+       }
+       return fData == NULL ? B_NO_MEMORY : B_OK;
+}
+
+
+uint8*
+BDataArray::Buffer(void)
+{
+       return fData;
+}
+
+
+int32
+BDataArray::Length(void)
+{
+       return fDataSize;
+}
+
+
+ssize_t
+BDataArray::WriteToStream(BPositionIO *stream)
+{
+       return stream->Write(fData, fDataSize);
+}
+
+
+status_t
+BDataArray::Append(uint8 val)
+{
+       status_t status = _ReallocArrayFor(sizeof(val));
+       if (status != B_OK)
+               return status;
+       fData[fDataSize] = val;
+       fDataSize++;
+       return B_OK;
+}
+
+
+status_t
+BDataArray::Append(int8 val)
+{
+       return Append((uint8)val);
+}
+
+
+status_t
+BDataArray::Append(uint16 val)
+{
+       status_t status = _ReallocArrayFor(sizeof(val));
+       if (status != B_OK)
+               return status;
+       val = B_HOST_TO_BENDIAN_INT16(val);
+       memcpy(fData + fDataSize, &val, sizeof(val));
+       fDataSize += sizeof(val);
+       return B_OK;    
+}
+
+
+status_t
+BDataArray::Append(int16 val)
+{
+       return Append((uint16)val);
+}
+
+
+status_t
+BDataArray::Append(uint32 val)
+{
+       status_t status = _ReallocArrayFor(sizeof(val));
+       if (status != B_OK)
+               return status;
+       val = B_HOST_TO_BENDIAN_INT32(val);
+       memcpy(fData + fDataSize, &val, sizeof(val));
+       fDataSize += sizeof(val);
+       return B_OK;
+}
+
+
+status_t
+BDataArray::Append(int32 val)
+{
+       return Append((uint32)val);
+}
+
+
+status_t
+BDataArray::Append(const char *str)
+{
+       int32 len = strlen(str);
+       status_t status = _ReallocArrayFor(len);
+       if (status != B_OK)
+               return status;
+       memcpy(fData + fDataSize, str, len);
+       fDataSize += len;
+       return B_OK;    
+}
+
+
+status_t
+BDataArray::Append(BString str)
+{
+       return Append(str.String());
+}
+
+
+status_t
+BDataArray::Append(uint8 *ptr, int32 len)
+{
+       status_t status = _ReallocArrayFor(len);
+       if (status != B_OK)
+               return status;
+       memcpy(fData + fDataSize, ptr, len);
+       fDataSize += len;
+       return B_OK;
+}
+
+
+status_t
+BDataArray::Repeat(uint8 byte, int32 count)
+{
+       status_t status = _ReallocArrayFor(count);
+       if (status != B_OK)
+               return status;
+       memset(fData + fDataSize, byte, count);
+       fDataSize += count;
+       return B_OK;    
+}
+
+
+BDataArray&
+BDataArray::operator<<(int8 val)
+{
+       Append(val);
+       return *this;
+}
+
+
+BDataArray&
+BDataArray::operator<<(uint8 val)
+{
+       Append(val);
+       return *this;
+}
+
+
+BDataArray&
+BDataArray::operator<<(int16 val)
+{
+       Append(val);
+       return *this;
+}
+
+
+BDataArray&
+BDataArray::operator<<(uint16 val)
+{
+       Append(val);
+       return *this;
+}
+
+
+BDataArray&
+BDataArray::operator<<(int32 val)
+{
+       Append(val);
+       return *this;
+}
+
+
+BDataArray&
+BDataArray::operator<<(uint32 val)
+{
+       Append(val);
+       return *this;
+}
+
+
+BDataArray&
+BDataArray::operator<<(const char* str)
+{
+       Append(str);
+       return *this;
+}
diff --git a/src/add-ons/translators/psd/DataArray.h 
b/src/add-ons/translators/psd/DataArray.h
new file mode 100644
index 0000000..33d97cf
--- /dev/null
+++ b/src/add-ons/translators/psd/DataArray.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2013, Gerasim Troeglazov, 3dEyes@xxxxxxxxx. All rights reserved.
+ * Distributed under the terms of the MIT License.
+ */
+
+
+#ifndef PSD_DATA_ARRAY_H
+#define PSD_DATA_ARRAY_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <String.h>
+#include <DataIO.h>
+#include <File.h>
+#include <ByteOrder.h>
+
+#define DATAARRAY_BLOCK_SIZE 1024
+
+class BDataArray {
+public:
+                                       BDataArray(int32 blockSize = 
DATAARRAY_BLOCK_SIZE);
+                                       ~BDataArray();
+
+       status_t                Append(int8 val);
+       status_t                Append(uint8 val);
+       status_t                Append(int16 val);
+       status_t                Append(uint16 val);
+       status_t                Append(int32 val);
+       status_t                Append(uint32 val);
+       status_t                Append(const char *str);
+       status_t                Append(BString str);
+       status_t                Append(uint8 *ptr, int32 len);
+       
+       status_t                Repeat(uint8 byte, int32 count);
+
+       BDataArray&             operator<<(int8);
+       BDataArray&             operator<<(uint8);
+       BDataArray&             operator<<(int16);
+       BDataArray&             operator<<(uint16);
+       BDataArray&             operator<<(int32);
+       BDataArray&             operator<<(uint32);
+       BDataArray&             operator<<(const char*);
+
+       uint8                   *Buffer(void);
+       int32                   Length(void);
+
+       ssize_t                 WriteToStream(BPositionIO *stream);
+
+private:
+       inline status_t _ReallocArrayFor(int32 size);
+
+       uint8                   *fData;
+       int32                   fDataSize;
+       int32                   fAllocatedDataSize;
+       int32                   fBlockSize;
+};
+
+
+#endif /* PSD_DATA_ARRAY_H */
diff --git a/src/add-ons/translators/psd/Jamfile 
b/src/add-ons/translators/psd/Jamfile
index 20dbc71..bbf7c3c 100644
--- a/src/add-ons/translators/psd/Jamfile
+++ b/src/add-ons/translators/psd/Jamfile
@@ -14,6 +14,7 @@ for architectureObject in [ MultiArchSubDirSetup ] {
                        PSDTranslator.cpp
                        PSDLoader.cpp
                        PSDWriter.cpp
+                       DataArray.cpp
                        ConfigView.cpp
                        : be translation 
                        [ MultiArchDefaultGristFiles libtranslatorsutils.a ]
@@ -30,5 +31,6 @@ DoCatalogs PSDTranslator :
        PSDTranslator.cpp
        PSDLoader.cpp
        PSDWriter.cpp
+       DataArray.cpp
        ConfigView.cpp
 ;

############################################################################

Commit:      7983058de34e9b8bf7345f2001a39242a83cf1f9
URL:         http://cgit.haiku-os.org/haiku/commit/?id=7983058
Author:      Gerasim Troeglazov <3dEyes@xxxxxxxxx>
Date:        Thu Dec 19 10:37:09 2013 UTC

PSDTranslator: Rework export module

----------------------------------------------------------------------------

diff --git a/src/add-ons/translators/psd/PSDTranslator.cpp 
b/src/add-ons/translators/psd/PSDTranslator.cpp
index 3324739..a4bdbd9 100644
--- a/src/add-ons/translators/psd/PSDTranslator.cpp
+++ b/src/add-ons/translators/psd/PSDTranslator.cpp
@@ -140,8 +140,10 @@ PSDTranslator::DerivedTranslate(BPositionIO *source,
                }
                case 1:
                {
-                       if (outType == PSD_IMAGE_FORMAT)
-                               return _TranslateFromBits(source, ioExtension, 
outType, target);
+                       if (outType == PSD_IMAGE_FORMAT) {
+                               PSDWriter psdFile(source);
+                               return psdFile.Encode(target);
+                       }
                        return B_NO_TRANSLATOR;
                }
                default:
@@ -151,50 +153,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
 PSDTranslator::DerivedCanHandleImageSize(float width, float height) const
 {
        return B_OK;
diff --git a/src/add-ons/translators/psd/PSDTranslator.h 
b/src/add-ons/translators/psd/PSDTranslator.h
index a4f211f..eaeb82b 100644
--- a/src/add-ons/translators/psd/PSDTranslator.h
+++ b/src/add-ons/translators/psd/PSDTranslator.h
@@ -21,7 +21,7 @@
 #define DOCUMENT_COUNT "/documentCount"
 #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_IN_QUALITY         0.7
@@ -53,9 +53,6 @@ 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/PSDTranslator.rdef 
b/src/add-ons/translators/psd/PSDTranslator.rdef
index 3b8d4c7..1cdd5a4 100644
--- a/src/add-ons/translators/psd/PSDTranslator.rdef
+++ b/src/add-ons/translators/psd/PSDTranslator.rdef
@@ -6,10 +6,10 @@ resource app_signature 
"application/x-vnd.Haiku-PSDTranslator";
 
 resource app_version {
        major  = 1,
-       middle = 1,
-       minor  = 3,
+       middle = 2,
+       minor  = 1,
        variety = 0,
        internal = 0,
-       short_info = "1.1.3",
+       short_info = "1.2.1",
        long_info = "Haiku PSDTranslator Add-Ons."
 };
diff --git a/src/add-ons/translators/psd/PSDWriter.cpp 
b/src/add-ons/translators/psd/PSDWriter.cpp
index 6c3184c..dc18ce5 100644
--- a/src/add-ons/translators/psd/PSDWriter.cpp
+++ b/src/add-ons/translators/psd/PSDWriter.cpp
@@ -8,11 +8,39 @@
 
 #include "BaseTranslator.h"
 #include "PSDWriter.h"
+#include "DataArray.h"
 
 
 PSDWriter::PSDWriter(BPositionIO *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
-PSDWriter::EncodeFromRGBA(BPositionIO *target, uint8 *buff,
-       int32 layers, int32 width, int32 height)
+bool
+PSDWriter::IsReady(void)
 {
-       int32 channelSize = width * height;
-
-       _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();
-       _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); // Channel size
-       }
-
-       if (layers == 4) {
-               _WriteInt16ToStream(target, -1);
-               _WriteUInt32ToStream(target, channelSize + 2); // Alpha channel 
size
-       }
-
-       _WriteUInt32ToStream(target, 0x3842494D); // 8BIM
+       return fReady;
+}
 
-       uint8 blendModeKey[4] = {'n','o','r','m'};
-       _WriteBlockToStream(target, blendModeKey, 4);  // Blend mode norm
 
-       _WriteUInt8ToStream(target, 255); // Alpha
+void
+PSDWriter::SetCompression(int16 compression)
+{
+       fCompression = compression;
+}
 
-       _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);
+status_t
+PSDWriter::Encode(BPositionIO *target)
+{
+       if (!fReady)
+               return B_NO_TRANSLATOR;
+
+       int32 channelSize = fWidth * fHeight;           
+
+       fStream->Seek(fBitmapDataPos, SEEK_SET);
+
+       BDataArray psdChannel[4];
+       
+       for (int i = 0; i < channelSize; i++) {
+               uint8 rgba[4];
+               fStream->Read(rgba, sizeof(uint32));
+               psdChannel[0].Append((uint8)rgba[2]); // Red channel
+               psdChannel[1].Append((uint8)rgba[1]); // Green channel
+               psdChannel[2].Append((uint8)rgba[0]); // Blue channel
+               if (fChannels == 4)
+                       psdChannel[3].Append((uint8)rgba[3]); // Alpha channel
+       }
 
-       _WriteUInt8ToStream(target, 15); // Layer name length
+       // PSD header
+       BDataArray psdHeader(64);
+       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;
+
+       psdLayersSection << (uint8)15; // Layer name length
        uint8 layerName[16] = {"Layer #1       "};
-       _WriteBlockToStream(target, layerName, 15); // Layer name
+       psdLayersSection.Append(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
+       for (int dataChannel = 0; dataChannel < fChannels; dataChannel++) {
+               psdLayersSection << fCompression; // Compression mode
+               psdLayersSection.Append(psdChannel[dataChannel].Buffer(),
+                       psdChannel[dataChannel].Length()); // 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);
+               
+       psdHeader.WriteToStream(target);
+       
+       psdColorModeSection.WriteToStream(target);
+       
+       _WriteUInt32ToStream(target, psdImageResourceSection.Length());
+       psdImageResourceSection.WriteToStream(target);
+
+       _WriteUInt32ToStream(target, psdLayersSection.Length() + 4);
+       _WriteUInt32ToStream(target, psdLayersSection.Length());
+       psdLayersSection.WriteToStream(target);
+
+       // Merged layer
+       _WriteUInt16ToStream(target, fCompression); // Compression mode
+       for (int dataChannel = 0; dataChannel < fChannels; dataChannel++)
+               psdChannel[dataChannel].WriteToStream(target);
 
        return B_OK;
 }
diff --git a/src/add-ons/translators/psd/PSDWriter.h 
b/src/add-ons/translators/psd/PSDWriter.h
index 5f428c7..9703d92 100644
--- a/src/add-ons/translators/psd/PSDWriter.h
+++ b/src/add-ons/translators/psd/PSDWriter.h
@@ -29,8 +29,9 @@ public:
                                        PSDWriter(BPositionIO *stream);
                                        ~PSDWriter();
 
-       status_t                EncodeFromRGBA(BPositionIO *target, uint8 *buff,
-                                               int32 layers, int32 width, 
int32 height);
+       bool                    IsReady(void);  
+       void                    SetCompression(int16 compression);
+       status_t                Encode(BPositionIO *target);
 
 private:
        void                    _WriteInt32ToStream(BPositionIO *stream, int32);
@@ -44,7 +45,17 @@ private:
        void                    _WriteBlockToStream(BPositionIO *stream,
                                                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;
 };
 
 

############################################################################

Revision:    hrev46565
Commit:      5a65c29781873d0e3b18ec9bc15f30623d8a6f08
URL:         http://cgit.haiku-os.org/haiku/commit/?id=5a65c29
Author:      Gerasim Troeglazov <3dEyes@xxxxxxxxx>
Date:        Thu Dec 19 12:20:14 2013 UTC

PSDTranslator: Add RLE compression method for export

----------------------------------------------------------------------------

diff --git a/src/add-ons/translators/psd/PSDTranslator.cpp 
b/src/add-ons/translators/psd/PSDTranslator.cpp
index a4bdbd9..466bad8 100644
--- a/src/add-ons/translators/psd/PSDTranslator.cpp
+++ b/src/add-ons/translators/psd/PSDTranslator.cpp
@@ -142,6 +142,7 @@ PSDTranslator::DerivedTranslate(BPositionIO *source,
                {
                        if (outType == PSD_IMAGE_FORMAT) {
                                PSDWriter psdFile(source);
+                               psdFile.SetCompression(PSD_COMPRESSED_RLE);
                                return psdFile.Encode(target);
                        }
                        return B_NO_TRANSLATOR;
diff --git a/src/add-ons/translators/psd/PSDWriter.cpp 
b/src/add-ons/translators/psd/PSDWriter.cpp
index dc18ce5..11f68ed 100644
--- a/src/add-ons/translators/psd/PSDWriter.cpp
+++ b/src/add-ons/translators/psd/PSDWriter.cpp
@@ -74,16 +74,45 @@ PSDWriter::Encode(BPositionIO *target)
        fStream->Seek(fBitmapDataPos, SEEK_SET);
 
        BDataArray psdChannel[4];
-       
-       for (int i = 0; i < channelSize; i++) {
-               uint8 rgba[4];
-               fStream->Read(rgba, sizeof(uint32));
-               psdChannel[0].Append((uint8)rgba[2]); // Red channel
-               psdChannel[1].Append((uint8)rgba[1]); // Green channel
-               psdChannel[2].Append((uint8)rgba[0]); // Blue channel
-               if (fChannels == 4)
-                       psdChannel[3].Append((uint8)rgba[3]); // Alpha channel
-       }
+       BDataArray psdByteCounts[4];
+
+       if (fCompression == PSD_COMPRESSED_RAW) {
+               for (int i = 0; i < channelSize; i++) {
+                       uint8 rgba[4];
+                       fStream->Read(rgba, sizeof(uint32));
+                       psdChannel[0].Append((uint8)rgba[2]); // Red channel
+                       psdChannel[1].Append((uint8)rgba[1]); // Green channel
+                       psdChannel[2].Append((uint8)rgba[0]); // Blue channel
+                       if (fChannels == 4)
+                               psdChannel[3].Append((uint8)rgba[3]); // Alpha 
channel
+               }
+       } else if (fCompression == PSD_COMPRESSED_RLE) {
+               for (int32 h = 0; h < fHeight; h++) {
+                       BDataArray lineData[4];
+                       
+                       for (int32 w = 0; w < fWidth; w++) {
+                               uint8 rgba[4];
+                               fStream->Read(rgba, sizeof(uint32));
+                               lineData[0].Append((uint8)rgba[2]); // Red 
channel
+                               lineData[1].Append((uint8)rgba[1]); // Green 
channel
+                               lineData[2].Append((uint8)rgba[0]); // Blue 
channel
+                               if (fChannels == 4)
+                                       lineData[3].Append((uint8)rgba[3]); // 
Alpha channel
+                               else
+                                       lineData[3].Append((uint8)255);
+                       }
+                       
+                       for (int channelIdx = 0; channelIdx < fChannels; 
channelIdx++) {
+                               BDataArray *packedLine = 
PackBits(lineData[channelIdx].Buffer(),
+                                       lineData[channelIdx].Length());
+                               
psdByteCounts[channelIdx].Append((uint16)packedLine->Length());
+                               
psdChannel[channelIdx].Append(packedLine->Buffer(),
+                                       packedLine->Length());
+                               delete packedLine;
+                       }
+               }
+       } else
+               return B_NO_TRANSLATOR;
 
        // PSD header
        BDataArray psdHeader(64);
@@ -126,13 +155,25 @@ PSDWriter::Encode(BPositionIO *target)
        psdLayersSection << (uint32)fWidth;     
        psdLayersSection << (uint16)fChannels;
        
-       for (int dataChannel = 0; dataChannel < 3; dataChannel++) {
-               psdLayersSection << (int16)dataChannel; // Channel num
-               psdLayersSection << (uint32)(psdChannel[dataChannel].Length() + 
2);
+       for (int channelIdx = 0; channelIdx < 3; channelIdx++) {
+               psdLayersSection << (int16)channelIdx; // Channel num
+               if (fCompression == PSD_COMPRESSED_RAW) {
+                       psdLayersSection << 
(uint32)(psdChannel[channelIdx].Length()
+                               + sizeof(int16));
+               } else {
+                       psdLayersSection << 
(uint32)(psdChannel[channelIdx].Length()
+                               + psdByteCounts[channelIdx].Length() + 
sizeof(int16));
+               }
        }
        if (fChannels == 4) {
                psdLayersSection << (int16)-1; // Alpha channel id (-1)
-               psdLayersSection << (uint32)(psdChannel[4].Length() + 2);
+               if (fCompression == PSD_COMPRESSED_RAW) {
+                       psdLayersSection << (uint32)(psdChannel[4].Length()
+                               + sizeof(int16));
+               } else {
+                       psdLayersSection << (uint32)(psdChannel[4].Length()
+                               + psdByteCounts[4].Length() + sizeof(int16));   
                
+               }
        }
        psdLayersSection << "8BIM";
        psdLayersSection << "norm"; // Blend mode = norm
@@ -148,12 +189,27 @@ PSDWriter::Encode(BPositionIO *target)
        uint8 layerName[16] = {"Layer #1       "};
        psdLayersSection.Append(layerName, 15); // Layer name
 
-       for (int dataChannel = 0; dataChannel < fChannels; dataChannel++) {
-               psdLayersSection << fCompression; // Compression mode
-               psdLayersSection.Append(psdChannel[dataChannel].Buffer(),
-                       psdChannel[dataChannel].Length()); // Layer image data
+       if (fCompression == PSD_COMPRESSED_RAW) {
+               for (int channelIdx = 0; channelIdx < fChannels; channelIdx++) {
+                       psdLayersSection << fCompression; // Compression mode
+                       psdLayersSection.Append(psdChannel[channelIdx].Buffer(),
+                               psdChannel[channelIdx].Length()); // Layer 
image data
+               }
+       } else {        
+               for (int channelIdx = 0; channelIdx < fChannels; channelIdx++) {
+                       psdLayersSection << fCompression; // Compression mode
+                       
psdLayersSection.Append(psdByteCounts[channelIdx].Buffer(),
+                               psdByteCounts[channelIdx].Length()); // Bytes 
count
+                       psdLayersSection.Append(psdChannel[channelIdx].Buffer(),
+                               psdChannel[channelIdx].Length()); // Layer 
image data
+               }
        }
-               
+
+       if (fCompression == PSD_COMPRESSED_RLE
+               && psdLayersSection.Length() % 2 != 0) {
+               psdLayersSection << (uint8)0;
+       }
+
        psdHeader.WriteToStream(target);
        
        psdColorModeSection.WriteToStream(target);
@@ -161,19 +217,70 @@ PSDWriter::Encode(BPositionIO *target)
        _WriteUInt32ToStream(target, psdImageResourceSection.Length());
        psdImageResourceSection.WriteToStream(target);
 
-       _WriteUInt32ToStream(target, psdLayersSection.Length() + 4);
+       _WriteUInt32ToStream(target, psdLayersSection.Length() + sizeof(int32));
        _WriteUInt32ToStream(target, psdLayersSection.Length());
        psdLayersSection.WriteToStream(target);
 
        // Merged layer
        _WriteUInt16ToStream(target, fCompression); // Compression mode
-       for (int dataChannel = 0; dataChannel < fChannels; dataChannel++)
-               psdChannel[dataChannel].WriteToStream(target);
+       
+       if (fCompression == PSD_COMPRESSED_RLE) {
+               for (int channelIdx = 0; channelIdx < fChannels; channelIdx++)
+                       psdByteCounts[channelIdx].WriteToStream(target);
+       }
+
+       for (int channelIdx = 0; channelIdx < fChannels; channelIdx++)
+               psdChannel[channelIdx].WriteToStream(target);
 
        return B_OK;
 }
 
 
+BDataArray*
+PSDWriter::PackBits(uint8 *buff, int32  len)
+{
+       BDataArray *packedBits = new BDataArray();
+
+       int32  count = len;  
+       len = 0;
+
+       while (count > 0) {
+               int i;
+               for (i = 0; (i < 128) && (buff[0] == buff[i]) && (count - i > 
0); i++);
+               if (i < 2) {
+                       for (i = 0; i < 128; i++) {
+                               bool b1 = buff[i] != buff[i + 1];
+                               bool b3 = buff[i] != buff[i + 2];
+                               bool b2 = count - (i + 2) < 1;
+                               if (count - (i + 1) <= 0)
+                                       break;
+                               if (!(b1 || b2 || b3))
+                                       break;
+                       }
+
+                       if (count == 1)
+                               i = 1;
+
+                       if (i > 0) {
+                               packedBits->Append((uint8)(i - 1));
+                               for (int j = 0; j < i; j++)
+                                       packedBits->Append((uint8)buff[j]);
+                               buff += i;
+                               count -= i;
+                               len += (i + 1);
+                       }
+               } else {
+                       packedBits->Append((uint8)(-(i - 1)));
+                       packedBits->Append((uint8)(*buff));
+                       buff += i;
+                       count -= i;
+                       len += 2;
+               }
+       }
+       return packedBits;
+}
+
+
 void
 PSDWriter::_WriteInt32ToStream(BPositionIO *stream, int32 val)
 {
diff --git a/src/add-ons/translators/psd/PSDWriter.h 
b/src/add-ons/translators/psd/PSDWriter.h
index 9703d92..739add7 100644
--- a/src/add-ons/translators/psd/PSDWriter.h
+++ b/src/add-ons/translators/psd/PSDWriter.h
@@ -23,6 +23,7 @@
 #include <List.h>
 
 #include "PSDLoader.h"
+#include "DataArray.h"
 
 class PSDWriter {
 public:
@@ -44,6 +45,8 @@ private:
                                                uint8 val, size_t count);
        void                    _WriteBlockToStream(BPositionIO *stream,
                                                uint8 *block, size_t count);
+                                               
+       BDataArray*             PackBits(uint8 *buff, int32  len);
 
        BPositionIO     *fStream;       
        size_t                  fBitmapDataPos;


Other related posts:

  • » [haiku-commits] haiku: hrev46565 - src/add-ons/translators/psd - Gerasim Troeglazov