PSDTranslator: Add Photoshop Big (PSB) format support
This commit is contained in:
parent
a47ae0d08e
commit
6d7acad27d
@ -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);
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <MenuField.h>
|
||||
|
||||
#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;
|
||||
};
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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."
|
||||
};
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user