xref: /haiku/src/add-ons/translators/psd/PSDTranslator.cpp (revision a38a6547d75b31d9a470d2eda07e2ca27ba673fe)
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 
129 	switch (baseType) {
130 		case 0:
131 		{
132 			if (outType != B_TRANSLATOR_BITMAP)
133 				return B_NO_TRANSLATOR;
134 
135 			PSDLoader psdFile(source);
136 			if (!psdFile.IsLoaded())
137 				return B_NO_TRANSLATOR;
138 
139 			return psdFile.Decode(target);
140 		}
141 		case 1:
142 		{
143 			if (outType == PSD_IMAGE_FORMAT)
144 				return _TranslateFromBits(source, ioExtension, outType, target);
145 			return B_NO_TRANSLATOR;
146 		}
147 		default:
148 			return B_NO_TRANSLATOR;
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 
169 	uint32 width = bitsHeader.bounds.IntegerWidth() + 1;
170 	uint32 height = bitsHeader.bounds.IntegerHeight() + 1;
171 
172 	int32 layerSize = height * width;
173 	int32 layersCount = bitsHeader.colors == B_RGB32 ? 3 : 4;
174 
175 	uint8 *buff = new uint8[layerSize * layersCount];
176 
177 	uint8 *ptr = buff;
178 	for (int i = 0; i < layerSize; i++) {
179 		uint8 rgba[4];
180 		stream->Read(rgba, sizeof(uint32));
181 		ptr[i] = rgba[2];
182 		ptr[i+layerSize] = rgba[1];
183 		ptr[i+layerSize+layerSize] = rgba[0];
184 		if (layersCount == 4)
185 			ptr[i+layerSize+layerSize+layerSize] = rgba[3];
186 	}
187 
188 	PSDWriter psdFile(stream);
189 	psdFile.EncodeFromRGBA(target, buff, layersCount, width, height);
190 
191 	delete buff;
192 
193 	return B_OK;
194 }
195 
196 
197 status_t
198 PSDTranslator::DerivedCanHandleImageSize(float width, float height) const
199 {
200 	return B_OK;
201 }
202 
203 
204 BView *
205 PSDTranslator::NewConfigView(TranslatorSettings *settings)
206 {
207 	return new ConfigView(settings);
208 }
209 
210 
211 BTranslator *
212 make_nth_translator(int32 n, image_id you, uint32 flags, ...)
213 {
214 	if (n != 0)
215 		return NULL;
216 
217 	return new PSDTranslator();
218 }
219 
220