mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 01:07:51 -04:00
add histogram/palette options
This commit is contained in:
parent
c1583ac567
commit
b38732a6e1
@ -217,3 +217,121 @@ INLINE void PNMImageHeader::
|
||||
set_type(PNMFileType *type) {
|
||||
_type = type;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PNMImageHeader::record_color
|
||||
// Access: Protected
|
||||
// Description: Records the indicated color in the histogram.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PNMImageHeader::
|
||||
record_color(PNMImageHeader::Histogram &hist,
|
||||
const PNMImageHeader::PixelSpec &color) {
|
||||
Histogram::iterator hi = hist.find(color);
|
||||
if (hi == hist.end()) {
|
||||
hist.insert(Histogram::value_type(color, 1));
|
||||
} else {
|
||||
(*hi).second++;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PNMImageHeader::PixelSpec::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PNMImageHeader::PixelSpec::
|
||||
PixelSpec(xelval gray) :
|
||||
_red(gray),
|
||||
_green(gray),
|
||||
_blue(gray),
|
||||
_alpha(0)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PNMImageHeader::PixelSpec::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PNMImageHeader::PixelSpec::
|
||||
PixelSpec(xelval gray, xelval alpha) :
|
||||
_red(gray),
|
||||
_green(gray),
|
||||
_blue(gray),
|
||||
_alpha(alpha)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PNMImageHeader::PixelSpec::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PNMImageHeader::PixelSpec::
|
||||
PixelSpec(xelval red, xelval green, xelval blue) :
|
||||
_red(red),
|
||||
_green(green),
|
||||
_blue(blue),
|
||||
_alpha(0)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PNMImageHeader::PixelSpec::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PNMImageHeader::PixelSpec::
|
||||
PixelSpec(xelval red, xelval green, xelval blue, xelval alpha) :
|
||||
_red(red),
|
||||
_green(green),
|
||||
_blue(blue),
|
||||
_alpha(alpha)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PNMImageHeader::PixelSpec::Copy Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PNMImageHeader::PixelSpec::
|
||||
PixelSpec(const PixelSpec ©) :
|
||||
_red(copy._red),
|
||||
_green(copy._green),
|
||||
_blue(copy._blue),
|
||||
_alpha(copy._alpha)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PNMImageHeader::PixelSpec::Copy Assignment Operator
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PNMImageHeader::PixelSpec::
|
||||
operator = (const PixelSpec ©) {
|
||||
_red = copy._red;
|
||||
_green = copy._green;
|
||||
_blue = copy._blue;
|
||||
_alpha = copy._alpha;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PNMImageHeader::PixelSpec::Comparison Operator
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool PNMImageHeader::PixelSpec::
|
||||
operator < (const PixelSpec &other) const {
|
||||
if (_red != other._red) {
|
||||
return _red < other._red;
|
||||
}
|
||||
if (_green != other._green) {
|
||||
return _green < other._green;
|
||||
}
|
||||
if (_blue != other._blue) {
|
||||
return _blue < other._blue;
|
||||
}
|
||||
return _alpha < other._alpha;
|
||||
}
|
||||
|
@ -347,6 +347,11 @@ make_writer(ostream *file, bool owns_file, const Filename &filename,
|
||||
delete file;
|
||||
}
|
||||
|
||||
if (!writer->is_valid()) {
|
||||
delete writer;
|
||||
writer = NULL;
|
||||
}
|
||||
|
||||
return writer;
|
||||
}
|
||||
|
||||
@ -383,3 +388,114 @@ output(ostream &out) const {
|
||||
out << "image: " << _x_size << " by " << _y_size << " pixels, "
|
||||
<< _num_channels << " channels, " << _maxval << " maxval.";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PNMImageHeader::compute_histogram
|
||||
// Access: Protected
|
||||
// Description: Computes a histogram of the colors used in the
|
||||
// indicated rgb/grayscale array and/or alpha array.
|
||||
// This is most likely to be useful in a PNMWriter
|
||||
// class, but it is defined at this level in case it has
|
||||
// general utilty for PNMImages.
|
||||
//
|
||||
// The max_colors parameter, if greater than zero,
|
||||
// limits the maximum number of colors we are interested
|
||||
// in. If we encounter more than this number of colors,
|
||||
// the function aborts before completion and returns
|
||||
// false; otherwise, it returns true.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PNMImageHeader::
|
||||
compute_histogram(PNMImageHeader::Histogram &hist,
|
||||
xel *array, xelval *alpha, int max_colors) {
|
||||
int num_pixels = _x_size * _y_size;
|
||||
|
||||
switch (get_color_type()) {
|
||||
case CT_invalid:
|
||||
return false;
|
||||
|
||||
case CT_grayscale:
|
||||
for (int pi = 0; pi < num_pixels; pi++) {
|
||||
record_color(hist, PixelSpec(PPM_GETB(array[pi])));
|
||||
if (max_colors > 0 && (int)hist.size() > max_colors) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
case CT_two_channel:
|
||||
for (int pi = 0; pi < num_pixels; pi++) {
|
||||
record_color(hist, PixelSpec(PPM_GETB(array[pi]), alpha[pi]));
|
||||
if (max_colors > 0 && (int)hist.size() > max_colors) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
case CT_color:
|
||||
for (int pi = 0; pi < num_pixels; pi++) {
|
||||
record_color(hist, PixelSpec(PPM_GETR(array[pi]), PPM_GETG(array[pi]), PPM_GETB(array[pi])));
|
||||
if (max_colors > 0 && (int)hist.size() > max_colors) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
case CT_four_channel:
|
||||
for (int pi = 0; pi < num_pixels; pi++) {
|
||||
record_color(hist, PixelSpec(PPM_GETR(array[pi]), PPM_GETG(array[pi]), PPM_GETB(array[pi]), alpha[pi]));
|
||||
if (max_colors > 0 && (int)hist.size() > max_colors) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PNMImageHeader::compute_palette
|
||||
// Access: Protected
|
||||
// Description: Returns a linear list of all of the colors in the
|
||||
// image, similar to compute_histogram().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PNMImageHeader::
|
||||
compute_palette(PNMImageHeader::Palette &palette,
|
||||
xel *array, xelval *alpha, int max_colors) {
|
||||
Histogram hist;
|
||||
|
||||
int num_pixels = _x_size * _y_size;
|
||||
|
||||
// In case there are already entries in the palette, preserve them.
|
||||
Palette::const_iterator pi;
|
||||
for (pi = palette.begin(); pi != palette.end(); ++pi) {
|
||||
hist.insert(Histogram::value_type(*pi, num_pixels + 1));
|
||||
}
|
||||
|
||||
if (!compute_histogram(hist, array, alpha, max_colors)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now append the new entries discovered in the histogram onto the
|
||||
// end of the palette.
|
||||
palette.reserve(hist.size());
|
||||
Histogram::const_iterator hi;
|
||||
for (hi = hist.begin(); hi != hist.end(); ++hi) {
|
||||
if ((*hi).second <= num_pixels) {
|
||||
palette.push_back((*hi).first);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PNMImageHeader::PixelSpec::output
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PNMImageHeader::PixelSpec::
|
||||
output(ostream &out) const {
|
||||
out << "(" << _red << ", " << _green << ", " << _blue << ", " << _alpha << ")";
|
||||
}
|
||||
|
||||
|
@ -96,7 +96,33 @@ public:
|
||||
|
||||
void output(ostream &out) const;
|
||||
|
||||
public:
|
||||
// These classes are used internally, but must be declared public
|
||||
// for fiddly reasons.
|
||||
class PixelSpec {
|
||||
public:
|
||||
INLINE PixelSpec(xelval gray);
|
||||
INLINE PixelSpec(xelval gray, xelval alpha);
|
||||
INLINE PixelSpec(xelval red, xelval green, xelval blue);
|
||||
INLINE PixelSpec(xelval red, xelval green, xelval blue, xelval alpha);
|
||||
INLINE PixelSpec(const PixelSpec ©);
|
||||
INLINE void operator = (const PixelSpec ©);
|
||||
|
||||
INLINE bool operator < (const PixelSpec &other) const;
|
||||
void output(ostream &out) const;
|
||||
|
||||
xelval _red, _green, _blue, _alpha;
|
||||
};
|
||||
typedef pmap<PixelSpec, int> Histogram;
|
||||
typedef pvector<PixelSpec> Palette;
|
||||
|
||||
protected:
|
||||
bool compute_histogram(Histogram &hist, xel *array, xelval *alpha,
|
||||
int max_colors = 0);
|
||||
bool compute_palette(Palette &palette, xel *array, xelval *alpha,
|
||||
int max_colors = 0);
|
||||
INLINE void record_color(Histogram &hist, const PixelSpec &color);
|
||||
|
||||
int _x_size, _y_size;
|
||||
int _num_channels;
|
||||
xelval _maxval;
|
||||
@ -108,6 +134,11 @@ INLINE ostream &operator << (ostream &out, const PNMImageHeader &header) {
|
||||
return out;
|
||||
}
|
||||
|
||||
INLINE ostream &operator << (ostream &out, const PNMImageHeader::PixelSpec &pixel) {
|
||||
pixel.output(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
#include "pnmImageHeader.I"
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user