--- OLD/pnm/xwdtopnm.c Thu Jan 1 00:00:00 1970 +++ NEW/pnm/xwdtopnm.c Thu Jan 1 00:00:00 1970 @@ -20,6 +20,11 @@ static long bs_long ARGS(( long l )); static unsigned long red_mask, green_mask, blue_mask; +static int red_shift, green_shift, blue_shift; +static unsigned long red_mul, green_mul, blue_mul; +static int red_amshift, green_amshift, blue_amshift; +static long int maxval; +static int fast_truedirect; static int bits_per_item, bits_used, bit_shift, bits_per_pixel; static char buf[4]; static char* byteP; @@ -28,6 +33,86 @@ static unsigned long pixel_mask; static int byte_swap, byte_order, bit_order; +static int mask_shift_count(unsigned long int mask) +{ + int i; + + for (i=0;!(mask&1);i++,mask>>=1) ; + return(i); +} + +static void compute_truedirect_values(void) +{ + unsigned long int rm; + unsigned long int gm; + unsigned long int bm; + unsigned long int m; + int rw; + int gw; + int bw; + int w; + unsigned long int f; + unsigned long int a; + unsigned long int s; + + rm = red_mask >> red_shift; + gm = green_mask >> green_shift; + bm = blue_mask >> blue_shift; + fast_truedirect = ((rm == gm) && (rm == bm) && (rm <= PNM_MAXMAXVAL)); + if (fast_truedirect) + { maxval = rm; + return; + } + m = PNM_MAXMAXVAL; + red_mul = 1; + red_amshift = 0; + green_mul = 1; + green_amshift = 0; + blue_mul = 1; + blue_amshift = 0; + if (rm > m) for (;rm>m;red_amshift++,rm>>=1) ; + if (gm > m) for (;gm>m;green_amshift++,gm>>=1) ; + if (bm > m) for (;bm>m;blue_amshift++,bm>>=1) ; + m = rm | gm | bm; + if (rm < m) + { for (f=rm,s=0;f;s++,f>>=1) ; + a = 1; + f = 1; + while (rm < m) + { a <<= s; + f += a; + rm |= rm << s; + } + red_mul = f; + for (;rm>m;red_amshift++,rm>>=1) ; + } + if (gm < m) + { for (f=gm,s=0;f;s++,f>>=1) ; + a = 1; + f = 1; + while (gm < m) + { a <<= s; + f += a; + gm |= gm << s; + } + green_mul = f; + for (;gm>m;green_amshift++,gm>>=1) ; + } + if (bm < m) + { for (f=bm,s=0;f;s++,f>>=1) ; + a = 1; + f = 1; + while (bm < m) + { a <<= s; + f += a; + bm |= bm << s; + } + blue_mul = f; + for (;bm>m;blue_amshift++,bm>>=1) ; + } + maxval = m; +} + int main( argc, argv ) int argc; @@ -39,7 +124,7 @@ xel* colors; int rows, cols, format, padright, row; register int col; - long maxval, visualclass; + long int visualclass; pnm_init( &argc, argv ); @@ -53,6 +138,14 @@ getinit( ifp, &cols, &rows, &padright, &maxval, &visualclass, &format, &colors ); + switch ( visualclass ) + { + case TrueColor: + case DirectColor: + compute_truedirect_values(); + break; + } + pnm_writepnminit( stdout, cols, rows, (xelval) maxval, format, 0 ); xelrow = pnm_allocrow( cols ); switch ( PNM_FORMAT_TYPE(format) ) @@ -89,28 +182,18 @@ case DirectColor: for ( col = 0, xP = xelrow; col < cols; ++col, ++xP ) { - register unsigned long ul; - - ul = getpixnum( ifp ); - switch ( bits_per_pixel ) - { - case 16: + unsigned long int v; + v = getpixnum(ifp); + if (fast_truedirect) PPM_ASSIGN( *xP, - ( ( ul & red_mask ) >> 0 ), - ( ( ul & green_mask ) >> 5 ), - ( ( ul & blue_mask ) >> 10 ) ); - break; - - case 24: - case 32: - PPM_ASSIGN( *xP, ( ( ul & 0xff0000 ) >> 16 ), - ( ( ul & 0xff00 ) >> 8 ), - ( ul & 0xff ) ); - break; - - default: - pm_error( "True/Direct only supports 16, 24, and 32 bits" ); - } + (v & red_mask) >> red_shift, + (v & green_mask) >> green_shift, + (v & blue_mask) >> blue_shift ); + else + PPM_ASSIGN( *xP, + (((v & red_mask) >> red_shift) * red_mul) >> red_amshift, + (((v & green_mask) >> green_shift) * green_mul) >> green_amshift, + (((v & blue_mask) >> blue_shift) * blue_mul) >> blue_amshift ); } break; @@ -385,13 +468,19 @@ *maxvalP = 31; else *maxvalP = 255; + red_mask = h11P->red_mask; + green_mask = h11P->green_mask; + blue_mask = h11P->blue_mask; + red_shift = mask_shift_count(red_mask); + green_shift = mask_shift_count(green_mask); + blue_shift = mask_shift_count(blue_mask); } else if ( *visualclassP == StaticGray && h11P->bits_per_pixel == 1 ) { *formatP = PBM_TYPE; *maxvalP = 1; *colorsP = pnm_allocrow( 2 ); - PNM_ASSIGN1( (*colorsP)[0], *maxvalP ); + PNM_ASSIGN1( (*colorsP)[0], 1 ); PNM_ASSIGN1( (*colorsP)[1], 0 ); } else if ( *visualclassP == StaticGray ) @@ -435,9 +524,6 @@ pixel_mask = -1; else pixel_mask = ( 1 << bits_per_pixel ) - 1; - red_mask = h11P->red_mask; - green_mask = h11P->green_mask; - blue_mask = h11P->blue_mask; } else pm_error( "unknown XWD file version: %d", h11P->file_version );