xref: /haiku/src/add-ons/translators/raw/RAWTranslator.cpp (revision 1acbe440b8dd798953bec31d18ee589aa3f71b73)
1 /*
2  * Copyright 2007, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "RAWTranslator.h"
8 #include "ConfigView.h"
9 #include "RAW.h"
10 
11 #include <TranslatorRoster.h>
12 
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include <string.h>
16 
17 
18 // Extensions that ShowImage supports
19 const char *kDocumentCount = "/documentCount";
20 const char *kDocumentIndex = "/documentIndex";
21 
22 // The input formats that this translator supports.
23 translation_format sInputFormats[] = {
24 	{
25 		RAW_IMAGE_FORMAT,
26 		B_TRANSLATOR_BITMAP,
27 		RAW_IN_QUALITY,
28 		RAW_IN_CAPABILITY,
29 		"image/x-vnd.adobe-dng",
30 		"Adobe Digital Negative"
31 	},
32 	{
33 		RAW_IMAGE_FORMAT,
34 		B_TRANSLATOR_BITMAP,
35 		RAW_IN_QUALITY,
36 		RAW_IN_CAPABILITY,
37 		"image/x-vnd.photo-raw",
38 		"Digital Photo RAW image"
39 	},
40 };
41 
42 // The output formats that this translator supports.
43 translation_format sOutputFormats[] = {
44 	{
45 		B_TRANSLATOR_BITMAP,
46 		B_TRANSLATOR_BITMAP,
47 		BITS_OUT_QUALITY,
48 		BITS_OUT_CAPABILITY,
49 		"x-be-bitmap",
50 		"Be Bitmap image"
51 	},
52 };
53 
54 // Default settings for the Translator
55 static TranSetting sDefaultSettings[] = {
56 	{B_TRANSLATOR_EXT_HEADER_ONLY, TRAN_SETTING_BOOL, false},
57 	{B_TRANSLATOR_EXT_DATA_ONLY, TRAN_SETTING_BOOL, false}
58 };
59 
60 const uint32 kNumInputFormats = sizeof(sInputFormats) / sizeof(translation_format);
61 const uint32 kNumOutputFormats = sizeof(sOutputFormats) / sizeof(translation_format);
62 const uint32 kNumDefaultSettings = sizeof(sDefaultSettings) / sizeof(TranSetting);
63 
64 
65 RAWTranslator::RAWTranslator()
66 	: BaseTranslator("Raw Images", "Raw Image Translator",
67 		RAW_TRANSLATOR_VERSION,
68 		sInputFormats, kNumInputFormats,
69 		sOutputFormats, kNumOutputFormats,
70 		"RawTranslator_Settings",
71 		sDefaultSettings, kNumDefaultSettings,
72 		B_TRANSLATOR_BITMAP, RAW_IMAGE_FORMAT)
73 {
74 }
75 
76 
77 RAWTranslator::~RAWTranslator()
78 {
79 }
80 
81 
82 status_t
83 RAWTranslator::DerivedIdentify(BPositionIO *stream,
84 	const translation_format *format, BMessage *settings,
85 	translator_info *info, uint32 outType)
86 {
87 	if (!outType)
88 		outType = B_TRANSLATOR_BITMAP;
89 	if (outType != B_TRANSLATOR_BITMAP)
90 		return B_NO_TRANSLATOR;
91 
92 	DCRaw raw(*stream);
93 	status_t status;
94 
95 	try {
96 		status = raw.Identify();
97 	} catch (status_t error) {
98 		status = error;
99 	}
100 
101 	if (status < B_OK)
102 		return B_NO_TRANSLATOR;
103 
104 	image_meta_info meta;
105 	raw.GetMetaInfo(meta);
106 
107 	if (settings) {
108 		int32 count = raw.CountImages();
109 
110 		// Add page count to ioExtension
111 		settings->RemoveName(kDocumentCount);
112 		settings->AddInt32(kDocumentCount, count);
113 
114 		// Check if a document index has been specified
115 		int32 index;
116 		if (settings->FindInt32(kDocumentIndex, &index) == B_OK)
117 			index--;
118 		else
119 			index = 0;
120 
121 		if (index < 0 || index >= count)
122 			return B_NO_TRANSLATOR;
123 	}
124 
125 	info->type = RAW_IMAGE_FORMAT;
126 	info->group = B_TRANSLATOR_BITMAP;
127 	info->quality = RAW_IN_QUALITY;
128 	info->capability = RAW_IN_CAPABILITY;
129 	snprintf(info->name, sizeof(info->name), "%s RAW image", meta.manufacturer);
130 	strcpy(info->MIME, "image/x-vnd.photo-raw");
131 
132 	return B_OK;
133 }
134 
135 
136 status_t
137 RAWTranslator::DerivedTranslate(BPositionIO* source,
138 	const translator_info* info, BMessage* settings,
139 	uint32 outType, BPositionIO* target, int32 baseType)
140 {
141 	if (!outType)
142 		outType = B_TRANSLATOR_BITMAP;
143 	if (outType != B_TRANSLATOR_BITMAP || baseType != 0)
144 		return B_NO_TRANSLATOR;
145 
146 	bool headerOnly = false;
147 	if (settings != NULL)
148 		settings->FindBool(B_TRANSLATOR_EXT_HEADER_ONLY, &headerOnly);
149 
150 	DCRaw raw(*source);
151 
152 	int32 imageIndex = 0;
153 	uint8* buffer = NULL;
154 	size_t bufferSize;
155 	status_t status;
156 
157 	try {
158 		status = raw.Identify();
159 
160 		if (status == B_OK && settings) {
161 			// Check if a document index has been specified
162 			if (settings->FindInt32(kDocumentIndex, &imageIndex) == B_OK)
163 				imageIndex--;
164 			else
165 				imageIndex = 0;
166 
167 			if (imageIndex < 0 || imageIndex >= (int32)raw.CountImages())
168 				status = B_BAD_VALUE;
169 		}
170 		if (status == B_OK && !headerOnly)
171 			status = raw.ReadImageAt(imageIndex, buffer, bufferSize);
172 	} catch (status_t error) {
173 		status = error;
174 	}
175 
176 	if (status < B_OK)
177 		return B_NO_TRANSLATOR;
178 
179 	image_meta_info meta;
180 	raw.GetMetaInfo(meta);
181 
182 	image_data_info data;
183 	raw.ImageAt(imageIndex, data);
184 
185 	if (!data.is_raw) {
186 		// let others handle embedded JPEG data
187 		BMemoryIO io(buffer, bufferSize);
188 		BTranslatorRoster* roster = BTranslatorRoster::Default();
189 		return roster->Translate(&io, NULL, settings, target, outType);
190 	}
191 
192 	uint32 dataSize = data.output_width * 4 * data.output_height;
193 
194 	TranslatorBitmap header;
195 	header.magic = B_TRANSLATOR_BITMAP;
196 	header.bounds.Set(0, 0, data.output_width - 1, data.output_height - 1);
197 	header.rowBytes = data.output_width * 4;
198 	header.colors = B_RGB32;
199 	header.dataSize = dataSize;
200 
201 	// write out Be's Bitmap header
202 	swap_data(B_UINT32_TYPE, &header, sizeof(TranslatorBitmap),
203 		B_SWAP_HOST_TO_BENDIAN);
204 	ssize_t bytesWritten = target->Write(&header, sizeof(TranslatorBitmap));
205 	if (bytesWritten < B_OK)
206 		return bytesWritten;
207 
208 	if ((size_t)bytesWritten != sizeof(TranslatorBitmap))
209 		return B_IO_ERROR;
210 
211 	if (headerOnly)
212 		return B_OK;
213 
214 	bytesWritten = target->Write(buffer, dataSize);
215 	if (bytesWritten < B_OK)
216 		return bytesWritten;
217 
218 	if ((size_t)bytesWritten != dataSize)
219 		return B_IO_ERROR;
220 
221 	return B_OK;
222 }
223 
224 
225 BView *
226 RAWTranslator::NewConfigView(TranslatorSettings *settings)
227 {
228 	return new ConfigView(BRect(0, 0, 225, 175));
229 }
230 
231 
232 //	#pragma mark -
233 
234 
235 BTranslator *
236 make_nth_translator(int32 n, image_id you, uint32 flags, ...)
237 {
238 	if (n != 0)
239 		return NULL;
240 
241 	return new RAWTranslator();
242 }
243 
244