*** empty log message ***

This commit is contained in:
David Rose 2001-04-27 23:19:30 +00:00
parent 4d1a141e10
commit 892f7f4798
7 changed files with 1057 additions and 3 deletions

View File

@ -13,8 +13,8 @@
// Description: Reads a sequence of bytes from the beginning of the
// datagram file. This may be called any number of
// times after the file has been opened and before the
// first datagram is written. It may not be called once
// the first datagram is written.
// first datagram is read. It may not be called once
// the first datagram has been read.
////////////////////////////////////////////////////////////////////
bool DatagramInputFile::
read_header(string &header, size_t num_bytes) {

View File

@ -16,6 +16,7 @@
pnmFileTypeSGI.cxx pnmFileTypeSGI.h pnmFileTypeSGIReader.cxx \
pnmFileTypeSGIWriter.cxx pnmFileTypeSoftImage.cxx \
pnmFileTypeSoftImage.h pnmFileTypeTIFF.cxx pnmFileTypeTIFF.h \
pnmFileTypeTGA.cxx pnmFileTypeTGA.h \
pnmFileTypeYUV.cxx pnmFileTypeYUV.h \
color.c colrops.c resolu.c header.c

View File

@ -9,6 +9,7 @@
#include "pnmFileTypeAlias.h"
#include "pnmFileTypeRadiance.h"
#include "pnmFileTypeTIFF.h"
#include "pnmFileTypeTGA.h"
#include "pnmFileTypeYUV.h"
#include "pnmFileTypeIMG.h"
#include "pnmFileTypeSoftImage.h"
@ -29,6 +30,7 @@ NotifyCategoryDef(pnmimage_sgi, pnmimage_cat);
NotifyCategoryDef(pnmimage_alias, pnmimage_cat);
NotifyCategoryDef(pnmimage_radiance, pnmimage_cat);
NotifyCategoryDef(pnmimage_tiff, pnmimage_cat);
NotifyCategoryDef(pnmimage_tga, pnmimage_cat);
NotifyCategoryDef(pnmimage_yuv, pnmimage_cat);
NotifyCategoryDef(pnmimage_img, pnmimage_cat);
NotifyCategoryDef(pnmimage_soft, pnmimage_cat);
@ -47,6 +49,14 @@ const int radiance_brightness_adjustment = config_pnmimagetypes.GetInt("radiance
const int yuv_xsize = config_pnmimagetypes.GetInt("yuv-xsize", 720);
const int yuv_ysize = config_pnmimagetypes.GetInt("yuv-ysize", 486);
// TGA supports RLE compression, as well as colormapping and/or
// grayscale images. Set these true to enable these features, if
// possible, or false to disable them. Some programs (like xv) have
// difficulty reading these advanced TGA files.
const bool tga_rle = config_pnmimagetypes.GetBool("tga-rle", false);
const bool tga_colormap = config_pnmimagetypes.GetBool("tga-colormap", false);
const bool tga_grayscale = config_pnmimagetypes.GetBool("tga-grayscale", false);
// IMG format is just a sequential string of r, g, b bytes. However,
// it may or may not include a "header" which consists of the xsize
// and the ysize of the image, either as shorts or as longs.
@ -97,6 +107,7 @@ init_libpnmimagetypes() {
PNMFileTypeAlias::init_type();
PNMFileTypeRadiance::init_type();
PNMFileTypeTIFF::init_type();
PNMFileTypeTGA::init_type();
PNMFileTypeYUV::init_type();
PNMFileTypeIMG::init_type();
PNMFileTypeSoftImage::init_type();
@ -137,6 +148,7 @@ init_libpnmimagetypes() {
tr->register_type(new PNMFileTypeAlias);
tr->register_type(new PNMFileTypeRadiance);
tr->register_type(new PNMFileTypeTIFF);
tr->register_type(new PNMFileTypeTGA);
tr->register_type(new PNMFileTypeYUV);
tr->register_type(new PNMFileTypeIMG);
tr->register_type(new PNMFileTypeSoftImage);
@ -151,6 +163,7 @@ init_libpnmimagetypes() {
PNMFileTypeAlias::register_with_read_factory();
PNMFileTypeRadiance::register_with_read_factory();
PNMFileTypeTIFF::register_with_read_factory();
PNMFileTypeTGA::register_with_read_factory();
PNMFileTypeYUV::register_with_read_factory();
PNMFileTypeIMG::register_with_read_factory();
PNMFileTypeSoftImage::register_with_read_factory();

View File

@ -14,6 +14,7 @@ NotifyCategoryDecl(pnmimage_sgi, EXPCL_PANDA, EXPTP_PANDA);
NotifyCategoryDecl(pnmimage_alias, EXPCL_PANDA, EXPTP_PANDA);
NotifyCategoryDecl(pnmimage_radiance, EXPCL_PANDA, EXPTP_PANDA);
NotifyCategoryDecl(pnmimage_tiff, EXPCL_PANDA, EXPTP_PANDA);
NotifyCategoryDecl(pnmimage_tga, EXPCL_PANDA, EXPTP_PANDA);
NotifyCategoryDecl(pnmimage_yuv, EXPCL_PANDA, EXPTP_PANDA);
NotifyCategoryDecl(pnmimage_img, EXPCL_PANDA, EXPTP_PANDA);
NotifyCategoryDecl(pnmimage_soft, EXPCL_PANDA, EXPTP_PANDA);
@ -26,6 +27,9 @@ extern const double radiance_gamma_correction;
extern const int radiance_brightness_adjustment;
extern const int yuv_xsize;
extern const int yuv_ysize;
extern const bool tga_rle;
extern const bool tga_colormap;
extern const bool tga_grayscale;
extern const int jpeg_quality;
extern const int jpeg_scale_num;

View File

@ -0,0 +1,918 @@
// Filename: pnmFileTypeTGA.cxx
// Created by: drose (27Apr01)
//
////////////////////////////////////////////////////////////////////
// Much code in this file is borrowed from Netpbm, specifically tgatoppm.c
// and ppmtotga.c.
/* 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.
*/
/* ppmtotga.c - read a portable pixmap and produce a TrueVision Targa file
**
** Copyright (C) 1989, 1991 by Mark Shand and 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 "pnmFileTypeTGA.h"
#include "config_pnmimagetypes.h"
#include <pnmFileTypeRegistry.h>
#include <bamReader.h>
#include <ppm.h>
#include <string.h>
static const char * const extensions[] = {
"tga"
};
static const int num_extensions = sizeof(extensions) / sizeof(const char *);
TypeHandle PNMFileTypeTGA::_type_handle;
/* Header definition. */
struct ImageHeader {
unsigned char IDLength; /* length of Identifier String */
unsigned char CoMapType; /* 0 = no map */
unsigned char ImgType; /* image type (see below for values) */
unsigned char Index_lo, Index_hi; /* index of first color map entry */
unsigned char Length_lo, Length_hi; /* number of entries in color map */
unsigned char CoSize; /* size of color map entry (15,16,24,32) */
unsigned char X_org_lo, X_org_hi; /* x origin of image */
unsigned char Y_org_lo, Y_org_hi; /* y origin of image */
unsigned char Width_lo, Width_hi; /* width of image */
unsigned char Height_lo, Height_hi; /* height of image */
unsigned char PixelSize; /* pixel size (8,16,24,32) */
unsigned char AttBits; /* 4 bits, number of attribute bits per pixel */
unsigned char Rsrvd; /* 1 bit, reserved */
unsigned char OrgBit; /* 1 bit, origin: 0=lower left, 1=upper left */
unsigned char IntrLve; /* 2 bits, interleaving flag */
};
typedef char ImageIDField[256];
/* Definitions for image types. */
#define TGA_Null 0
#define TGA_Map 1
#define TGA_RGB 2
#define TGA_Mono 3
#define TGA_RLEMap 9
#define TGA_RLERGB 10
#define TGA_RLEMono 11
#define TGA_CompMap 32
#define TGA_CompMap4 33
/* Definitions for interleave flag. */
#define TGA_IL_None 0
#define TGA_IL_Two 1
#define TGA_IL_Four 2
////////////////////////////////////////////////////////////////////
// Function: PNMFileTypeTGA::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
PNMFileTypeTGA::
PNMFileTypeTGA() {
}
////////////////////////////////////////////////////////////////////
// Function: PNMFileTypeTGA::get_name
// Access: Public, Virtual
// Description: Returns a few words describing the file type.
////////////////////////////////////////////////////////////////////
string PNMFileTypeTGA::
get_name() const {
return "Targa";
}
////////////////////////////////////////////////////////////////////
// Function: PNMFileTypeTGA::get_num_extensions
// Access: Public, Virtual
// Description: Returns the number of different possible filename
// extensions associated with this particular file type.
////////////////////////////////////////////////////////////////////
int PNMFileTypeTGA::
get_num_extensions() const {
return num_extensions;
}
////////////////////////////////////////////////////////////////////
// Function: PNMFileTypeTGA::get_extension
// Access: Public, Virtual
// Description: Returns the nth possible filename extension
// associated with this particular file type, without a
// leading dot.
////////////////////////////////////////////////////////////////////
string PNMFileTypeTGA::
get_extension(int n) const {
nassertr(n >= 0 && n < num_extensions, string());
return extensions[n];
}
////////////////////////////////////////////////////////////////////
// Function: PNMFileTypeTGA::get_suggested_extension
// Access: Public, Virtual
// Description: Returns a suitable filename extension (without a
// leading dot) to suggest for files of this type, or
// empty string if no suggestions are available.
////////////////////////////////////////////////////////////////////
string PNMFileTypeTGA::
get_suggested_extension() const {
return "tga";
}
////////////////////////////////////////////////////////////////////
// Function: PNMFileTypeTGA::make_reader
// Access: Public, Virtual
// Description: Allocates and returns a new PNMReader suitable for
// reading from this file type, if possible. If reading
// from this file type is not supported, returns NULL.
////////////////////////////////////////////////////////////////////
PNMReader *PNMFileTypeTGA::
make_reader(FILE *file, bool owns_file, const string &magic_number) {
init_pnm();
return new Reader(this, file, owns_file, magic_number);
}
////////////////////////////////////////////////////////////////////
// Function: PNMFileTypeTGA::make_writer
// Access: Public, Virtual
// Description: Allocates and returns a new PNMWriter suitable for
// reading from this file type, if possible. If writing
// files of this type is not supported, returns NULL.
////////////////////////////////////////////////////////////////////
PNMWriter *PNMFileTypeTGA::
make_writer(FILE *file, bool owns_file) {
init_pnm();
return new Writer(this, file, owns_file);
}
////////////////////////////////////////////////////////////////////
// Function: PNMFileTypeTGA::Reader::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
PNMFileTypeTGA::Reader::
Reader(PNMFileType *type, FILE *file, bool owns_file, string magic_number) :
PNMReader(type, file, owns_file)
{
tga_head = new ImageHeader;
RLE_count = 0;
RLE_flag = 0;
/* Read the Targa file header. */
readtga( file, tga_head, magic_number );
/*
{
pm_message( "IDLength = %d", (int) tga_head->IDLength );
pm_message( "CoMapType = %d", (int) tga_head->CoMapType );
pm_message( "ImgType = %d", (int) tga_head->ImgType );
pm_message( "Index_lo = %d", (int) tga_head->Index_lo );
pm_message( "Index_hi = %d", (int) tga_head->Index_hi );
pm_message( "Length_lo = %d", (int) tga_head->Length_lo );
pm_message( "Length_hi = %d", (int) tga_head->Length_hi );
pm_message( "CoSize = %d", (int) tga_head->CoSize );
pm_message( "X_org_lo = %d", (int) tga_head->X_org_lo );
pm_message( "X_org_hi = %d", (int) tga_head->X_org_hi );
pm_message( "Y_org_lo = %d", (int) tga_head->Y_org_lo );
pm_message( "Y_org_hi = %d", (int) tga_head->Y_org_hi );
pm_message( "Width_lo = %d", (int) tga_head->Width_lo );
pm_message( "Width_hi = %d", (int) tga_head->Width_hi );
pm_message( "Height_lo = %d", (int) tga_head->Height_lo );
pm_message( "Height_hi = %d", (int) tga_head->Height_hi );
pm_message( "PixelSize = %d", (int) tga_head->PixelSize );
pm_message( "AttBits = %d", (int) tga_head->AttBits );
pm_message( "Rsrvd = %d", (int) tga_head->Rsrvd );
pm_message( "OrgBit = %d", (int) tga_head->OrgBit );
pm_message( "IntrLve = %d", (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 );
}
int size;
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. */
size = tga_head->CoSize;
}
else
{ /* Not colormap, so figure maxval from PixelSize. */
mapped = 0;
size = tga_head->PixelSize;
}
switch ( size ) {
case 8:
_num_channels = 1;
_maxval = 255;
break;
case 24:
_num_channels = 3;
_maxval = 255;
break;
case 32:
_num_channels = 4;
_maxval = 255;
break;
case 15:
case 16:
_num_channels = 3;
_maxval = 31;
break;
default:
pm_error("unknown pixel size - %d", size );
}
/* If required, read the color map information. */
if ( tga_head->CoMapType != 0 )
{
unsigned int temp1, temp2;
temp1 = tga_head->Index_lo + tga_head->Index_hi * 256;
temp2 = tga_head->Length_lo + tga_head->Length_hi * 256;
if ( ( temp1 + temp2 + 1 ) >= TGA_MAXCOLORS )
pm_error( "too many colors - %d", ( temp1 + temp2 + 1 ) );
for ( unsigned int i = temp1; i < ( temp1 + temp2 ); ++i )
get_map_entry( file, &ColorMap[i], (int) tga_head->CoSize,
&AlphaMap[i]);
}
/* 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;
_x_size = cols;
_y_size = rows;
_num_channels = 3;
}
////////////////////////////////////////////////////////////////////
// Function: PNMFileTypeTGA::Reader::Destructor
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
PNMFileTypeTGA::Reader::
~Reader() {
delete tga_head;
}
////////////////////////////////////////////////////////////////////
// Function: PNMFileTypeTGA::Reader::read_data
// Access: Public, Virtual
// Description: Reads in an entire image all at once, storing it in
// the pre-allocated _x_size * _y_size array and alpha
// pointers. (If the image type has no alpha channel,
// alpha is ignored.) Returns the number of rows
// correctly read.
//
// Derived classes need not override this if they
// instead provide supports_read_row() and read_row(),
// below.
////////////////////////////////////////////////////////////////////
int PNMFileTypeTGA::Reader::
read_data(xel *array, xelval *alpha) {
int truerow = 0;
int baserow = 0;
for ( int row = 0; row < rows; ++row )
{
int realrow = truerow;
if ( tga_head->OrgBit == 0 )
realrow = rows - realrow - 1;
for ( int col = 0; col < cols; ++col )
get_pixel( _file, &(array[realrow * cols + col]),
(int) tga_head->PixelSize,
&(alpha[realrow * cols + col]) );
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;
}
return rows;
}
////////////////////////////////////////////////////////////////////
// Function: PNMFileTypeTGA::Writer::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
PNMFileTypeTGA::Writer::
Writer(PNMFileType *type, FILE *file, bool owns_file) :
PNMWriter(type, file, owns_file)
{
tgaHeader = new ImageHeader;
chv = (colorhist_vector)0;
cht = (colorhash_table)0;
runlength = (int*)0;
}
////////////////////////////////////////////////////////////////////
// Function: PNMFileTypeTGA::Writer::Destructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
PNMFileTypeTGA::Writer::
~Writer() {
delete tgaHeader;
if (chv != (colorhist_vector)0) {
ppm_freecolorhist(chv);
}
if (cht != (colorhash_table)0) {
ppm_freecolorhash(cht);
}
if (runlength != (int *)0) {
pm_freerow((char *)runlength);
}
}
////////////////////////////////////////////////////////////////////
// Function: PNMFileTypeBMP::Writer::write_data
// Access: Public, Virtual
// Description: Writes out an entire image all at once, including the
// header, based on the image data stored in the given
// _x_size * _y_size array and alpha pointers. (If the
// image type has no alpha channel, alpha is ignored.)
// Returns the number of rows correctly written.
//
// It is the user's responsibility to fill in the header
// data via calls to set_x_size(), set_num_channels(),
// etc., or copy_header_from(), before calling
// write_data().
//
// It is important to delete the PNMWriter class after
// successfully writing the data. Failing to do this
// may result in some data not getting flushed!
//
// Derived classes need not override this if they
// instead provide supports_streaming() and write_row(),
// below.
////////////////////////////////////////////////////////////////////
int PNMFileTypeTGA::Writer::
write_data(xel *array, xelval *) {
// We don't presently support writing 4-channel tga files (since
// ppmtotga doesn't support this).
rle_flag = tga_rle;
int row, col;
int i;
pixel* pP;
cols = _x_size;
rows = _y_size;
if (is_grayscale() && tga_grayscale) {
// We allow grayscale TGA files, and this is a grayscale image, so...
tgaHeader->ImgType = TGA_Mono;
// There's no real point in colormapping a grayscale image.
pnmimage_tga_cat.info()
<< "writing grayscale.\n";
} else {
// This will be an RGB image.
tgaHeader->ImgType = TGA_RGB;
if (tga_colormap) {
// It may even be colormapped if there are few enough colors.
pnmimage_tga_cat.info()
<< "computing colormap...\n";
chv = ppm_computecolorhist(&array, cols * rows, 1, TGA_MAXCOLORS, &ncolors );
if ( chv == (colorhist_vector) 0 ) {
pnmimage_tga_cat.info()
<< "too many colors, writing RGB.\n";
} else {
pnmimage_tga_cat.info()
<< ncolors << " colors found.\n";
tgaHeader->ImgType = TGA_Map;
}
}
}
if ( rle_flag )
{
switch ( tgaHeader->ImgType )
{
case TGA_Mono:
tgaHeader->ImgType = TGA_RLEMono;
break;
case TGA_Map:
tgaHeader->ImgType = TGA_RLEMap;
break;
case TGA_RGB:
tgaHeader->ImgType = TGA_RLERGB;
break;
default:
pm_error( "can't happen" );
}
runlength = (int*) pm_allocrow( cols, sizeof(int) );
}
tgaHeader->IDLength = 0;
tgaHeader->Index_lo = 0;
tgaHeader->Index_hi = 0;
if ( tgaHeader->ImgType == TGA_Map || tgaHeader->ImgType == TGA_RLEMap )
{
/* Make a hash table for fast color lookup. */
cht = ppm_colorhisttocolorhash( chv, ncolors );
tgaHeader->CoMapType = 1;
tgaHeader->Length_lo = ncolors % 256;
tgaHeader->Length_hi = ncolors / 256;
tgaHeader->CoSize = 24;
}
else
{
tgaHeader->CoMapType = 0;
tgaHeader->Length_lo = 0;
tgaHeader->Length_hi = 0;
tgaHeader->CoSize = 0;
}
if ( tgaHeader->ImgType == TGA_RGB || tgaHeader->ImgType == TGA_RLERGB )
tgaHeader->PixelSize = 24;
else
tgaHeader->PixelSize = 8;
tgaHeader->X_org_lo = tgaHeader->X_org_hi = 0;
tgaHeader->Y_org_lo = tgaHeader->Y_org_hi = 0;
tgaHeader->Width_lo = cols % 256;
tgaHeader->Width_hi = cols / 256;
tgaHeader->Height_lo = rows % 256;
tgaHeader->Height_hi = rows / 256;
tgaHeader->AttBits = 0;
tgaHeader->Rsrvd = 0;
tgaHeader->IntrLve = 0;
tgaHeader->OrgBit = 0;
/* Write out the Targa header. */
writetga( tgaHeader, (char*) 0 );
if ( tgaHeader->ImgType == TGA_Map || tgaHeader->ImgType == TGA_RLEMap )
{
/* Write out the Targa colormap. */
for ( i = 0; i < ncolors; ++i )
put_map_entry( &chv[i].color, tgaHeader->CoSize, _maxval );
}
/* Write out the pixels */
for ( row = 0; row < rows; ++row )
{
int realrow = row;
if ( tgaHeader->OrgBit == 0 )
realrow = rows - realrow - 1;
if ( rle_flag )
{
compute_runlengths( cols, &array[realrow * cols], runlength );
for ( col = 0; col < cols; )
{
if ( runlength[col] > 0 )
{
fputc( 0x80 + runlength[col] - 1, _file );
put_pixel(&(array[realrow * cols + col]),
tgaHeader->ImgType, _maxval, cht );
col += runlength[col];
}
else if ( runlength[col] < 0 )
{
fputc( -runlength[col] - 1, _file );
for ( i = 0; i < -runlength[col]; ++i )
put_pixel(&(array[realrow * cols + (col + i)]),
tgaHeader->ImgType, _maxval, cht );
col += -runlength[col];
}
else
pm_error( "can't happen" );
}
}
else
{
for ( col = 0, pP = &array[realrow * cols]; col < cols; ++col, ++pP )
put_pixel( pP, tgaHeader->ImgType, _maxval, cht );
}
}
return rows;
}
////////////////////////////////////////////////////////////////////
// Function: PNMFileTypeTGA::register_with_read_factory
// Access: Public, Static
// Description: Registers the current object as something that can be
// read from a Bam file.
////////////////////////////////////////////////////////////////////
void PNMFileTypeTGA::
register_with_read_factory() {
BamReader::get_factory()->
register_factory(get_class_type(), make_PNMFileTypeTGA);
}
////////////////////////////////////////////////////////////////////
// Function: PNMFileTypeTGA::make_PNMFileTypeTGA
// Access: Protected, Static
// Description: This method is called by the BamReader when an object
// of this type is encountered in a Bam file; it should
// allocate and return a new object with all the data
// read.
//
// In the case of the PNMFileType objects, since these
// objects are all shared, we just pull the object from
// the registry.
////////////////////////////////////////////////////////////////////
TypedWriteable *PNMFileTypeTGA::
make_PNMFileTypeTGA(const FactoryParams &params) {
return PNMFileTypeRegistry::get_ptr()->get_type_by_handle(get_class_type());
}
void PNMFileTypeTGA::Reader::
readtga( FILE *ifp, struct ImageHeader *tgaP, const string &magic_number ) {
unsigned char flags;
ImageIDField junk;
if (magic_number.length() > 0) {
tgaP->IDLength = (unsigned char)magic_number[0];
} else {
tgaP->IDLength = getbyte( ifp );
}
if (magic_number.length() > 1) {
tgaP->CoMapType = (unsigned char)magic_number[1];
} else {
tgaP->CoMapType = getbyte( ifp );
}
if (magic_number.length() > 2) {
tgaP->ImgType = (unsigned char)magic_number[2];
} else {
tgaP->ImgType = getbyte( ifp );
}
if (magic_number.length() > 3) {
tgaP->Index_lo = (unsigned char)magic_number[3];
} else {
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 );
}
void PNMFileTypeTGA::Reader::
get_map_entry( FILE *ifp, pixel *Value, int Size, gray *Alpha ) {
unsigned char j, k, r, g, b, a;
/* 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 );
a = 0;
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;
a = 0;
break;
case 32: /* 8 bits each of blue, green, red, and alpha */
case 24: /* 8 bits each of blue green and red. */
b = getbyte( ifp );
g = getbyte( ifp );
r = getbyte( ifp );
if ( Size == 32 )
a = getbyte( ifp );
else
a = 0;
break;
default:
pm_error( "unknown colormap pixel size (#2) - %d", Size );
}
PPM_ASSIGN( *Value, r, g, b );
*Alpha = a;
}
void PNMFileTypeTGA::Reader::
get_pixel( FILE *ifp, pixel *dest, int Size, gray *alpha_p) {
static pixval Red, Grn, Blu;
static pixval Alpha;
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 );
Alpha = 0;
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;
Alpha = 0;
break;
case 32: /* 8 bits each of blue, green, red, and alpha */
case 24: /* 8 bits each of blue, green, and red. */
Blu = getbyte( ifp );
Grn = getbyte( ifp );
Red = getbyte( ifp );
if ( Size == 32 )
Alpha = getbyte( ifp );
else
Alpha = 0;
l = 0;
break;
default:
pm_error( "unknown pixel size (#2) - %d", Size );
}
PixEncode:
if ( mapped ) {
*dest = ColorMap[l];
if (has_alpha()) {
*alpha_p = AlphaMap[l];
}
} else {
PPM_ASSIGN( *dest, Red, Grn, Blu );
if (has_alpha()) {
*alpha_p = Alpha;
}
}
}
unsigned char PNMFileTypeTGA::Reader::
getbyte( FILE *ifp ) {
unsigned char c;
if ( fread( (char*) &c, 1, 1, ifp ) != 1 )
pm_error( "EOF / read error" );
return c;
}
void PNMFileTypeTGA::Writer::
writetga( struct ImageHeader *tgaP, char *id )
{
unsigned char flags;
fputc( tgaP->IDLength, _file );
fputc( tgaP->CoMapType, _file );
fputc( tgaP->ImgType, _file );
fputc( tgaP->Index_lo, _file );
fputc( tgaP->Index_hi, _file );
fputc( tgaP->Length_lo, _file );
fputc( tgaP->Length_hi, _file );
fputc( tgaP->CoSize, _file );
fputc( tgaP->X_org_lo, _file );
fputc( tgaP->X_org_hi, _file );
fputc( tgaP->Y_org_lo, _file );
fputc( tgaP->Y_org_hi, _file );
fputc( tgaP->Width_lo, _file );
fputc( tgaP->Width_hi, _file );
fputc( tgaP->Height_lo, _file );
fputc( tgaP->Height_hi, _file );
fputc( tgaP->PixelSize, _file );
flags = ( tgaP->AttBits & 0xf ) | ( ( tgaP->Rsrvd & 0x1 ) << 4 ) |
( ( tgaP->OrgBit & 0x1 ) << 5 ) | ( ( tgaP->OrgBit & 0x3 ) << 6 );
fputc( flags, _file );
if ( tgaP->IDLength )
fwrite( id, 1, (int) tgaP->IDLength, _file );
}
void PNMFileTypeTGA::Writer::
put_map_entry( pixel* valueP, int size, pixval maxval )
{
int j;
pixel p;
switch ( size )
{
case 8: /* Grey scale. */
put_mono( valueP, maxval );
break;
case 16: /* 5 bits each of red green and blue. */
case 15: /* Watch for byte order. */
PPM_DEPTH( p, *valueP, maxval, 31 );
j = (int) PPM_GETB( p ) | ( (int) PPM_GETG( p ) << 5 ) |
( (int) PPM_GETR( p ) << 10 );
fputc( j % 256, _file );
fputc( j / 256, _file );
break;
case 32:
case 24: /* 8 bits each of blue green and red. */
put_rgb( valueP, maxval );
break;
default:
pm_error( "unknown colormap pixel size (#2) - %d", size );
}
}
void PNMFileTypeTGA::Writer::
compute_runlengths( int cols, pixel *pixelrow, int *runlength )
{
int col, start;
/* Initialize all run lengths to 0. (This is just an error check.) */
for ( col = 0; col < cols; ++col )
runlength[col] = 0;
/* Find runs of identical pixels. */
for ( col = 0; col < cols; )
{
start = col;
do {
++col;
}
while ( col < cols &&
col - start < 128 &&
PPM_EQUAL( pixelrow[col], pixelrow[start] ) );
runlength[start] = col - start;
}
/* Now look for runs of length-1 runs, and turn them into negative runs. */
for ( col = 0; col < cols; )
{
if ( runlength[col] == 1 )
{
start = col;
while ( col < cols &&
col - start < 128 &&
runlength[col] == 1 )
{
runlength[col] = 0;
++col;
}
runlength[start] = - ( col - start );
}
else
col += runlength[col];
}
}
void PNMFileTypeTGA::Writer::
put_pixel( pixel* pP, int imgtype, pixval maxval, colorhash_table cht )
{
switch ( imgtype )
{
case TGA_Mono:
case TGA_RLEMono:
put_mono( pP, maxval );
break;
case TGA_Map:
case TGA_RLEMap:
put_map( pP, cht );
break;
case TGA_RGB:
case TGA_RLERGB:
put_rgb( pP, maxval );
break;
default:
pm_error( "can't happen" );
}
}
void PNMFileTypeTGA::Writer::
put_mono( pixel* pP, pixval maxval )
{
pixel p;
PPM_DEPTH( p, *pP, maxval, (pixval) 255 );
fputc( PPM_GETB( p ), _file );
}
void PNMFileTypeTGA::Writer::
put_map( pixel *pP, colorhash_table cht )
{
fputc( ppm_lookupcolor( cht, pP ), _file );
}
void PNMFileTypeTGA::Writer::
put_rgb( pixel* pP, pixval maxval ) {
pixel p;
PPM_DEPTH( p, *pP, maxval, (pixval) 255 );
fputc( PPM_GETB( p ), _file );
if (is_grayscale()) {
fputc( PPM_GETB( p ), _file );
fputc( PPM_GETB( p ), _file );
} else {
fputc( PPM_GETG( p ), _file );
fputc( PPM_GETR( p ), _file );
}
}

View File

@ -0,0 +1,118 @@
// Filename: pnmFileTypeTGA.h
// Created by: drose (27Apr01)
//
////////////////////////////////////////////////////////////////////
#ifndef PNMFILETYPETGA_H
#define PNMFILETYPETGA_H
#include <pandabase.h>
#include <pnmFileType.h>
#include <pnmReader.h>
#include <pnmWriter.h>
extern "C" {
#include <ppmcmap.h>
}
struct ImageHeader;
/* Max number of colors allowed for colormapped output. */
#define TGA_MAXCOLORS 256
////////////////////////////////////////////////////////////////////
// Class : PNMFileTypeTGA
// Description : For reading and writing Targa image files.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA PNMFileTypeTGA : public PNMFileType {
public:
PNMFileTypeTGA();
virtual string get_name() const;
virtual int get_num_extensions() const;
virtual string get_extension(int n) const;
virtual string get_suggested_extension() const;
virtual PNMReader *make_reader(FILE *file, bool owns_file = true,
const string &magic_number = string());
virtual PNMWriter *make_writer(FILE *file, bool owns_file = true);
public:
class Reader : public PNMReader {
public:
Reader(PNMFileType *type, FILE *file, bool owns_file, string magic_number);
virtual ~Reader();
virtual int read_data(xel *array, xelval *alpha);
private:
void readtga ( FILE* ifp, struct ImageHeader* tgaP, const string &magic_number );
void get_map_entry ( FILE* ifp, pixel* Value, int Size,
gray* Alpha);
void get_pixel ( FILE* ifp, pixel* dest, int Size, gray* alpha_p);
unsigned char getbyte ( FILE* ifp );
int rows, cols, rlencoded, mapped;
struct ImageHeader *tga_head;
pixel ColorMap[TGA_MAXCOLORS];
gray AlphaMap[TGA_MAXCOLORS];
int RLE_count, RLE_flag;
};
class Writer : public PNMWriter {
public:
Writer(PNMFileType *type, FILE *file, bool owns_file);
virtual ~Writer();
virtual int write_data(xel *array, xelval *alpha);
private:
void writetga ( struct ImageHeader* tgaP, char* id );
void put_map_entry ( pixel* valueP, int size, pixval maxval );
void compute_runlengths ( int cols, pixel* pixelrow, int* runlength );
void put_pixel ( pixel* pP, int imgtype, pixval maxval, colorhash_table cht );
void put_mono ( pixel* pP, pixval maxval );
void put_map ( pixel* pP, colorhash_table cht );
void put_rgb ( pixel* pP, pixval maxval );
int rle_flag;
int rows, cols;
struct ImageHeader *tgaHeader;
colorhist_vector chv;
colorhash_table cht;
int ncolors;
int *runlength;
};
// The TypedWriteable interface follows.
public:
static void register_with_read_factory();
protected:
static TypedWriteable *make_PNMFileTypeTGA(const FactoryParams &params);
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
PNMFileType::init_type();
register_type(_type_handle, "PNMFileTypeTGA",
PNMFileType::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
};
#endif

View File

@ -14,7 +14,7 @@
////////////////////////////////////////////////////////////////////
// Class : PNMFileTypeYUV
// Description : For reading and Abekas YUV files.
// Description : For reading and writing Abekas YUV files.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA PNMFileTypeYUV : public PNMFileType {
public: