*** empty log message ***

This commit is contained in:
David Rose 2000-11-03 19:24:06 +00:00
parent d0e0566716
commit efdb07d62f
25 changed files with 197 additions and 3647 deletions

View File

@ -49,6 +49,7 @@ ConfigureFn(config_egg) {
EggComment::init_type();
EggCoordinateSystem::init_type();
EggCurve::init_type();
EggData::init_type();
EggExternalReference::init_type();
EggFilenameNode::init_type();
EggGroup::init_type();

View File

@ -17,6 +17,8 @@ extern int eggyyparse(void);
#include "parserDefs.h"
#include "lexerDefs.h"
TypeHandle EggData::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: EggData::resolve_egg_filename
// Access: Public, Static

View File

@ -62,6 +62,23 @@ private:
CoordinateSystem _coordsys;
Filename _egg_filename;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
EggGroupNode::init_type();
register_type(_type_handle, "EggData",
EggGroupNode::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;
};
#include "eggData.I"

View File

@ -116,7 +116,6 @@ private:
public:
static TypeHandle get_class_type() {
return _type_handle;
}

View File

@ -22,8 +22,28 @@ LODSwitch(float in, float out) {
////////////////////////////////////////////////////////////////////
INLINE void LODSwitch::
get_range(float &in, float &out) const {
in = sqrtf(_in);
out = sqrtf(_out);
in = get_in();
out = get_out();
}
////////////////////////////////////////////////////////////////////
// Function: LODSwitch::get_in
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE float LODSwitch::
get_in() const {
return sqrtf(_in);
}
////////////////////////////////////////////////////////////////////
// Function: LODSwitch::get_out
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE float LODSwitch::
get_out() const {
return sqrtf(_out);
}
////////////////////////////////////////////////////////////////////

View File

@ -10,6 +10,7 @@
#include <datagram.h>
#include <datagramIterator.h>
#include <indent.h>
////////////////////////////////////////////////////////////////////
// Static variables
@ -127,3 +128,46 @@ read_datagram(DatagramIterator &source) {
_switch_vector.back().read_datagram(source);
}
}
////////////////////////////////////////////////////////////////////
// Function: LOD::output
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
void LOD::
output(ostream &out) const {
if (_switch_vector.empty()) {
out << "no switches.";
} else {
LODSwitchVector::const_iterator si;
si = _switch_vector.begin();
out << "(" << (*si).get_in() << "/" << (*si).get_out() << ")";
++si;
while (si != _switch_vector.end()) {
out << " (" << (*si).get_in() << "/" << (*si).get_out() << ")";
++si;
}
}
}
////////////////////////////////////////////////////////////////////
// Function: LOD::write
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
void LOD::
write(ostream &out, int indent_level) const {
indent(out, indent_level)
<< "LOD, " << _switch_vector.size() << " switches:\n";
LODSwitchVector::const_iterator si;
int i = 0;
for (si = _switch_vector.begin();
si != _switch_vector.end();
++si) {
indent(out, indent_level + 2)
<< i << ". in at " << (*si).get_in()
<< ", out at " << (*si).get_out() << "\n";
i++;
}
}

View File

@ -11,9 +11,8 @@
////////////////////////////////////////////////////////////////////
#include <pandabase.h>
#include <typeHandle.h>
#include <luse.h>
#include <referenceCount.h>
#include <typedReferenceCount.h>
class Datagram;
class DatagramIterator;
@ -34,6 +33,8 @@ class EXPCL_PANDA LODSwitch {
public:
INLINE LODSwitch(float in, float out);
INLINE void get_range(float &in, float &out) const;
INLINE float get_in() const;
INLINE float get_out() const;
INLINE void set_range(float in, float out);
INLINE bool in_range(float dist_squared) const;
@ -61,7 +62,7 @@ typedef vector<LODSwitch> LODSwitchVector;
// Description : Computes whether a level-of-detail should be rendered
// or not based on distance from the rendering camera.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA LOD : public ReferenceCount, public TypedObject {
class EXPCL_PANDA LOD : public TypedReferenceCount {
public:
LOD(void);
LOD(const LOD &copy);
@ -75,6 +76,9 @@ public:
void write_datagram(Datagram &destination) const;
void read_datagram(DatagramIterator &source);
void output(ostream &out) const;
void write(ostream &out, int indent_level = 0) const;
public:
LPoint3f _center;
LODSwitchVector _switch_vector;
@ -84,11 +88,9 @@ public:
return _type_handle;
}
static void init_type() {
ReferenceCount::init_type();
TypedObject::init_type();
TypedReferenceCount::init_type();
register_type(_type_handle, "LOD",
ReferenceCount::get_class_type(),
TypedObject::get_class_type());
TypedReferenceCount::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
@ -99,6 +101,11 @@ private:
static TypeHandle _type_handle;
};
INLINE ostream &operator << (ostream &out, const LOD &lod) {
lod.output(out);
return out;
}
#include "LOD.I"
#endif

View File

@ -1,178 +0,0 @@
// pnm-image-alias.cc
//
// PNMImage::ReadAlias()
// PNMImage::WriteAlias()
#include <pandabase.h>
#include "pnmImage.h"
#include "pnmReader.h"
#include "pnmReaderTypes.h"
#include "pnmWriter.h"
#include "pnmWriterTypes.h"
// Since Alias image files don't have a magic number, we'll make a little
// sanity check on the size of the image. If either the width or height is
// larger than this, it must be bogus.
#define INSANE_SIZE 20000
inline unsigned short
read_ushort(FILE *file) {
unsigned short x;
return pm_readbigshort(file, (short *)&x)==0 ? x : 0;
}
inline unsigned char
read_uchar(FILE *file) {
int x;
x = getc(file);
return (x!=EOF) ? (unsigned char)x : 0;
}
inline void
write_ushort(FILE *file, unsigned short x) {
pm_writebigshort(file, (short)x);
}
inline void
write_uchar(FILE *file, unsigned char x) {
putc(x, file);
}
PNMReaderAlias::
PNMReaderAlias(FILE *file, int already_read_magic) : PNMReader(file) {
if (already_read_magic >= 0) {
cols = already_read_magic;
} else {
cols = read_ushort(file);
}
rows = read_ushort(file);
if (cols==0 || rows==0 ||
cols>INSANE_SIZE || rows>INSANE_SIZE) {
valid = false;
return;
}
read_ushort(file);
read_ushort(file);
int bpp = read_ushort(file);
switch (bpp) {
case 8:
color_type = PNMImage::Grayscale;
break;
case 24:
color_type = PNMImage::Color;
break;
default:
valid = false;
return;
}
maxval = 255;
}
bool PNMReaderAlias::
ReadRow(xel *row, xelval *) {
int x;
int num;
unsigned char red, grn, blu;
x = 0;
while (x < cols) {
num = read_uchar(file);
if (num==0 || x+num > cols) {
return false;
}
blu = read_uchar(file);
if (color_type == PNMImage::Color) {
grn = read_uchar(file);
red = read_uchar(file);
while (num>0) {
PPM_ASSIGN(row[x], red, grn, blu);
x++;
num--;
}
} else {
while (num>0) {
PPM_PUTB(row[x], blu);
x++;
num--;
}
}
}
return true;
}
static unsigned char last_red = 0, last_blu = 0, last_grn = 0;
static int num_count = 0;
static void
flush_color(FILE *file) {
if (num_count>0) {
write_uchar(file, num_count);
write_uchar(file, last_blu);
write_uchar(file, last_grn);
write_uchar(file, last_red);
num_count = 0;
}
}
static void
write_color(FILE *file,
unsigned char red, unsigned char blu, unsigned char grn) {
if (red==last_red && blu==last_blu && grn==last_grn && num_count<0377) {
num_count++;
} else {
flush_color(file);
last_red = red;
last_grn = grn;
last_blu = blu;
num_count = 1;
}
}
bool PNMWriterAlias::
WriteHeader() {
write_ushort(file, cols);
write_ushort(file, rows);
write_ushort(file, 0);
write_ushort(file, 0);
// We'll always write full-color Alias images, even if the source was
// grayscale. Many programs don't seem to understand grayscale Alias images.
write_ushort(file, 24);
return true;
}
bool PNMWriterAlias::
WriteRow(xel *row_data, xelval *) {
int x;
unsigned char red, grn, blu;
int is_grayscale = PNMImage::IsGrayscale(color_type);
for (x = 0; x<cols; x++) {
if (is_grayscale) {
red = grn = blu = (unsigned char)(255*PPM_GETB(row_data[x])/maxval);
} else {
red = (unsigned char)(255*PPM_GETR(row_data[x])/maxval);
grn = (unsigned char)(255*PPM_GETG(row_data[x])/maxval);
blu = (unsigned char)(255*PPM_GETB(row_data[x])/maxval);
}
write_color(file, red, blu, grn);
}
flush_color(file);
return true;
}

View File

@ -1,103 +0,0 @@
// pnm-image-img.cc
//
// PNMImage::ReadImg()
// PNMImage::WriteImg()
#include <pandabase.h>
#include "pnmImage.h"
#include "pnmReader.h"
#include "pnmReaderTypes.h"
#include "pnmWriter.h"
#include "pnmWriterTypes.h"
// Since raw image files don't have a magic number, we'll make a little
// sanity check on the size of the image. If either the width or height is
// larger than this, it must be bogus.
#define INSANE_SIZE 20000
inline unsigned long
read_ulong(FILE *file) {
unsigned long x;
return pm_readbiglong(file, (long *)&x)==0 ? x : 0;
}
inline unsigned short
read_ushort(FILE *file) {
unsigned short x;
return pm_readbigshort(file, (short *)&x)==0 ? x : 0;
}
inline unsigned char
read_uchar(FILE *file) {
int x;
x = getc(file);
return (x!=EOF) ? (unsigned char)x : 0;
}
inline void
write_ulong(FILE *file, unsigned long x) {
pm_writebiglong(file, (long)x);
}
inline void
write_uchar(FILE *file, unsigned char x) {
putc(x, file);
}
PNMReaderIMG::
PNMReaderIMG(FILE *file, int already_read_magic) : PNMReader(file) {
if (already_read_magic>=0) {
cols = (already_read_magic << 16) | read_ushort(file);
} else {
cols = (int)read_ulong(file);
}
rows = (int)read_ulong(file);
color_type = PNMImage::Color;
if (cols==0 || rows==0 ||
cols>INSANE_SIZE || rows>INSANE_SIZE) {
valid = false;
return;
}
maxval = 255;
}
bool PNMReaderIMG::
ReadRow(xel *row, xelval *) {
int x;
xelval red, grn, blu;
for (x = 0; x<cols; x++) {
red = read_uchar(file);
grn = read_uchar(file);
blu = read_uchar(file);
PPM_ASSIGN(row[x], red, grn, blu);
}
return true;
}
bool PNMWriterIMG::
WriteHeader() {
write_ulong(file, cols);
write_ulong(file, rows);
return true;
}
bool PNMWriterIMG::
WriteRow(xel *row_data, xelval *) {
int x;
for (x = 0; x<cols; x++) {
write_uchar(file, (unsigned char)(255*PPM_GETR(row_data[x])/maxval));
write_uchar(file, (unsigned char)(255*PPM_GETG(row_data[x])/maxval));
write_uchar(file, (unsigned char)(255*PPM_GETB(row_data[x])/maxval));
}
return true;
}

View File

@ -1,151 +0,0 @@
// pnm-image-radiance.cc
//
// PNMImage::ReadRadiance() and PNMImage::WriteRadiance().
// Code in this file was initially taken from ra_skel.c, a skeletal Radiance
// picture file conversion program provided on the Radiance WWW server, and
// heavily modified.
/* Copyright (c) 1992 Regents of the University of California */
/*
* Skeletal 24-bit image conversion program. Replace "skel"
* in this file with a more appropriate image type identifier.
*
* The Rmakefile entry should look something like this:
* ra_skel: ra_skel.o
* cc $(CFLAGS) -o ra_skel ra_skel.o -lrt -lm
* ra_skel.o: ../common/color.h ../common/resolu.h
*
* If you like to do things the hard way, you can link directly
* to the object files "color.o colrops.o resolu.o header.o" in
* the common subdirectory instead of using the -lrt library.
*/
#include <pandabase.h>
#include <stdio.h>
#include <math.h>
#include "pnmImage.h"
#include "pnmReader.h"
#include "pnmReaderTypes.h"
#include "pnmWriter.h"
#include "pnmWriterTypes.h"
extern "C" {
#include "color.h"
#include "resolu.h"
void setcolrgam(double);
int checkheader(FILE *, char *, FILE *);
int fgetresolu(int *, int *, FILE *);
int freadcolrs(COLR *, int, FILE *);
int fwritecolrs(COLR *, unsigned, FILE *);
void fputformat(char *, FILE *);
void shiftcolrs(COLR *, int, int);
void colrs_gambs(COLR *, int);
void newheader(char *, FILE *);
void printargs(int, char **, FILE *);
void gambs_colrs(COLR *, int);
}
double gamcor = 2.2; /* gamma correction */
int bradj = 0; /* brightness adjustment */
static const int COLR_MAX = 255;
PNMReaderRadiance::
PNMReaderRadiance(FILE *file, int already_read_magic) : PNMReader(file) {
setcolrgam(gamcor); /* set up gamma correction */
if (already_read_magic >= 0) {
ungetc(already_read_magic >> 8, file);
ungetc(already_read_magic & 0xff, file);
}
/* get our header */
if (checkheader(file, COLRFMT, NULL) < 0 ||
fgetresolu(&cols, &rows, file) < 0) {
valid = false;
return;
}
color_type = PNMImage::Color;
maxval = COLR_MAX;
}
bool PNMReaderRadiance::
ReadRow(xel *row_data, xelval *) {
COLR *scanin;
int x;
scanin = (COLR *)alloca(cols * sizeof(COLR));
if (freadcolrs(scanin, cols, file) < 0) {
return false;
}
if (bradj) { /* adjust exposure */
shiftcolrs(scanin, cols, bradj);
}
colrs_gambs(scanin, cols); /* gamma correction */
for (x = 0; x < cols; x++) {
PPM_ASSIGN(row_data[x], scanin[x][RED], scanin[x][GRN], scanin[x][BLU]);
}
return true;
}
bool PNMWriterRadiance::
WriteHeader() {
setcolrgam(gamcor); /* set up gamma correction */
/* put our header */
newheader("RADIANCE", file);
fputs("Generated via DRR's pnm-image library\n", file);
fputformat(COLRFMT, file);
putc('\n', file);
fprtresolu(cols, rows, file);
return true;
}
bool PNMWriterRadiance::
WriteRow(xel *row_data, xelval *) {
/* convert file */
int is_grayscale = PNMImage::IsGrayscale(color_type);
COLR *scanout;
int x;
/* allocate scanline */
scanout = (COLR *)alloca(cols * sizeof(COLR));
/* convert image */
for (x = 0; x < cols; x++) {
if (is_grayscale) {
scanout[x][RED] =
scanout[x][GRN] =
scanout[x][BLU] = (BYTE)((int)COLR_MAX * PPM_GETB(row_data[x]) / maxval);
} else {
scanout[x][RED] = (BYTE)((int)COLR_MAX * PPM_GETR(row_data[x]) / maxval);
scanout[x][GRN] = (BYTE)((int)COLR_MAX * PPM_GETG(row_data[x]) / maxval);
scanout[x][BLU] = (BYTE)((int)COLR_MAX * PPM_GETB(row_data[x]) / maxval);
}
}
/* undo gamma */
gambs_colrs(scanout, cols);
if (bradj) /* adjust exposure */
shiftcolrs(scanout, cols, bradj);
if (fwritecolrs(scanout, cols, file) < 0)
return false;
return true;
}

View File

@ -1,515 +0,0 @@
// pnm-image-readbmp.cc
//
// PNMImage::ReadBMP() and supporting functions.
// Much code in this file is borrowed from Netpbm, specifically bmptoppm.c.
/*\
* $Id$
*
* bmptoppm.c - Converts from a Microsoft Windows or OS/2 .BMP file to a
* PPM file.
*
* The current implementation is probably not complete, but it works for
* all the BMP files I have. I welcome feedback.
*
* Copyright (C) 1992 by David W. Sanderson.
*
* 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.
*
* $Log$
* Revision 1.2 2000/10/17 21:49:09 drose
* *** empty log message ***
*
* Revision 1.1.1.1 2000/10/04 01:14:42 drose
*
*
* Revision 1.10 1992/11/24 19:38:17 dws
* Added code to verify that reading occurred at the correct offsets.
* Added copyright.
*
* Revision 1.9 1992/11/17 02:15:24 dws
* Changed to include bmp.h.
* Eliminated need for fseek(), and therefore the need for a
* temporary file.
*
* Revision 1.8 1992/11/13 23:48:57 dws
* Made definition of Seekable() static, to match its prototype.
*
* Revision 1.7 1992/11/11 00:17:50 dws
* Generalized to use bitio routines.
*
* Revision 1.6 1992/11/10 23:51:44 dws
* Enhanced command-line handling.
*
* Revision 1.5 1992/11/08 00:38:46 dws
* Changed some names to help w/ addition of ppmtobmp.
*
* Revision 1.4 1992/10/27 06:28:28 dws
* Corrected stupid typo.
*
* Revision 1.3 1992/10/27 06:17:10 dws
* Removed a magic constant value.
*
* Revision 1.2 1992/10/27 06:09:58 dws
* Made stdin seekable.
*
* Revision 1.1 1992/10/27 05:31:41 dws
* Initial revision
\*/
#include "pnmImage.h"
#include "pnmReader.h"
#include "pnmReaderTypes.h"
extern "C" {
#include "../pnm/bmp.h"
#include "../pnm/bitio.h"
}
static char *ifname;
/*
* Utilities
*/
static int GetByte ARGS((FILE * fp));
static short GetShort ARGS((FILE * fp));
static long GetLong ARGS((FILE * fp));
static void readto ARGS((FILE *fp, unsigned long *ppos, unsigned long dst));
static void BMPreadfileheader ARGS((FILE *fp, unsigned long *ppos,
unsigned long *poffBits));
static void BMPreadinfoheader ARGS((FILE *fp, unsigned long *ppos,
unsigned long *pcx, unsigned long *pcy, unsigned short *pcBitCount,
int *pclassv));
static int BMPreadrgbtable ARGS((FILE *fp, unsigned long *ppos,
unsigned short cBitCount, int classv, pixval *R, pixval *G, pixval *B));
static int BMPreadrow ARGS((FILE *fp, unsigned long *ppos, pixel *row,
unsigned long cx, unsigned short cBitCount, pixval *R, pixval *G, pixval *B));
static pixel ** BMPreadbits ARGS((FILE *fp, unsigned long *ppos,
unsigned long offBits, unsigned long cx, unsigned long cy,
unsigned short cBitCount, int classv, pixval *R, pixval *G, pixval *B));
static char er_read[] = "%s: read error";
static char er_seek[] = "%s: seek error";
static int
GetByte(FILE *fp)
{
int v;
if ((v = getc(fp)) == EOF)
{
pm_error(er_read, ifname);
}
return v;
}
static short
GetShort(FILE *fp)
{
short v;
if (pm_readlittleshort(fp, &v) == -1)
{
pm_error(er_read, ifname);
}
return v;
}
static long
GetLong(FILE *fp)
{
long v;
if (pm_readlittlelong(fp, &v) == -1)
{
pm_error(er_read, ifname);
}
return v;
}
/*
* readto - read as many bytes as necessary to position the
* file at the desired offset.
*/
static void
readto(FILE *fp,
unsigned long *ppos, /* pointer to number of bytes read from fp */
unsigned long dst)
{
unsigned long pos;
if(!fp || !ppos)
return;
pos = *ppos;
if(pos > dst)
pm_error("%s: internal error in readto()", ifname);
for(; pos < dst; pos++)
{
if (getc(fp) == EOF)
{
pm_error(er_read, ifname);
}
}
*ppos = pos;
}
/*
* BMP reading routines
*/
static void
BMPreadfileheader(
FILE *fp,
unsigned long *ppos, /* number of bytes read from fp */
unsigned long *poffBits)
{
/*
unsigned long cbSize;
unsigned short xHotSpot;
unsigned short yHotSpot;
*/
unsigned long offBits;
/*
We've already read the magic number.
if (GetByte(fp) != 'B')
{
pm_error("%s is not a BMP file", ifname);
}
if (GetByte(fp) != 'M')
{
pm_error("%s is not a BMP file", ifname);
}
*/
/* cbSize = */ GetLong(fp);
/* xHotSpot = */ GetShort(fp);
/* yHotSpot = */ GetShort(fp);
offBits = GetLong(fp);
*poffBits = offBits;
*ppos += 14;
}
static void
BMPreadinfoheader(
FILE *fp,
unsigned long *ppos, /* number of bytes read from fp */
unsigned long *pcx,
unsigned long *pcy,
unsigned short *pcBitCount,
int *pclassv)
{
unsigned long cbFix;
unsigned short cPlanes;
unsigned long cx;
unsigned long cy;
unsigned short cBitCount;
int classv;
cbFix = GetLong(fp);
switch (cbFix)
{
case 12:
classv = C_OS2;
cx = GetShort(fp);
cy = GetShort(fp);
cPlanes = GetShort(fp);
cBitCount = GetShort(fp);
break;
case 40:
classv = C_WIN;
cx = GetLong(fp);
cy = GetLong(fp);
cPlanes = GetShort(fp);
cBitCount = GetShort(fp);
/*
* We've read 16 bytes so far, need to read 24 more
* for the required total of 40.
*/
GetLong(fp);
GetLong(fp);
GetLong(fp);
GetLong(fp);
GetLong(fp);
GetLong(fp);
break;
default:
pm_error("%s: unknown cbFix: %d", ifname, cbFix);
break;
}
if (cPlanes != 1)
{
pm_error("%s: don't know how to handle cPlanes = %d"
,ifname
,cPlanes);
}
switch (classv)
{
case C_WIN:
pm_message("Windows BMP, %dx%dx%d"
,cx
,cy
,cBitCount);
break;
case C_OS2:
pm_message("OS/2 BMP, %dx%dx%d"
,cx
,cy
,cBitCount);
break;
}
#ifdef DEBUG
pm_message("cbFix: %d", cbFix);
pm_message("cx: %d", cx);
pm_message("cy: %d", cy);
pm_message("cPlanes: %d", cPlanes);
pm_message("cBitCount: %d", cBitCount);
#endif
*pcx = cx;
*pcy = cy;
*pcBitCount = cBitCount;
*pclassv = classv;
*ppos += cbFix;
}
/*
* returns the number of bytes read, or -1 on error.
*/
static int
BMPreadrgbtable(
FILE *fp,
unsigned long *ppos, /* number of bytes read from fp */
unsigned short cBitCount,
int classv,
pixval *R,
pixval *G,
pixval *B)
{
int i;
int nbyte = 0;
long ncolors = (1 << cBitCount);
for (i = 0; i < ncolors; i++)
{
B[i] = (pixval) GetByte(fp);
G[i] = (pixval) GetByte(fp);
R[i] = (pixval) GetByte(fp);
nbyte += 3;
if (classv == C_WIN)
{
(void) GetByte(fp);
nbyte++;
}
}
*ppos += nbyte;
return nbyte;
}
/*
* returns the number of bytes read, or -1 on error.
*/
static int
BMPreadrow(
FILE *fp,
unsigned long *ppos, /* number of bytes read from fp */
pixel *row,
unsigned long cx,
unsigned short cBitCount,
int indexed,
pixval *R,
pixval *G,
pixval *B)
{
BITSTREAM b;
unsigned nbyte = 0;
int rc;
unsigned x;
if (indexed) {
if ((b = pm_bitinit(fp, "r")) == (BITSTREAM) 0)
{
return -1;
}
}
for (x = 0; x < cx; x++, row++)
{
unsigned long v;
if (!indexed) {
int r, g, b;
b = GetByte(fp);
g = GetByte(fp);
r = GetByte(fp);
nbyte += 3;
PPM_ASSIGN(*row, r, g, b);
} else {
if ((rc = pm_bitread(b, cBitCount, &v)) == -1)
{
return -1;
}
nbyte += rc;
PPM_ASSIGN(*row, R[v], G[v], B[v]);
}
}
if (indexed) {
if ((rc = pm_bitfini(b)) != 0)
{
return -1;
}
}
/*
* Make sure we read a multiple of 4 bytes.
*/
while (nbyte % 4)
{
GetByte(fp);
nbyte++;
}
*ppos += nbyte;
return nbyte;
}
static void
BMPreadbits(xel *array,
FILE *fp,
unsigned long *ppos, /* number of bytes read from fp */
unsigned long offBits,
unsigned long cx,
unsigned long cy,
unsigned short cBitCount,
int /* classv */,
int indexed,
pixval *R,
pixval *G,
pixval *B)
{
long y;
readto(fp, ppos, offBits);
if(cBitCount > 24)
{
pm_error("%s: cannot handle cBitCount: %d"
,ifname
,cBitCount);
}
/*
* The picture is stored bottom line first, top line last
*/
for (y = (long)cy - 1; y >= 0; y--)
{
int rc;
rc = BMPreadrow(fp, ppos, array + y*cx, cx, cBitCount, indexed, R, G, B);
if(rc == -1)
{
pm_error("%s: couldn't read row %d"
,ifname
,y);
}
if(rc%4)
{
pm_error("%s: row had bad number of bytes: %d"
,ifname
,rc);
}
}
}
PNMReaderBMP::
PNMReaderBMP(FILE *file, int already_read_magic) : PNMReader(file) {
int rc;
unsigned long cx;
unsigned long cy;
if (already_read_magic < 0) {
// Skip the magic number.
GetByte(file);
GetByte(file);
}
pos = 0;
BMPreadfileheader(file, &pos, &offBits);
BMPreadinfoheader(file, &pos, &cx, &cy, &cBitCount, &classv);
if (offBits != BMPoffbits(classv, cBitCount)) {
pm_message("warning: offBits is %d, expected %d",
offBits,
BMPoffbits(classv, cBitCount));
}
indexed = false;
if (cBitCount <= 8) {
indexed = true;
rc = BMPreadrgbtable(file, &pos, cBitCount, classv, R, G, B);
if (rc != BMPlenrgbtable(classv, cBitCount)) {
pm_message("warning: %d-byte RGB table, expected %d bytes",
rc,
BMPlenrgbtable(classv, cBitCount));
}
}
color_type = Color;
cols = (int)cx;
rows = (int)cy;
maxval = 255;
}
int PNMReaderBMP::
ReadData(xel *array, xelval *) {
BMPreadbits(array, file, &pos, offBits, cols, rows,
cBitCount, classv, indexed, R, G, B);
if (pos != BMPlenfile(classv, cBitCount, cols, rows)) {
pm_message("warning: read %d bytes, expected to read %d bytes",
pos, BMPlenfile(classv, cBitCount, cols, rows));
}
return rows;
}

View File

@ -1,430 +0,0 @@
// pnm-image-readsgi.cc
//
// PNMImage::ReadSGI() and supporting functions.
// Much code in this file is borrowed from Netpbm, specifically sgitopnm.c.
/* sgitopnm.c - read an SGI image and and produce a portable anymap
**
** Copyright (C) 1994 by Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de)
**
** Based on the SGI image description v0.9 by Paul Haeberli (paul@sgi.comp)
** Available via ftp from sgi.com:graphics/SGIIMAGESPEC
**
** 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.
**
** 29Jan94: first version
** 08Feb94: minor bugfix
*/
#include "pnmImage.h"
#include "pnmReader.h"
#include "pnmReaderTypes.h"
#include "../pnm/sgi.h"
#include <notify.h>
/* entry in RLE offset table */
typedef PNMReaderSGI::TabEntry TabEntry;
typedef short ScanElem;
typedef ScanElem * ScanLine;
/* prototypes */
static unsigned char get_byte ( FILE* f );
static long get_big_long (FILE *f);
static short get_big_short (FILE *f);
static short get_byte_as_short (FILE *f);
static int readerr (FILE *f);
static void * xmalloc (int bytes);
#define MALLOC(n, type) (type *)xmalloc((n) * sizeof(type))
//static char * compression_name (char compr);
static void read_bytes (FILE *ifp, int n, char *buf);
static void read_header(FILE *ifp, Header *head, int already_read_magic);
static TabEntry * read_table (FILE *ifp, int tablen);
static void read_channel (FILE *ifp, int xsize, int ysize,
int zsize, int bpc, TabEntry *table,
ScanElem *channel_data, long table_start,
int channel, int row);
static void rle_decompress (ScanElem *src, long srclen, ScanElem *dest, long destlen);
#define WORSTCOMPR(x) (2*(x) + 2)
#define MAXVAL_BYTE 255
#define MAXVAL_WORD 65535
static int eof_err = false;
PNMReaderSGI::
PNMReaderSGI(FILE *file, int already_read_magic) : PNMReader(file) {
eof_err = false;
table = NULL;
Header head;
read_header(file, &head, already_read_magic);
long pixmax = (head.bpc == 1) ? MAXVAL_BYTE : MAXVAL_WORD;
if( pixmax > PNM_MAXMAXVAL )
pm_error("pixel values too large - try reconfiguring with PGM_BIGGRAYS\n or without PPM_PACKCOLORS");
maxval = (xelval)pixmax;
table_start = ftell(file);
if( head.storage != STORAGE_VERBATIM )
table = read_table(file, head.ysize * head.zsize);
cols = head.xsize;
rows = head.ysize;
zsize = head.zsize;
bpc = head.bpc;
switch (zsize) {
case 1:
color_type = PNMImage::Grayscale;
break;
case 2:
color_type = PNMImage::TwoChannel;
break;
case 3:
color_type = PNMImage::Color;
break;
case 4:
color_type = PNMImage::FourChannel;
break;
default:
pm_error("Can't happen.");
}
current_row = rows-1;
}
bool PNMReaderSGI::
ReadRow(xel *row_data, xelval *alpha_data) {
nassertr(current_row >= 0, false);
int is_grayscale = PNMImage::IsGrayscale(color_type);
int has_alpha = PNMImage::HasAlpha(color_type);
int col;
ScanElem *red = (ScanElem *)alloca(cols * sizeof(ScanElem));
ScanElem *grn = (ScanElem *)alloca(cols * sizeof(ScanElem));
ScanElem *blu = (ScanElem *)alloca(cols * sizeof(ScanElem));
ScanElem *alpha = (ScanElem *)alloca(cols * sizeof(ScanElem));
read_channel(file, cols, rows, zsize, bpc, table, red, table_start,
0, current_row);
if (!is_grayscale) {
read_channel(file, cols, rows, zsize, bpc, table, grn, table_start,
1, current_row);
read_channel(file, cols, rows, zsize, bpc, table, blu, table_start,
2, current_row);
}
if (has_alpha) {
read_channel(file, cols, rows, zsize, bpc, table, alpha, table_start,
zsize-1, current_row);
}
for ( col = 0; col < cols; col++ ) {
if (is_grayscale) {
PPM_PUTB(row_data[col], (xelval)red[col]);
} else {
xelval r, g, b;
r = (xelval)red[col];
g = (xelval)grn[col];
b = (xelval)blu[col];
PPM_ASSIGN(row_data[col], r, g, b);
}
if (has_alpha) {
alpha_data[col] = (xelval)alpha[col];
}
}
current_row--;
return true;
}
PNMReaderSGI::
~PNMReaderSGI() {
if (table != NULL) {
free(table);
}
}
static void
read_header(FILE *ifp, Header *head, int already_read_magic) {
if (already_read_magic >= 0) {
head->magic = (short)already_read_magic;
} else {
head->magic = get_big_short(ifp);
}
head->storage = get_byte(ifp);
head->bpc = get_byte(ifp);
head->dimension = get_big_short(ifp);
head->xsize = get_big_short(ifp);
head->ysize = get_big_short(ifp);
head->zsize = get_big_short(ifp);
head->pixmin = get_big_long(ifp);
head->pixmax = get_big_long(ifp);
read_bytes(ifp, 4, head->dummy1);
read_bytes(ifp, 80, head->name);
head->colormap = get_big_long(ifp);
read_bytes(ifp, 404, head->dummy2);
if( head->magic != SGI_MAGIC )
pm_error("bad magic number - not an SGI image");
if( head->storage != 0 && head->storage != 1 )
pm_error("unknown compression type");
if( head->bpc < 1 || head->bpc > 2 )
pm_error("illegal precision value %d (only 1-2 allowed)", head->bpc );
if( head->colormap != CMAP_NORMAL )
pm_message("unsupported non-normal pixel data (%d)",
head->colormap);
/* adjust ysize/zsize to dimension, just to be sure */
switch( head->dimension ) {
case 1:
head->ysize = 1;
break;
case 2:
head->zsize = 1;
break;
case 3:
switch( head->zsize ) {
case 1:
case 2:
head->dimension = 2;
break;
case 3:
case 4:
break;
default:
pm_message("%d-channel image, using only first 4 channels", head->zsize);
head->zsize = 4;
break;
}
break;
default:
pm_error("illegal dimension value %d (only 1-3 allowed)", head->dimension);
}
#ifdef DEBUG
fprintf(stderr, "raster size %dx%d, %d channels\n", head->xsize, head->ysize, head->zsize);
fprintf(stderr, "compression: %d = %s\n", head->storage, compression_name(head->storage));
head->name[79] = '\0'; /* just to be safe */
fprintf(stderr, "Image name: \"%s\"\n", head->name);
fprintf(stderr, "bpc: %d dimension: %d zsize: %d\n", head->bpc, head->dimension, head->zsize);
fprintf(stderr, "pixmin: %ld pixmax: %ld colormap: %ld\n", head->pixmin, head->pixmax, head->colormap);
#endif
}
static TabEntry *
read_table(FILE *ifp, int tablen) {
TabEntry *table;
int i;
table = MALLOC(tablen, TabEntry);
for( i = 0; i < tablen; i++ )
table[i].start = get_big_long(ifp);
for( i = 0; i < tablen; i++ )
table[i].length = get_big_long(ifp);
return table;
}
static void
read_channel(FILE *ifp,
int xsize, int ysize, int, int bpc,
TabEntry *table,
ScanElem *channel_data, long table_start,
int channel, int row) {
ScanElem *temp;
int sgi_index, i;
long offset, length;
short (*func)(FILE *);
func = (bpc==1) ? get_byte_as_short : get_big_short;
if ( table )
temp = (ScanElem *)alloca(WORSTCOMPR(xsize) * sizeof(ScanElem));
sgi_index = channel * ysize + row;
if( table ) {
offset = table[sgi_index].start;
length = table[sgi_index].length;
if( bpc == 2 )
length /= 2; /* doc says length is in bytes, we are reading words */
if( fseek(ifp, offset, SEEK_SET) != 0 )
pm_error("seek error for offset %ld", offset);
for( i = 0; i < length; i++ )
temp[i] = (*func)(ifp);
rle_decompress(temp, length, channel_data, xsize);
}
else {
offset = sgi_index * xsize + table_start;
if( fseek(ifp, offset, SEEK_SET) != 0 )
pm_error("seek error for offset %ld", offset);
for( i = 0; i < xsize; i++ )
channel_data[i] = (*func)(ifp);
}
}
static void
rle_decompress(ScanElem *src,
long srcleft,
ScanElem *dest,
long destleft) {
int count;
unsigned char el;
while( srcleft ) {
el = (unsigned char)(*src++ & 0xff);
--srcleft;
count = (int)(el & 0x7f);
if( count == 0 )
return;
if( destleft < count )
pm_error("RLE error: too much input data (space left %d, need %d)", destleft, count);
destleft -= count;
if( el & 0x80 ) {
if( srcleft < count )
pm_error("RLE error: not enough data for literal run (data left %d, need %d)", srcleft, count);
srcleft -= count;
while( count-- )
*dest++ = *src++;
}
else {
if( srcleft == 0 )
pm_error("RLE error: not enough data for replicate run");
while( count-- )
*dest++ = *src;
++src;
--srcleft;
}
}
pm_error("RLE error: no terminating 0-byte");
}
/* basic I/O functions, taken from ilbmtoppm.c */
static short
get_big_short(FILE *ifp) {
short s;
if( pm_readbigshort(ifp, &s) == -1 )
s = readerr(ifp);
return s;
}
static long
get_big_long(FILE *ifp) {
long l;
if( pm_readbiglong(ifp, &l) == -1 )
l = readerr(ifp);
return l;
}
static unsigned char
get_byte(FILE *ifp) {
int i;
i = getc(ifp);
if( i == EOF )
i = readerr(ifp);
return (unsigned char) i;
}
static int
readerr(FILE *f) {
// This will return only if the error is EOF.
if( ferror(f) )
pm_error("read error");
static FILE *last_eof = NULL;
if (!eof_err) {
fprintf(stderr, "Warning: premature EOF on file\n");
eof_err = true;
}
return 0;
}
static void
read_bytes(FILE *ifp,
int n,
char *buf) {
int r;
r = fread((void *)buf, 1, n, ifp);
if( r != n ) {
readerr(ifp);
memset(buf+r, 0, n-r);
}
}
static short
get_byte_as_short(FILE *ifp) {
return (short)get_byte(ifp);
}
static void *
xmalloc(int bytes) {
void *mem;
if( bytes == 0 )
return NULL;
mem = malloc(bytes);
if( mem == NULL )
pm_error("out of memory allocating %d bytes", bytes);
return mem;
}
/*
static char *
compression_name(char compr) {
switch( compr ) {
case STORAGE_VERBATIM:
return "none";
case STORAGE_RLE:
return "RLE";
default:
return "unknown";
}
}
*/

View File

@ -1,114 +0,0 @@
// pnm-image-readyuv.cc
//
// PNMImage::ReadYUV() and supporting functions.
// Much code in this file is borrowed from Netpbm, specifically yuvtoppm.c.
/* yuvtoppm.c - convert Abekas YUV bytes into a portable pixmap
**
** by Marc Boucher
** Internet: marc@PostImage.cxxOM
**
** Based on Example Conversion Program, A60/A64 Digital Video Interface
** Manual, page 69
**
** Uses integer arithmetic rather than floating point for better performance
**
** Copyright (C) 1991 by DHD PostImage Inc.
** Copyright (C) 1987 by Abekas Video Systems Inc.
** Copyright (C) 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 "pnmImage.h"
#include "pnmReader.h"
#include "pnmReaderTypes.h"
#include <notify.h>
// YUV format doesn't include an image size specification, so the image size
// must be specified externally. The defaults here are likely candidates,
// since this is the Abekas native size; the ysize is automatically adjusted
// down to account for a short file.
int yuv_xsize = 720;
int yuv_ysize = 486;
/* x must be signed for the following to work correctly */
#define limit(x) (xelval)(((x>0xffffff)?0xff0000:((x<=0xffff)?0:x&0xff0000))>>16)
PNMReaderYUV::
PNMReaderYUV(FILE *file, int already_read_magic) : PNMReader(file) {
yuvbuf = NULL;
if (already_read_magic >= 0) {
ungetc(already_read_magic >> 8, file);
ungetc(already_read_magic & 0xff, file);
}
cols = yuv_xsize;
rows = yuv_ysize;
color_type = PNMImage::Color;
if (cols <= 0 || rows <= 0) {
valid = false;
return;
}
nassertv(255 <= PGM_MAXMAXVAL);
yuvbuf = (long *) pm_allocrow(cols, 2);
maxval = 255;
}
bool PNMReaderYUV::
ReadRow(xel *row_data, xelval *) {
long tmp, y, u, v, y1, r, g, b, *yuvptr;
int col;
if (fread(yuvbuf, cols * 2, 1, file) != 1) {
// Short file--perhaps it's just a field instead of a full frame.
// Since the YUV format does not include a length designation, we'll
// have to assume this is not a problem and just truncate here.
return false;
}
for (col = 0, yuvptr = yuvbuf; col < cols; col += 2) {
tmp = *yuvptr++;
u = (0xff & (tmp >> 24)) - 128;
y = ((0xff & (tmp >> 16)) - 16);
if (y < 0) y = 0;
v = (0xff & (tmp >> 8)) - 128;
y1 = ((0xff & tmp) - 16);
if (y1 < 0) y1 = 0;
r = 104635 * v;
g = -25690 * u + -53294 * v;
b = 132278 * u;
y*=76310; y1*=76310;
PPM_ASSIGN(row_data[col], limit(r+y), limit(g+y), limit(b+y));
PPM_ASSIGN(row_data[col+1], limit(r+y1), limit(g+y1), limit(b+y1));
}
return true;
}
PNMReaderYUV::
~PNMReaderYUV() {
if (yuvbuf!=NULL) {
pm_freerow((char *)yuvbuf);
}
}

View File

@ -1,539 +0,0 @@
// pnm-image-softimage.cc
//
// PNMImage::ReadSoftImage()
// PNMImage::WriteSoftImage()
#include "pnmImage.h"
#include "pnmReader.h"
#include "pnmReaderTypes.h"
#include "pnmWriter.h"
#include "pnmWriterTypes.h"
#include "config_pnmimage.h"
#include <notify.h>
#include <stdio.h>
static const float imageVersionNumber = 3.0;
static const int imageCommentLength = 80;
static const char imageComment[imageCommentLength+1] =
"Written by DRR's PNMImage library.";
// Values to indicate compressed/uncompressed types
#define UNCOMPRESSED 0x00
#define MIXED_RUN_LENGTH 0x02
// Bits to indicate channel type
#define RGB_CHANNEL 0xe0
#define ALPHA_CHANNEL 0x10
inline float
read_float(FILE *file) {
long l;
if (pm_readbiglong(file, &l)==0) {
return *(float *)&l;
} else {
return 0.0;
}
}
inline unsigned short
read_ushort(FILE *file) {
unsigned short x;
return pm_readbigshort(file, (short *)&x)==0 ? x : 0;
}
inline unsigned char
read_uchar(FILE *file) {
int x;
x = getc(file);
return (x!=EOF) ? (unsigned char)x : 0;
}
inline void
write_ushort(FILE *file, unsigned short x) {
pm_writebigshort(file, (short)x);
}
inline void
write_uchar(FILE *file, unsigned char x) {
putc(x, file);
}
inline void
write_float(FILE *file, float x) {
pm_writebiglong(file, *(long *)&x);
}
static int
read_channel_pkt(FILE *file,
int &chained, int &size, int &type, int &channel) {
chained = read_uchar(file);
size = read_uchar(file);
type = read_uchar(file);
channel = read_uchar(file);
if (feof(file)) {
return false;
}
if (size!=8) {
pnmimage_cat.error()
<< "Don't know how to interpret " << size << " bits per pixel!\n";
return false;
}
return true;
}
static void
read_rgb(xel *row_data, xelval *, FILE *file, int x, int repeat) {
xelval red, grn, blu;
red = read_uchar(file);
grn = read_uchar(file);
blu = read_uchar(file);
while (repeat>0) {
PPM_ASSIGN(row_data[x], red, grn, blu);
x++;
repeat--;
}
}
static void
read_alpha(xel *, xelval *alpha_data, FILE *file, int x, int repeat) {
xelval alpha = read_uchar(file);
while (repeat>0) {
alpha_data[x] = alpha;
x++;
repeat--;
}
}
static void
read_rgba(xel *row_data, xelval *alpha_data, FILE *file, int x, int repeat) {
xelval red, grn, blu, alpha;
red = read_uchar(file);
grn = read_uchar(file);
blu = read_uchar(file);
alpha = read_uchar(file);
while (repeat>0) {
PPM_ASSIGN(row_data[x], red, grn, blu);
alpha_data[x] = alpha;
x++;
repeat--;
}
}
static int
read_scanline(xel *row_data, xelval *alpha_data, int cols, FILE *file,
void (*read_data)(xel *row_data, xelval *alpha_data, FILE *file,
int x, int repeat),
int ctype) {
if (ctype==UNCOMPRESSED) {
for (int x = 0; x<cols; x++) {
read_data(row_data, alpha_data, file, x, 1);
}
return true;
} else {
int x;
int num;
x = 0;
while (x < cols) {
num = read_uchar(file);
if (num<128) {
// Sequence of non-repeated values.
num++;
if (x+num > cols) {
return false;
}
while (num>0) {
read_data(row_data, alpha_data, file, x, 1);
if (feof(file)) {
return false;
}
x++;
num--;
}
} else {
// Sequence of repeated values.
if (num==128) {
num = read_ushort(file);
} else {
num -= 127;
}
if (x+num > cols) {
return false;
}
read_data(row_data, alpha_data, file, x, num);
if (feof(file)) {
return false;
}
x += num;
}
}
return (x==cols);
}
}
PNMReaderSoftImage::
PNMReaderSoftImage(FILE *file, int already_read_magic) : PNMReader(file) {
unsigned short magic1, magic2;
magic1 = (already_read_magic >= 0) ? already_read_magic : read_ushort(file);
if (magic1 != SOFTIMAGE_MAGIC1) {
valid = false;
return;
}
magic2 = read_ushort(file);
if (magic2 != SOFTIMAGE_MAGIC2) {
valid = false;
return;
}
// skip version number
read_float(file);
// Skip comment
fseek(file, imageCommentLength, SEEK_CUR);
char pict_id[4];
if (fread(pict_id, 1, 4, file) < 4) {
valid = false;
return;
}
if (memcmp(pict_id, "PICT", 4)!=0) {
valid = false;
return;
}
cols = read_ushort(file);
rows = read_ushort(file);
float ratio = read_float(file);
int fields = read_ushort(file);
read_ushort(file);
int chained, size, channel;
if (!read_channel_pkt(file, chained, size, rgb_ctype, channel)) {
valid = false;
return;
}
soft_color = unknown;
if (channel == (RGB_CHANNEL | ALPHA_CHANNEL)) {
// Four components in the first part: RGBA.
soft_color = rgba;
} else if (channel == RGB_CHANNEL) {
// Three components in the first part: RGB.
soft_color = rgb;
if (chained) {
if (!read_channel_pkt(file, chained, size, alpha_ctype, channel)) {
valid = false;
return;
}
if (channel == ALPHA_CHANNEL) {
// Alpha component in the second part: RGBA.
soft_color = rgb_a;
}
}
}
switch (soft_color) {
case rgb:
color_type = PNMImage::Color;
break;
case rgba:
case rgb_a:
color_type = PNMImage::FourChannel;
break;
default:
pnmimage_cat.error()
<< "Image is not RGB or RGBA!\n";
valid = false;
return;
}
if (chained) {
pnmimage_cat.error()
<< "Unexpected additional channels in image file.\n";
valid = false;
return;
}
maxval = 255;
}
bool PNMReaderSoftImage::
ReadRow(xel *row_data, xelval *alpha_data) {
switch (soft_color) {
case rgb:
if (!read_scanline(row_data, alpha_data, cols, file,
read_rgb, rgb_ctype)) {
return false;
}
break;
case rgba:
if (!read_scanline(row_data, alpha_data, cols, file,
read_rgba, rgb_ctype)) {
return false;
}
break;
case rgb_a:
if (!read_scanline(row_data, alpha_data, cols, file,
read_rgb, rgb_ctype)) {
return false;
}
if (!read_scanline(row_data, alpha_data, cols, file,
read_alpha, alpha_ctype)) {
return false;
}
break;
}
return true;
}
static void
write_channel_pkt(FILE *file,
int chained, int size, int type, int channel) {
write_uchar(file, chained);
write_uchar(file, size);
write_uchar(file, type);
write_uchar(file, channel);
}
static void
write_rgb(xel *row_data, xelval *, FILE *file, int x) {
write_uchar(file, PPM_GETR(row_data[x]));
write_uchar(file, PPM_GETG(row_data[x]));
write_uchar(file, PPM_GETB(row_data[x]));
}
static int
compare_rgb(xel *row_data, xelval *, int x1, int x2) {
return PPM_EQUAL(row_data[x1], row_data[x2]);
}
static void
write_gray(xel *row_data, xelval *, FILE *file, int x) {
write_uchar(file, PPM_GETB(row_data[x]));
write_uchar(file, PPM_GETB(row_data[x]));
write_uchar(file, PPM_GETB(row_data[x]));
}
static int
compare_gray(xel *row_data, xelval *, int x1, int x2) {
return (PPM_GETB(row_data[x1])==PPM_GETB(row_data[x2]));
}
static void
write_alpha(xel *, xelval *alpha_data, FILE *file, int x) {
write_uchar(file, alpha_data[x]);
}
static int
compare_alpha(xel *, xelval *alpha_data, int x1, int x2) {
return (alpha_data[x1]==alpha_data[x2]);
}
static void
write_diff(xel *row_data, xelval *alpha_data, FILE *file,
void (*write_data)(xel *row_data, xelval *alpha_data, FILE *file,
int x),
int tox, int length) {
if (length>0) {
nassertv(length<=128);
write_uchar(file, length-1);
while (length>0) {
length--;
write_data(row_data, alpha_data, file, tox-length);
}
}
}
static void
write_same(xel *row_data, xelval *alpha_data, FILE *file,
void (*write_data)(xel *row_data, xelval *alpha_data, FILE *file,
int x),
int tox, int length) {
if (length==1) {
write_diff(row_data, alpha_data, file, write_data, tox, length);
} else if (length>0) {
if (length<128) {
write_uchar(file, length+127);
} else {
write_uchar(file, 128);
write_ushort(file, length);
}
write_data(row_data, alpha_data, file, tox);
}
}
static void
write_scanline(xel *row_data, xelval *alpha_data, int cols, FILE *file,
int (*compare_data)(xel *row_data, xelval *alpha_data,
int x1, int x2),
void (*write_data)(xel *row_data, xelval *alpha_data,
FILE *file, int x)) {
int run_length = 0;
int x = 0;
int same = true;
// Go through each value in the scanline, from beginning to end, looking
// for runs of identical values.
while (x < cols) {
if (same) {
// We have been scanning past a run of identical values. In this case,
// the run is the sequence of values from x-run_length to x-1.
if (!compare_data(row_data, alpha_data, x, x-run_length)) {
// Oops, the end of a run.
if (run_length <= 1) {
// If run_length is only 1, no big deal--this is actually the
// beginning of a different-valued run.
same = false;
} else {
// Write out the old run and begin a new one. We'll be optimistic
// and hope the new run will also represent a sequence of identical
// values (until we find otherwise).
write_same(row_data, alpha_data, file, write_data, x-1, run_length);
same = true;
run_length = 0;
}
}
} else { // !same
// We have been scanning past a run of different values. In this case,
// the run is the sequence of values from x-run_length to x-1.
if (run_length>128) {
// We can't have different runs of more than 128 characters. Close
// off the old run.
int excess = run_length - 128;
write_diff(row_data, alpha_data, file, write_data, x-excess-1, 128);
run_length = excess;
} else if (run_length > 2 &&
compare_data(row_data, alpha_data, x, x-1) &&
compare_data(row_data, alpha_data, x, x-2)) {
// If the last three values have been the same, then it's time to
// begin a new run of similar values. Close off the old run.
write_diff(row_data, alpha_data, file, write_data, x-3, run_length-2);
same = true;
run_length = 2;
}
}
x++;
run_length++;
}
// We made it all the way to the end. Flush out the last run.
if (run_length>0) {
if (same) {
write_same(row_data, alpha_data, file, write_data, cols-1, run_length);
} else {
// Mighty unlikely, but we might have just run over the
// 128-pixel limit.
if (run_length>128) {
int excess = run_length - 128;
write_diff(row_data, alpha_data, file, write_data, cols-excess-1, 128);
run_length = excess;
}
write_diff(row_data, alpha_data, file, write_data, cols-1, run_length);
}
}
}
bool PNMWriterSoftImage::
WriteHeader() {
write_ushort(file, SOFTIMAGE_MAGIC1);
write_ushort(file, SOFTIMAGE_MAGIC2);
write_float(file, imageVersionNumber);
fwrite(imageComment, 1, imageCommentLength, file);
fwrite("PICT", 1, 4, file);
write_ushort(file, cols);
write_ushort(file, rows);
write_float(file, 1.0); // pixel aspect ratio; we don't know.
write_ushort(file, 3); // fields value; we don't really know either.
write_ushort(file, 0); // padding
// There doesn't seem to be a variation on SoftImage image formats for
// grayscale images. We'll write out grayscale as a 3-channel image.
switch (color_type) {
case PNMImage::Grayscale:
case PNMImage::Color:
write_channel_pkt(file, 0, 8, MIXED_RUN_LENGTH, RGB_CHANNEL);
break;
case PNMImage::FourChannel:
case PNMImage::TwoChannel:
write_channel_pkt(file, 1, 8, MIXED_RUN_LENGTH, RGB_CHANNEL);
write_channel_pkt(file, 0, 8, MIXED_RUN_LENGTH, ALPHA_CHANNEL);
break;
}
return true;
}
bool PNMWriterSoftImage::
WriteRow(xel *row_data, xelval *alpha_data) {
if (PNMImage::IsGrayscale(color_type)) {
write_scanline(row_data, alpha_data, cols, file, compare_gray, write_gray);
} else {
write_scanline(row_data, alpha_data, cols, file, compare_rgb, write_rgb);
}
if (PNMImage::HasAlpha(color_type)) {
write_scanline(row_data, alpha_data, cols, file, compare_alpha, write_alpha);
}
return !ferror(file);
}

View File

@ -1,561 +0,0 @@
// pnm-image-readtiff.cc
//
// PNMImage::ReadTIFF() and supporting functions.
// Much code in this file is borrowed from Netpbm, specifically tifftopnm.c
// and pnmtotiff.c.
/*
** tifftopnm.c - converts a Tagged Image File to a portable anymap
**
** Derived by Jef Poskanzer from tif2ras.c, which is:
**
** Copyright (c) 1990 by Sun Microsystems, Inc.
**
** Author: Patrick J. Naughton
** naughton@wind.sun.com
**
** 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 file is provided AS IS with no warranties of any kind. The author
** shall have no liability with respect to the infringement of copyrights,
** trade secrets or any patents by this file or any part thereof. In no
** event will the author be liable for any lost revenue or profits or
** other special, indirect and consequential damages.
*/
#include "pnmImage.h"
#include "pnmReader.h"
#include "pnmReaderTypes.h"
#include "pnmWriter.h"
#include "pnmWriterTypes.h"
extern "C" {
#include "../pnm/sgi.h"
#include "../pnm/ppmcmap.h"
#include "../tiff/tiff.h"
#include "../tiff/tiffio.h"
}
// true to display image information on load; false otherwise.
int tiff_headerdump = false;
// These are configurable parameters to specify TIFF details on output.
// See tools/drr/../pnm/libtiff/tiff.h or type man pnmtotiff for a better
// explanation of options.
unsigned short tiff_compression = COMPRESSION_LZW;
/* One of:
COMPRESSION_NONE
COMPRESSION_CCITTRLE
COMPRESSION_CCITTFAX3
COMPRESSION_CCITTFAX4
COMPRESSION_LZW
COMPRESSION_JPEG
COMPRESSION_NEXT
COMPRESSION_CCITTRLEW
COMPRESSION_PACKBITS
COMPRESSION_THUNDERSCAN
*/
long tiff_g3options = 0;
/* One or more of:
GROUP3OPT_2DENCODING
GROUP3OPT_FILLBITS
meaningful when tiff_compression == COMPRESSION_CCITTFAX3.
*/
unsigned short tiff_fillorder = FILLORDER_MSB2LSB;
/* One of:
FILLORDER_MSB2LSB
FILLORDER_LSB2MSB
*/
short tiff_predictor = 0;
/* 0, 1, or 2; meaningful when tiff_compression == COMPRESSION_LZW. */
long tiff_rowsperstrip = 0;
/* 0 or any positive number */
#define MAXCOLORS 1024
#ifndef PHOTOMETRIC_DEPTH
#define PHOTOMETRIC_DEPTH 32768
#endif
static tsize_t
StdioReadProc(thandle_t fd, tdata_t buf, tsize_t size)
{
return ((tsize_t)fread((void *)buf, 1, (size_t) size, (FILE *)fd));
}
static tsize_t
StdioWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
{
return ((tsize_t)fwrite((void *)buf, 1, (size_t) size, (FILE *)fd));
}
static toff_t
StdioSeekProc(thandle_t fd, off_t off, int whence)
{
fseek((FILE *)fd, (long)off, whence);
return (toff_t)ftell((FILE *)fd);
}
static int
StdioCloseProc(thandle_t)
{
// We don't actually close the file; we'll leave that up to our calling
// procedure.
return true;
}
static toff_t
StdioSizeProc(thandle_t fd)
{
fseek((FILE *)fd, 0, SEEK_END);
return (toff_t)ftell((FILE *)fd);
}
static int
StdioMapProc(thandle_t, tdata_t*, toff_t*)
{
return (0);
}
static void
StdioUnmapProc(thandle_t, tdata_t, toff_t)
{
}
PNMReaderTIFF::
PNMReaderTIFF(FILE *file, int already_read_magic) : PNMReader(file) {
int grayscale;
int numcolors;
int i;
unsigned short* redcolormap;
unsigned short* greencolormap;
unsigned short* bluecolormap;
if (already_read_magic >= 0) {
ungetc(already_read_magic >> 8, file);
ungetc(already_read_magic & 0xff, file);
}
tif = TIFFClientOpen("TIFF file", "r",
(thandle_t) file,
StdioReadProc, StdioWriteProc,
(TIFFSeekProc)StdioSeekProc,
StdioCloseProc, StdioSizeProc,
StdioMapProc, StdioUnmapProc);
if ( tif == NULL )
pm_error( "error opening TIFF file" );
if ( tiff_headerdump )
TIFFPrintDirectory( tif, stderr, TIFFPRINT_NONE );
if ( ! TIFFGetField( tif, TIFFTAG_BITSPERSAMPLE, &bps ) )
bps = 1;
if ( ! TIFFGetField( tif, TIFFTAG_SAMPLESPERPIXEL, &spp ) )
spp = 1;
if ( ! TIFFGetField( tif, TIFFTAG_PHOTOMETRIC, &photomet ) )
pm_error( "error getting photometric" );
switch ( spp )
{
case 1:
color_type = PNMImage::Grayscale;
break;
case 3:
color_type = PNMImage::Color;
break;
case 4:
color_type = PNMImage::FourChannel;
break;
default:
pm_error(
"can only handle 1-channel gray scale or 1- or 3-channel color" );
}
(void) TIFFGetField( tif, TIFFTAG_IMAGEWIDTH, &cols );
(void) TIFFGetField( tif, TIFFTAG_IMAGELENGTH, &rows );
if ( tiff_headerdump )
{
pm_message( "%dx%dx%d image", cols, rows, bps * spp );
pm_message( "%d bits/sample, %d samples/pixel", bps, spp );
}
maxval = ( 1 << bps ) - 1;
if ( maxval == 1 && spp == 1 )
{
if ( tiff_headerdump )
pm_message("monochrome" );
grayscale = 1;
}
else
{
switch ( photomet )
{
case PHOTOMETRIC_MINISBLACK:
if ( tiff_headerdump )
pm_message( "%d graylevels (min=black)", maxval + 1 );
grayscale = 1;
break;
case PHOTOMETRIC_MINISWHITE:
if ( tiff_headerdump )
pm_message( "%d graylevels (min=white)", maxval + 1 );
grayscale = 1;
break;
case PHOTOMETRIC_PALETTE:
if ( tiff_headerdump )
pm_message( "colormapped" );
if ( ! TIFFGetField( tif, TIFFTAG_COLORMAP, &redcolormap, &greencolormap, &bluecolormap ) )
pm_error( "error getting colormaps" );
numcolors = maxval + 1;
if ( numcolors > MAXCOLORS )
pm_error( "too many colors" );
maxval = PNM_MAXMAXVAL;
grayscale = 0;
for ( i = 0; i < numcolors; ++i )
{
xelval r, g, b;
r = (xelval)(maxval * (double)(redcolormap[i] / 65535.0));
g = (xelval)(maxval * (double)(greencolormap[i] / 65535.0));
b = (xelval)(maxval * (double)(bluecolormap[i] / 65535.0));
PPM_ASSIGN( colormap[i], r, g, b );
}
break;
case PHOTOMETRIC_RGB:
if ( tiff_headerdump )
pm_message( "truecolor" );
grayscale = 0;
break;
case PHOTOMETRIC_MASK:
pm_error( "don't know how to handle PHOTOMETRIC_MASK" );
case PHOTOMETRIC_DEPTH:
pm_error( "don't know how to handle PHOTOMETRIC_DEPTH" );
default:
pm_error( "unknown photometric: %d", photomet );
}
}
if ( maxval > PNM_MAXMAXVAL )
pm_error(
"bits/sample is too large - try reconfiguring with PGM_BIGGRAYS\n or without PPM_PACKCOLORS" );
if ( grayscale ) {
color_type = PNMImage::Grayscale;
} else if (color_type == PNMImage::Grayscale) {
color_type = PNMImage::Color;
}
current_row = 0;
}
#define NEXTSAMPLE \
{ \
if ( bitsleft == 0 ) \
{ \
++inP; \
bitsleft = 8; \
} \
bitsleft -= bps; \
sample = ( *inP >> bitsleft ) & maxval; \
}
bool PNMReaderTIFF::
ReadRow(xel *row_data, xelval *alpha_data) {
unsigned char *buf = (unsigned char*) alloca((size_t)TIFFScanlineSize(tif));
int col;
unsigned char sample;
if ( TIFFReadScanline( tif, buf, current_row, 0 ) < 0 )
pm_error( "bad data read on line %d", current_row );
unsigned char *inP = buf;
int bitsleft = 8;
switch ( photomet ) {
case PHOTOMETRIC_MINISBLACK:
for ( col = 0; col < cols; ++col )
{
NEXTSAMPLE;
PPM_PUTB(row_data[col], sample);
}
break;
case PHOTOMETRIC_MINISWHITE:
for ( col = 0; col < cols; ++col )
{
NEXTSAMPLE;
sample = maxval - sample;
PPM_PUTB(row_data[col], sample);
}
break;
case PHOTOMETRIC_PALETTE:
for ( col = 0; col < cols; ++col )
{
NEXTSAMPLE;
row_data[col] = colormap[sample];
}
break;
case PHOTOMETRIC_RGB:
for ( col = 0; col < cols; ++col ) {
xelval r, g, b;
NEXTSAMPLE;
r = sample;
NEXTSAMPLE;
g = sample;
NEXTSAMPLE;
b = sample;
PPM_ASSIGN(row_data[col], r, g, b);
if ( spp == 4 ) {
NEXTSAMPLE; // Alpha channel
alpha_data[col] = sample;
}
}
break;
default:
pm_error( "unknown photometric: %d", photomet );
}
current_row++;
return true;
}
PNMReaderTIFF::
~PNMReaderTIFF() {
TIFFClose( tif );
// owns_file = false;
}
int PNMWriterTIFF::
WriteData(xel *array, xelval *alpha) {
colorhist_vector chv;
colorhash_table cht;
unsigned short red[MAXCOLORS], grn[MAXCOLORS], blu[MAXCOLORS];
int row, colors, i;
register int col;
int grayscale;
struct tiff * tif;
short photometric;
short samplesperpixel;
short bitspersample;
int bytesperrow;
unsigned char* buf;
unsigned char* tP;
/* Check for grayscale. */
int is_grayscale = PNMImage::IsGrayscale(color_type);
switch ( color_type ) {
case PNMImage::Color:
pm_message( "computing colormap..." );
// This call is a bit of fakery to convert our proper 2-d array of
// xels to an indirect 2-d array of pixels. We make it look like a
// single row of cols * rows pixels.
chv = ppm_computecolorhist( (pixel **)&array, cols * rows, 1,
MAXCOLORS, &colors );
if ( chv == (colorhist_vector) 0 ) {
pm_message("Too many colors - proceeding to write a 24-bit RGB file." );
pm_message("If you want an 8-bit palette file, try doing a 'ppmquant %d'.",
MAXCOLORS );
grayscale = 0;
} else {
pm_message( "%d colors found", colors );
grayscale = 1;
for ( i = 0; i < colors; ++i ) {
register xelval r, g, b;
r = PPM_GETR( chv[i].color );
g = PPM_GETG( chv[i].color );
b = PPM_GETB( chv[i].color );
if ( r != g || g != b ) {
grayscale = 0;
break;
}
}
}
break;
case PNMImage::FourChannel:
chv = (colorhist_vector) 0;
grayscale = 0;
break;
case PNMImage::TwoChannel: // We don't yet support two-channel output for TIFF's.
case PNMImage::Grayscale:
chv = (colorhist_vector) 0;
grayscale = 1;
break;
}
/* Open output file. */
tif = TIFFClientOpen("TIFF file", "w",
(thandle_t) file,
StdioReadProc, StdioWriteProc,
(TIFFSeekProc)StdioSeekProc,
StdioCloseProc, StdioSizeProc,
StdioMapProc, StdioUnmapProc);
if ( tif == NULL )
return 0;
/* Figure out TIFF parameters. */
switch ( color_type ) {
case PNMImage::Color:
case PNMImage::FourChannel:
if ( chv == (colorhist_vector) 0 ) {
samplesperpixel = (color_type==PNMImage::FourChannel ? 4 : 3);
bitspersample = 8;
photometric = PHOTOMETRIC_RGB;
bytesperrow = cols * samplesperpixel;
} else if ( grayscale ) {
samplesperpixel = 1;
bitspersample = pm_maxvaltobits( maxval );
photometric = PHOTOMETRIC_MINISBLACK;
bytesperrow = ( cols + i - 1 ) / i;
} else {
samplesperpixel = 1;
bitspersample = 8;
photometric = PHOTOMETRIC_PALETTE;
bytesperrow = cols;
}
break;
case PNMImage::Grayscale:
case PNMImage::TwoChannel:
samplesperpixel = 1;
bitspersample = pm_maxvaltobits( maxval );
photometric = PHOTOMETRIC_MINISBLACK;
i = 8 / bitspersample;
bytesperrow = ( cols + i - 1 ) / i;
break;
}
if ( tiff_rowsperstrip == 0 )
tiff_rowsperstrip = ( 8 * 1024 ) / bytesperrow;
buf = (unsigned char*) malloc( bytesperrow );
if ( buf == (unsigned char*) 0 )
pm_error( "can't allocate memory for row buffer" );
/* Set TIFF parameters. */
TIFFSetField( tif, TIFFTAG_IMAGEWIDTH, cols );
TIFFSetField( tif, TIFFTAG_IMAGELENGTH, rows );
TIFFSetField( tif, TIFFTAG_BITSPERSAMPLE, bitspersample );
TIFFSetField( tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT );
TIFFSetField( tif, TIFFTAG_COMPRESSION, tiff_compression );
if ( tiff_compression == COMPRESSION_CCITTFAX3 && tiff_g3options != 0 )
TIFFSetField( tif, TIFFTAG_GROUP3OPTIONS, tiff_g3options );
if ( tiff_compression == COMPRESSION_LZW && tiff_predictor != 0 )
TIFFSetField( tif, TIFFTAG_PREDICTOR, tiff_predictor );
TIFFSetField( tif, TIFFTAG_PHOTOMETRIC, photometric );
TIFFSetField( tif, TIFFTAG_FILLORDER, tiff_fillorder );
//TIFFSetField( tif, TIFFTAG_DOCUMENTNAME, "TIFF Image File");
TIFFSetField( tif, TIFFTAG_IMAGEDESCRIPTION,
"Generated via DRR's pnm-image library\n" );
TIFFSetField( tif, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel );
TIFFSetField( tif, TIFFTAG_ROWSPERSTRIP, tiff_rowsperstrip );
/* TIFFSetField( tif, TIFFTAG_STRIPBYTECOUNTS, rows / tiff_rowsperstrip ); */
TIFFSetField( tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG );
if ( chv == (colorhist_vector) 0 ) {
cht = (colorhash_table) 0;
} else {
/* Make TIFF colormap. */
for ( i = 0; i < colors; ++i ) {
red[i] = (unsigned short) (PPM_GETR( chv[i].color ) * 65535L / maxval);
grn[i] = (unsigned short) (PPM_GETG( chv[i].color ) * 65535L / maxval);
blu[i] = (unsigned short) (PPM_GETB( chv[i].color ) * 65535L / maxval);
}
TIFFSetField( tif, TIFFTAG_COLORMAP, red, grn, blu );
/* Convert color vector to color hash table, for fast lookup. */
cht = ppm_colorhisttocolorhash( chv, colors );
ppm_freecolorhist( chv );
}
/* Now write the TIFF data. */
for ( row = 0; row < rows; ++row ) {
xel *row_data = array + row*cols;
xelval *alpha_data = alpha + row*cols;
if ( !is_grayscale && ! grayscale ) {
if ( cht == (colorhash_table) 0 ) {
tP = buf;
for ( col = 0; col < cols; ++col ) {
*tP++ = (unsigned char)(255 * PPM_GETR(row_data[col]) / maxval);
*tP++ = (unsigned char)(255 * PPM_GETG(row_data[col]) / maxval);
*tP++ = (unsigned char)(255 * PPM_GETB(row_data[col]) / maxval);
if (samplesperpixel==4) {
*tP++ = (unsigned char)(255 * alpha_data[col] / maxval);
}
}
} else {
tP = buf;
for ( col = 0; col < cols; ++col ) {
register int s;
s = ppm_lookupcolor( cht, (pixel *)(&row_data[col]) );
if ( s == -1 )
pm_error("color not found?!? row=%d col=%d", row, col);
*tP++ = (unsigned char) s;
}
}
} else {
register xelval bigger_maxval;
register int bitshift;
register unsigned char byte;
register xelval s;
bigger_maxval = pm_bitstomaxval( bitspersample );
bitshift = 8 - bitspersample;
byte = 0;
tP = buf;
for ( col = 0; col < cols; ++col ) {
s = PPM_GETB(row_data[col]);
if ( maxval != bigger_maxval )
s = (xelval)((long) s * bigger_maxval / maxval);
byte |= s << bitshift;
bitshift -= bitspersample;
if ( bitshift < 0 ) {
*tP++ = byte;
bitshift = 8 - bitspersample;
byte = 0;
}
}
if ( bitshift != 8 - bitspersample )
*tP++ = byte;
}
if ( TIFFWriteScanline( tif, buf, row, 0 ) < 0 )
pm_error( "failed a scanline write on row %d", row );
}
TIFFFlushData( tif );
TIFFClose( tif );
// owns_file = false;
return rows;
}

View File

@ -1,606 +0,0 @@
// pnm-image-writebmp.cc
//
// PNMImage::WriteBMP() and supporting functions.
// Much code in this file is borrowed from Netpbm, specifically ppmtobmp.c.
/*\
* $Id$
*
* ppmtobmp.c - Converts from a PPM file to a Microsoft Windows or OS/2
* .BMP file.
*
* The current implementation is probably not complete, but it works for
* me. I welcome feedback.
*
* Copyright (C) 1992 by David W. Sanderson.
*
* 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.
*
* $Log$
* Revision 1.2 2000/10/17 21:49:09 drose
* *** empty log message ***
*
* Revision 1.1.1.1 2000/10/04 01:14:42 drose
*
*
* Revision 1.9 1992/11/24 19:39:33 dws
* Added copyright.
*
* Revision 1.8 1992/11/17 02:16:52 dws
* Moved length functions to bmp.h.
*
* Revision 1.7 1992/11/11 23:18:16 dws
* Modified to adjust the bits per pixel to 1, 4, or 8.
*
* Revision 1.6 1992/11/11 22:43:39 dws
* Commented out a superfluous message.
*
* Revision 1.5 1992/11/11 05:58:06 dws
* First version that works.
*
* Revision 1.4 1992/11/11 03:40:32 dws
* Moved calculation of bits per pixel to BMPEncode.
*
* Revision 1.3 1992/11/11 03:02:34 dws
* Added BMPEncode function.
*
* Revision 1.2 1992/11/08 01:44:35 dws
* Added option processing and reading of PPM file.
*
* Revision 1.1 1992/11/08 00:46:07 dws
* Initial revision
\*/
#include "pnmImage.h"
#include "pnmWriter.h"
#include "pnmWriterTypes.h"
extern "C" {
#include "../pnm/bmp.h"
#include "../pnm/ppmcmap.h"
#include "../pnm/bitio.h"
}
#define MAXCOLORS 256
/*
* Utilities
*/
static char er_write[] = "stdout: write error";
/* prototypes */
static void PutByte ARGS((FILE *fp, char v));
static void PutShort ARGS((FILE *fp, short v));
static void PutLong ARGS((FILE *fp, long v));
static int BMPwritefileheader ARGS((FILE *fp, int classv, unsigned long bitcount,
unsigned long x, unsigned long y));
static int BMPwriteinfoheader ARGS((FILE *fp, int classv, unsigned long bitcount,
unsigned long x, unsigned long y));
static int BMPwritergb ARGS((FILE *fp, int classv, pixval R, pixval G, pixval B));
static int BMPwritergbtable ARGS((FILE *fp, int classv, int bpp, int colors,
pixval *R, pixval *G, pixval *B));
static int BMPwriterow ARGS((FILE *fp, pixel *row, unsigned long cx,
unsigned short bpp, colorhash_table cht));
static int BMPwritebits ARGS((FILE *fp, unsigned long cx, unsigned long cy,
unsigned short cBitCount, pixel **pixels, colorhash_table cht));
static int colorstobpp ARGS((int colors));
static void BMPEncode ARGS((FILE *fp, int classv, int x, int y, pixel **pixels,
int colors, colorhash_table cht, pixval *R, pixval *G, pixval *B));
static void
PutByte(
FILE *fp,
char v)
{
if (putc(v, fp) == EOF)
{
pm_error(er_write);
}
}
static void
PutShort(
FILE *fp,
short v)
{
if (pm_writelittleshort(fp, v) == -1)
{
pm_error(er_write);
}
}
static void
PutLong(
FILE *fp,
long v)
{
if (pm_writelittlelong(fp, v) == -1)
{
pm_error(er_write);
}
}
/*
* BMP writing
*/
/*
* returns the number of bytes written, or -1 on error.
*/
static int
BMPwritefileheader(
FILE *fp,
int classv,
unsigned long bitcount,
unsigned long x,
unsigned long y)
{
PutByte(fp, 'B');
PutByte(fp, 'M');
/* cbSize */
PutLong(fp, (long)BMPlenfile(classv, bitcount, x, y));
/* xHotSpot */
PutShort(fp, 0);
/* yHotSpot */
PutShort(fp, 0);
/* offBits */
PutLong(fp, (long)BMPoffbits(classv, bitcount));
return 14;
}
/*
* returns the number of bytes written, or -1 on error.
*/
static int
BMPwriteinfoheader(
FILE *fp,
int classv,
unsigned long bitcount,
unsigned long x,
unsigned long y)
{
long cbFix;
/* cbFix */
switch (classv)
{
case C_WIN:
cbFix = 40;
PutLong(fp, cbFix);
/* cx */
PutLong(fp, (long)x);
/* cy */
PutLong(fp, (long)y);
/* cPlanes */
PutShort(fp, 1);
/* cBitCount */
PutShort(fp, (short)bitcount);
/*
* We've written 16 bytes so far, need to write 24 more
* for the required total of 40.
*/
PutLong(fp, 0);
PutLong(fp, 0);
PutLong(fp, 0);
PutLong(fp, 0);
PutLong(fp, 0);
PutLong(fp, 0);
break;
case C_OS2:
cbFix = 12;
PutLong(fp, cbFix);
/* cx */
PutShort(fp, (short)x);
/* cy */
PutShort(fp, (short)y);
/* cPlanes */
PutShort(fp, 1);
/* cBitCount */
PutShort(fp, (short)bitcount);
break;
default:
pm_error(er_internal, "BMPwriteinfoheader");
}
return cbFix;
}
/*
* returns the number of bytes written, or -1 on error.
*/
static int
BMPwritergb(
FILE *fp,
int classv,
pixval R,
pixval G,
pixval B)
{
switch (classv)
{
case C_WIN:
PutByte(fp, B);
PutByte(fp, G);
PutByte(fp, R);
PutByte(fp, 0);
return 4;
case C_OS2:
PutByte(fp, B);
PutByte(fp, G);
PutByte(fp, R);
return 3;
default:
pm_error(er_internal, "BMPwritergb");
}
return -1;
}
/*
* returns the number of bytes written, or -1 on error.
*/
static int
BMPwritergbtable(
FILE *fp,
int classv,
int bpp,
int colors,
pixval *R,
pixval *G,
pixval *B)
{
int nbyte = 0;
int i;
long ncolors;
for (i = 0; i < colors; i++)
{
nbyte += BMPwritergb(fp,classv,R[i],G[i],B[i]);
}
ncolors = (1 << bpp);
for (; i < ncolors; i++)
{
nbyte += BMPwritergb(fp,classv,0,0,0);
}
return nbyte;
}
/*
* returns the number of bytes written, or -1 on error.
*/
static int
BMPwriterow(
FILE *fp,
pixel *row,
unsigned long cx,
unsigned short bpp,
int indexed,
colorhash_table cht)
{
BITSTREAM b;
unsigned nbyte = 0;
int rc;
unsigned x;
if (indexed) {
if ((b = pm_bitinit(fp, "w")) == (BITSTREAM) 0)
{
return -1;
}
for (x = 0; x < cx; x++, row++)
{
if ((rc = pm_bitwrite(b, bpp, ppm_lookupcolor(cht, row))) == -1)
{
return -1;
}
nbyte += rc;
}
if ((rc = pm_bitfini(b)) == -1)
{
return -1;
}
nbyte += rc;
} else {
for (x = 0; x < cx; x++, row++)
{
PutByte(fp, PPM_GETB(*row));
PutByte(fp, PPM_GETG(*row));
PutByte(fp, PPM_GETR(*row));
nbyte += 3;
}
}
/*
* Make sure we write a multiple of 4 bytes.
*/
while (nbyte % 4)
{
PutByte(fp, 0);
nbyte++;
}
return nbyte;
}
/*
* returns the number of bytes written, or -1 on error.
*/
static int
BMPwritebits(
FILE *fp,
unsigned long cx,
unsigned long cy,
unsigned short cBitCount,
pixel **pixels,
int indexed,
colorhash_table cht)
{
int nbyte = 0;
long y;
if(cBitCount > 24)
{
pm_error("cannot handle cBitCount: %d"
,cBitCount);
}
/*
* The picture is stored bottom line first, top line last
*/
for (y = (long)cy - 1; y >= 0; y--)
{
int rc;
rc = BMPwriterow(fp, pixels[y], cx, cBitCount, indexed, cht);
if(rc == -1)
{
pm_error("couldn't write row %d"
,y);
}
if(rc%4)
{
pm_error("row had bad number of bytes: %d"
,rc);
}
nbyte += rc;
}
return nbyte;
}
/*
* Return the number of bits per pixel required to represent the
* given number of colors.
*/
static int
colorstobpp(int colors)
{
int bpp;
if (colors < 1)
{
pm_error("can't have less than one color");
}
if ((bpp = pm_maxvaltobits(colors - 1)) > 8)
{
pm_error("can't happen");
}
return bpp;
}
/*
* Write a BMP file of the given classv.
*
* Note that we must have 'colors' in order to know exactly how many
* colors are in the R, G, B, arrays. Entries beyond those in the
* arrays are undefined.
*/
static void
BMPEncode(
FILE *fp,
int classv,
int x,
int y,
pixel **pixels,
int colors, /* number of valid entries in R,G,B */
colorhash_table cht,
pixval *R,
pixval *G,
pixval *B)
{
int bpp; /* bits per pixel */
unsigned long nbyte = 0;
bpp = colorstobpp(colors);
/*
* I have found empirically at least one BMP-displaying program
* that can't deal with (for instance) using 3 bits per pixel.
* I have seen no programs that can deal with using 3 bits per
* pixel. I have seen programs which can deal with 1, 4, and
* 8 bits per pixel.
*
* Based on this, I adjust actual the number of bits per pixel
* as follows. If anyone knows better, PLEASE tell me!
*/
switch(bpp)
{
case 2:
case 3:
bpp = 4;
break;
case 5:
case 6:
case 7:
bpp = 8;
break;
}
pm_message("Using %d bits per pixel", bpp);
nbyte += BMPwritefileheader(fp, classv, bpp, x, y);
nbyte += BMPwriteinfoheader(fp, classv, bpp, x, y);
nbyte += BMPwritergbtable(fp, classv, bpp, colors, R, G, B);
if(nbyte != ( BMPlenfileheader(classv)
+ BMPleninfoheader(classv)
+ BMPlenrgbtable(classv, bpp)))
{
pm_error(er_internal, "BMPEncode");
}
nbyte += BMPwritebits(fp, x, y, bpp, pixels, true, cht);
if(nbyte != BMPlenfile(classv, bpp, x, y))
{
pm_error(er_internal, "BMPEncode");
}
}
/*
* Write a BMP file of the given class, with 24 bits per pixel nonindexed.
*/
static void
BMPEncode24(
FILE *fp,
int classv,
int x,
int y,
pixel **pixels)
{
unsigned long nbyte = 0;
int bpp = 24;
pm_message("Using %d bits per pixel", bpp);
nbyte += BMPwritefileheader(fp, classv, bpp, x, y);
nbyte += BMPwriteinfoheader(fp, classv, bpp, x, y);
if(nbyte != ( BMPlenfileheader(classv)
+ BMPleninfoheader(classv)))
{
pm_error(er_internal, "BMPEncode24");
}
nbyte += BMPwritebits(fp, x, y, bpp, pixels, false, colorhash_table());
if(nbyte != BMPlenfile(classv, bpp, x, y))
{
pm_error(er_internal, "BMPEncode24");
}
}
int PNMWriterBMP::
WriteData(xel *array, xelval *) {
if (rows<=0 || cols<=0) {
return 0;
}
int classv = C_WIN;
int colors;
int i;
colorhist_vector chv;
pixval Red[MAXCOLORS];
pixval Green[MAXCOLORS];
pixval Blue[MAXCOLORS];
pixel** pixels;
colorhash_table cht;
#if 0
{
char *name;
switch (classv)
{
case C_WIN:
name = "a Windows";
break;
case C_OS2:
name = "an OS/2";
break;
default:
pm_error(er_internal, "report");
break;
}
pm_message("generating %s BMP file", name);
}
#endif
// We need an honest 2-d array of pixels, instead of one big 1-d array.
pixels = (pixel **)alloca(sizeof(pixel *) * rows);
for (i = 0; i < rows; i++) {
pixels[i] = (pixel *)(array + i * cols);
}
/* Figure out the colormap. */
pm_message("computing colormap...");
chv = ppm_computecolorhist(pixels, cols, rows, MAXCOLORS, &colors);
if (chv == (colorhist_vector) 0) {
pm_message("too many colors; generating 24-bit BMP file");
BMPEncode24(file, classv, cols, rows, pixels);
} else {
pm_message("%d colors found", colors);
/*
* Now turn the ppm colormap into the appropriate GIF
* colormap.
*/
if (maxval > 255)
{
pm_message("maxval is not 255 - automatically rescaling colors");
}
for (i = 0; i < colors; ++i)
{
if (maxval == 255)
{
Red[i] = PPM_GETR(chv[i].color);
Green[i] = PPM_GETG(chv[i].color);
Blue[i] = PPM_GETB(chv[i].color);
}
else
{
Red[i] = (pixval) PPM_GETR(chv[i].color) * 255 / maxval;
Green[i] = (pixval) PPM_GETG(chv[i].color) * 255 / maxval;
Blue[i] = (pixval) PPM_GETB(chv[i].color) * 255 / maxval;
}
}
/* And make a hash table for fast lookup. */
cht = ppm_colorhisttocolorhash(chv, colors);
ppm_freecolorhist(chv);
BMPEncode(file, classv, cols, rows, pixels, colors, cht,
Red, Green, Blue);
}
return rows;
}

View File

@ -1,304 +0,0 @@
// pnm-image-writesgi.cc
//
// PNMImage::WriteSGI() and supporting functions.
// Much code in this file originally came from from Netpbm,
// specifically pnmtosgi.c. It has since been fairly heavily
// modified.
/* pnmtosgi.c - convert portable anymap to SGI image
**
** Copyright (C) 1994 by Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de)
**
** Based on the SGI image description v0.9 by Paul Haeberli (paul@sgi.comp)
** Available via ftp from sgi.com:graphics/SGIIMAGESPEC
**
** 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.
**
** 29Jan94: first version
*/
#include "pnmImage.h"
#include "pnmWriter.h"
#include "pnmWriterTypes.h"
#include "../pnm/sgi.h"
#define WORSTCOMPR(x) (2*(x) + 2)
#define MAXVAL_BYTE 255
#define MAXVAL_WORD 65535
static char storage = STORAGE_RLE;
inline void
put_byte(FILE *out_file, unsigned char b) {
putc(b, out_file);
}
static void
put_big_short(FILE *out_file, short s) {
if ( pm_writebigshort( out_file, s ) == -1 )
pm_error( "write error" );
}
static void
put_big_long(FILE *out_file, long l) {
if ( pm_writebiglong( out_file, l ) == -1 )
pm_error( "write error" );
}
static void
put_short_as_byte(FILE *out_file, short s) {
put_byte(out_file, (unsigned char)s);
}
PNMWriterSGI::
~PNMWriterSGI() {
if (table!=NULL) {
// Rewrite the table with the correct values in it.
fseek(file, table_start, SEEK_SET);
WriteTable();
delete[] table;
}
}
bool PNMWriterSGI::
WriteHeader() {
table = NULL;
switch (color_type) {
case PNMImage::Grayscale:
dimensions = 2; channels = 1;
break;
case PNMImage::TwoChannel:
dimensions = 2; channels = 2;
break;
case PNMImage::Color:
dimensions = 3; channels = 3;
break;
case PNMImage::FourChannel:
dimensions = 3; channels = 4;
break;
}
// For some reason, we have problems with SGI image files whose pixmax value
// is not 255 or 65535. So, we'll round up when writing.
if( maxval <= MAXVAL_BYTE ) {
bpc = 1;
new_maxval = MAXVAL_BYTE;
} else if( maxval <= MAXVAL_WORD ) {
bpc = 2;
new_maxval = MAXVAL_WORD;
} else {
return false;
}
if( storage != STORAGE_VERBATIM ) {
table = new TabEntry[channels * rows];
memset(table, 0, channels * rows * sizeof(TabEntry));
}
write_header("no name");
if (table!=NULL) {
table_start = ftell(file);
// The first time we write the table, it has zeroes. We'll correct
// this later.
WriteTable();
}
current_row = rows-1;
return true;
}
bool PNMWriterSGI::
WriteRow(xel *row_data, xelval *alpha_data) {
ScanLine channel[4];
BuildScanline(channel, row_data, alpha_data);
if( bpc == 1 )
WriteChannels(channel, put_short_as_byte);
else
WriteChannels(channel, put_big_short);
for (int i = 0; i < channels; i++) {
delete[] channel[i].data;
}
current_row--;
return true;
}
void PNMWriterSGI::
write_header(char *imagename) {
int i;
put_big_short(file, SGI_MAGIC);
put_byte(file, storage);
put_byte(file, (char)bpc);
put_big_short(file, dimensions);
put_big_short(file, cols);
put_big_short(file, rows);
put_big_short(file, channels);
put_big_long(file, 0); /* PIXMIN */
put_big_long(file, maxval); /* PIXMAX */
for( i = 0; i < 4; i++ )
put_byte(file, 0);
for( i = 0; i < 79 && imagename[i] != '\0'; i++ )
put_byte(file, imagename[i]);
for(; i < 80; i++ )
put_byte(file, 0);
put_big_long(file, CMAP_NORMAL);
for( i = 0; i < 404; i++ )
put_byte(file, 0);
}
void PNMWriterSGI::
WriteTable() {
int i;
int tabsize = rows*channels;
for( i = 0; i < tabsize; i++ ) {
put_big_long(file, table[i].start);
}
for( i = 0; i < tabsize; i++ )
put_big_long(file, table[i].length);
}
void PNMWriterSGI::
WriteChannels(ScanLine channel[], void (*put)(FILE *, short)) {
int i, col;
for( i = 0; i < channels; i++ ) {
Table(i).start = ftell(file);
Table(i).length = channel[i].length * bpc;
for( col = 0; col < channel[i].length; col++ ) {
(*put)(file, channel[i].data[col]);
}
}
}
void PNMWriterSGI::
BuildScanline(ScanLine output[], xel *row_data, xelval *alpha_data) {
int col;
ScanElem *temp;
if( storage != STORAGE_VERBATIM ) {
rletemp = (ScanElem *)alloca(WORSTCOMPR(cols) * sizeof(ScanElem));
}
temp = new ScanElem[cols];
if( channels <= 2 ) {
for( col = 0; col < cols; col++ )
temp[col] = (ScanElem)
(new_maxval * PPM_GETB(row_data[col]) / maxval);
temp = Compress(temp, output[0]);
if (channels == 2) {
for( col = 0; col < cols; col++ )
temp[col] = (ScanElem)
(new_maxval * alpha_data[col] / maxval);
temp = Compress(temp, output[1]);
}
} else {
for( col = 0; col < cols; col++ )
temp[col] = (ScanElem)
(new_maxval * PPM_GETR(row_data[col]) / maxval);
temp = Compress(temp, output[0]);
for( col = 0; col < cols; col++ )
temp[col] = (ScanElem)
(new_maxval * PPM_GETG(row_data[col]) / maxval);
temp = Compress(temp, output[1]);
for( col = 0; col < cols; col++ )
temp[col] = (ScanElem)
(new_maxval * PPM_GETB(row_data[col]) / maxval);
temp = Compress(temp, output[2]);
if (channels == 4) {
for( col = 0; col < cols; col++ )
temp[col] = (ScanElem)
(new_maxval * alpha_data[col] / maxval);
temp = Compress(temp, output[3]);
}
}
delete[] temp;
}
PNMWriterSGI::ScanElem *PNMWriterSGI::
Compress(ScanElem *temp, ScanLine &output) {
int len;
switch( storage ) {
case STORAGE_VERBATIM:
output.length = cols;
output.data = temp;
temp = new ScanElem[cols];
break;
case STORAGE_RLE:
len = RLECompress(temp, cols); /* writes result into rletemp */
output.length = len;
output.data = new ScanElem[len];
memcpy(output.data, rletemp, len * sizeof(ScanElem));
break;
default:
pm_error("unknown storage type - can\'t happen");
}
return temp;
}
/*
slightly modified RLE algorithm from ppmtoilbm.c
written by Robert A. Knop (rknop@mop.caltech.edu)
*/
int PNMWriterSGI::
RLECompress(ScanElem *inbuf, int size) {
int in, out, hold, count;
ScanElem *outbuf = rletemp;
in=out=0;
while( in<size ) {
if( (in<size-1) && (inbuf[in]==inbuf[in+1]) ) { /*Begin replicate run*/
for( count=0,hold=in; in<size && inbuf[in]==inbuf[hold] && count<127; in++,count++)
;
outbuf[out++]=(ScanElem)(count);
outbuf[out++]=inbuf[hold];
}
else { /*Do a literal run*/
hold=out; out++; count=0;
while( ((in>=size-2)&&(in<size)) || ((in<size-2) && ((inbuf[in]!=inbuf[in+1])||(inbuf[in]!=inbuf[in+2]))) ) {
outbuf[out++]=inbuf[in++];
if( ++count>=127 )
break;
}
outbuf[hold]=(ScanElem)(count | 0x80);
}
}
outbuf[out++] = (ScanElem)0; /* terminator */
return(out);
}

View File

@ -1,96 +0,0 @@
// pnm-image-writeyuv.cc
//
// PNMImage::WriteYUV() and supporting functions.
// Much code in this file is borrowed from Netpbm, specifically ppmtoyuv.c.
/* ppmtoyuv.c - convert a portable pixmap into an Abekas YUV file
**
** by Marc Boucher
** Internet: marc@PostImage.cxxOM
**
** Based on Example Conversion Program, A60/A64 Digital Video Interface
** Manual, page 69.
**
** Copyright (C) 1991 by DHD PostImage Inc.
** Copyright (C) 1987 by Abekas Video Systems Inc.
**
** 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 "pnmImage.h"
#include "pnmWriter.h"
#include "pnmWriterTypes.h"
bool PNMWriterYUV::
WriteHeader() {
if (yuvbuf!=NULL) {
pm_freerow((char *)yuvbuf);
}
yuvbuf = (unsigned char *) pm_allocrow( cols, 2 );
return true;
}
bool PNMWriterYUV::
WriteRow(xel *row_data, xelval *) {
int col;
unsigned long y1, y2=0, u=0, v=0, u0=0, u1, u2, v0=0, v1, v2;
static const int max_byte = 255;
unsigned char *yuvptr;
for (col = 0, yuvptr=yuvbuf; col < cols; col += 2) {
pixval r, g, b;
/* first pixel gives Y and 0.5 of chroma */
r = (pixval)(max_byte * PPM_GETR(row_data[col])/maxval);
g = (pixval)(max_byte * PPM_GETG(row_data[col])/maxval);
b = (pixval)(max_byte * PPM_GETB(row_data[col])/maxval);
y1 = 16829 * r + 33039 * g + 6416 * b + (0xffff & y2);
u1 = -4853 * r - 9530 * g + 14383 * b;
v1 = 14386 * r - 12046 * g - 2340 * b;
/* second pixel just yields a Y and 0.25 U, 0.25 V */
r = (pixval)(max_byte * PPM_GETR(row_data[col])/maxval);
g = (pixval)(max_byte * PPM_GETG(row_data[col])/maxval);
b = (pixval)(max_byte * PPM_GETB(row_data[col])/maxval);
y2 = 16829 * r + 33039 * g + 6416 * b + (0xffff & y1);
u2 = -2426 * r - 4765 * g + 7191 * b;
v2 = 7193 * r - 6023 * g - 1170 * b;
/* filter the chroma */
u = u0 + u1 + u2 + (0xffff & u);
v = v0 + v1 + v2 + (0xffff & v);
u0 = u2;
v0 = v2;
*yuvptr++ = (unsigned char)((u >> 16) + 128);
*yuvptr++ = (unsigned char)((y1 >> 16) + 16);
*yuvptr++ = (unsigned char)((v >> 16) + 128);
*yuvptr++ = (unsigned char)((y2 >> 16) + 16);
}
fwrite(yuvbuf, cols*2, 1, file);
return true;
}
PNMWriterYUV::
~PNMWriterYUV() {
if (yuvbuf!=NULL) {
pm_freerow((char *)yuvbuf);
}
}

View File

@ -11,7 +11,7 @@
////////////////////////////////////////////////////////////////////
// Function: PNMImageHeader::read_header
// Access: Public, Static
// Access: Public
// Description: Opens up the image file and tries to read its header
// information to determine its size, number of
// channels, etc. If successful, updates the header
@ -24,6 +24,7 @@ read_header(const Filename &filename, PNMFileType *type) {
if (reader != (PNMReader *)NULL) {
(*this) = (*reader);
_type = reader->get_type();
delete reader;
return true;
}
@ -32,13 +33,16 @@ read_header(const Filename &filename, PNMFileType *type) {
////////////////////////////////////////////////////////////////////
// Function: PNMImageHeader::make_reader
// Access: Public, Static
// Description: Returns a PNMReader of the suitable type for reading
// from the indicated image filename, or NULL if the
// filename cannot be read for some reason. The
// filename "-" always stands for standard input. If
// type is specified, it is a suggestion for the file
// type to use.
// Access: Public
// Description: Returns a newly-allocated PNMReader of the suitable
// type for reading from the indicated image filename,
// or NULL if the filename cannot be read for some
// reason. The filename "-" always stands for standard
// input. If type is specified, it is a suggestion for
// the file type to use.
//
// The PNMReader should be deleted when it is no longer
// needed.
////////////////////////////////////////////////////////////////////
PNMReader *PNMImageHeader::
make_reader(const Filename &filename, PNMFileType *type) const {
@ -87,10 +91,10 @@ make_reader(const Filename &filename, PNMFileType *type) const {
////////////////////////////////////////////////////////////////////
// Function: PNMImageHeader::make_reader
// Access: Public, Static
// Description: Returns a PNMReader of the suitable type for reading
// from the already-opened image file, or NULL if the
// file cannot be read for some reason.
// Access: Public
// Description: Returns a newly-allocated PNMReader of the suitable
// type for reading from the already-opened image file,
// or NULL if the file cannot be read for some reason.
//
// owns_file should be set true if the PNMReader is to
// be considered the owner of the FILE stream (in which
@ -110,6 +114,9 @@ make_reader(const Filename &filename, PNMFileType *type) const {
//
// If type is non-NULL, it is a suggestion for the file
// type to use.
//
// The PNMReader should be deleted when it is no longer
// needed.
////////////////////////////////////////////////////////////////////
PNMReader *PNMImageHeader::
make_reader(FILE *file, bool owns_file, const Filename &filename,
@ -199,13 +206,16 @@ make_reader(FILE *file, bool owns_file, const Filename &filename,
////////////////////////////////////////////////////////////////////
// Function: PNMImageHeader::make_writer
// Access: Public, Static
// Description: Returns a PNMWriter of the suitable type for writing
// an image to the indicated filename, or NULL if the
// filename cannot be written for some reason. The
// filename "-" always stands for standard output. If
// type is specified, it is a suggestion for the file
// type to use.
// Access: Public
// Description: Returns a newly-allocated PNMWriter of the suitable
// type for writing an image to the indicated filename,
// or NULL if the filename cannot be written for some
// reason. The filename "-" always stands for standard
// output. If type is specified, it is a suggestion for
// the file type to use.
//
// The PNMWriter should be deleted when it is no longer
// needed.
////////////////////////////////////////////////////////////////////
PNMWriter *PNMImageHeader::
make_writer(const Filename &filename, PNMFileType *type) const {
@ -244,10 +254,10 @@ make_writer(const Filename &filename, PNMFileType *type) const {
////////////////////////////////////////////////////////////////////
// Function: PNMImageHeader::make_writer
// Access: Public, Static
// Description: Returns a PNMWriter of the suitable type for writing
// to the already-opened image file, or NULL if the
// file cannot be written for some reason.
// Access: Public
// Description: Returns a newly-allocated PNMWriter of the suitable
// type for writing to the already-opened image file, or
// NULL if the file cannot be written for some reason.
//
// owns_file should be set true if the PNMWriter is to
// be considered the owner of the FILE stream (in which
@ -262,6 +272,9 @@ make_writer(const Filename &filename, PNMFileType *type) const {
//
// If type is non-NULL, it is a suggestion for the file
// type to use.
//
// The PNMWriter should be deleted when it is no longer
// needed.
////////////////////////////////////////////////////////////////////
PNMWriter *PNMImageHeader::
make_writer(FILE *file, bool owns_file, const Filename &filename,
@ -325,7 +338,7 @@ make_writer(FILE *file, bool owns_file, const Filename &filename,
////////////////////////////////////////////////////////////////////
bool PNMImageHeader::
read_magic_number(FILE *file, string &magic_number, int num_bytes) {
while (magic_number.size() < num_bytes) {
while ((int)magic_number.size() < num_bytes) {
int ch = getc(file);
if (ch == EOF) {
return false;

View File

@ -11,8 +11,8 @@
INLINE PNMReader::
PNMReader(PNMFileType *type, FILE *file, bool owns_file) :
_type(type),
_file(file),
_owns_file(owns_file),
_file(file),
_is_valid(true)
{
}

View File

@ -12,8 +12,8 @@
INLINE PNMWriter::
PNMWriter(PNMFileType *type, FILE *file, bool owns_file) :
_type(type),
_file(file),
_owns_file(owns_file)
_owns_file(owns_file),
_file(file)
{
}

View File

@ -6,19 +6,6 @@
//
//
////////////////////////////////////////////////////////////////////
// Copyright (C) 1992,93,94,95 Walt Disney Imagineering, Inc.
//
// These coded instructions, statements, data structures and
// computer programs contain unpublished proprietary information of
// Walt Disney Imagineering and are protected by Federal copyright
// law. They may not be disclosed to third parties or copied or
// duplicated in any form, in whole or in part, without the prior
// written consent of Walt Disney Imagineering Inc.
////////////////////////////////////////////////////////////////////
//
// RCSID:
// $Header$
//
#ifndef _PNMMINMAX_H_
#define _PNMMINMAX_H_

View File

@ -74,3 +74,42 @@ clear_switches(void) {
_lod._switch_vector.erase(_lod._switch_vector.begin(),
_lod._switch_vector.end());
}
////////////////////////////////////////////////////////////////////
// Function: LODNode::get_num_switches
// Access: Public
// Description: Returns the number of switch ranges added to the
// LODNode. This should correspond to the number of
// children of the node in order for the LODNode to
// function correctly.
////////////////////////////////////////////////////////////////////
INLINE int LODNode::
get_num_switches() const {
return _lod._switch_vector.size();
}
////////////////////////////////////////////////////////////////////
// Function: LODNode::get_in
// Access: Public
// Description: Returns the "in" distance of the indicated switch
// range. This should be larger than the "out" distance
// of the same range.
////////////////////////////////////////////////////////////////////
INLINE float LODNode::
get_in(int index) const {
nassertr(index >= 0 && index < (int)_lod._switch_vector.size(), 0.0);
return _lod._switch_vector[index].get_in();
}
////////////////////////////////////////////////////////////////////
// Function: LODNode::get_out
// Access: Public
// Description: Returns the "out" distance of the indicated switch
// range. This should be smaller than the "in" distance
// of the same range.
////////////////////////////////////////////////////////////////////
INLINE float LODNode::
get_out(int index) const {
nassertr(index >= 0 && index < (int)_lod._switch_vector.size(), 0.0);
return _lod._switch_vector[index].get_out();
}

View File

@ -50,6 +50,18 @@ xform(const LMatrix4f &mat) {
_lod.xform(mat);
}
////////////////////////////////////////////////////////////////////
// Function: LODNode::output
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void LODNode::
output(ostream &out) const {
NamedNode::output(out);
out << " ";
_lod.output(out);
}
////////////////////////////////////////////////////////////////////
// Function: sub_render
// Access:

View File

@ -39,6 +39,12 @@ public:
INLINE bool set_switch(int index, float in, float out);
INLINE void clear_switches(void);
INLINE int get_num_switches() const;
INLINE float get_in(int index) const;
INLINE float get_out(int index) const;
virtual void output(ostream &out) const;
virtual bool sub_render(const AllAttributesWrapper &attrib,
AllTransitionsWrapper &trans,
GraphicsStateGuardianBase *gsgbase);