46#define WORSTCOMPR(x) (2*(x) + 2)
49#define MAXVAL_BYTE 255
50#define MAXVAL_WORD 65535
55put_byte(ostream *out_file,
unsigned char b) {
60put_big_short(ostream *out_file,
short s) {
61 if ( pm_writebigshort( out_file, s ) == -1 )
67put_big_long(ostream *out_file,
long l) {
68 if ( pm_writebiglong( out_file, l ) == -1 )
74put_short_as_byte(ostream *out_file,
short s) {
75 put_byte(out_file, (
unsigned char)s);
82PNMFileTypeSGI::Writer::
83Writer(
PNMFileType *type, ostream *file,
bool owns_file) :
91PNMFileTypeSGI::Writer::
95 _file->seekp(table_start);
97 PANDA_FREE_ARRAY(table);
107bool PNMFileTypeSGI::Writer::
108supports_write_row()
const {
122bool 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;
185bool PNMFileTypeSGI::Writer::
186write_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);
205void PNMFileTypeSGI::Writer::
206write_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++ )
230void 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);
243void PNMFileTypeSGI::Writer::
244write_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]);
258void PNMFileTypeSGI::Writer::
259build_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);
306PNMFileTypeSGI::Writer::ScanElem *PNMFileTypeSGI::Writer::
307compress(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");
333int PNMFileTypeSGI::Writer::
334rle_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;
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.