xref: /haiku/src/add-ons/translators/sgi/SGITranslator.cpp (revision 7749d0bb0c358a3279b1b9cc76d8376e900130a5)
1 /*****************************************************************************/
2 // SGITranslator
3 // Written by Stephan Aßmus
4 // based on TIFFTranslator written mostly by
5 // Michael Wilber
6 //
7 // SGITranslator.cpp
8 //
9 // This BTranslator based object is for opening and writing
10 // SGI images.
11 //
12 //
13 // Copyright (c) 2003-2009 Haiku, Inc. All rights reserved.
14 //
15 // Permission is hereby granted, free of charge, to any person obtaining a
16 // copy of this software and associated documentation files (the "Software"),
17 // to deal in the Software without restriction, including without limitation
18 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
19 // and/or sell copies of the Software, and to permit persons to whom the
20 // Software is furnished to do so, subject to the following conditions:
21 //
22 // The above copyright notice and this permission notice shall be included
23 // in all copies or substantial portions of the Software.
24 //
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
26 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
28 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
30 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
31 // DEALINGS IN THE SOFTWARE.
32 /*****************************************************************************/
33 //
34 // How this works:
35 //
36 // libtiff has a special version of SGIOpen() that gets passed custom
37 // functions for reading writing etc. and a handle. This handle in our case
38 // is a BPositionIO object, which libtiff passes on to the functions for reading
39 // writing etc. So when operations are performed on the SGI* handle that is
40 // returned by SGIOpen(), libtiff uses the special reading writing etc
41 // functions so that all stream io happens on the BPositionIO object.
42 
43 #include <new>
44 #include <stdio.h>
45 #include <string.h>
46 #include <syslog.h>
47 
48 #include <Catalog.h>
49 #include <OS.h>
50 
51 #include "SGIImage.h"
52 #include "SGITranslator.h"
53 #include "SGIView.h"
54 
55 using std::nothrow;
56 
57 #undef B_TRANSLATE_CONTEXT
58 #define B_TRANSLATE_CONTEXT "SGITranslator"
59 
60 
61 // The input formats that this translator supports.
62 static const translation_format sInputFormats[] = {
63 	{
64 		B_TRANSLATOR_BITMAP,
65 		B_TRANSLATOR_BITMAP,
66 		BBT_IN_QUALITY,
67 		BBT_IN_CAPABILITY,
68 		"image/x-be-bitmap",
69 		"Be Bitmap Format (SGITranslator)"
70 	},
71 	{
72 		SGI_FORMAT,
73 		B_TRANSLATOR_BITMAP,
74 		SGI_IN_QUALITY,
75 		SGI_IN_CAPABILITY,
76 		"image/sgi",
77 		"SGI image"
78 	}
79 };
80 
81 // The output formats that this translator supports.
82 static const translation_format sOutputFormats[] = {
83 	{
84 		B_TRANSLATOR_BITMAP,
85 		B_TRANSLATOR_BITMAP,
86 		BBT_OUT_QUALITY,
87 		BBT_OUT_CAPABILITY,
88 		"image/x-be-bitmap",
89 		"Be Bitmap Format (SGITranslator)"
90 	},
91 	{
92 		SGI_FORMAT,
93 		B_TRANSLATOR_BITMAP,
94 		SGI_OUT_QUALITY,
95 		SGI_OUT_CAPABILITY,
96 		"image/sgi",
97 		"SGI image"
98 	}
99 };
100 
101 // Default settings for the Translator
102 static const TranSetting sDefaultSettings[] = {
103 	{B_TRANSLATOR_EXT_HEADER_ONLY, TRAN_SETTING_BOOL, false},
104 	{B_TRANSLATOR_EXT_DATA_ONLY, TRAN_SETTING_BOOL, false},
105 	{SGI_SETTING_COMPRESSION, TRAN_SETTING_INT32, SGI_COMP_RLE}
106 		// compression is set to RLE by default
107 };
108 
109 const uint32 kNumInputFormats = sizeof(sInputFormats) / sizeof(translation_format);
110 const uint32 kNumOutputFormats = sizeof(sOutputFormats) / sizeof(translation_format);
111 const uint32 kNumDefaultSettings = sizeof(sDefaultSettings) / sizeof(TranSetting);
112 
113 
114 // ---------------------------------------------------------------
115 // make_nth_translator
116 //
117 // Creates a SGITranslator object to be used by BTranslatorRoster
118 //
119 // Preconditions:
120 //
121 // Parameters: n,		The translator to return. Since
122 //						SGITranslator only publishes one
123 //						translator, it only returns a
124 //						SGITranslator if n == 0
125 //
126 //             you, 	The image_id of the add-on that
127 //						contains code (not used).
128 //
129 //             flags,	Has no meaning yet, should be 0.
130 //
131 // Postconditions:
132 //
133 // Returns: NULL if n is not zero,
134 //          a new SGITranslator if n is zero
135 // ---------------------------------------------------------------
136 BTranslator *
137 make_nth_translator(int32 n, image_id you, uint32 flags, ...)
138 {
139 	if (!n)
140 		return new SGITranslator();
141 	else
142 		return NULL;
143 }
144 
145 // ---------------------------------------------------------------
146 // Constructor
147 //
148 // Sets up the version info and the name of the translator so that
149 // these values can be returned when they are requested.
150 //
151 // Preconditions:
152 //
153 // Parameters:
154 //
155 // Postconditions:
156 //
157 // Returns:
158 // ---------------------------------------------------------------
159 SGITranslator::SGITranslator()
160 	:
161 	BaseTranslator(B_TRANSLATE("SGI images"),
162 		B_TRANSLATE("SGI image translator"),
163 		SGI_TRANSLATOR_VERSION,
164 		sInputFormats, kNumInputFormats,
165 		sOutputFormats, kNumOutputFormats,
166 		"SGITranslator_Settings",
167 		sDefaultSettings, kNumDefaultSettings,
168 		B_TRANSLATOR_BITMAP, SGI_FORMAT)
169 {
170 }
171 
172 // ---------------------------------------------------------------
173 // Destructor
174 //
175 // Does nothing
176 //
177 // Preconditions:
178 //
179 // Parameters:
180 //
181 // Postconditions:
182 //
183 // Returns:
184 // ---------------------------------------------------------------
185 SGITranslator::~SGITranslator()
186 {
187 }
188 
189 status_t
190 identify_sgi_header(BPositionIO *inSource, translator_info *outInfo, uint32 outType,
191 	SGIImage **poutSGIImage = NULL)
192 {
193 	status_t status = B_NO_MEMORY;
194 	// construct new SGIImage object and set it to the provided BPositionIO
195 	SGIImage* sgiImage = new(nothrow) SGIImage();
196 	if (sgiImage)
197 		status = sgiImage->SetTo(inSource);
198 
199 	if (status >= B_OK) {
200 		if (outInfo) {
201 			outInfo->type = SGI_FORMAT;
202 			outInfo->group = B_TRANSLATOR_BITMAP;
203 			outInfo->quality = SGI_IN_QUALITY;
204 			outInfo->capability = SGI_IN_CAPABILITY;
205 			strcpy(outInfo->MIME, "image/sgi");
206 			strcpy(outInfo->name, B_TRANSLATE("SGI image"));
207 		}
208 	} else {
209 		delete sgiImage;
210 		sgiImage = NULL;
211 	}
212 	if (!poutSGIImage)
213 		// close SGIImage if caller is not interested in SGIImage handle
214 		delete sgiImage;
215 	else
216 		// leave SGIImage open (if it is) and return handle if caller needs it
217 		*poutSGIImage = sgiImage;
218 
219 	return status;
220 }
221 
222 // ---------------------------------------------------------------
223 // DerivedIdentify
224 //
225 // Examines the data from inSource and determines if it is in a
226 // format that this translator knows how to work with.
227 //
228 // Preconditions:
229 //
230 // Parameters:	inSource,	where the data to examine is
231 //
232 //				inFormat,	a hint about the data in inSource,
233 //							it is ignored since it is only a hint
234 //
235 //				ioExtension,	configuration settings for the
236 //								translator (not used)
237 //
238 //				outInfo,	information about what data is in
239 //							inSource and how well this translator
240 //							can handle that data is stored here
241 //
242 //				outType,	The format that the user wants
243 //							the data in inSource to be
244 //							converted to
245 //
246 // Postconditions:
247 //
248 // Returns: B_NO_TRANSLATOR,	if this translator can't handle
249 //								the data in inSource
250 //
251 // B_ERROR,	if there was an error converting the data to the host
252 //			format
253 //
254 // B_BAD_VALUE, if the settings in ioExtension are bad
255 //
256 // B_OK,	if this translator understood the data and there were
257 //			no errors found
258 //
259 // Other errors if BPositionIO::Read() returned an error value
260 // ---------------------------------------------------------------
261 status_t
262 SGITranslator::DerivedIdentify(BPositionIO *inSource,
263 	const translation_format *inFormat, BMessage *ioExtension,
264 	translator_info *outInfo, uint32 outType)
265 {
266 	return identify_sgi_header(inSource, outInfo, outType);
267 }
268 
269 // translate_from_bits
270 status_t
271 SGITranslator::translate_from_bits(BPositionIO *inSource, uint32 outType,
272 	BPositionIO *outDestination)
273 {
274 	TranslatorBitmap bitsHeader;
275 
276 	uint32 compression = fSettings->SetGetInt32(SGI_SETTING_COMPRESSION);
277 
278 	status_t ret = identify_bits_header(inSource, NULL, &bitsHeader);
279 	if (ret < B_OK)
280 		return ret;
281 
282 	// Translate B_TRANSLATOR_BITMAP to SGI_FORMAT
283 	if (outType == SGI_FORMAT) {
284 
285 		// common fields which are independent of the bitmap format
286 		uint32 width = bitsHeader.bounds.IntegerWidth() + 1;
287 		uint32 height = bitsHeader.bounds.IntegerHeight() + 1;
288 		uint32 bytesPerRow = bitsHeader.rowBytes;
289 		uint32 bytesPerChannel = 1;
290 		color_space format = bitsHeader.colors;
291 
292 		uint32 channelCount;
293 		switch (format) {
294 			case B_GRAY8:
295 				channelCount = 1;
296 				break;
297 			case B_RGB32:
298 			case B_RGB32_BIG:
299 			case B_RGB24:
300 			case B_RGB24_BIG:
301 				channelCount = 3;
302 				break;
303 			case B_RGBA32:
304 			case B_RGBA32_BIG:
305 				channelCount = 4;
306 				break;
307 			default:
308 				return B_NO_TRANSLATOR;
309 		}
310 
311 		// Set up SGI header
312 		SGIImage* sgiImage = new SGIImage();
313 		status_t ret = sgiImage->SetTo(outDestination, width, height,
314 									   channelCount, bytesPerChannel, compression);
315 		if (ret >= B_OK) {
316 			// read one row at a time,
317 			// convert to the correct format
318 			// and write out the results
319 
320 			// SGI Images store each channel separately
321 			// a buffer is allocated big enough to hold all channels
322 			// then the pointers are assigned with offsets into that buffer
323 			uint8** rows = new(nothrow) uint8*[channelCount];
324 			if (rows)
325 				rows[0] = new(nothrow) uint8[width * channelCount * bytesPerChannel];
326 			// rowBuffer is going to hold the converted data
327 			uint8* rowBuffer = new(nothrow) uint8[bytesPerRow];
328 			if (rows && rows[0] && rowBuffer) {
329 				// assign the other pointers (channel offsets in row buffer)
330 				for (uint32 i = 1; i < channelCount; i++)
331 					rows[i] = rows[0] + i * width;
332 				// loop through all lines of the image
333 				for (int32 y = height - 1; y >= 0 && ret >= B_OK; y--) {
334 
335 					ret = inSource->Read(rowBuffer, bytesPerRow);
336 					// see if an error happened while reading
337 					if (ret < B_OK)
338 						break;
339 					// convert to native format (big endian)
340 					switch (format) {
341 						case B_GRAY8: {
342 							uint8* src = rowBuffer;
343 							for (uint32 x = 0; x < width; x++) {
344 								rows[0][x] = src[0];
345 								src += 1;
346 							}
347 							break;
348 						}
349 						case B_RGB24: {
350 							uint8* src = rowBuffer;
351 							for (uint32 x = 0; x < width; x++) {
352 								rows[0][x] = src[2];
353 								rows[1][x] = src[1];
354 								rows[2][x] = src[0];
355 								src += 3;
356 							}
357 							break;
358 						}
359 						case B_RGB24_BIG: {
360 							uint8* src = rowBuffer;
361 							for (uint32 x = 0; x < width; x++) {
362 								rows[0][x] = src[0];
363 								rows[1][x] = src[1];
364 								rows[2][x] = src[2];
365 								src += 3;
366 							}
367 							break;
368 						}
369 						case B_RGB32: {
370 							uint8* src = rowBuffer;
371 							for (uint32 x = 0; x < width; x++) {
372 								rows[0][x] = src[2];
373 								rows[1][x] = src[1];
374 								rows[2][x] = src[0];
375 								// ignore src[3]
376 								src += 4;
377 							}
378 							break;
379 						}
380 						case B_RGB32_BIG: {
381 							uint8* src = rowBuffer;
382 							for (uint32 x = 0; x < width; x++) {
383 								rows[0][x] = src[1];
384 								rows[1][x] = src[2];
385 								rows[2][x] = src[3];
386 								// ignore src[0]
387 								src += 4;
388 							}
389 							break;
390 						}
391 						case B_RGBA32: {
392 							uint8* src = rowBuffer;
393 							for (uint32 x = 0; x < width; x++) {
394 								rows[0][x] = src[2];
395 								rows[1][x] = src[1];
396 								rows[2][x] = src[0];
397 								rows[3][x] = src[3];
398 								src += 4;
399 							}
400 							break;
401 						}
402 						case B_RGBA32_BIG: {
403 							uint8* src = rowBuffer;
404 							for (uint32 x = 0; x < width; x++) {
405 								rows[0][x] = src[1];
406 								rows[1][x] = src[2];
407 								rows[2][x] = src[3];
408 								rows[3][x] = src[0];
409 								src += 4;
410 							}
411 							break;
412 						}
413 						default:
414 							// cannot be here
415 							break;
416 					} // switch (format)
417 
418 					// for each channel, write a row buffer
419 					for (uint32 z = 0; z < channelCount; z++) {
420 						ret = sgiImage->WriteRow(rows[z], y, z);
421 						if (ret < B_OK) {
422 							syslog(LOG_ERR,
423 								"WriteRow() returned %s!\n"), strerror(ret);
424 							break;
425 						}
426 					}
427 
428 				} // for (uint32 y = 0; y < height && ret >= B_OK; y++)
429 				if (ret >= B_OK)
430 					ret = B_OK;
431 			} else // if (rows && rows[0] && rowBuffer)
432 				ret = B_NO_MEMORY;
433 
434 			delete[] rows[0];
435 			delete[] rows;
436 			delete[] rowBuffer;
437 		}
438 
439 		// done with the SGIImage object
440 		delete sgiImage;
441 
442 		return ret;
443 	}
444 	return B_NO_TRANSLATOR;
445 }
446 
447 // translate_from_sgi
448 status_t
449 SGITranslator::translate_from_sgi(BPositionIO *inSource, uint32 outType,
450 	BPositionIO *outDestination)
451 {
452 	status_t ret = B_NO_TRANSLATOR;
453 
454 	// if copying SGI_FORMAT to SGI_FORMAT
455 	if (outType == SGI_FORMAT) {
456 		translate_direct_copy(inSource, outDestination);
457 		return B_OK;
458 	}
459 
460 	// variables needing cleanup
461 	SGIImage* sgiImage = NULL;
462 
463 	ret = identify_sgi_header(inSource, NULL, outType, &sgiImage);
464 
465 	if (ret >= B_OK) {
466 
467 		bool bheaderonly = false, bdataonly = false;
468 
469 		uint32 width = sgiImage->Width();
470 		uint32 height = sgiImage->Height();
471 		uint32 channelCount = sgiImage->CountChannels();
472 		color_space format = B_RGBA32;
473 		uint32 bytesPerRow = 0;
474 		uint32 bytesPerChannel = sgiImage->BytesPerChannel();
475 
476 		if (channelCount == 1) {
477 //			format = B_GRAY8;	// this format is not supported by most applications
478 //			bytesPerRow = width;
479 			format = B_RGB32;
480 			bytesPerRow = width * 4;
481 		} else if (channelCount == 2) {
482 			// means gray (luminance) + alpha, we convert that to B_RGBA32
483 			format = B_RGBA32;
484 			bytesPerRow = width * 4;
485 		} else if (channelCount == 3) {
486 			format = B_RGB32; // should be B_RGB24, but let's not push it too hard...
487 			bytesPerRow = width * 4;
488 		} else if (channelCount == 4) {
489 			format = B_RGBA32;
490 			bytesPerRow = width * 4;
491 		} else
492 			ret = B_NO_TRANSLATOR; // we cannot handle this image
493 
494 		if (ret >= B_OK && !bdataonly) {
495 			// Construct and write Be bitmap header
496 			TranslatorBitmap bitsHeader;
497 			bitsHeader.magic = B_TRANSLATOR_BITMAP;
498 			bitsHeader.bounds.left = 0;
499 			bitsHeader.bounds.top = 0;
500 			bitsHeader.bounds.right = width - 1;
501 			bitsHeader.bounds.bottom = height - 1;
502 			bitsHeader.rowBytes = bytesPerRow;
503 			bitsHeader.colors = format;
504 			bitsHeader.dataSize = bitsHeader.rowBytes * height;
505 			if ((ret = swap_data(B_UINT32_TYPE, &bitsHeader,
506 				sizeof(TranslatorBitmap), B_SWAP_HOST_TO_BENDIAN)) < B_OK) {
507 				return ret;
508 			} else
509 				ret = outDestination->Write(&bitsHeader,
510 					sizeof(TranslatorBitmap));
511 		}
512 		if (ret < B_OK)
513 			syslog(LOG_ERR, "error writing bits header: %s\n", strerror(ret));
514 		if (ret >= B_OK && !bheaderonly) {
515 			// read one row at a time,
516 			// convert to the correct format
517 			// and write out the results
518 
519 			// SGI Images store each channel separately
520 			// a buffer is allocated big enough to hold all channels
521 			// then the pointers are assigned with offsets into that buffer
522 			uint8** rows = new(nothrow) uint8*[channelCount];
523 			if (rows)
524 				rows[0] = new(nothrow) uint8[width * channelCount * bytesPerChannel];
525 			// rowBuffer is going to hold the converted data
526 			uint8* rowBuffer = new(nothrow) uint8[bytesPerRow];
527 			if (rows && rows[0] && rowBuffer) {
528 				// assign the other pointers (channel offsets in row buffer)
529 				for (uint32 i = 1; i < channelCount; i++)
530 					rows[i] = rows[0] + i * width * bytesPerChannel;
531 				// loop through all lines of the image
532 				for (int32 y = height - 1; y >= 0 && ret >= B_OK; y--) {
533 					// fill the row buffer with each channel
534 					for (uint32 z = 0; z < channelCount; z++) {
535 						ret = sgiImage->ReadRow(rows[z], y, z);
536 						if (ret < B_OK)
537 							break;
538 					}
539 					// see if an error happened while reading
540 					if (ret < B_OK)
541 						break;
542 					// convert to native format (big endian)
543 					if (bytesPerChannel == 1) {
544 						switch (format) {
545 							case B_GRAY8: {
546 								uint8* dst = rowBuffer;
547 								for (uint32 x = 0; x < width; x++) {
548 									dst[0] = rows[0][x];
549 									dst += 1;
550 								}
551 								break;
552 							}
553 							case B_RGB24: {
554 								uint8* dst = rowBuffer;
555 								for (uint32 x = 0; x < width; x++) {
556 									dst[0] = rows[2][x];
557 									dst[1] = rows[1][x];
558 									dst[2] = rows[0][x];
559 									dst += 3;
560 								}
561 								break;
562 							}
563 							case B_RGB32: {
564 								uint8* dst = rowBuffer;
565 								if (channelCount == 1) {
566 									for (uint32 x = 0; x < width; x++) {
567 										dst[0] = rows[0][x];
568 										dst[1] = rows[0][x];
569 										dst[2] = rows[0][x];
570 										dst[3] = 255;
571 										dst += 4;
572 									}
573 								} else {
574 									for (uint32 x = 0; x < width; x++) {
575 										dst[0] = rows[2][x];
576 										dst[1] = rows[1][x];
577 										dst[2] = rows[0][x];
578 										dst[3] = 255;
579 										dst += 4;
580 									}
581 								}
582 								break;
583 							}
584 							case B_RGBA32: {
585 								uint8* dst = rowBuffer;
586 								if (channelCount == 2) {
587 									for (uint32 x = 0; x < width; x++) {
588 										dst[0] = rows[0][x];
589 										dst[1] = rows[0][x];
590 										dst[2] = rows[0][x];
591 										dst[3] = rows[1][x];
592 										dst += 4;
593 									}
594 								} else {
595 									for (uint32 x = 0; x < width; x++) {
596 										dst[0] = rows[2][x];
597 										dst[1] = rows[1][x];
598 										dst[2] = rows[0][x];
599 										dst[3] = rows[3][x];
600 										dst += 4;
601 									}
602 								}
603 								break;
604 							}
605 							default:
606 								// cannot be here
607 								break;
608 						} // switch (format)
609 						ret = outDestination->Write(rowBuffer, bytesPerRow);
610 					} else {
611 						// support for 16 bits per channel images
612 						uint16** rows16 = (uint16**)rows;
613 						switch (format) {
614 							case B_GRAY8: {
615 								uint8* dst = rowBuffer;
616 								for (uint32 x = 0; x < width; x++) {
617 									dst[0] = rows16[0][x] >> 8;
618 									dst += 1;
619 								}
620 								break;
621 							}
622 							case B_RGB24: {
623 								uint8* dst = rowBuffer;
624 								for (uint32 x = 0; x < width; x++) {
625 									dst[0] = rows16[2][x] >> 8;
626 									dst[1] = rows16[1][x] >> 8;
627 									dst[2] = rows16[0][x] >> 8;
628 									dst += 3;
629 								}
630 								break;
631 							}
632 							case B_RGB32: {
633 								uint8* dst = rowBuffer;
634 								if (channelCount == 1) {
635 									for (uint32 x = 0; x < width; x++) {
636 										dst[0] = rows16[0][x] >> 8;
637 										dst[1] = rows16[0][x] >> 8;
638 										dst[2] = rows16[0][x] >> 8;
639 										dst[3] = 255;
640 										dst += 4;
641 									}
642 								} else {
643 									for (uint32 x = 0; x < width; x++) {
644 										dst[0] = rows16[2][x] >> 8;
645 										dst[1] = rows16[1][x] >> 8;
646 										dst[2] = rows16[0][x] >> 8;
647 										dst[3] = 255;
648 										dst += 4;
649 									}
650 								}
651 								break;
652 							}
653 							case B_RGBA32: {
654 								uint8* dst = rowBuffer;
655 								if (channelCount == 2) {
656 									for (uint32 x = 0; x < width; x++) {
657 										dst[0] = rows16[0][x] >> 8;
658 										dst[1] = rows16[0][x] >> 8;
659 										dst[2] = rows16[0][x] >> 8;
660 										dst[3] = rows16[1][x] >> 8;
661 										dst += 4;
662 									}
663 								} else {
664 									for (uint32 x = 0; x < width; x++) {
665 										dst[0] = rows16[2][x] >> 8;
666 										dst[1] = rows16[1][x] >> 8;
667 										dst[2] = rows16[0][x] >> 8;
668 										dst[3] = rows16[3][x] >> 8;
669 										dst += 4;
670 									}
671 								}
672 								break;
673 							}
674 							default:
675 								// cannot be here
676 								break;
677 						} // switch (format)
678 						ret = outDestination->Write(rowBuffer, bytesPerRow);
679 					} // 16 bit version
680 				} // for (uint32 y = 0; y < height && ret >= B_OK; y++)
681 				if (ret >= B_OK)
682 					ret = B_OK;
683 			} else // if (rows && rows[0] && rowBuffer)
684 				ret = B_NO_MEMORY;
685 			delete[] rows[0];
686 			delete[] rows;
687 			delete[] rowBuffer;
688 		} // if (ret >= B_OK && !bheaderonly)
689 	} // if (ret >= B_OK)
690 	delete sgiImage;
691 
692 	return ret;
693 }
694 
695 // ---------------------------------------------------------------
696 // DerivedTranslate
697 //
698 // Translates the data in inSource to the type outType and stores
699 // the translated data in outDestination.
700 //
701 // Preconditions:
702 //
703 // Parameters:	inSource,	the data to be translated
704 //
705 //				inInfo,	hint about the data in inSource (not used)
706 //
707 //				ioExtension,	configuration options for the
708 //								translator
709 //
710 //				outType,	the type to convert inSource to
711 //
712 //				outDestination,	where the translated data is
713 //								put
714 //
715 //				baseType, indicates whether inSource is in the
716 //				          bits format, not in the bits format or
717 //				          is unknown
718 //
719 // Postconditions:
720 //
721 // Returns: B_BAD_VALUE, if the options in ioExtension are bad
722 //
723 // B_NO_TRANSLATOR, if this translator doesn't understand the data
724 //
725 // B_ERROR, if there was an error allocating memory or converting
726 //          data
727 //
728 // B_OK, if all went well
729 // ---------------------------------------------------------------
730 status_t
731 SGITranslator::DerivedTranslate(BPositionIO *inSource,
732 		const translator_info *inInfo, BMessage *ioExtension,
733 		uint32 outType, BPositionIO *outDestination, int32 baseType)
734 {
735 	if (baseType == 1)
736 		// if inSource is in bits format
737 		return translate_from_bits(inSource, outType, outDestination);
738 	else if (baseType == 0)
739 		// if inSource is NOT in bits format
740 		return translate_from_sgi(inSource, outType, outDestination);
741 	else
742 		// if BaseTranslator did not properly identify the data as
743 		// bits or not bits
744 		return B_NO_TRANSLATOR;
745 }
746 
747 BView *
748 SGITranslator::NewConfigView(TranslatorSettings *settings)
749 {
750 	return new SGIView(B_TRANSLATE("SGITranslator Settings"), B_WILL_DRAW,
751 		settings);
752 }
753