📄 tga.c
字号:
/* * This software is copyrighted as noted below. It may be freely copied, * modified, and redistributed, provided that the copyright notice is * preserved on all copies. * * There is no warranty or other guarantee of fitness for this software, * it is provided solely "as is". Bug reports or fixes may be sent * to the author, who may or may not act on them as he desires. * * You may not include this software in a program or other software product * without supplying the source, or without informing the end-user that the * source is available for no extra charge. * * If you modify this software, you should include a notice giving the * name of the person performing the modification, the date of modification, * and the reason for such modification. *//* * tga.c - interface with Targa format. * * Author: Raul Rivero * Mathematics Dept. * University of Oviedo * Date: Wed Jan 22 1992 * Copyright (c) 1992, Raul Rivero * */#include "lug.h"#include "lugfnts.h"read_tga_file( name, bitmap )char *name;bitmap_hdr *bitmap;{ FILE *handle; /* Open the file descriptor */ if ( name != NULL ) handle = Fopen( name, "rb" ); else handle = stdin; /* Read the bitmap */ read_tga( handle, bitmap ); rm_compress(); /* Close the file */ Fclose( handle );}read_tga(handle, image)FILE *handle;bitmap_hdr *image;{ register int i; tga_hdr tga; int allplanes = 0; int lessplanes = 0; int forceallplanes = 0; byte aux4[4]; int totalsize; byte *ptr; byte *r, *g, *b; byte *aux; /* Read the Tagar header */ read_tga_header( handle, &tga ); /* Fill our header */ image->magic = LUGUSED; image->xsize = tga.xsize; image->ysize = tga.ysize; totalsize = image->xsize * image->ysize; /* * Targa format can be mapped but with moer than 256 colors, * our mapped images only support 8 bits, so we need convert * these images to 24 bits. */ switch ( tga.image_type ) { case TGA_RGB: case TGA_RLE_RGB: allplanes = 1; break; case TGA_MAPPED: case TGA_RLE_MAPPED: lessplanes = 1; if ( tga.cmap_type != 1 ) error( 10 ); if ( tga.cmap_length > 256 ) forceallplanes = 1; break; } /* * Read the cmap info ( if exists ). */ if ( tga.cmap_type ) {/* VPRINTF(stderr, "Reading cmap info\n"); */ if ( allplanes ) { /* We only need skip the cmap block */ for ( i = 0; i < tga.cmap_length; i++ ) read_tga_data( aux4, tga.cmap_entry_size, handle ); }else { ptr = image->cmap = (byte *) Malloc( 3 * tga.cmap_length ); for ( i = 0; i < tga.cmap_length; i++) { read_tga_data( ptr, tga.cmap_entry_size, handle ); ptr += 3; } } } /* * Allocate memory for the bitmap and fill our header. */ image->xsize = tga.xsize; image->ysize = tga.ysize; totalsize = image->xsize * image->ysize; if ( allplanes || forceallplanes ) { r = image->r = (byte *) Malloc( totalsize ); g = image->g = (byte *) Malloc( totalsize ); b = image->b = (byte *) Malloc( totalsize ); image->depth = 24; }else { r = image->r = (byte *) Malloc( totalsize ); image->depth = no_bits( tga.cmap_length ) + 1; } image->colors = ( 1 << image->depth ); /* * Read the raster information. */ if ( allplanes ) { read_tga24( handle, r, g, b, &tga ); }else if ( forceallplanes ) read_tga_to24( handle, r, g, b, &tga, image->cmap ); else read_tga8( handle, r, &tga );/* if ( TGA_FLIP( tga.image_descriptor ) ) { VPRINTF(stderr, "Flipping the image\n"); aux = (byte *) flip( r, image->xsize, image->ysize ); free( r ); image->r = aux; if ( allplanes ) { aux = (byte *) flip( g, image->xsize, image->ysize ); free( g ); image->g = aux; aux = (byte *) flip( b, image->xsize, image->ysize ); free( b ); image->b = aux; }} */}read_tga24( handle, r, g, b, tga )FILE *handle;byte *r, *g, *b;tga_hdr *tga;{ register int i, j; int aux; byte *ptr; byte *buffer; int totalsize; int count = 0; byte repeat; byte rbyte, gbyte, bbyte; int code; if ( tga->image_type < 9 ) { /* No RLE ! *//* VPRINTF(stderr, "Reading true color Targa image\n"); */ buffer = (byte *) Malloc( tga->pixel_size * tga->xsize ); for ( j = 0; j < tga->ysize; j++ ) {#ifdef DEBUG/* VPRINTF(stderr, "Reading line %d\r", j); VFLUSH( stderr ); */#endif fread( buffer, tga->xsize, tga->pixel_size, handle); ptr = buffer; if ( tga->pixel_size < 3 ) { for ( i = 0 ; i < tga->xsize; i++ ) { aux = ( ptr[1] << 8 ) | ptr[0]; *r++ = (aux & 0x7c00) >> 7; *g++ = (aux & 0x03e0) >> 2; *b++ = (aux & 0x001F) << 3; ptr += 2; } }else { for ( i = 0 ; i < tga->xsize; i++ ) { *b++ = *ptr++; *g++ = *ptr++; *r++ = *ptr++; if ( tga->pixel_size == 4 ) ptr++; } } }#ifdef DEBUG/* VPRINTF( stderr, "\n" ); */#endif free( buffer ); }else {/* VPRINTF(stderr, "Reading true color Targa RLE image\n"); */ /* RLE */ buffer = (byte *) Malloc( 256 * tga->pixel_size ); totalsize = tga->xsize * tga->ysize; while ( count < totalsize ) { Fread( &repeat, 1, 1, handle ); code = (repeat & 127) + 1; count += code; if ( (repeat & 128) ) { Fread( buffer, tga->pixel_size, 1, handle ); if ( tga->pixel_size < 3 ) { aux = ( buffer[1] << 8 ) | buffer[0]; rbyte = (aux & 0x7c00) >> 7; gbyte = (aux & 0x03e0) >> 2; bbyte = (aux & 0x001F) << 3; }else { rbyte = buffer[2]; gbyte = buffer[1]; bbyte = buffer[0]; } memset( r, rbyte, code ); r += code; memset( g, gbyte, code ); g += code; memset( b, bbyte, code ); b += code; }else { Fread( buffer, tga->pixel_size, code, handle ); ptr = buffer; while ( code-- ) { if ( tga->pixel_size < 3 ) { aux = ( ptr[1] << 8 ) | ptr[0]; *r++ = (aux & 0x7c00) >> 7; *g++ = (aux & 0x03e0) >> 2; *b++ = (aux & 0x001F) << 3; ptr += 2; }else { *b++ = *ptr++; *g++ = *ptr++; *r++ = *ptr++; if ( tga->pixel_size == 4 ) ptr++; } } } /* if ( (repeat ... ) ) */ } /* while ( count ... ) */ free( buffer ); }}read_tga_to24( handle, r, g, b, tga, cmap )FILE *handle;byte *r, *g, *b;tga_hdr *tga;byte *cmap;{ fprintf(stderr, "Converting to 24 planes\n"); error( 99 );}read_tga8( handle, r, tga )FILE *handle;byte *r;tga_hdr *tga;{ if ( tga->image_type == 1 ) {/* VPRINTF( stderr, "Reading mapped Targa image\n" ); */ Fread( r, tga->xsize, tga->ysize, handle ); }else { byte buffer, repeat; int totalsize = tga->xsize * tga->ysize; int count = 0; int code;/* VPRINTF( stderr, "Reading mapped RLE Targa image\n" ); */ /* RLE */ while ( count < totalsize ) { Fread( &repeat, 1, 1, handle ); code = (repeat & 127) + 1; count += code; if ( (repeat & 128) ) { Fread( &buffer, 1, 1, handle ); memset( r, buffer, code ); r += code; }else { Fread( r, code, 1, handle ); r += code; } } /* while ( count ... ) */ }}read_tga_header(handle, tga)FILE *handle;tga_hdr *tga;{ byte buffer[18]; Fread( buffer, 18, 1, handle ); /* * Bytes are in reverse order so ... */ tga->num_id = buffer[0]; tga->cmap_type = buffer[1]; tga->image_type = buffer[2]; tga->cmap_orign = ( buffer[4] << 8 ) | buffer[3]; tga->cmap_length = ( buffer[6] << 8 ) | buffer[5]; tga->cmap_entry_size = buffer[7] / 8; tga->xorig = ( buffer[9] << 8 ) | buffer[8]; tga->yorig = ( buffer[11] << 8 ) | buffer[10]; tga->xsize = ( buffer[13] << 8 ) | buffer[12]; tga->ysize = ( buffer[15] << 8 ) | buffer[14]; tga->pixel_size = buffer[16] / 8; /* we'll use it directly */ tga->image_descriptor = buffer[17];/* VPRINTF(stderr, "Image type %d\n", tga->image_type); VPRINTF(stderr, "%s color map\n", (tga->cmap_type ? "With" : "Without")); VPRINTF(stderr, "Cmap origin: %d\n", tga->cmap_orign ); VPRINTF(stderr, "Cmap length: %d\n", tga->cmap_length ); VPRINTF(stderr, "Cmap entry size: %d\n", tga->cmap_entry_size ); VPRINTF(stderr, "Image size: %dx%d\n", tga->xsize, tga->ysize ); VPRINTF(stderr, "Pixel size: %d\n", tga->pixel_size ); *//* if ( TGA_INTERLACED(tga->image_descriptor) ) VPRINTF(stderr, "Interlace image\n"); if ( TGA_FLIP(tga->image_descriptor) ) VPRINTF(stderr, "Flipped image\n"); */ /* Interlaced ? */ if ( TGA_INTERLACED(tga->image_descriptor) ) { fprintf( stderr, "Interlaced image\n"); error( 99 ); } /* * Skip the identification. */ if ( tga->num_id ) {/* VPRINTF( stderr, "Image identification: "); */ while ( tga->num_id ) { (void) getc( handle ); tga->num_id--; }/* VPRINTF( stderr, "\n" ); */ } /* * Check the image type. */ switch ( tga->image_type ) { case TGA_RGB: case TGA_RLE_RGB: case TGA_MAPPED: case TGA_RLE_MAPPED: break; default: fprintf(stderr, "Image type %d\n", tga->image_type); error( 99 ); break; }}read_tga_data( buffer, no_bytes, handle )byte *buffer;int no_bytes;FILE *handle;{ int aux1; byte aux[4]; Fread( aux, no_bytes, 1, handle ); if ( no_bytes < 3 ) { aux1 = ( aux[1] << 8 ) | aux[0]; *buffer++ = (aux1 & 0x7c00) >> 7; *buffer++ = (aux1 & 0x03e0) >> 2; *buffer++ = (aux1 & 0x001F) << 3; }else { *buffer++ = aux[2]; *buffer++ = aux[1]; *buffer++ = aux[0]; }}write_tga_file( name, image )char *name;bitmap_hdr *image;{ FILE *handle; /* Open the file descriptor */ if ( name != NULL ) handle = Fopen( name, "wb" ); else handle = stdout; /* Write the bitmap */ write_tga( handle, image, 0 ); /* Close the file */ Fclose( handle );}write_rle_tga_file( name, image )char *name;bitmap_hdr *image;{ FILE *handle; /* Open the file descriptor */ if ( name != NULL ) handle = Fopen( name, "wb" ); else handle = stdout; /* Write the bitmap */ write_tga( handle, image, 1 ); /* Close the file */ Fclose( handle );}write_tga(handle, image, rle)FILE *handle;bitmap_hdr *image;int rle;{ register int i; byte *r, *g, *b; if ( image->magic != LUGUSED ) error( 19 ); if ( image->depth <= 8 ) error( 7 ); /* Write the header */ write_tga_header( handle, image, rle ); /* Set the pointers */ r = image->r; g = image->g; b = image->b; /* Write each line *//* VPRINTF(stderr, "Writing Targa %s raster data\n", (rle ? "RLE" : "")); */ for ( i = 0; i < image->ysize; i++ ) { if ( !rle ) write_tga_line24( handle, r, g, b, image->xsize ); else write_tga_rle_line24( handle, r, g, b, image->xsize ); r += image->xsize; g += image->xsize; b += image->xsize; }}write_tga_header(handle, image, rle)FILE *handle;bitmap_hdr *image;int rle;{ byte buffer[ sizeof(tga_hdr) ];/* VPRINTF(stderr, "Writing Targa header\n"); */ /* First we fill with zero, then skip too asigments */ bzero( buffer, sizeof(tga_hdr) ); /* image_type */ if ( image->depth > 8 ) { if ( rle ) buffer[2] = TGA_RLE_RGB; else buffer[2] = TGA_RGB; }else { if ( rle ) buffer[2] = TGA_RLE_MAPPED; else buffer[2] = TGA_MAPPED; } buffer[12] = LSB( image->xsize ); buffer[13] = MSB( image->xsize ); /* the weigth */ buffer[14] = LSB( image->ysize ); buffer[15] = MSB( image->ysize ); /* the height */ buffer[16] = 24; /* Targa 24 => RGB */ buffer[17] = 32; /* flipped */ /* Write the header */ Fwrite( buffer, 18, 1, handle );}write_tga_line24(handle, r, g, b, xsize)FILE *handle;byte *r, *g, *b;int xsize;{ static byte buffer[3*2560]; byte *ptr; byte *end; end = r + xsize; ptr = buffer; /* Do a single buffer */ while ( r < end ) { *ptr++ = *b++; *ptr++ = *g++; *ptr++ = *r++; } /* Write it ! */ Fwrite( buffer, xsize, 3, handle );}write_tga_rle_line24(handle, r, g, b, xsize)FILE *handle;byte *r, *g, *b;int xsize;{ byte *end; byte cr, cb, cg; short repeat= 1; short diferent= 0; static byte salida[4*2560]; byte bufaux[4*256]; byte *ptr, *aux; ptr = salida; end = r + xsize + 1; cr = *r++; cg = *g++; cb = *b++; while ( r < end ) { while ( cr == *r && cg == *g && cb == *b && repeat < 127 && r < end) { r++, g++, b++; repeat++; } if (repeat > 1 ) { /* Put this information on our buffer */ *ptr++ = 128 | (repeat - 1); *ptr++ = cb; *ptr++ = cg; *ptr++ = cr; repeat = 1; cr = *r++; cg = *g++; cb = *b++; } aux= bufaux; /* * If there are diferents bytes, then we need * know how many. */ while ( (cr != *r || cg != *g || cb != *b) && diferent< 127 && r < end) { *aux++ = cb; *aux++ = cg; *aux++ = cr; cr = *r++; cg = *g++; cb = *b++; diferent++; } if (diferent) { *ptr++ = diferent - 1; bcopy( bufaux, ptr, 3*diferent ); ptr += 3*diferent; diferent = 0; } } Fwrite(salida, ptr-salida, 1, handle);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -