diff --git a/src/add-ons/translators/psd/ConfigView.cpp b/src/add-ons/translators/psd/ConfigView.cpp index 9380080766..f95b41da35 100644 --- a/src/add-ons/translators/psd/ConfigView.cpp +++ b/src/add-ons/translators/psd/ConfigView.cpp @@ -22,18 +22,31 @@ ConfigView::ConfigView(TranslatorSettings *settings) { fSettings = settings; - BPopUpMenu* popupMenu = new BPopUpMenu("popup_compression"); + BPopUpMenu* compressionPopupMenu = new BPopUpMenu("popup_compression"); uint32 currentCompression = fSettings->SetGetInt32(PSD_SETTING_COMPRESSION); - _AddItemToMenu(popupMenu, "Uncompressed", - PSD_COMPRESSED_RAW, currentCompression); - _AddItemToMenu(popupMenu, "RLE", - PSD_COMPRESSED_RLE, currentCompression); + _AddItemToMenu(compressionPopupMenu, "Uncompressed", + MSG_COMPRESSION_CHANGED, PSD_COMPRESSED_RAW, currentCompression); + _AddItemToMenu(compressionPopupMenu, "RLE", + MSG_COMPRESSION_CHANGED, PSD_COMPRESSED_RLE, currentCompression); - fCompressionField = new BMenuField("compression", - "Compression: ", popupMenu); + fCompressionField = new BMenuField("compression", + "Compression: ", compressionPopupMenu); + + BPopUpMenu* versionPopupMenu = new BPopUpMenu("popup_version"); + + uint32 currentVersion = + fSettings->SetGetInt32(PSD_SETTING_VERSION); + + _AddItemToMenu(versionPopupMenu, "Photoshop Document (PSD File)", + MSG_VERSION_CHANGED, PSD_FILE, currentVersion); + _AddItemToMenu(versionPopupMenu, "Photoshop Big Document (PSB File)", + MSG_VERSION_CHANGED, PSB_FILE, currentVersion); + + fVersionField = new BMenuField("version", + "Format: ", versionPopupMenu); BAlignment leftAlignment(B_ALIGN_LEFT, B_ALIGN_VERTICAL_UNSET); @@ -66,6 +79,8 @@ ConfigView::ConfigView(TranslatorSettings *settings) stringView->SetExplicitAlignment(leftAlignment); AddChild(stringView); + AddChild(fVersionField); + AddChild(fCompressionField); AddChild(BSpaceLayoutItem::CreateGlue()); @@ -86,6 +101,7 @@ void ConfigView::AllAttached() { fCompressionField->Menu()->SetTargetForItems(this); + fVersionField->Menu()->SetTargetForItems(this); } @@ -101,6 +117,14 @@ ConfigView::MessageReceived(BMessage* message) } break; } + case MSG_VERSION_CHANGED: { + int32 value; + if (message->FindInt32("value", &value) >= B_OK) { + fSettings->SetGetInt32(PSD_SETTING_VERSION, &value); + fSettings->SaveSettings(); + } + break; + } default: BView::MessageReceived(message); } @@ -109,9 +133,9 @@ ConfigView::MessageReceived(BMessage* message) void ConfigView::_AddItemToMenu(BMenu* menu, const char* label, - uint32 value, uint32 current_value) + uint32 mess, uint32 value, uint32 current_value) { - BMessage* message = new BMessage(MSG_COMPRESSION_CHANGED); + BMessage* message = new BMessage(mess); message->AddInt32("value", value); BMenuItem* item = new BMenuItem(label, message); item->SetMarked(value == current_value); diff --git a/src/add-ons/translators/psd/ConfigView.h b/src/add-ons/translators/psd/ConfigView.h index c390288bff..2ef8f50c4f 100644 --- a/src/add-ons/translators/psd/ConfigView.h +++ b/src/add-ons/translators/psd/ConfigView.h @@ -16,6 +16,7 @@ #include #define MSG_COMPRESSION_CHANGED 'cchg' +#define MSG_VERSION_CHANGED 'vchg' class ConfigView : public BGroupView { public: @@ -27,10 +28,11 @@ class ConfigView : public BGroupView { private: void _AddItemToMenu(BMenu* menu, const char* label, - uint32 value, uint32 current_value); + uint32 mess, uint32 value, uint32 current_value); BTextView* fCopyrightView; BMenuField* fCompressionField; + BMenuField* fVersionField; TranslatorSettings *fSettings; }; diff --git a/src/add-ons/translators/psd/PSDLoader.cpp b/src/add-ons/translators/psd/PSDLoader.cpp index a7e606c6a7..2afc4ac1af 100644 --- a/src/add-ons/translators/psd/PSDLoader.cpp +++ b/src/add-ons/translators/psd/PSDLoader.cpp @@ -46,7 +46,12 @@ PSDLoader::PSDLoader(BPositionIO *src) _SkipStreamBlock(fStream, fImageResourceSectionSize); // Skip [layer and mask] block - _SkipStreamBlock(fStream, _GetInt32FromStream(fStream)); + if (fVersion == PSD_FILE) + _SkipStreamBlock(fStream, _GetInt32FromStream(fStream)); + else if (fVersion == PSB_FILE) + _SkipStreamBlock(fStream, _GetInt64FromStream(fStream)); + else + return; fCompression = _GetInt16FromStream(fStream); @@ -74,8 +79,10 @@ PSDLoader::IsSupported(void) if (!fLoaded) return false; - if (fVersion != 1) + if (fVersion != PSD_FILE + && fVersion != PSB_FILE) { return false; + } if (fChannels < 0 || fChannels > PSD_MAX_CHANNELS) return false; @@ -87,8 +94,9 @@ PSDLoader::IsSupported(void) return false; if (fCompression != PSD_COMPRESSED_RAW - && fCompression != PSD_COMPRESSED_RLE) + && fCompression != PSD_COMPRESSED_RLE) { return false; + } return true; } @@ -207,7 +215,11 @@ PSDLoader::Decode(BPositionIO *target) } case PSD_COMPRESSED_RLE: { - fStreamPos += fHeight * fChannels * 2; + if (fVersion == PSD_FILE) + fStreamPos += fHeight * fChannels * 2; + else if (fVersion == PSB_FILE) + fStreamPos += fHeight * fChannels * 4; + for (int channelIdx = 0; channelIdx < fChannels; channelIdx++) { uint8 *ptr = imageData[channelIdx]; // Read the RLE data. @@ -448,6 +460,15 @@ PSDLoader::Decode(BPositionIO *target) } +int64 +PSDLoader::_GetInt64FromStream(BPositionIO *in) +{ + int64 ret; + in->Read(&ret, sizeof(int64)); + return B_BENDIAN_TO_HOST_INT64(ret); +} + + int32 PSDLoader::_GetInt32FromStream(BPositionIO *in) { diff --git a/src/add-ons/translators/psd/PSDLoader.h b/src/add-ons/translators/psd/PSDLoader.h index 4e6a85263b..dca0ed49f6 100644 --- a/src/add-ons/translators/psd/PSDLoader.h +++ b/src/add-ons/translators/psd/PSDLoader.h @@ -25,6 +25,12 @@ #define PSD_MAX_CHANNELS 16 +enum psd_version { + PSD_FILE = 1, + PSB_FILE = 2 +}; + + enum psd_compressed_type { PSD_COMPRESSED_RAW = 0, PSD_COMPRESSED_RLE = 1 @@ -72,6 +78,7 @@ public: BString ColorFormatName(void); private: + int64 _GetInt64FromStream(BPositionIO *in); int32 _GetInt32FromStream(BPositionIO *in); int16 _GetInt16FromStream(BPositionIO *in); uint8 _GetUInt8FromStream(BPositionIO *in); diff --git a/src/add-ons/translators/psd/PSDTranslator.cpp b/src/add-ons/translators/psd/PSDTranslator.cpp index 52beccbd91..061bfb6c26 100644 --- a/src/add-ons/translators/psd/PSDTranslator.cpp +++ b/src/add-ons/translators/psd/PSDTranslator.cpp @@ -61,7 +61,8 @@ static const translation_format sOutputFormats[] = { static const TranSetting sDefaultSettings[] = { {B_TRANSLATOR_EXT_HEADER_ONLY, TRAN_SETTING_BOOL, false}, {B_TRANSLATOR_EXT_DATA_ONLY, TRAN_SETTING_BOOL, false}, - {PSD_SETTING_COMPRESSION, TRAN_SETTING_INT32, PSD_COMPRESSED_RLE} + {PSD_SETTING_COMPRESSION, TRAN_SETTING_INT32, PSD_COMPRESSED_RLE}, + {PSD_SETTING_VERSION, TRAN_SETTING_INT32, PSD_FILE} }; const uint32 kNumInputFormats = sizeof(sInputFormats) @@ -141,11 +142,17 @@ PSDTranslator::DerivedTranslate(BPositionIO *source, } case 1: { - if (outType == PSD_IMAGE_FORMAT) { + if (outType == PSD_IMAGE_FORMAT) { PSDWriter psdFile(source); + uint32 compression = fSettings->SetGetInt32(PSD_SETTING_COMPRESSION); + uint32 version = + fSettings->SetGetInt32(PSD_SETTING_VERSION); + psdFile.SetCompression(compression); + psdFile.SetVersion(version); + if (psdFile.IsReady()) return psdFile.Encode(target); } diff --git a/src/add-ons/translators/psd/PSDTranslator.h b/src/add-ons/translators/psd/PSDTranslator.h index 6b7ce32eaa..38142b11d8 100644 --- a/src/add-ons/translators/psd/PSDTranslator.h +++ b/src/add-ons/translators/psd/PSDTranslator.h @@ -22,8 +22,9 @@ #define DOCUMENT_INDEX "/documentIndex" #define PSD_SETTING_COMPRESSION "psd /compression" +#define PSD_SETTING_VERSION "psd /psdversion" -#define PSD_TRANSLATOR_VERSION B_TRANSLATION_MAKE_VERSION(1, 2, 1) +#define PSD_TRANSLATOR_VERSION B_TRANSLATION_MAKE_VERSION(1, 3, 0) #define PSD_IMAGE_FORMAT 'PSD ' #define PSD_IN_QUALITY 0.7 diff --git a/src/add-ons/translators/psd/PSDTranslator.rdef b/src/add-ons/translators/psd/PSDTranslator.rdef index 1cdd5a4f1e..e5bfee4967 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 = 2, - minor = 1, + middle = 3, + minor = 0, variety = 0, internal = 0, - short_info = "1.2.1", + short_info = "1.3.0", 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 b39d5fb500..df0c6b99c8 100644 --- a/src/add-ons/translators/psd/PSDWriter.cpp +++ b/src/add-ons/translators/psd/PSDWriter.cpp @@ -33,11 +33,14 @@ PSDWriter::PSDWriter(BPositionIO *stream) 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); + if (fColorSpace != B_RGB32 && fColorSpace != B_RGBA32) + return; fChannels = fColorSpace == B_RGB32 ? 3 : 4; fWidth = bounds.IntegerWidth() + 1; fHeight = bounds.IntegerHeight() + 1; + fVersion = PSD_FILE; fCompression = PSD_COMPRESSED_RAW; fReady = true; @@ -63,6 +66,13 @@ PSDWriter::SetCompression(int16 compression) } +void +PSDWriter::SetVersion(int16 ver) +{ + fVersion = ver; +} + + status_t PSDWriter::Encode(BPositionIO *target) { @@ -98,16 +108,18 @@ PSDWriter::Encode(BPositionIO *target) 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()); + + if (fVersion == PSD_FILE) + psdByteCounts[channelIdx].Append((uint16)packedLine->Length()); + else + psdByteCounts[channelIdx].Append((uint32)packedLine->Length()); + + psdChannel[channelIdx].Append(*packedLine); delete packedLine; } } @@ -117,7 +129,7 @@ PSDWriter::Encode(BPositionIO *target) // PSD header BDataArray psdHeader(64); psdHeader << "8BPS"; // Signature - psdHeader << (uint16)1; // Version = 1 + psdHeader << (uint16)fVersion; // Version psdHeader.Repeat(0, 6); // Reserved psdHeader << fChannels; // Channels psdHeader << fHeight << fWidth; // Image size @@ -155,26 +167,31 @@ PSDWriter::Encode(BPositionIO *target) psdLayersSection << (uint32)fWidth; psdLayersSection << (uint16)fChannels; - for (int channelIdx = 0; channelIdx < 3; channelIdx++) { - psdLayersSection << (int16)channelIdx; // Channel num + for (int channelIdx = 0; channelIdx < fChannels; channelIdx++) { + if (channelIdx == 3) + psdLayersSection << (int16)-1; // Alpha channel id (-1) + else + psdLayersSection << (int16)channelIdx; // Channel num + if (fCompression == PSD_COMPRESSED_RAW) { - psdLayersSection << (uint32)(psdChannel[channelIdx].Length() - + sizeof(int16)); + if (fVersion == PSD_FILE) { + psdLayersSection << (uint32)(psdChannel[channelIdx].Length() + + sizeof(int16)); + } else { + psdLayersSection << (uint64)(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) - if (fCompression == PSD_COMPRESSED_RAW) { - psdLayersSection << (uint32)(psdChannel[3].Length() - + sizeof(int16)); - } else { - psdLayersSection << (uint32)(psdChannel[3].Length() - + psdByteCounts[3].Length() + sizeof(int16)); + if (fVersion == PSD_FILE) { + psdLayersSection << (uint32)(psdChannel[channelIdx].Length() + + psdByteCounts[channelIdx].Length() + sizeof(int16)); + } else { + psdLayersSection << (uint64)(psdChannel[channelIdx].Length() + + psdByteCounts[channelIdx].Length() + sizeof(int16)); + } } } + psdLayersSection << "8BIM"; psdLayersSection << "norm"; // Blend mode = norm psdLayersSection << (uint8)255; // Opacity @@ -192,16 +209,13 @@ PSDWriter::Encode(BPositionIO *target) 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 + psdLayersSection.Append(psdChannel[channelIdx]); // Channel 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 + psdLayersSection.Append(psdByteCounts[channelIdx]); // Bytes count + psdLayersSection.Append(psdChannel[channelIdx]); // Channel data } } @@ -217,8 +231,13 @@ PSDWriter::Encode(BPositionIO *target) _WriteUInt32ToStream(target, psdImageResourceSection.Length()); psdImageResourceSection.WriteToStream(target); - _WriteUInt32ToStream(target, psdLayersSection.Length() + sizeof(int32)); - _WriteUInt32ToStream(target, psdLayersSection.Length()); + if (fVersion == PSD_FILE) { + _WriteUInt32ToStream(target, psdLayersSection.Length() + sizeof(int32)); + _WriteUInt32ToStream(target, psdLayersSection.Length()); + } else { + _WriteUInt64ToStream(target, psdLayersSection.Length() + sizeof(int64)); + _WriteUInt64ToStream(target, psdLayersSection.Length()); + } psdLayersSection.WriteToStream(target); // Merged layer @@ -281,6 +300,22 @@ PSDWriter::PackBits(uint8 *buff, int32 len) } +void +PSDWriter::_WriteInt64ToStream(BPositionIO *stream, int64 val) +{ + val = B_HOST_TO_BENDIAN_INT64(val); + stream->Write(&val, sizeof(int32)); +} + + +void +PSDWriter::_WriteUInt64ToStream(BPositionIO *stream, uint64 val) +{ + val = B_HOST_TO_BENDIAN_INT64(val); + stream->Write(&val, sizeof(uint64)); +} + + 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 739add7974..be9712890f 100644 --- a/src/add-ons/translators/psd/PSDWriter.h +++ b/src/add-ons/translators/psd/PSDWriter.h @@ -30,11 +30,14 @@ public: PSDWriter(BPositionIO *stream); ~PSDWriter(); - bool IsReady(void); + bool IsReady(void); void SetCompression(int16 compression); + void SetVersion(int16 version); status_t Encode(BPositionIO *target); private: + void _WriteInt64ToStream(BPositionIO *stream, int64); + void _WriteUInt64ToStream(BPositionIO *stream, uint64); void _WriteInt32ToStream(BPositionIO *stream, int32); void _WriteUInt32ToStream(BPositionIO *stream, uint32); void _WriteInt16ToStream(BPositionIO *stream, int16); @@ -57,6 +60,7 @@ private: int32 fWidth; int32 fHeight; int16 fCompression; + int16 fVersion; bool fReady; };