46 #define WORSTCOMPR(x) (2*(x) + 2) 49 #define MAXVAL_BYTE 255 50 #define MAXVAL_WORD 65535 55 put_byte(ostream *out_file,
unsigned char b) {
60 put_big_short(ostream *out_file,
short s) {
61 if ( pm_writebigshort( out_file, s ) == -1 )
67 put_big_long(ostream *out_file,
long l) {
68 if ( pm_writebiglong( out_file, l ) == -1 )
74 put_short_as_byte(ostream *out_file,
short s) {
75 put_byte(out_file, (
unsigned char)s);
82 PNMFileTypeSGI::Writer::
83 Writer(
PNMFileType *type, ostream *file,
bool owns_file) :
91 PNMFileTypeSGI::Writer::
95 _file->seekp(table_start);
97 PANDA_FREE_ARRAY(table);
107 bool PNMFileTypeSGI::Writer::
108 supports_write_row()
const {
122 bool PNMFileTypeSGI::Writer::
126 switch (_num_channels) {
138 nassert_raise(
"unexpected channel count");
144 if( _maxval <= MAXVAL_BYTE ) {
146 new_maxval = MAXVAL_BYTE;
147 }
else if( _maxval <= MAXVAL_WORD ) {
149 new_maxval = MAXVAL_WORD;
154 if( sgi_storage_type != STORAGE_VERBATIM ) {
155 table = (TabEntry *)PANDA_MALLOC_ARRAY(_num_channels * _y_size *
sizeof(TabEntry));
156 memset(table, 0, _num_channels * _y_size *
sizeof(TabEntry));
159 write_rgb_header(sgi_imagename.c_str());
161 if (table!=
nullptr) {
162 table_start = _file->tellp();
169 current_row = _y_size - 1;
185 bool PNMFileTypeSGI::Writer::
186 write_row(
xel *row_data, xelval *alpha_data) {
189 build_scanline(channel, row_data, alpha_data);
192 write_channels(channel, put_short_as_byte);
194 write_channels(channel, put_big_short);
196 for (
int i = 0; i < _num_channels; i++) {
197 PANDA_FREE_ARRAY(channel[i].data);
205 void PNMFileTypeSGI::Writer::
206 write_rgb_header(
const char *imagename) {
209 put_big_short(_file, SGI_MAGIC);
210 put_byte(_file, sgi_storage_type);
211 put_byte(_file, (
char)bpc);
212 put_big_short(_file, dimensions);
213 put_big_short(_file, _x_size);
214 put_big_short(_file, _y_size);
215 put_big_short(_file, _num_channels);
216 put_big_long(_file, 0);
217 put_big_long(_file, new_maxval);
218 for( i = 0; i < 4; i++ )
220 for( i = 0; i < 79 && imagename[i] !=
'\0'; i++ )
221 put_byte(_file, imagename[i]);
224 put_big_long(_file, CMAP_NORMAL);
225 for( i = 0; i < 404; i++ )
230 void PNMFileTypeSGI::Writer::
233 int tabsize = _y_size*_num_channels;
235 for( i = 0; i < tabsize; i++ ) {
236 put_big_long(_file, table[i].start);
238 for( i = 0; i < tabsize; i++ )
239 put_big_long(_file, table[i].length);
243 void PNMFileTypeSGI::Writer::
244 write_channels(ScanLine channel[],
void (*put)(ostream *,
short)) {
247 for( i = 0; i < _num_channels; i++ ) {
248 Table(i).start = _file->tellp();
249 Table(i).length = channel[i].length * bpc;
251 for( col = 0; col < channel[i].length; col++ ) {
252 (*put)(_file, channel[i].data[col]);
258 void PNMFileTypeSGI::Writer::
259 build_scanline(ScanLine output[],
xel *row_data, xelval *alpha_data) {
263 if( sgi_storage_type != STORAGE_VERBATIM ) {
264 rletemp = (ScanElem *)alloca(WORSTCOMPR(_x_size) *
sizeof(ScanElem));
266 temp = (ScanElem *)PANDA_MALLOC_ARRAY(_x_size *
sizeof(ScanElem));
268 if( _num_channels <= 2 ) {
269 for( col = 0; col < _x_size; col++ )
270 temp[col] = (ScanElem)
271 (new_maxval * PPM_GETB(row_data[col]) / _maxval);
272 temp = compress(temp, output[0]);
274 if (_num_channels == 2) {
275 for( col = 0; col < _x_size; col++ )
276 temp[col] = (ScanElem)
277 (new_maxval * alpha_data[col] / _maxval);
278 temp = compress(temp, output[1]);
282 for( col = 0; col < _x_size; col++ )
283 temp[col] = (ScanElem)
284 (new_maxval * PPM_GETR(row_data[col]) / _maxval);
285 temp = compress(temp, output[0]);
286 for( col = 0; col < _x_size; col++ )
287 temp[col] = (ScanElem)
288 (new_maxval * PPM_GETG(row_data[col]) / _maxval);
289 temp = compress(temp, output[1]);
290 for( col = 0; col < _x_size; col++ )
291 temp[col] = (ScanElem)
292 (new_maxval * PPM_GETB(row_data[col]) / _maxval);
293 temp = compress(temp, output[2]);
294 if (_num_channels == 4) {
295 for( col = 0; col < _x_size; col++ )
296 temp[col] = (ScanElem)
297 (new_maxval * alpha_data[col] / _maxval);
298 temp = compress(temp, output[3]);
302 PANDA_FREE_ARRAY(temp);
306 PNMFileTypeSGI::Writer::ScanElem *PNMFileTypeSGI::Writer::
307 compress(ScanElem *temp, ScanLine &output) {
310 switch( sgi_storage_type ) {
311 case STORAGE_VERBATIM:
312 output.length = _x_size;
314 temp = (ScanElem *)PANDA_MALLOC_ARRAY(_x_size *
sizeof(ScanElem));
317 len = rle_compress(temp, _x_size);
319 output.data = (ScanElem *)PANDA_MALLOC_ARRAY(len *
sizeof(ScanElem));
320 memcpy(output.data, rletemp, len *
sizeof(ScanElem));
323 pm_error(
"unknown storage type - can\'t happen");
333 int PNMFileTypeSGI::Writer::
334 rle_compress(ScanElem *inbuf,
int size) {
335 int in, out, hold, count;
336 ScanElem *outbuf = rletemp;
340 if( (in<size-1) && (inbuf[in]==inbuf[in+1]) ) {
341 for( count=0,hold=in; in<size && inbuf[in]==inbuf[hold] && count<127; in++,count++)
343 outbuf[out++]=(ScanElem)(count);
344 outbuf[out++]=inbuf[hold];
347 hold=out; out++; count=0;
348 while( ((in>=size-2)&&(in<size)) || ((in<size-2) && ((inbuf[in]!=inbuf[in+1])||(inbuf[in]!=inbuf[in+2]))) ) {
349 outbuf[out++]=inbuf[in++];
353 outbuf[hold]=(ScanElem)(count | 0x80);
356 outbuf[out++] = (ScanElem)0;
360 #endif // HAVE_SGI_RGB PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is the base class of a family of classes that represent particular image file types that PNMImag...
void pm_error(const char *format,...)
Outputs the given printf-style message to the user and terminates messily.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is an abstract base class that defines the interface for writing image files of various types.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.