Panda3D

imageFixHiddenColor.cxx
Go to the documentation of this file.
1 /**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file imageFixHiddenColor.cxx
10 * @author drose
11 * @date 2003-03-13
12 */
13
14 #include "imageFixHiddenColor.h"
15 #include "string_utils.h"
16
17 /**
18 *
19 */
20 ImageFixHiddenColor::
21 ImageFixHiddenColor() : ImageFilter(true) {
22 set_program_brief("change the color of transparent pixels in an image");
23 set_program_description
24 ("This program is designed to fix the color channels of an "
25 "alpha-cutout image, making the \"color\" of the invisible part of the "
26 "image consistent with the rest of the image. It does this by "
27 "analyzing the RGB values of the image where alpha == 1, and using the "
28 "average of these values as the overall image color, which it then "
29 "applies to the image wherever alpha == 0. When the alpha value is "
30 "neither 1 nor 0, the pixel is ignored.\n\n"
31
32 "This process is important for applications that filter the texture "
33 "size down by averaging neighboring pixels. If the color under the "
34 "alpha == 0 pixels is very different from the color elsewhere, this "
35 "kind of filtering can have a visible effect on the image's color, even "
36 "where alpha != 0.");
37
38 add_option
39 ("alpha", "filename", 0,
40 "Specifies a separate filename that will be used in lieu of the "
41 "alpha channel on the source image. If this file has an alpha "
42 "channel, that alpha channel is used; otherwise, the grayscale "
43 "value of the image is used.",
44 &ImageFixHiddenColor::dispatch_filename, nullptr, &_alpha_filename);
45
46 add_option
47 ("opaque", "alpha", 0,
48 "Specifies the minimum alpha value (in the range of 0 to 1) for a "
49 "pixel to be considered fully opaque. The default is 1.",
50 &ImageFixHiddenColor::dispatch_double, nullptr, &_min_opaque_alpha);
51
52 add_option
53 ("transparent", "alpha", 0,
54 "Specifies the maximum alpha value (in the range of 0 to 1) for a "
55 "pixel to be considered fully transparent. The default is 0.",
56 &ImageFixHiddenColor::dispatch_double, nullptr, &_max_transparent_alpha);
57
58 _min_opaque_alpha = 1.0;
59 _max_transparent_alpha = 0.0;
60 }
61
62 /**
63 *
64 */
65 void ImageFixHiddenColor::
66 run() {
67 PNMImage alpha_image;
68
69 if (_alpha_filename.empty()) {
70 // No separate alpha file is provided; use the base file's alpha channel.
71 if (!_image.has_alpha()) {
72 nout << "Image does not have an alpha channel.\n";
73 exit(1);
74 }
75 alpha_image = _image;
76
77 } else {
78 // In this case, the alpha channel is in a separate file.
79 if (!alpha_image.read(_alpha_filename)) {
80 nout << "Unable to read " << _alpha_filename << ".\n";
81 exit(1);
82 }
83
84 if (!alpha_image.has_alpha()) {
85 // Copy the grayscale value to the alpha channel for the benefit of the
86 // code below.
87 alpha_image.add_alpha();
88 int xi, yi;
89 for (yi = 0; yi < alpha_image.get_y_size(); ++yi) {
90 for (xi = 0; xi < alpha_image.get_x_size(); ++xi) {
91 alpha_image.set_alpha(xi, yi, alpha_image.get_gray(xi, yi));
92 }
93 }
94 }
95
96 // Make sure the alpha image matches the size of the source image.
97 if (alpha_image.get_x_size() != _image.get_x_size() ||
98 alpha_image.get_y_size() != _image.get_y_size()) {
99 PNMImage scaled(_image.get_x_size(), _image.get_y_size(), alpha_image.get_num_channels());
100 scaled.quick_filter_from(alpha_image);
101 alpha_image = scaled;
102 }
103 }
104
105 // First, get the average color of all the opaque pixels.
106 int count = 0;
107 LRGBColor color(0.0, 0.0, 0.0);
108 int xi, yi;
109 for (yi = 0; yi < _image.get_y_size(); ++yi) {
110 for (xi = 0; xi < _image.get_x_size(); ++xi) {
111 if (alpha_image.get_alpha(xi, yi) >= _min_opaque_alpha) {
112 color += _image.get_xel(xi, yi);
113 ++count;
114 }
115 }
116 }
117 if (count == 0) {
118 nout << "Image has no opaque pixels.\n";
119 exit(1);
120 }
121 color /= (double)count;
122 nout << " average color of " << count << " opaque pixels is " << color << "\n";
123
124 // Now, apply that wherever there are transparent pixels.
125 count = 0;
126 for (yi = 0; yi < _image.get_y_size(); ++yi) {
127 for (xi = 0; xi < _image.get_x_size(); ++xi) {
128 if (alpha_image.get_alpha(xi, yi) <= _max_transparent_alpha) {
129 _image.set_xel(xi, yi, color);
130 ++count;
131 }
132 }
133 }
134 if (count == 0) {
135 nout << "Image has no transparent pixels.\n";
136 exit(1);
137 }
138 nout << " applied to " << count << " transparent pixels.\n";
139
140 write_image(_image);
141 }
142
143
144 int main(int argc, char *argv[]) {
145 ImageFixHiddenColor prog;
146 prog.parse_command_line(argc, argv);
147 prog.run();
148 return 0;
149 }
ImageFilter
This is the base class for a program that reads an image file, operates on it, and writes another ima...
Definition: imageFilter.h:26
ImageFixHiddenColor
This program repairs an image's RGB values hidden behind an A value of 0.
Definition: imageFixHiddenColor.h:24
ImageWriter::write_image
void write_image()
Writes the generated to the user's specified output filename.
Definition: imageWriter.I:18
PNMImageHeader::get_x_size
int get_x_size() const
Returns the number of pixels in the X direction.
Definition: pnmImageHeader.I:144
PNMImageHeader::get_num_channels
get_num_channels
Returns the number of channels in the image.
Definition: pnmImageHeader.h:60
PNMImageHeader::has_alpha
static bool has_alpha(ColorType color_type)
This static variant of has_alpha() returns true if the indicated image type includes an alpha channel...
Definition: pnmImageHeader.I:106
PNMImageHeader::get_y_size
int get_y_size() const
Returns the number of pixels in the Y direction.
Definition: pnmImageHeader.I:153
PNMImage
The name of this class derives from the fact that we originally implemented it as a layer on top of t...
Definition: pnmImage.h:58
PNMImage::get_alpha
float get_alpha(int x, int y) const
Returns the alpha component color at the indicated pixel.
Definition: pnmImage.I:809
PNMImage::get_gray
float get_gray(int x, int y) const
Returns the gray component color at the indicated pixel.
Definition: pnmImage.I:799
PNMImage::read
bool read(const Filename &filename, PNMFileType *type=nullptr, bool report_unknown_type=true)
Reads the indicated image filename.
Definition: pnmImage.cxx:278
PNMImage::set_alpha
void set_alpha(int x, int y, float a)
Sets the alpha component color only at the indicated pixel.
Definition: pnmImage.I:859
PNMImage::add_alpha
void add_alpha()
Adds an alpha channel to the image, if it does not already have one.
Definition: pnmImage.I:363
ProgramBase::parse_command_line
virtual void parse_command_line(int argc, char **argv)
Dispatches on each of the options on the command line, and passes the remaining parameters to handle_...
Definition: programBase.cxx:286
imageFixHiddenColor.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
string_utils.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.