This is tgatoppm.c in view mode; [Download] [Up]
/* tgatoppm.c - read a TrueVision Targa file and write a portable pixmap ** ** Partially based on tga2rast, version 1.0, by Ian MacPhedran. ** ** Copyright (C) 1989 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 "ppm.h" #include "tga.h" #define MAXCOLORS 16384 static int mapped, rlencoded; static pixel ColorMap[MAXCOLORS]; static int RLE_count = 0, RLE_flag = 0; static void readtga ARGS(( FILE* ifp, struct ImageHeader* tgaP )); static void get_map_entry ARGS(( FILE* ifp, pixel* Value, int Size )); static void get_pixel ARGS(( FILE* ifp, pixel* dest, int Size )); static unsigned char getbyte ARGS(( FILE* ifp )); int main( argc, argv ) int argc; char* argv[]; { struct ImageHeader tga_head; int i; unsigned int temp1, temp2; FILE* ifp; int argn, debug, rows, cols, row, col, realrow, truerow, baserow; int maxval; pixel** pixels; char* usage = " [-debug] [tgafile]"; ppm_init( &argc, argv ); argn = 1; debug = 0; if ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' ) { if ( pm_keymatch( argv[argn], "-debug", 2 ) ) debug = 1; else pm_usage( usage ); ++argn; } if ( argn != argc ) { ifp = pm_openr( argv[argn] ); ++argn; } else ifp = stdin; if ( argn != argc ) pm_usage( usage ); /* Read the Targa file header. */ readtga( ifp, &tga_head ); if ( debug ) { pm_message( "IDLength = %d\n", (int) tga_head.IDLength ); pm_message( "CoMapType = %d\n", (int) tga_head.CoMapType ); pm_message( "ImgType = %d\n", (int) tga_head.ImgType ); pm_message( "Index_lo = %d\n", (int) tga_head.Index_lo ); pm_message( "Index_hi = %d\n", (int) tga_head.Index_hi ); pm_message( "Length_lo = %d\n", (int) tga_head.Length_lo ); pm_message( "Length_hi = %d\n", (int) tga_head.Length_hi ); pm_message( "CoSize = %d\n", (int) tga_head.CoSize ); pm_message( "X_org_lo = %d\n", (int) tga_head.X_org_lo ); pm_message( "X_org_hi = %d\n", (int) tga_head.X_org_hi ); pm_message( "Y_org_lo = %d\n", (int) tga_head.Y_org_lo ); pm_message( "Y_org_hi = %d\n", (int) tga_head.Y_org_hi ); pm_message( "Width_lo = %d\n", (int) tga_head.Width_lo ); pm_message( "Width_hi = %d\n", (int) tga_head.Width_hi ); pm_message( "Height_lo = %d\n", (int) tga_head.Height_lo ); pm_message( "Height_hi = %d\n", (int) tga_head.Height_hi ); pm_message( "PixelSize = %d\n", (int) tga_head.PixelSize ); pm_message( "AttBits = %d\n", (int) tga_head.AttBits ); pm_message( "Rsrvd = %d\n", (int) tga_head.Rsrvd ); pm_message( "OrgBit = %d\n", (int) tga_head.OrgBit ); pm_message( "IntrLve = %d\n", (int) tga_head.IntrLve ); } rows = ( (int) tga_head.Height_lo ) + ( (int) tga_head.Height_hi ) * 256; cols = ( (int) tga_head.Width_lo ) + ( (int) tga_head.Width_hi ) * 256; switch ( tga_head.ImgType ) { case TGA_Map: case TGA_RGB: case TGA_Mono: case TGA_RLEMap: case TGA_RLERGB: case TGA_RLEMono: break; default: pm_error( "unknown Targa image type %d", tga_head.ImgType ); } if ( tga_head.ImgType == TGA_Map || tga_head.ImgType == TGA_RLEMap || tga_head.ImgType == TGA_CompMap || tga_head.ImgType == TGA_CompMap4 ) { /* Color-mapped image */ if ( tga_head.CoMapType != 1 ) pm_error( "mapped image (type %d) with color map type != 1", tga_head.ImgType ); mapped = 1; /* Figure maxval from CoSize. */ switch ( tga_head.CoSize ) { case 8: case 24: case 32: maxval = 255; break; case 15: case 16: maxval = 31; break; default: pm_error( "unknown colormap pixel size - %d", tga_head.CoSize ); } if ( maxval > PPM_MAXMAXVAL ) pm_error( "CoSize is too large - try reconfiguring with PGM_BIGGRAYS\n or without PPM_PACKCOLORS" ); } else { /* Not colormap, so figure maxval from PixelSize. */ mapped = 0; switch ( tga_head.PixelSize ) { case 8: case 24: case 32: maxval = 255; break; case 15: case 16: maxval = 31; break; default: pm_error( "unknown pixel size - %d", tga_head.PixelSize ); } if ( maxval > PPM_MAXMAXVAL ) pm_error( "PixelSize is too large - try reconfiguring with PGM_BIGGRAYS\n or without PPM_PACKCOLORS" ); } /* If required, read the color map information. */ if ( tga_head.CoMapType != 0 ) { temp1 = tga_head.Index_lo + tga_head.Index_hi * 256; temp2 = tga_head.Length_lo + tga_head.Length_hi * 256; if ( ( temp1 + temp2 + 1 ) >= MAXCOLORS ) pm_error( "too many colors - %d", ( temp1 + temp2 + 1 ) ); for ( i = temp1; i < ( temp1 + temp2 ); ++i ) get_map_entry( ifp, &ColorMap[i], (int) tga_head.CoSize ); } /* Check run-length encoding. */ if ( tga_head.ImgType == TGA_RLEMap || tga_head.ImgType == TGA_RLERGB || tga_head.ImgType == TGA_RLEMono ) rlencoded = 1; else rlencoded = 0; /* Read the Targa file body and convert to portable format. */ pixels = ppm_allocarray( cols, rows ); truerow = 0; baserow = 0; for ( row = 0; row < rows; ++row ) { realrow = truerow; if ( tga_head.OrgBit == 0 ) realrow = rows - realrow - 1; for ( col = 0; col < cols; ++col ) get_pixel( ifp, &(pixels[realrow][col]), (int) tga_head.PixelSize ); if ( tga_head.IntrLve == TGA_IL_Four ) truerow += 4; else if ( tga_head.IntrLve == TGA_IL_Two ) truerow += 2; else ++truerow; if ( truerow >= rows ) truerow = ++baserow; } pm_close( ifp ); ppm_writeppm( stdout, pixels, cols, rows, (pixval) maxval, 0 ); pm_close( stdout ); exit( 0 ); } static void readtga( ifp, tgaP ) FILE* ifp; struct ImageHeader* tgaP; { unsigned char flags; ImageIDField junk; tgaP->IDLength = getbyte( ifp ); tgaP->CoMapType = getbyte( ifp ); tgaP->ImgType = getbyte( ifp ); tgaP->Index_lo = getbyte( ifp ); tgaP->Index_hi = getbyte( ifp ); tgaP->Length_lo = getbyte( ifp ); tgaP->Length_hi = getbyte( ifp ); tgaP->CoSize = getbyte( ifp ); tgaP->X_org_lo = getbyte( ifp ); tgaP->X_org_hi = getbyte( ifp ); tgaP->Y_org_lo = getbyte( ifp ); tgaP->Y_org_hi = getbyte( ifp ); tgaP->Width_lo = getbyte( ifp ); tgaP->Width_hi = getbyte( ifp ); tgaP->Height_lo = getbyte( ifp ); tgaP->Height_hi = getbyte( ifp ); tgaP->PixelSize = getbyte( ifp ); flags = getbyte( ifp ); tgaP->AttBits = flags & 0xf; tgaP->Rsrvd = ( flags & 0x10 ) >> 4; tgaP->OrgBit = ( flags & 0x20 ) >> 5; tgaP->IntrLve = ( flags & 0xc0 ) >> 6; if ( tgaP->IDLength != 0 ) fread( junk, 1, (int) tgaP->IDLength, ifp ); } static void get_map_entry( ifp, Value, Size ) FILE* ifp; pixel* Value; int Size; { unsigned char j, k, r, g, b; /* Read appropriate number of bytes, break into rgb & put in map. */ switch ( Size ) { case 8: /* Grey scale, read and triplicate. */ r = g = b = getbyte( ifp ); break; case 16: /* 5 bits each of red green and blue. */ case 15: /* Watch for byte order. */ j = getbyte( ifp ); k = getbyte( ifp ); r = ( k & 0x7C ) >> 2; g = ( ( k & 0x03 ) << 3 ) + ( ( j & 0xE0 ) >> 5 ); b = j & 0x1F; break; case 32: case 24: /* 8 bits each of blue green and red. */ b = getbyte( ifp ); g = getbyte( ifp ); r = getbyte( ifp ); if ( Size == 32 ) (void) getbyte( ifp ); /* Read alpha byte & throw away. */ break; default: pm_error( "unknown colormap pixel size (#2) - %d", Size ); } PPM_ASSIGN( *Value, r, g, b ); } static void get_pixel( ifp, dest, Size ) FILE* ifp; pixel* dest; int Size; { static pixval Red, Grn, Blu; unsigned char j, k; static unsigned int l; /* Check if run length encoded. */ if ( rlencoded ) { if ( RLE_count == 0 ) { /* Have to restart run. */ unsigned char i; i = getbyte( ifp ); RLE_flag = ( i & 0x80 ); if ( RLE_flag == 0 ) /* Stream of unencoded pixels. */ RLE_count = i + 1; else /* Single pixel replicated. */ RLE_count = i - 127; /* Decrement count & get pixel. */ --RLE_count; } else { /* Have already read count & (at least) first pixel. */ --RLE_count; if ( RLE_flag != 0 ) /* Replicated pixels. */ goto PixEncode; } } /* Read appropriate number of bytes, break into RGB. */ switch ( Size ) { case 8: /* Grey scale, read and triplicate. */ Red = Grn = Blu = l = getbyte( ifp ); break; case 16: /* 5 bits each of red green and blue. */ case 15: /* Watch byte order. */ j = getbyte( ifp ); k = getbyte( ifp ); l = ( (unsigned int) k << 8 ) + j; Red = ( k & 0x7C ) >> 2; Grn = ( ( k & 0x03 ) << 3 ) + ( ( j & 0xE0 ) >> 5 ); Blu = j & 0x1F; break; case 32: case 24: /* 8 bits each of blue green and red. */ Blu = getbyte( ifp ); Grn = getbyte( ifp ); Red = getbyte( ifp ); if ( Size == 32 ) (void) getbyte( ifp ); /* Read alpha byte & throw away. */ l = 0; break; default: pm_error( "unknown pixel size (#2) - %d", Size ); } PixEncode: if ( mapped ) *dest = ColorMap[l]; else PPM_ASSIGN( *dest, Red, Grn, Blu ); } static unsigned char getbyte( ifp ) FILE* ifp; { unsigned char c; if ( fread( (char*) &c, 1, 1, ifp ) != 1 ) pm_error( "EOF / read error" ); return c; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.