| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- /**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University. All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license. You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file imageFixHiddenColor.cxx
- * @author drose
- * @date 2003-03-13
- */
- #include "imageFixHiddenColor.h"
- #include "string_utils.h"
- /**
- *
- */
- ImageFixHiddenColor::
- ImageFixHiddenColor() : ImageFilter(true) {
- set_program_brief("change the color of transparent pixels in an image");
- set_program_description
- ("This program is designed to fix the color channels of an "
- "alpha-cutout image, making the \"color\" of the invisible part of the "
- "image consistent with the rest of the image. It does this by "
- "analyzing the RGB values of the image where alpha == 1, and using the "
- "average of these values as the overall image color, which it then "
- "applies to the image wherever alpha == 0. When the alpha value is "
- "neither 1 nor 0, the pixel is ignored.\n\n"
- "This process is important for applications that filter the texture "
- "size down by averaging neighboring pixels. If the color under the "
- "alpha == 0 pixels is very different from the color elsewhere, this "
- "kind of filtering can have a visible effect on the image's color, even "
- "where alpha != 0.");
- add_option
- ("alpha", "filename", 0,
- "Specifies a separate filename that will be used in lieu of the "
- "alpha channel on the source image. If this file has an alpha "
- "channel, that alpha channel is used; otherwise, the grayscale "
- "value of the image is used.",
- &ImageFixHiddenColor::dispatch_filename, nullptr, &_alpha_filename);
- add_option
- ("opaque", "alpha", 0,
- "Specifies the minimum alpha value (in the range of 0 to 1) for a "
- "pixel to be considered fully opaque. The default is 1.",
- &ImageFixHiddenColor::dispatch_double, nullptr, &_min_opaque_alpha);
- add_option
- ("transparent", "alpha", 0,
- "Specifies the maximum alpha value (in the range of 0 to 1) for a "
- "pixel to be considered fully transparent. The default is 0.",
- &ImageFixHiddenColor::dispatch_double, nullptr, &_max_transparent_alpha);
- _min_opaque_alpha = 1.0;
- _max_transparent_alpha = 0.0;
- }
- /**
- *
- */
- void ImageFixHiddenColor::
- run() {
- PNMImage alpha_image;
- if (_alpha_filename.empty()) {
- // No separate alpha file is provided; use the base file's alpha channel.
- if (!_image.has_alpha()) {
- nout << "Image does not have an alpha channel.\n";
- exit(1);
- }
- alpha_image = _image;
- } else {
- // In this case, the alpha channel is in a separate file.
- if (!alpha_image.read(_alpha_filename)) {
- nout << "Unable to read " << _alpha_filename << ".\n";
- exit(1);
- }
- if (!alpha_image.has_alpha()) {
- // Copy the grayscale value to the alpha channel for the benefit of the
- // code below.
- alpha_image.add_alpha();
- int xi, yi;
- for (yi = 0; yi < alpha_image.get_y_size(); ++yi) {
- for (xi = 0; xi < alpha_image.get_x_size(); ++xi) {
- alpha_image.set_alpha(xi, yi, alpha_image.get_gray(xi, yi));
- }
- }
- }
- // Make sure the alpha image matches the size of the source image.
- if (alpha_image.get_x_size() != _image.get_x_size() ||
- alpha_image.get_y_size() != _image.get_y_size()) {
- PNMImage scaled(_image.get_x_size(), _image.get_y_size(), alpha_image.get_num_channels());
- scaled.quick_filter_from(alpha_image);
- alpha_image = scaled;
- }
- }
- // First, get the average color of all the opaque pixels.
- int count = 0;
- LRGBColor color(0.0, 0.0, 0.0);
- int xi, yi;
- for (yi = 0; yi < _image.get_y_size(); ++yi) {
- for (xi = 0; xi < _image.get_x_size(); ++xi) {
- if (alpha_image.get_alpha(xi, yi) >= _min_opaque_alpha) {
- color += _image.get_xel(xi, yi);
- ++count;
- }
- }
- }
- if (count == 0) {
- nout << "Image has no opaque pixels.\n";
- exit(1);
- }
- color /= (double)count;
- nout << " average color of " << count << " opaque pixels is " << color << "\n";
- // Now, apply that wherever there are transparent pixels.
- count = 0;
- for (yi = 0; yi < _image.get_y_size(); ++yi) {
- for (xi = 0; xi < _image.get_x_size(); ++xi) {
- if (alpha_image.get_alpha(xi, yi) <= _max_transparent_alpha) {
- _image.set_xel(xi, yi, color);
- ++count;
- }
- }
- }
- if (count == 0) {
- nout << "Image has no transparent pixels.\n";
- exit(1);
- }
- nout << " applied to " << count << " transparent pixels.\n";
- write_image(_image);
- }
- int main(int argc, char *argv[]) {
- ImageFixHiddenColor prog;
- prog.parse_command_line(argc, argv);
- prog.run();
- return 0;
- }
|