auto-scale textures at load time, without loading full-res and then downrezzing

This commit is contained in:
David Rose 2007-05-16 02:21:58 +00:00
parent c7a09a3926
commit 161e2cd5b3
23 changed files with 380 additions and 77 deletions

View File

@ -1979,6 +1979,7 @@ do_read_one(const Filename &fullpath, const Filename &alpha_fullpath,
x_size = 1;
y_size = 1;
}
image = PNMImage(x_size, y_size, image.get_num_channels(),
image.get_maxval(), image.get_type());
image.fill(0.2, 0.3, 1.0);
@ -1987,6 +1988,19 @@ do_read_one(const Filename &fullpath, const Filename &alpha_fullpath,
}
} else {
if (!image.read_header(fullpath, NULL, false)) {
gobj_cat.error()
<< "Texture::read() - couldn't read: " << fullpath << endl;
return false;
}
if (z == 0 && n == 0) {
consider_rescale(image, fullpath.get_basename());
} else {
image.set_read_size(get_expected_mipmap_x_size(n),
get_expected_mipmap_y_size(n));
}
if (!image.read(fullpath, NULL, false)) {
gobj_cat.error()
<< "Texture::read() - couldn't read: " << fullpath << endl;
@ -2021,6 +2035,22 @@ do_read_one(const Filename &fullpath, const Filename &alpha_fullpath,
}
} else {
if (!alpha_image.read_header(alpha_fullpath, NULL, true)) {
gobj_cat.error()
<< "Texture::read() - couldn't read (alpha): " << alpha_fullpath << endl;
return false;
}
if (image.get_x_size() != alpha_image.get_x_size() ||
image.get_y_size() != alpha_image.get_y_size()) {
gobj_cat.info()
<< "Implicitly rescaling " << alpha_fullpath.get_basename()
<< " from " << alpha_image.get_x_size() << " by "
<< alpha_image.get_y_size() << " to " << image.get_x_size()
<< " by " << image.get_y_size() << "\n";
alpha_image.set_read_size(image.get_x_size(), image.get_y_size());
}
if (!alpha_image.read(alpha_fullpath, NULL, true)) {
gobj_cat.error()
<< "Texture::read() - couldn't read (alpha): " << alpha_fullpath << endl;
@ -2045,13 +2075,12 @@ do_read_one(const Filename &fullpath, const Filename &alpha_fullpath,
set_fullpath(fullpath);
set_alpha_fullpath(alpha_fullpath);
consider_rescale(image, fullpath.get_basename());
}
if (!alpha_fullpath.empty()) {
// The grayscale (alpha channel) image must be the same size as the
// main image.
// The grayscale (alpha channel) image must be the same size as
// the main image. This should really have been already
// guaranteed by the above.
if (image.get_x_size() != alpha_image.get_x_size() ||
image.get_y_size() != alpha_image.get_y_size()) {
gobj_cat.info()
@ -2818,8 +2847,13 @@ clear_prepared(PreparedGraphicsObjects *prepared_objects) {
////////////////////////////////////////////////////////////////////
// Function: Texture::consider_rescale
// Access: Private
// Description: Scales the PNMImage according to the whims of the
// Config.prc file.
// Description: Asks the PNMImage to change its scale when it reads
// the image, according to the whims of the Config.prc
// file.
//
// This method should be called after
// pnmimage.read_header() has been called, but before
// pnmimage.read().
////////////////////////////////////////////////////////////////////
void Texture::
consider_rescale(PNMImage &pnmimage, const string &name) {
@ -2877,14 +2911,11 @@ consider_rescale(PNMImage &pnmimage, const string &name) {
if (pnmimage.get_x_size() != new_x_size ||
pnmimage.get_y_size() != new_y_size) {
gobj_cat.info()
<< "Automatically rescaling " << name << " from "
<< "Implicitly rescaling " << name << " from "
<< pnmimage.get_x_size() << " by " << pnmimage.get_y_size() << " to "
<< new_x_size << " by " << new_y_size << "\n";
PNMImage scaled(new_x_size, new_y_size, pnmimage.get_num_channels(),
pnmimage.get_maxval(), pnmimage.get_type());
scaled.quick_filter_from(pnmimage);
pnmimage = scaled;
pnmimage.set_read_size(new_x_size, new_y_size);
}
}

View File

@ -25,6 +25,8 @@ INLINE PNMImage::
PNMImage() {
_array = NULL;
_alpha = NULL;
clear();
}
////////////////////////////////////////////////////////////////////
@ -155,6 +157,39 @@ alpha_fill(double alpha) {
alpha_fill_val((xelval)(alpha * get_maxval()));
}
////////////////////////////////////////////////////////////////////
// Function: PNMImage::set_read_size
// Access: Published
// Description: Specifies the size to we'd like to scale the image
// upon reading it. This will affect the next call to
// read(). This is usually used to reduce the image
// size, e.g. for a thumbnail.
//
// If the file type reader supports it (e.g. JPEG), then
// this will scale the image during the read operation,
// consequently reducing memory and CPU utilization. If
// the file type reader does not support it, this will
// load the image normally, and them perform a linear
// scale after it has been loaded.
////////////////////////////////////////////////////////////////////
INLINE void PNMImage::
set_read_size(int x_size, int y_size) {
_read_x_size = x_size;
_read_y_size = y_size;
_has_read_size = true;
}
////////////////////////////////////////////////////////////////////
// Function: PNMImage::clear_read_size
// Access: Published
// Description: Undoes the effect of a previous call to
// set_read_size().
////////////////////////////////////////////////////////////////////
INLINE void PNMImage::
clear_read_size() {
_has_read_size = false;
}
////////////////////////////////////////////////////////////////////
// Function: PNMImage::is_valid
// Access: Published

View File

@ -31,6 +31,7 @@ PNMImage::
PNMImage(const Filename &filename, PNMFileType *type) {
_array = NULL;
_alpha = NULL;
_has_read_size = false;
bool result = read(filename, type);
if (!result) {
@ -61,6 +62,7 @@ clear() {
_maxval = 255;
_comment.clear();
_type = (PNMFileType *)NULL;
_has_read_size = false;
}
////////////////////////////////////////////////////////////////////
@ -81,6 +83,7 @@ clear(int x_size, int y_size, int num_channels,
_maxval = maxval;
_comment.clear();
_type = type;
_has_read_size = false;
if (has_alpha()) {
allocate_alpha();
@ -220,13 +223,12 @@ remix_channels(const LMatrix4f &conv) {
////////////////////////////////////////////////////////////////////
bool PNMImage::
read(const Filename &filename, PNMFileType *type, bool report_unknown_type) {
clear();
PNMReader *reader = PNMImageHeader::make_reader(filename, type,
report_unknown_type);
PNMReader *reader = make_reader(filename, type, report_unknown_type);
if (reader == (PNMReader *)NULL) {
clear();
return false;
}
return read(reader);
}
@ -247,11 +249,10 @@ read(const Filename &filename, PNMFileType *type, bool report_unknown_type) {
bool PNMImage::
read(istream &data, const string &filename, PNMFileType *type,
bool report_unknown_type) {
clear();
PNMReader *reader = PNMImageHeader::make_reader
(&data, false, filename, string(), type, report_unknown_type);
if (reader == (PNMReader *)NULL) {
clear();
return false;
}
return read(reader);
@ -272,6 +273,10 @@ read(istream &data, const string &filename, PNMFileType *type,
////////////////////////////////////////////////////////////////////
bool PNMImage::
read(PNMReader *reader) {
bool has_read_size = _has_read_size;
int read_x_size = _read_x_size;
int read_y_size = _read_y_size;
clear();
if (reader == NULL) {
@ -283,6 +288,11 @@ read(PNMReader *reader) {
return false;
}
if (has_read_size) {
reader->set_read_size(read_x_size, read_y_size);
}
reader->prepare_read();
copy_header_from(*reader);
// We reassign y_size after reading because we might have read a
@ -293,10 +303,20 @@ read(PNMReader *reader) {
if (_y_size == 0) {
clear();
return false;
} else {
setup_rc();
return true;
}
setup_rc();
if (has_read_size && (_x_size != read_x_size || _y_size != read_y_size)) {
// The Reader didn't comply with our size request. Do the sizing
// explicitly, then.
PNMImage new_image(read_x_size, read_y_size, get_num_channels(),
get_maxval(), get_type());
new_image.quick_filter_from(*this);
take_from(new_image);
}
return true;
}
////////////////////////////////////////////////////////////////////

View File

@ -91,6 +91,9 @@ PUBLISHED:
INLINE void alpha_fill(double alpha = 0.0);
void alpha_fill_val(xelval alpha = 0);
INLINE void set_read_size(int x_size, int y_size);
INLINE void clear_read_size();
bool read(const Filename &filename, PNMFileType *type = NULL,
bool report_unknown_type = true);
bool read(istream &data, const string &filename = string(),
@ -239,6 +242,9 @@ private:
xel *_array;
xelval *_alpha;
double _default_rc, _default_gc, _default_bc;
int _read_x_size, _read_y_size;
bool _has_read_size;
};
#include "pnmImage.I"

View File

@ -35,8 +35,9 @@
// false.
////////////////////////////////////////////////////////////////////
bool PNMImageHeader::
read_header(const Filename &filename, PNMFileType *type) {
PNMReader *reader = make_reader(filename, type);
read_header(const Filename &filename, PNMFileType *type,
bool report_unknown_type) {
PNMReader *reader = make_reader(filename, type, report_unknown_type);
if (reader != (PNMReader *)NULL) {
(*this) = (*reader);
delete reader;

View File

@ -82,7 +82,8 @@ PUBLISHED:
INLINE PNMFileType *get_type() const;
INLINE void set_type(PNMFileType *type);
bool read_header(const Filename &filename, PNMFileType *type = NULL);
bool read_header(const Filename &filename, PNMFileType *type = NULL,
bool report_unknown_type = true);
PNMReader *make_reader(const Filename &filename,
PNMFileType *type = NULL,

View File

@ -26,10 +26,28 @@ PNMReader(PNMFileType *type, istream *file, bool owns_file) :
_type(type),
_owns_file(owns_file),
_file(file),
_is_valid(true)
_is_valid(true),
_has_read_size(false)
{
}
////////////////////////////////////////////////////////////////////
// Function: PNMReader::set_read_size
// Access: Public
// Description: Instructs the reader to attempt to scale the image to
// the indicated size while reading it. The reader may
// or may not follow this suggestion, or may follow it
// only partially (e.g. by reading a file which is
// slightly reduced in size, but not the precise size
// requested).
////////////////////////////////////////////////////////////////////
void PNMReader::
set_read_size(int x_size, int y_size) {
_read_x_size = x_size;
_read_y_size = y_size;
_has_read_size = true;
}
////////////////////////////////////////////////////////////////////
// Function: PNMReader::get_type
// Access: Public

View File

@ -39,6 +39,40 @@ PNMReader::
_file = (istream *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: PNMReader::prepare_read
// Access: Public, Virtual
// Description: This method will be called before read_data() or
// read_row() is called. It instructs the reader to
// initialize its data structures as necessary to
// actually perform the read operation.
//
// After this call, _x_size and _y_size should reflect
// the actual size that will be filled by read_data()
// (as possibly modified by set_read_size()).
////////////////////////////////////////////////////////////////////
void PNMReader::
prepare_read() {
if (!_is_valid) {
return;
}
_x_shift = 0;
_y_shift = 0;
_orig_x_size = _x_size;
_orig_y_size = _y_size;
if (supports_read_row()) {
// Maybe we can quick-filter each row down as we go.
if (_has_read_size) {
_x_shift = get_reduction_shift(_x_size, _read_x_size);
_x_size = _x_size / (1 << _x_shift);
_y_shift = get_reduction_shift(_y_size, _read_y_size);
_y_size = _y_size / (1 << _y_shift);
}
}
}
////////////////////////////////////////////////////////////////////
// Function: PNMReader::read_data
// Access: Public, Virtual
@ -58,12 +92,102 @@ read_data(xel *array, xelval *alpha) {
return 0;
}
int y;
for (y = 0; y < _y_size; y++) {
if (!read_row(array + y * _x_size, alpha + y * _x_size)) {
return y;
if (_x_shift == 0 && _y_shift == 0) {
// Read with no reduction.
int y;
for (y = 0; y < _y_size; ++y) {
if (!read_row(array + y * _x_size, alpha + y * _x_size, _x_size, _y_size)) {
return y;
}
}
} else {
int x_reduction = (1 << _x_shift);
int y_reduction = (1 << _y_shift);
int shift = _x_shift + _y_shift;
// We need a temporary buffer, at least one row wide, with
// full-width integers, for accumulating pixel data.
int *accum_row_array = (int *)alloca(_orig_x_size * sizeof(int) * 3);
int *accum_row_alpha = (int *)alloca(_orig_x_size * sizeof(int));
// Each time we read a row, we will actually read the full row
// here, before we filter it down into the above.
xel *orig_row_array = (xel *)alloca(_orig_x_size * sizeof(xel));
xelval *orig_row_alpha = (xelval *)alloca(_orig_x_size * sizeof(xelval));
int y;
for (y = 0; y < _y_size; ++y) {
// Zero out the accumulation data, in preparation for
// holding the results of the below.
memset(accum_row_array, 0, _x_size * sizeof(int) * 3);
if (has_alpha()) {
memset(accum_row_alpha, 0, _x_size * sizeof(int));
}
for (int yi = 0; yi < y_reduction; ++yi) {
// OK, read a row. This reads the original, full-size row.
if (!read_row(orig_row_array, orig_row_alpha, _orig_x_size, _orig_y_size)) {
return y;
}
// Boil that row down to its proper, reduced size, and
// accumulate it into the target row.
xel *p = orig_row_array;
int *q = accum_row_array;
int *qstop = q + _x_size * 3;
while (q < qstop) {
for (int xi = 0; xi < x_reduction; ++xi) {
q[0] += (*p).r;
q[1] += (*p).g;
q[2] += (*p).b;
++p;
}
q += 3;
}
if (has_alpha()) {
// Now do it again for the alpha channel.
xelval *p = orig_row_alpha;
int *q = accum_row_alpha;
int *qstop = q + _x_size;
while (q < qstop) {
for (int xi = 0; xi < x_reduction; ++xi) {
(*q) += (*p);
++p;
}
++q;
}
}
}
// OK, now copy the accumulated pixel data into the final
// result.
xel *target_row_array = array + y * _x_size;
xelval *target_row_alpha = alpha + y * _x_size;
int *p = accum_row_array;
xel *q = target_row_array;
xel *qstop = q + _x_size;
while (q < qstop) {
(*q).r = (*p++) >> shift;
(*q).g = (*p++) >> shift;
(*q).b = (*p++) >> shift;
++q;
}
if (has_alpha()) {
int *p = accum_row_alpha;
xelval *q = target_row_alpha;
xelval *qstop = q + _x_size;
while (q < qstop) {
(*q) = (*p++) >> shift;
++q;
}
}
}
}
return _y_size;
}
@ -91,9 +215,17 @@ supports_read_row() const {
// one horizontal row at a time, beginning from the top.
// Returns true if the row is successfully read, false
// if there is an error or end of file.
//
// The x_size and y_size parameters are the value of
// _x_size and _y_size as originally filled in by the
// constructor; it is the actual number of pixels in the
// image. (The _x_size and _y_size members may have
// been automatically modified by the time this method
// is called if we are scaling on load, so should not be
// used.)
////////////////////////////////////////////////////////////////////
bool PNMReader::
read_row(xel *, xelval *) {
read_row(xel *, xelval *, int, int) {
return false;
}
@ -111,3 +243,38 @@ bool PNMReader::
supports_stream_read() const {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: PNMReader::get_reduction_shift
// Access: Private
// Description: Determines the reduction factor between the original
// size and the requested size, returned as an exponent
// of power of 2 (that is, a bit shift).
//
// Only power-of-two reductions are supported, since
// those are common, easy, and fast. Other reductions
// will be handled in the higher level code.
////////////////////////////////////////////////////////////////////
int PNMReader::
get_reduction_shift(int orig_size, int new_size) {
if (new_size == 0) {
return 0;
}
int reduction = max(orig_size / new_size, 1);
int shift = 0;
int r = 2;
while (r <= reduction) {
shift += 1;
r <<= 1;
}
if ((orig_size % r) != 0) {
// If the reduction isn't even, never mind.
shift = 0;
}
return shift;
}

View File

@ -38,22 +38,33 @@ protected:
public:
virtual ~PNMReader();
INLINE void set_read_size(int x_size, int y_size);
INLINE PNMFileType *get_type() const;
virtual void prepare_read();
virtual int read_data(xel *array, xelval *alpha);
virtual bool supports_read_row() const;
virtual bool read_row(xel *array, xelval *alpha);
virtual bool read_row(xel *array, xelval *alpha, int x_size, int y_size);
virtual bool supports_stream_read() const;
INLINE bool is_valid() const;
private:
int get_reduction_shift(int orig_size, int new_size);
protected:
PNMFileType *_type;
bool _owns_file;
istream *_file;
bool _is_valid;
int _read_x_size, _read_y_size;
bool _has_read_size;
int _x_shift, _y_shift;
int _orig_x_size, _orig_y_size;
};
#include "pnmReader.I"

View File

@ -90,18 +90,6 @@ ConfigVariableInt jpeg_quality
"size)."));
// These control the scaling that is automatically performed on a JPEG
// file for decompression. You might specify to scale down by a
// fraction, e.g. 1/8, by specifying jpeg_scale_num = 1 and
// jpeg_scale_denom = 8. This will reduce decompression time
// correspondingly. Attempting to use this to scale up, or to scale
// by any fraction other than an even power of two, may not be
// supported.
ConfigVariableInt jpeg_scale_num
("jpeg-scale-num", 1);
ConfigVariableInt jpeg_scale_denom
("jpeg-scale-denom", 1);
ConfigVariableInt bmp_bpp
("bmp-bpp", 0,
PRC_DESC("This controls how many bits per pixel are written out for BMP "

View File

@ -52,8 +52,6 @@ extern ConfigVariableBool tga_colormap;
extern ConfigVariableBool tga_grayscale;
extern ConfigVariableInt jpeg_quality;
extern ConfigVariableInt jpeg_scale_num;
extern ConfigVariableInt jpeg_scale_denom;
extern ConfigVariableInt bmp_bpp;

View File

@ -229,7 +229,7 @@ supports_read_row() const {
// if there is an error or end of file.
////////////////////////////////////////////////////////////////////
bool PNMFileTypeAlias::Reader::
read_row(xel *row_data, xelval *) {
read_row(xel *row_data, xelval *, int x_size, int) {
if (!is_valid()) {
return false;
}
@ -239,9 +239,9 @@ read_row(xel *row_data, xelval *) {
unsigned char red, grn, blu;
x = 0;
while (x < _x_size) {
while (x < x_size) {
num = read_uchar_ALIAS(_file);
if (num==0 || x+num > _x_size) {
if (num==0 || x+num > x_size) {
return false;
}
blu = read_uchar_ALIAS(_file);

View File

@ -49,7 +49,7 @@ public:
Reader(PNMFileType *type, istream *file, bool owns_file, string magic_number);
virtual bool supports_read_row() const;
virtual bool read_row(xel *array, xelval *alpha);
virtual bool read_row(xel *array, xelval *alpha, int x_size, int y_size);
};
class Writer : public PNMWriter {

View File

@ -254,10 +254,10 @@ supports_read_row() const {
// if there is an error or end of file.
////////////////////////////////////////////////////////////////////
bool PNMFileTypeIMG::Reader::
read_row(xel *row_data, xelval *) {
read_row(xel *row_data, xelval *, int x_size, int) {
int x;
xelval red, grn, blu;
for (x = 0; x < _x_size; x++) {
for (x = 0; x < x_size; x++) {
red = read_uchar_IMG(_file);
grn = read_uchar_IMG(_file);
blu = read_uchar_IMG(_file);

View File

@ -49,7 +49,7 @@ public:
Reader(PNMFileType *type, istream *file, bool owns_file, string magic_number);
virtual bool supports_read_row() const;
virtual bool read_row(xel *array, xelval *alpha);
virtual bool read_row(xel *array, xelval *alpha, int x_size, int y_size);
};
class Writer : public PNMWriter {

View File

@ -73,6 +73,7 @@ public:
Reader(PNMFileType *type, istream *file, bool owns_file, string magic_number);
~Reader();
virtual void prepare_read();
virtual int read_data(xel *array, xelval *alpha);
private:

View File

@ -295,9 +295,36 @@ Reader(PNMFileType *type, istream *file, bool owns_file, string magic_number) :
* See libjpeg.doc for more info.
*/
_num_channels = _cinfo.num_components;
_x_size = (int)_cinfo.image_width;
_y_size = (int)_cinfo.image_height;
_maxval = MAXJSAMPLE;
/* Step 6: set parameters for decompression */
_cinfo.scale_num = jpeg_scale_num;
_cinfo.scale_denom = jpeg_scale_denom;
_cinfo.scale_num = 1;
_cinfo.scale_denom = 1;
}
////////////////////////////////////////////////////////////////////
// Function: PNMFileTypeJPG::Reader::prepare_read
// Access: Public, Virtual
// Description: This method will be called before read_data() or
// read_row() is called. It instructs the reader to
// initialize its data structures as necessary to
// actually perform the read operation.
//
// After this call, _x_size and _y_size should reflect
// the actual size that will be filled by read_data()
// (as possibly modified by set_read_size()).
////////////////////////////////////////////////////////////////////
void PNMFileTypeJPG::Reader::
prepare_read() {
if (_has_read_size && _read_x_size != 0 && _read_y_size != 0) {
// Attempt to get the scale close to our target scale.
int x_reduction = _cinfo.image_width / _read_x_size;
int y_reduction = _cinfo.image_height / _read_y_size;
_cinfo.scale_denom = max(min(x_reduction, y_reduction), 1);
}
/* Step 7: Start decompressor */
@ -309,7 +336,6 @@ Reader(PNMFileType *type, istream *file, bool owns_file, string magic_number) :
_num_channels = _cinfo.output_components;
_x_size = (int)_cinfo.output_width;
_y_size = (int)_cinfo.output_height;
_maxval = MAXJSAMPLE;
}
////////////////////////////////////////////////////////////////////

View File

@ -53,7 +53,7 @@ public:
virtual ~Reader();
virtual bool supports_read_row() const;
virtual bool read_row(xel *array, xelval *alpha);
virtual bool read_row(xel *array, xelval *alpha, int x_size, int y_size);
typedef struct {
long start; /* offset in file */

View File

@ -182,33 +182,33 @@ supports_read_row() const {
// if there is an error or end of file.
////////////////////////////////////////////////////////////////////
bool PNMFileTypeSGI::Reader::
read_row(xel *row_data, xelval *alpha_data) {
read_row(xel *row_data, xelval *alpha_data, int x_size, int y_size) {
if (!is_valid()) {
return false;
}
nassertr(current_row >= 0, false);
ScanElem *red = (ScanElem *)alloca(_x_size * sizeof(ScanElem));
ScanElem *grn = (ScanElem *)alloca(_x_size * sizeof(ScanElem));
ScanElem *blu = (ScanElem *)alloca(_x_size * sizeof(ScanElem));
ScanElem *alpha = (ScanElem *)alloca(_x_size * sizeof(ScanElem));
ScanElem *red = (ScanElem *)alloca(x_size * sizeof(ScanElem));
ScanElem *grn = (ScanElem *)alloca(x_size * sizeof(ScanElem));
ScanElem *blu = (ScanElem *)alloca(x_size * sizeof(ScanElem));
ScanElem *alpha = (ScanElem *)alloca(x_size * sizeof(ScanElem));
read_channel(_file, _x_size, _y_size, _num_channels, bpc, table, red,
read_channel(_file, x_size, y_size, _num_channels, bpc, table, red,
table_start, 0, current_row);
if (!is_grayscale()) {
read_channel(_file, _x_size, _y_size, _num_channels, bpc, table, grn,
read_channel(_file, x_size, y_size, _num_channels, bpc, table, grn,
table_start, 1, current_row);
read_channel(_file, _x_size, _y_size, _num_channels, bpc, table, blu,
read_channel(_file, x_size, y_size, _num_channels, bpc, table, blu,
table_start, 2, current_row);
}
if (has_alpha()) {
read_channel(_file, _x_size, _y_size, _num_channels, bpc, table, alpha,
read_channel(_file, x_size, y_size, _num_channels, bpc, table, alpha,
table_start, _num_channels - 1, current_row);
}
for (int x = 0; x < _x_size; x++) {
for (int x = 0; x < x_size; x++) {
if (is_grayscale()) {
PPM_PUTB(row_data[x], (xelval)red[x]);
} else {

View File

@ -454,31 +454,31 @@ supports_read_row() const {
// if there is an error or end of file.
////////////////////////////////////////////////////////////////////
bool PNMFileTypeSoftImage::Reader::
read_row(xel *row_data, xelval *alpha_data) {
read_row(xel *row_data, xelval *alpha_data, int x_size, int) {
if (!is_valid()) {
return false;
}
switch (soft_color) {
case rgb:
if (!read_scanline(row_data, alpha_data, _x_size, _file,
if (!read_scanline(row_data, alpha_data, x_size, _file,
read_rgb, rgb_ctype)) {
return false;
}
break;
case rgba:
if (!read_scanline(row_data, alpha_data, _x_size, _file,
if (!read_scanline(row_data, alpha_data, x_size, _file,
read_rgba, rgb_ctype)) {
return false;
}
break;
case rgb_a:
if (!read_scanline(row_data, alpha_data, _x_size, _file,
if (!read_scanline(row_data, alpha_data, x_size, _file,
read_rgb, rgb_ctype)) {
return false;
}
if (!read_scanline(row_data, alpha_data, _x_size, _file,
if (!read_scanline(row_data, alpha_data, x_size, _file,
read_alpha, alpha_ctype)) {
return false;
}

View File

@ -52,7 +52,7 @@ public:
Reader(PNMFileType *type, istream *file, bool owns_file, string magic_number);
virtual bool supports_read_row() const;
virtual bool read_row(xel *array, xelval *alpha);
virtual bool read_row(xel *array, xelval *alpha, int x_size, int y_size);
private:
enum { unknown, rgb, rgba, rgb_a } soft_color;

View File

@ -592,7 +592,7 @@ supports_read_row() const {
// if there is an error or end of file.
////////////////////////////////////////////////////////////////////
bool PNMFileTypeTIFF::Reader::
read_row(xel *row_data, xelval *alpha_data) {
read_row(xel *row_data, xelval *alpha_data, int x_size, int) {
if (!is_valid()) {
return false;
}
@ -639,7 +639,7 @@ read_row(xel *row_data, xelval *alpha_data) {
switch ( photomet ) {
case PHOTOMETRIC_MINISBLACK:
for ( col = 0; col < _x_size; ++col )
for ( col = 0; col < x_size; ++col )
{
sample = (this->*next_sample)(buf_ptr, bits_left);
gray = sample;
@ -661,7 +661,7 @@ read_row(xel *row_data, xelval *alpha_data) {
break;
case PHOTOMETRIC_MINISWHITE:
for ( col = 0; col < _x_size; ++col )
for ( col = 0; col < x_size; ++col )
{
sample = (this->*next_sample)(buf_ptr, bits_left);
gray = _maxval - sample;
@ -685,7 +685,7 @@ read_row(xel *row_data, xelval *alpha_data) {
break;
case PHOTOMETRIC_PALETTE:
for ( col = 0; col < _x_size; ++col )
for ( col = 0; col < x_size; ++col )
{
sample = (this->*next_sample)(buf_ptr, bits_left);
row_data[col] = colormap[sample];
@ -712,7 +712,7 @@ read_row(xel *row_data, xelval *alpha_data) {
break;
case PHOTOMETRIC_RGB:
for ( col = 0; col < _x_size; ++col ) {
for ( col = 0; col < x_size; ++col ) {
sample = (this->*next_sample)(buf_ptr, bits_left);
r = sample;
sample = (this->*next_sample)(buf_ptr, bits_left);

View File

@ -60,7 +60,7 @@ public:
virtual ~Reader();
virtual bool supports_read_row() const;
virtual bool read_row(xel *array, xelval *alpha);
virtual bool read_row(xel *array, xelval *alpha, int x_size, int y_size);
private:
xelval next_sample_lt_8(unsigned char *&buf_ptr, int &bits_left) const;