xref: /haiku/src/add-ons/translators/psd/PSDTranslator.cpp (revision 3459199e5dd0e7fbf1c93fd1aa270ecb5d490fa1)
1 /*
2  * Copyright 2013, Gerasim Troeglazov, 3dEyes@gmail.com. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <string.h>
10 
11 #include "ConfigView.h"
12 #include "PSDTranslator.h"
13 #include "PSDLoader.h"
14 #include "PSDWriter.h"
15 
16 const char *kDocumentCount = "/documentCount";
17 const char *kDocumentIndex = "/documentIndex";
18 
19 #define kPSDMimeType "image/vnd.adobe.photoshop"
20 #define kPSDName "Photoshop image"
21 
22 static const translation_format sInputFormats[] = {
23 	{
24 		B_TRANSLATOR_BITMAP,
25 		B_TRANSLATOR_BITMAP,
26 		BITS_IN_QUALITY,
27 		BITS_IN_CAPABILITY,
28 		"image/x-be-bitmap",
29 		"Be Bitmap Format (PSDTranslator)"
30 	},
31 	{
32 		PSD_IMAGE_FORMAT,
33 		B_TRANSLATOR_BITMAP,
34 		PSD_IN_QUALITY,
35 		PSD_IN_CAPABILITY,
36 		kPSDMimeType,
37 		kPSDName
38 	}
39 };
40 
41 static const translation_format sOutputFormats[] = {
42 	{
43 		B_TRANSLATOR_BITMAP,
44 		B_TRANSLATOR_BITMAP,
45 		BITS_OUT_QUALITY,
46 		BITS_OUT_CAPABILITY,
47 		"image/x-be-bitmap",
48 		"Be Bitmap Format (PSDTranslator)"
49 	},
50 	{
51 		PSD_IMAGE_FORMAT,
52 		B_TRANSLATOR_BITMAP,
53 		PSD_OUT_QUALITY,
54 		PSD_OUT_CAPABILITY,
55 		kPSDMimeType,
56 		kPSDName
57 	}
58 };
59 
60 
61 static const TranSetting sDefaultSettings[] = {
62 	{B_TRANSLATOR_EXT_HEADER_ONLY, TRAN_SETTING_BOOL, false},
63 	{B_TRANSLATOR_EXT_DATA_ONLY, TRAN_SETTING_BOOL, false}
64 };
65 
66 const uint32 kNumInputFormats = sizeof(sInputFormats)
67 	/ sizeof(translation_format);
68 const uint32 kNumOutputFormats = sizeof(sOutputFormats)
69 	/ sizeof(translation_format);
70 const uint32 kNumDefaultSettings = sizeof(sDefaultSettings)
71 	/ sizeof(TranSetting);
72 
73 
74 PSDTranslator::PSDTranslator()
75 	: BaseTranslator(kPSDName,
76 		"Photoshop image translator",
77 		PSD_TRANSLATOR_VERSION,
78 		sInputFormats, kNumInputFormats,
79 		sOutputFormats, kNumOutputFormats,
80 		"PSDTranslator",
81 		sDefaultSettings, kNumDefaultSettings,
82 		B_TRANSLATOR_BITMAP, PSD_IMAGE_FORMAT)
83 {
84 }
85 
86 
87 PSDTranslator::~PSDTranslator()
88 {
89 }
90 
91 
92 status_t
93 PSDTranslator::DerivedIdentify(BPositionIO *stream,
94 	const translation_format *format, BMessage *ioExtension,
95 	translator_info *info, uint32 outType)
96 {
97 	if (!outType)
98 		outType = B_TRANSLATOR_BITMAP;
99 	if (outType != B_TRANSLATOR_BITMAP && outType != PSD_IMAGE_FORMAT)
100 		return B_NO_TRANSLATOR;
101 
102 	PSDLoader psdFile(stream);
103 	if (!psdFile.IsSupported())
104 		return B_ILLEGAL_DATA;
105 
106 	info->type = PSD_IMAGE_FORMAT;
107 	info->group = B_TRANSLATOR_BITMAP;
108 	info->quality = PSD_IN_QUALITY;
109 	info->capability = PSD_IN_CAPABILITY;
110 	BString name(kPSDName);
111 	name << " (" << psdFile.ColorFormatName() << ")";
112 	strcpy(info->name, name.String());
113 	strcpy(info->MIME, kPSDMimeType);
114 
115 	return B_OK;
116 }
117 
118 
119 status_t
120 PSDTranslator::DerivedTranslate(BPositionIO *source,
121 	const translator_info *info, BMessage *ioExtension,
122 	uint32 outType, BPositionIO *target, int32 baseType)
123 {
124 	if (outType != B_TRANSLATOR_BITMAP
125 		&& outType != PSD_IMAGE_FORMAT)
126 		return B_NO_TRANSLATOR;
127 
128 	switch (baseType) {
129 		case 0:
130 		{
131 			if (outType != B_TRANSLATOR_BITMAP)
132 				return B_NO_TRANSLATOR;
133 
134 			PSDLoader psdFile(source);
135 			if (!psdFile.IsLoaded())
136 				return B_NO_TRANSLATOR;
137 
138 			return psdFile.Decode(target);
139 		}
140 		case 1:
141 		{
142 			if (outType == PSD_IMAGE_FORMAT)
143 				return _TranslateFromBits(source, ioExtension, outType, target);
144 			return B_NO_TRANSLATOR;
145 		}
146 		default:
147 			return B_NO_TRANSLATOR;
148 	}
149 }
150 
151 
152 
153 status_t
154 PSDTranslator::_TranslateFromBits(BPositionIO* stream,
155 					BMessage* ioExtension, uint32 outType,
156 					BPositionIO* target)
157 {
158 	TranslatorBitmap bitsHeader;
159 	status_t result;
160 	result = identify_bits_header(stream, NULL, &bitsHeader);
161 	if (result != B_OK)
162 		return result;
163 
164 	if (bitsHeader.colors != B_RGB32
165 		&& bitsHeader.colors != B_RGBA32)
166 		return B_NO_TRANSLATOR;
167 
168 	uint32 width = bitsHeader.bounds.IntegerWidth() + 1;
169 	uint32 height = bitsHeader.bounds.IntegerHeight() + 1;
170 
171 	int32 layerSize = height * width;
172 	int32 layersCount = bitsHeader.colors == B_RGB32 ? 3 : 4;
173 
174 	uint8 *buff = new uint8[layerSize * layersCount];
175 
176 	uint8 *ptr = buff;
177 	for(int i = 0; i < layerSize; i++) {
178 		uint8 rgba[4];
179 		stream->Read(rgba, sizeof(uint32));
180 		ptr[i] = rgba[2];
181 		ptr[i+layerSize] = rgba[1];
182 		ptr[i+layerSize+layerSize] = rgba[0];
183 		if (layersCount == 4)
184 			ptr[i+layerSize+layerSize+layerSize] = rgba[3];
185 	}
186 
187 	PSDWriter psdFile(stream);
188 	psdFile.EncodeFromRGBA(target, buff, layersCount, width, height);
189 
190 	delete buff;
191 
192 	return B_OK;
193 }
194 
195 
196 status_t
197 PSDTranslator::DerivedCanHandleImageSize(float width, float height) const
198 {
199 	return B_OK;
200 }
201 
202 
203 BView *
204 PSDTranslator::NewConfigView(TranslatorSettings *settings)
205 {
206 	return new ConfigView(settings);
207 }
208 
209 
210 BTranslator *
211 make_nth_translator(int32 n, image_id you, uint32 flags, ...)
212 {
213 	if (n != 0)
214 		return NULL;
215 
216 	return new PSDTranslator();
217 }
218 
219