15 #include "pnmFileTypeSGI.h" 19 #include "config_pnmimagetypes.h" 23 #include "pnmWriter.h" 47 #define WORSTCOMPR(x) (2*(x) + 2) 50 #define MAXVAL_BYTE 255 51 #define MAXVAL_WORD 65535 54 put_byte(ostream *out_file,
unsigned char b) {
59 put_big_short(ostream *out_file,
short s) {
60 if ( pm_writebigshort( out_file, s ) == -1 )
61 pm_error(
"write error" );
66 put_big_long(ostream *out_file,
long l) {
67 if ( pm_writebiglong( out_file, l ) == -1 )
68 pm_error(
"write error" );
73 put_short_as_byte(ostream *out_file,
short s) {
74 put_byte(out_file, (
unsigned char)s);
83 PNMFileTypeSGI::Writer::
84 Writer(
PNMFileType *type, ostream *file,
bool owns_file) :
94 PNMFileTypeSGI::Writer::
98 _file->seekp(table_start);
100 PANDA_FREE_ARRAY(table);
114 bool PNMFileTypeSGI::Writer::
115 supports_write_row()
const {
133 bool PNMFileTypeSGI::Writer::
137 switch (_num_channels) {
149 nassertr(
false,
false);
154 if( _maxval <= MAXVAL_BYTE ) {
156 new_maxval = MAXVAL_BYTE;
157 }
else if( _maxval <= MAXVAL_WORD ) {
159 new_maxval = MAXVAL_WORD;
164 if( sgi_storage_type != STORAGE_VERBATIM ) {
165 table = (TabEntry *)PANDA_MALLOC_ARRAY(_num_channels * _y_size *
sizeof(TabEntry));
166 memset(table, 0, _num_channels * _y_size *
sizeof(TabEntry));
169 write_rgb_header(sgi_imagename.c_str());
172 table_start = _file->tellp();
179 current_row = _y_size - 1;
199 bool PNMFileTypeSGI::Writer::
200 write_row(
xel *row_data, xelval *alpha_data) {
203 build_scanline(channel, row_data, alpha_data);
206 write_channels(channel, put_short_as_byte);
208 write_channels(channel, put_big_short);
210 for (
int i = 0; i < _num_channels; i++) {
211 PANDA_FREE_ARRAY(channel[i].data);
219 void PNMFileTypeSGI::Writer::
220 write_rgb_header(
const char *imagename) {
223 put_big_short(_file, SGI_MAGIC);
224 put_byte(_file, sgi_storage_type);
225 put_byte(_file, (
char)bpc);
226 put_big_short(_file, dimensions);
227 put_big_short(_file, _x_size);
228 put_big_short(_file, _y_size);
229 put_big_short(_file, _num_channels);
230 put_big_long(_file, 0);
231 put_big_long(_file, new_maxval);
232 for( i = 0; i < 4; i++ )
234 for( i = 0; i < 79 && imagename[i] !=
'\0'; i++ )
235 put_byte(_file, imagename[i]);
238 put_big_long(_file, CMAP_NORMAL);
239 for( i = 0; i < 404; i++ )
244 void PNMFileTypeSGI::Writer::
247 int tabsize = _y_size*_num_channels;
249 for( i = 0; i < tabsize; i++ ) {
250 put_big_long(_file, table[i].start);
252 for( i = 0; i < tabsize; i++ )
253 put_big_long(_file, table[i].length);
257 void PNMFileTypeSGI::Writer::
258 write_channels(ScanLine channel[],
void (*put)(ostream *,
short)) {
261 for( i = 0; i < _num_channels; i++ ) {
262 Table(i).start = _file->tellp();
263 Table(i).length = channel[i].length * bpc;
265 for( col = 0; col < channel[i].length; col++ ) {
266 (*put)(_file, channel[i].data[col]);
272 void PNMFileTypeSGI::Writer::
273 build_scanline(ScanLine output[],
xel *row_data, xelval *alpha_data) {
277 if( sgi_storage_type != STORAGE_VERBATIM ) {
278 rletemp = (ScanElem *)alloca(WORSTCOMPR(_x_size) *
sizeof(ScanElem));
280 temp = (ScanElem *)PANDA_MALLOC_ARRAY(_x_size *
sizeof(ScanElem));
282 if( _num_channels <= 2 ) {
283 for( col = 0; col < _x_size; col++ )
284 temp[col] = (ScanElem)
285 (new_maxval * PPM_GETB(row_data[col]) / _maxval);
286 temp = compress(temp, output[0]);
288 if (_num_channels == 2) {
289 for( col = 0; col < _x_size; col++ )
290 temp[col] = (ScanElem)
291 (new_maxval * alpha_data[col] / _maxval);
292 temp = compress(temp, output[1]);
296 for( col = 0; col < _x_size; col++ )
297 temp[col] = (ScanElem)
298 (new_maxval * PPM_GETR(row_data[col]) / _maxval);
299 temp = compress(temp, output[0]);
300 for( col = 0; col < _x_size; col++ )
301 temp[col] = (ScanElem)
302 (new_maxval * PPM_GETG(row_data[col]) / _maxval);
303 temp = compress(temp, output[1]);
304 for( col = 0; col < _x_size; col++ )
305 temp[col] = (ScanElem)
306 (new_maxval * PPM_GETB(row_data[col]) / _maxval);
307 temp = compress(temp, output[2]);
308 if (_num_channels == 4) {
309 for( col = 0; col < _x_size; col++ )
310 temp[col] = (ScanElem)
311 (new_maxval * alpha_data[col] / _maxval);
312 temp = compress(temp, output[3]);
316 PANDA_FREE_ARRAY(temp);
320 PNMFileTypeSGI::Writer::ScanElem *PNMFileTypeSGI::Writer::
321 compress(ScanElem *temp, ScanLine &output) {
324 switch( sgi_storage_type ) {
325 case STORAGE_VERBATIM:
326 output.length = _x_size;
328 temp = (ScanElem *)PANDA_MALLOC_ARRAY(_x_size *
sizeof(ScanElem));
331 len = rle_compress(temp, _x_size);
333 output.data = (ScanElem *)PANDA_MALLOC_ARRAY(len *
sizeof(ScanElem));
334 memcpy(output.data, rletemp, len *
sizeof(ScanElem));
337 pm_error(
"unknown storage type - can\'t happen");
347 int PNMFileTypeSGI::Writer::
348 rle_compress(ScanElem *inbuf,
int size) {
349 int in, out, hold, count;
350 ScanElem *outbuf = rletemp;
354 if( (in<size-1) && (inbuf[in]==inbuf[in+1]) ) {
355 for( count=0,hold=in; in<size && inbuf[in]==inbuf[hold] && count<127; in++,count++)
357 outbuf[out++]=(ScanElem)(count);
358 outbuf[out++]=inbuf[hold];
361 hold=out; out++; count=0;
362 while( ((in>=size-2)&&(in<size)) || ((in<size-2) && ((inbuf[in]!=inbuf[in+1])||(inbuf[in]!=inbuf[in+2]))) ) {
363 outbuf[out++]=inbuf[in++];
367 outbuf[hold]=(ScanElem)(count | 0x80);
370 outbuf[out++] = (ScanElem)0;
374 #endif // HAVE_SGI_RGB This is the base class of a family of classes that represent particular image file types that PNMImag...
This is an abstract base class that defines the interface for writing image files of various types...