home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Resource Library: Graphics
/
graphics-16000.iso
/
general
/
convrtrs
/
pbmplus
/
ntpbmsrc.lha
/
netpbm
/
pnm
/
pnmtoxwd.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-10-04
|
9KB
|
336 lines
/* pnmtoxwd.c - read a portable anymap and produce a color X11 window dump
**
** Copyright (C) 1989, 1991 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/
#include "pnm.h"
#include "x11wd.h"
#include "ppmcmap.h"
int
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
xel** xels;
register xel* xP;
char* dumpname;
int argn, rows, cols, format, colors, i, row, col;
int pseudodepth;
int forcedirect, direct, grayscale;
xelval maxval;
long lmaxval, xmaxval;
colorhist_vector chv;
colorhash_table cht;
X11WDFileHeader h11;
X11XColor color;
char* usage = "[-pseudodepth n] [-directcolor] [pnmfile]";
pnm_init( &argc, argv );
argn = 1;
pseudodepth = 8;
forcedirect = 0;
while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
{
if ( pm_keymatch( argv[argn], "-pseudodepth", 2 ) )
{
++argn;
if ( argn == argc || sscanf( argv[argn], "%d", &pseudodepth ) != 1 )
pm_usage( usage );
if ( pseudodepth < 1 || pseudodepth > 16 )
pm_usage( usage );
}
else if ( pm_keymatch( argv[argn], "-directcolor", 2 ) )
forcedirect = 1;
else
pm_usage( usage );
++argn;
}
if ( argn != argc )
{
dumpname = argv[1];
ifp = pm_openr( argv[1] );
++argn;
}
else
{
dumpname = "stdin";
ifp = stdin;
}
if ( argn != argc )
pm_usage( usage );
xels = pnm_readpnm( ifp, &cols, &rows, &maxval, &format );
lmaxval = (long) maxval;
xmaxval = ( 1 << pseudodepth ) - 1;
pm_close( ifp );
if ( forcedirect )
direct = 1;
else
{
/* Figure out the colormap. */
switch ( PNM_FORMAT_TYPE(format) )
{
case PPM_TYPE:
direct = 0;
pm_message( "computing colormap..." );
chv = ppm_computecolorhist( xels, cols, rows, xmaxval+1, &colors );
if ( chv == (colorhist_vector) 0 )
{
pm_message(
"Too many colors - proceeding to write a 24-bit DirectColor" );
pm_message(
"dump file. If you want PseudoColor, try doing a 'ppmquant %d'.",
xmaxval );
direct = 1;
}
else
{
pm_message( "%d colors found", colors );
grayscale = 0;
direct = 0;
/* Make a hash table for fast color lookup. */
cht = ppm_colorhisttocolorhash( chv, colors );
}
break;
default:
direct = 0;
grayscale = 1;
break;
}
}
/* Set up the header. */
h11.header_size = sizeof(h11) + strlen( dumpname ) + 1;
h11.file_version = X11WD_FILE_VERSION;
h11.pixmap_format = ZPixmap;
h11.pixmap_width = cols;
h11.pixmap_height = rows;
h11.xoffset = 0;
h11.byte_order = MSBFirst;
h11.bitmap_bit_order = MSBFirst;
h11.window_width = cols;
h11.window_height = rows;
h11.window_x = 0;
h11.window_y = 0;
h11.window_bdrwidth = 0;
if ( direct )
{
h11.pixmap_depth = 24;
h11.bitmap_unit = 32;
h11.bitmap_pad = 32;
h11.bits_per_pixel = 32;
h11.visual_class = DirectColor;
h11.colormap_entries = 256;
h11.ncolors = 0;
h11.red_mask = 0xff0000;
h11.green_mask = 0xff00;
h11.blue_mask = 0xff;
h11.bytes_per_line = cols * 4;
}
else if ( grayscale )
{
if ( PNM_FORMAT_TYPE(format) == PBM_TYPE )
{
h11.pixmap_depth = 1;
h11.bits_per_pixel = 1;
colors = 2;
h11.colormap_entries = colors;
h11.ncolors = colors;
h11.bytes_per_line = ( cols + 7 ) / 8;
}
else
{
h11.pixmap_depth = pseudodepth;
h11.bits_per_pixel = pseudodepth;
colors = xmaxval + 1;
h11.colormap_entries = colors;
h11.ncolors = colors;
h11.bytes_per_line = cols;
}
h11.bitmap_unit = 8;
h11.bitmap_pad = 8;
h11.visual_class = StaticGray;
h11.red_mask = 0;
h11.green_mask = 0;
h11.blue_mask = 0;
}
else
{
h11.pixmap_depth = pseudodepth;
h11.bits_per_pixel = pseudodepth;
h11.visual_class = PseudoColor;
h11.colormap_entries = xmaxval + 1;
h11.ncolors = colors;
h11.red_mask = 0;
h11.green_mask = 0;
h11.blue_mask = 0;
h11.bytes_per_line = cols;
h11.bitmap_unit = 8;
h11.bitmap_pad = 8;
}
h11.bits_per_rgb = h11.pixmap_depth;
/* Write out the header in big-endian order. */
pm_writebiglong( stdout, h11.header_size );
pm_writebiglong( stdout, h11.file_version );
pm_writebiglong( stdout, h11.pixmap_format );
pm_writebiglong( stdout, h11.pixmap_depth );
pm_writebiglong( stdout, h11.pixmap_width );
pm_writebiglong( stdout, h11.pixmap_height );
pm_writebiglong( stdout, h11.xoffset );
pm_writebiglong( stdout, h11.byte_order );
pm_writebiglong( stdout, h11.bitmap_unit );
pm_writebiglong( stdout, h11.bitmap_bit_order );
pm_writebiglong( stdout, h11.bitmap_pad );
pm_writebiglong( stdout, h11.bits_per_pixel );
pm_writebiglong( stdout, h11.bytes_per_line );
pm_writebiglong( stdout, h11.visual_class );
pm_writebiglong( stdout, h11.red_mask );
pm_writebiglong( stdout, h11.green_mask );
pm_writebiglong( stdout, h11.blue_mask );
pm_writebiglong( stdout, h11.bits_per_rgb );
pm_writebiglong( stdout, h11.colormap_entries );
pm_writebiglong( stdout, h11.ncolors );
pm_writebiglong( stdout, h11.window_width );
pm_writebiglong( stdout, h11.window_height );
pm_writebiglong( stdout, h11.window_x );
pm_writebiglong( stdout, h11.window_y );
pm_writebiglong( stdout, h11.window_bdrwidth );
/* Write out the dump name. */
fwrite( dumpname, 1, strlen( dumpname ) + 1, stdout );
if ( ! direct )
{
/* Write out the colormap, big-endian order. */
color.flags = 7;
color.pad = 0;
for ( i = 0; i < colors; ++i )
{
color.num = i;
if ( grayscale )
{
/* Stupid hack because xloadimage and xwud disagree on
** how to interpret bitmaps. */
if ( PNM_FORMAT_TYPE(format) == PBM_TYPE )
color.red = (long) ( colors-1-i ) * 65535L / ( colors - 1 );
else
color.red = (long) i * 65535L / ( colors - 1 );
color.green = color.red;
color.blue = color.red;
}
else
{
color.red = PPM_GETR( chv[i].color );
color.green = PPM_GETG( chv[i].color );
color.blue = PPM_GETB( chv[i].color );
if ( lmaxval != 65535L )
{
color.red = (long) color.red * 65535L / lmaxval;
color.green = (long) color.green * 65535L / lmaxval;
color.blue = (long) color.blue * 65535L / lmaxval;
}
}
pm_writebiglong( stdout, color.num );
pm_writebigshort( stdout, color.red );
pm_writebigshort( stdout, color.green );
pm_writebigshort( stdout, color.blue );
(void) putc( color.flags, stdout );
(void) putc( color.pad, stdout );
}
}
/* Finally, write out the data. */
for ( row = 0; row < rows; ++row )
if ( direct )
{
switch ( PNM_FORMAT_TYPE(format) )
{
case PPM_TYPE:
for ( col = 0, xP = xels[row]; col < cols; ++col, ++xP )
{
unsigned long ul;
ul = ( ( PPM_GETR( *xP ) * xmaxval / lmaxval ) << 16 ) |
( ( PPM_GETG( *xP ) * xmaxval / lmaxval ) << 8 ) |
( PPM_GETB( *xP ) * xmaxval / lmaxval );
fwrite( &ul, sizeof(ul), 1, stdout );
}
break;
default:
for ( col = 0, xP = xels[row]; col < cols; ++col, ++xP )
{
unsigned long ul;
register unsigned long val;
val = PNM_GET1( *xP );
ul = ( ( val * xmaxval / lmaxval ) << 16 ) |
( ( val * xmaxval / lmaxval ) << 8 ) |
( val * xmaxval / lmaxval );
fwrite( &ul, sizeof(ul), 1, stdout );
}
break;
}
}
else if ( grayscale )
{
register xelval bigger_maxval;
register int bitshift;
unsigned char byte;
register xelval s;
bigger_maxval = pm_bitstomaxval( h11.bits_per_pixel );
bitshift = 8 - h11.bits_per_pixel;
byte = 0;
for ( col = 0, xP = xels[row]; col < cols; ++col, ++xP )
{
s = PNM_GET1( *xP );
/* More stupid hack. */
if ( PNM_FORMAT_TYPE(format) == PBM_TYPE )
s = 1 - s;
if ( maxval != bigger_maxval )
s = (long) s * bigger_maxval / maxval;
byte |= s << bitshift;
bitshift -= h11.bits_per_pixel;
if ( bitshift < 0 )
{
putchar( byte );
bitshift = 8 - h11.bits_per_pixel;
byte = 0;
}
}
if ( bitshift < 8 - h11.bits_per_pixel )
putchar( byte );
}
else
{
for ( col = 0, xP = xels[row]; col < cols; ++col, ++xP )
putchar( ppm_lookupcolor( cht, xP ) );
}
exit( 0 );
}