xref: /haiku/src/add-ons/translators/sgi/SGITranslator.cpp (revision 899e0ef82b5624ace2ccfa5f5a58c8ebee54aaef)
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_TRANSLATION_CONTEXT
58 #define B_TRANSLATION_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 			strlcpy(outInfo->name, B_TRANSLATE("SGI image"),
207 				sizeof(outInfo->name));
208 		}
209 	} else {
210 		delete sgiImage;
211 		sgiImage = NULL;
212 	}
213 	if (!poutSGIImage)
214 		// close SGIImage if caller is not interested in SGIImage handle
215 		delete sgiImage;
216 	else
217 		// leave SGIImage open (if it is) and return handle if caller needs it
218 		*poutSGIImage = sgiImage;
219 
220 	return status;
221 }
222 
223 // ---------------------------------------------------------------
224 // DerivedIdentify
225 //
226 // Examines the data from inSource and determines if it is in a
227 // format that this translator knows how to work with.
228 //
229 // Preconditions:
230 //
231 // Parameters:	inSource,	where the data to examine is
232 //
233 //				inFormat,	a hint about the data in inSource,
234 //							it is ignored since it is only a hint
235 //
236 //				ioExtension,	configuration settings for the
237 //								translator (not used)
238 //
239 //				outInfo,	information about what data is in
240 //							inSource and how well this translator
241 //							can handle that data is stored here
242 //
243 //				outType,	The format that the user wants
244 //							the data in inSource to be
245 //							converted to
246 //
247 // Postconditions:
248 //
249 // Returns: B_NO_TRANSLATOR,	if this translator can't handle
250 //								the data in inSource
251 //
252 // B_ERROR,	if there was an error converting the data to the host
253 //			format
254 //
255 // B_BAD_VALUE, if the settings in ioExtension are bad
256 //
257 // B_OK,	if this translator understood the data and there were
258 //			no errors found
259 //
260 // Other errors if BPositionIO::Read() returned an error value
261 // ---------------------------------------------------------------
262 status_t
263 SGITranslator::DerivedIdentify(BPositionIO *inSource,
264 	const translation_format *inFormat, BMessage *ioExtension,
265 	translator_info *outInfo, uint32 outType)
266 {
267 	return identify_sgi_header(inSource, outInfo, outType);
268 }
269 
270 // translate_from_bits
271 status_t
272 SGITranslator::translate_from_bits(BPositionIO *inSource, uint32 outType,
273 	BPositionIO *outDestination)
274 {
275 	TranslatorBitmap bitsHeader;
276 
277 	uint32 compression = fSettings->SetGetInt32(SGI_SETTING_COMPRESSION);
278 
279 	status_t ret = identify_bits_header(inSource, NULL, &bitsHeader);
280 	if (ret < B_OK)
281 		return ret;
282 
283 	// Translate B_TRANSLATOR_BITMAP to SGI_FORMAT
284 	if (outType == SGI_FORMAT) {
285 
286 		// common fields which are independent of the bitmap format
287 		uint32 width = bitsHeader.bounds.IntegerWidth() + 1;
288 		uint32 height = bitsHeader.bounds.IntegerHeight() + 1;
289 		uint32 bytesPerRow = bitsHeader.rowBytes;
290 		uint32 bytesPerChannel = 1;
291 		color_space format = bitsHeader.colors;
292 
293 		uint32 channelCount;
294 		switch (format) {
295 			case B_GRAY8:
296 				channelCount = 1;
297 				break;
298 			case B_RGB32:
299 			case B_RGB32_BIG:
300 			case B_RGB24:
301 			case B_RGB24_BIG:
302 				channelCount = 3;
303 				break;
304 			case B_RGBA32:
305 			case B_RGBA32_BIG:
306 				channelCount = 4;
307 				break;
308 			default:
309 				return B_NO_TRANSLATOR;
310 		}
311 
312 		// Set up SGI header
313 		SGIImage* sgiImage = new SGIImage();
314 		status_t ret = sgiImage->SetTo(outDestination, width, height,
315 									   channelCount, bytesPerChannel, compression);
316 		if (ret >= B_OK) {
317 			// read one row at a time,
318 			// convert to the correct format
319 			// and write out the results
320 
321 			// SGI Images store each channel separately
322 			// a buffer is allocated big enough to hold all channels
323 			// then the pointers are assigned with offsets into that buffer
324 			uint8** rows = new(nothrow) uint8*[channelCount];
325 			if (rows)
326 				rows[0] = new(nothrow) uint8[width * channelCount * bytesPerChannel];
327 			// rowBuffer is going to hold the converted data
328 			uint8* rowBuffer = new(nothrow) uint8[bytesPerRow];
329 			if (rows && rows[0] && rowBuffer) {
330 				// assign the other pointers (channel offsets in row buffer)
331 				for (uint32 i = 1; i < channelCount; i++)
332 					rows[i] = rows[0] + i * width;
333 				// loop through all lines of the image
334 				for (int32 y = height - 1; y >= 0 && ret >= B_OK; y--) {
335 
336 					ret = inSource->Read(rowBuffer, bytesPerRow);
337 					// see if an error happened while reading
338 					if (ret < B_OK)
339 						break;
340 					// convert to native format (big endian)
341 					switch (format) {
342 						case B_GRAY8: {
343 							uint8* src = rowBuffer;
344 							for (uint32 x = 0; x < width; x++) {
345 								rows[0][x] = src[0];
346 								src += 1;
347 							}
348 							break;
349 						}
350 						case B_RGB24: {
351 							uint8* src = rowBuffer;
352 							for (uint32 x = 0; x < width; x++) {
353 								rows[0][x] = src[2];
354 								rows[1][x] = src[1];
355 								rows[2][x] = src[0];
356 								src += 3;
357 							}
358 							break;
359 						}
360 						case B_RGB24_BIG: {
361 							uint8* src = rowBuffer;
362 							for (uint32 x = 0; x < width; x++) {
363 								rows[0][x] = src[0];
364 								rows[1][x] = src[1];
365 								rows[2][x] = src[2];
366 								src += 3;
367 							}
368 							break;
369 						}
370 						case B_RGB32: {
371 							uint8* src = rowBuffer;
372 							for (uint32 x = 0; x < width; x++) {
373 								rows[0][x] = src[2];
374 								rows[1][x] = src[1];
375 								rows[2][x] = src[0];
376 								// ignore src[3]
377 								src += 4;
378 							}
379 							break;
380 						}
381 						case B_RGB32_BIG: {
382 							uint8* src = rowBuffer;
383 							for (uint32 x = 0; x < width; x++) {
384 								rows[0][x] = src[1];
385 								rows[1][x] = src[2];
386 								rows[2][x] = src[3];
387 								// ignore src[0]
388 								src += 4;
389 							}
390 							break;
391 						}
392 						case B_RGBA32: {
393 							uint8* src = rowBuffer;
394 							for (uint32 x = 0; x < width; x++) {
395 								rows[0][x] = src[2];
396 								rows[1][x] = src[1];
397 								rows[2][x] = src[0];
398 								rows[3][x] = src[3];
399 								src += 4;
400 							}
401 							break;
402 						}
403 						case B_RGBA32_BIG: {
404 							uint8* src = rowBuffer;
405 							for (uint32 x = 0; x < width; x++) {
406 								rows[0][x] = src[1];
407 								rows[1][x] = src[2];
408 								rows[2][x] = src[3];
409 								rows[3][x] = src[0];
410 								src += 4;
411 							}
412 							break;
413 						}
414 						default:
415 							// cannot be here
416 							break;
417 					} // switch (format)
418 
419 					// for each channel, write a row buffer
420 					for (uint32 z = 0; z < channelCount; z++) {
421 						ret = sgiImage->WriteRow(rows[z], y, z);
422 						if (ret < B_OK) {
423 							syslog(LOG_ERR,
424 								"WriteRow() returned %s!\n", strerror(ret));
425 							break;
426 						}
427 					}
428 
429 				} // for (uint32 y = 0; y < height && ret >= B_OK; y++)
430 				if (ret >= B_OK)
431 					ret = B_OK;
432 			} else // if (rows && rows[0] && rowBuffer)
433 				ret = B_NO_MEMORY;
434 
435 			delete[] rows[0];
436 			delete[] rows;
437 			delete[] rowBuffer;
438 		}
439 
440 		// done with the SGIImage object
441 		delete sgiImage;
442 
443 		return ret;
444 	}
445 	return B_NO_TRANSLATOR;
446 }
447 
448 // translate_from_sgi
449 status_t
450 SGITranslator::translate_from_sgi(BPositionIO *inSource, uint32 outType,
451 	BPositionIO *outDestination)
452 {
453 	status_t ret = B_NO_TRANSLATOR;
454 
455 	// if copying SGI_FORMAT to SGI_FORMAT
456 	if (outType == SGI_FORMAT) {
457 		translate_direct_copy(inSource, outDestination);
458 		return B_OK;
459 	}
460 
461 	// variables needing cleanup
462 	SGIImage* sgiImage = NULL;
463 
464 	ret = identify_sgi_header(inSource, NULL, outType, &sgiImage);
465 
466 	if (ret >= B_OK) {
467 
468 		bool bheaderonly = false, bdataonly = false;
469 
470 		uint32 width = sgiImage->Width();
471 		uint32 height = sgiImage->Height();
472 		uint32 channelCount = sgiImage->CountChannels();
473 		color_space format = B_RGBA32;
474 		uint32 bytesPerRow = 0;
475 		uint32 bytesPerChannel = sgiImage->BytesPerChannel();
476 
477 		if (channelCount == 1) {
478 //			format = B_GRAY8;	// this format is not supported by most applications
479 //			bytesPerRow = width;
480 			format = B_RGB32;
481 			bytesPerRow = width * 4;
482 		} else if (channelCount == 2) {
483 			// means gray (luminance) + alpha, we convert that to B_RGBA32
484 			format = B_RGBA32;
485 			bytesPerRow = width * 4;
486 		} else if (channelCount == 3) {
487 			format = B_RGB32; // should be B_RGB24, but let's not push it too hard...
488 			bytesPerRow = width * 4;
489 		} else if (channelCount == 4) {
490 			format = B_RGBA32;
491 			bytesPerRow = width * 4;
492 		} else
493 			ret = B_NO_TRANSLATOR; // we cannot handle this image
494 
495 		if (ret >= B_OK && !bdataonly) {
496 			// Construct and write Be bitmap header
497 			TranslatorBitmap bitsHeader;
498 			bitsHeader.magic = B_TRANSLATOR_BITMAP;
499 			bitsHeader.bounds.left = 0;
500 			bitsHeader.bounds.top = 0;
501 			bitsHeader.bounds.right = width - 1;
502 			bitsHeader.bounds.bottom = height - 1;
503 			bitsHeader.rowBytes = bytesPerRow;
504 			bitsHeader.colors = format;
505 			bitsHeader.dataSize = bitsHeader.rowBytes * height;
506 			if ((ret = swap_data(B_UINT32_TYPE, &bitsHeader,
507 				sizeof(TranslatorBitmap), B_SWAP_HOST_TO_BENDIAN)) < B_OK) {
508 				return ret;
509 			} else
510 				ret = outDestination->Write(&bitsHeader,
511 					sizeof(TranslatorBitmap));
512 		}
513 		if (ret < B_OK)
514 			syslog(LOG_ERR, "error writing bits header: %s\n", strerror(ret));
515 		if (ret >= B_OK && !bheaderonly) {
516 			// read one row at a time,
517 			// convert to the correct format
518 			// and write out the results
519 
520 			// SGI Images store each channel separately
521 			// a buffer is allocated big enough to hold all channels
522 			// then the pointers are assigned with offsets into that buffer
523 			uint8** rows = new(nothrow) uint8*[channelCount];
524 			if (rows)
525 				rows[0] = new(nothrow) uint8[width * channelCount * bytesPerChannel];
526 			// rowBuffer is going to hold the converted data
527 			uint8* rowBuffer = new(nothrow) uint8[bytesPerRow];
528 			if (rows && rows[0] && rowBuffer) {
529 				// assign the other pointers (channel offsets in row buffer)
530 				for (uint32 i = 1; i < channelCount; i++)
531 					rows[i] = rows[0] + i * width * bytesPerChannel;
532 				// loop through all lines of the image
533 				for (int32 y = height - 1; y >= 0 && ret >= B_OK; y--) {
534 					// fill the row buffer with each channel
535 					for (uint32 z = 0; z < channelCount; z++) {
536 						ret = sgiImage->ReadRow(rows[z], y, z);
537 						if (ret < B_OK)
538 							break;
539 					}
540 					// see if an error happened while reading
541 					if (ret < B_OK)
542 						break;
543 					// convert to native format (big endian)
544 					if (bytesPerChannel == 1) {
545 						switch (format) {
546 							case B_GRAY8: {
547 								uint8* dst = rowBuffer;
548 								for (uint32 x = 0; x < width; x++) {
549 									dst[0] = rows[0][x];
550 									dst += 1;
551 								}
552 								break;
553 							}
554 							case B_RGB24: {
555 								uint8* dst = rowBuffer;
556 								for (uint32 x = 0; x < width; x++) {
557 									dst[0] = rows[2][x];
558 									dst[1] = rows[1][x];
559 									dst[2] = rows[0][x];
560 									dst += 3;
561 								}
562 								break;
563 							}
564 							case B_RGB32: {
565 								uint8* dst = rowBuffer;
566 								if (channelCount == 1) {
567 									for (uint32 x = 0; x < width; x++) {
568 										dst[0] = rows[0][x];
569 										dst[1] = rows[0][x];
570 										dst[2] = rows[0][x];
571 										dst[3] = 255;
572 										dst += 4;
573 									}
574 								} else {
575 									for (uint32 x = 0; x < width; x++) {
576 										dst[0] = rows[2][x];
577 										dst[1] = rows[1][x];
578 										dst[2] = rows[0][x];
579 										dst[3] = 255;
580 										dst += 4;
581 									}
582 								}
583 								break;
584 							}
585 							case B_RGBA32: {
586 								uint8* dst = rowBuffer;
587 								if (channelCount == 2) {
588 									for (uint32 x = 0; x < width; x++) {
589 										dst[0] = rows[0][x];
590 										dst[1] = rows[0][x];
591 										dst[2] = rows[0][x];
592 										dst[3] = rows[1][x];
593 										dst += 4;
594 									}
595 								} else {
596 									for (uint32 x = 0; x < width; x++) {
597 										dst[0] = rows[2][x];
598 										dst[1] = rows[1][x];
599 										dst[2] = rows[0][x];
600 										dst[3] = rows[3][x];
601 										dst += 4;
602 									}
603 								}
604 								break;
605 							}
606 							default:
607 								// cannot be here
608 								break;
609 						} // switch (format)
610 						ret = outDestination->Write(rowBuffer, bytesPerRow);
611 					} else {
612 						// support for 16 bits per channel images
613 						uint16** rows16 = (uint16**)rows;
614 						switch (format) {
615 							case B_GRAY8: {
616 								uint8* dst = rowBuffer;
617 								for (uint32 x = 0; x < width; x++) {
618 									dst[0] = rows16[0][x] >> 8;
619 									dst += 1;
620 								}
621 								break;
622 							}
623 							case B_RGB24: {
624 								uint8* dst = rowBuffer;
625 								for (uint32 x = 0; x < width; x++) {
626 									dst[0] = rows16[2][x] >> 8;
627 									dst[1] = rows16[1][x] >> 8;
628 									dst[2] = rows16[0][x] >> 8;
629 									dst += 3;
630 								}
631 								break;
632 							}
633 							case B_RGB32: {
634 								uint8* dst = rowBuffer;
635 								if (channelCount == 1) {
636 									for (uint32 x = 0; x < width; x++) {
637 										dst[0] = rows16[0][x] >> 8;
638 										dst[1] = rows16[0][x] >> 8;
639 										dst[2] = rows16[0][x] >> 8;
640 										dst[3] = 255;
641 										dst += 4;
642 									}
643 								} else {
644 									for (uint32 x = 0; x < width; x++) {
645 										dst[0] = rows16[2][x] >> 8;
646 										dst[1] = rows16[1][x] >> 8;
647 										dst[2] = rows16[0][x] >> 8;
648 										dst[3] = 255;
649 										dst += 4;
650 									}
651 								}
652 								break;
653 							}
654 							case B_RGBA32: {
655 								uint8* dst = rowBuffer;
656 								if (channelCount == 2) {
657 									for (uint32 x = 0; x < width; x++) {
658 										dst[0] = rows16[0][x] >> 8;
659 										dst[1] = rows16[0][x] >> 8;
660 										dst[2] = rows16[0][x] >> 8;
661 										dst[3] = rows16[1][x] >> 8;
662 										dst += 4;
663 									}
664 								} else {
665 									for (uint32 x = 0; x < width; x++) {
666 										dst[0] = rows16[2][x] >> 8;
667 										dst[1] = rows16[1][x] >> 8;
668 										dst[2] = rows16[0][x] >> 8;
669 										dst[3] = rows16[3][x] >> 8;
670 										dst += 4;
671 									}
672 								}
673 								break;
674 							}
675 							default:
676 								// cannot be here
677 								break;
678 						} // switch (format)
679 						ret = outDestination->Write(rowBuffer, bytesPerRow);
680 					} // 16 bit version
681 				} // for (uint32 y = 0; y < height && ret >= B_OK; y++)
682 				if (ret >= B_OK)
683 					ret = B_OK;
684 			} else // if (rows && rows[0] && rowBuffer)
685 				ret = B_NO_MEMORY;
686 			delete[] rows[0];
687 			delete[] rows;
688 			delete[] rowBuffer;
689 		} // if (ret >= B_OK && !bheaderonly)
690 	} // if (ret >= B_OK)
691 	delete sgiImage;
692 
693 	return ret;
694 }
695 
696 // ---------------------------------------------------------------
697 // DerivedTranslate
698 //
699 // Translates the data in inSource to the type outType and stores
700 // the translated data in outDestination.
701 //
702 // Preconditions:
703 //
704 // Parameters:	inSource,	the data to be translated
705 //
706 //				inInfo,	hint about the data in inSource (not used)
707 //
708 //				ioExtension,	configuration options for the
709 //								translator
710 //
711 //				outType,	the type to convert inSource to
712 //
713 //				outDestination,	where the translated data is
714 //								put
715 //
716 //				baseType, indicates whether inSource is in the
717 //				          bits format, not in the bits format or
718 //				          is unknown
719 //
720 // Postconditions:
721 //
722 // Returns: B_BAD_VALUE, if the options in ioExtension are bad
723 //
724 // B_NO_TRANSLATOR, if this translator doesn't understand the data
725 //
726 // B_ERROR, if there was an error allocating memory or converting
727 //          data
728 //
729 // B_OK, if all went well
730 // ---------------------------------------------------------------
731 status_t
732 SGITranslator::DerivedTranslate(BPositionIO *inSource,
733 		const translator_info *inInfo, BMessage *ioExtension,
734 		uint32 outType, BPositionIO *outDestination, int32 baseType)
735 {
736 	if (baseType == 1)
737 		// if inSource is in bits format
738 		return translate_from_bits(inSource, outType, outDestination);
739 	else if (baseType == 0)
740 		// if inSource is NOT in bits format
741 		return translate_from_sgi(inSource, outType, outDestination);
742 	else
743 		// if BaseTranslator did not properly identify the data as
744 		// bits or not bits
745 		return B_NO_TRANSLATOR;
746 }
747 
748 BView *
749 SGITranslator::NewConfigView(TranslatorSettings *settings)
750 {
751 	return new SGIView(B_TRANSLATE("SGITranslator Settings"), B_WILL_DRAW,
752 		settings);
753 }
754