diff --git a/panda/src/pnmimagetypes/config_pnmimagetypes.cxx b/panda/src/pnmimagetypes/config_pnmimagetypes.cxx index 3c04c28545..039c4c7f8c 100644 --- a/panda/src/pnmimagetypes/config_pnmimagetypes.cxx +++ b/panda/src/pnmimagetypes/config_pnmimagetypes.cxx @@ -55,8 +55,22 @@ IMGHeaderType img_header_type; const int img_xsize = config_pnmimagetypes.GetInt("img-xsize", 0); const int img_ysize = config_pnmimagetypes.GetInt("img-ysize", 0); +// Set this to the quality percentage for writing JPEG files. 95 is +// the highest useful value (values greater than 95 do not lead to +// significantly better quality, but do lead to significantly greater +// size). const int jpeg_quality = config_pnmimagetypes.GetInt("jpeg-quality", 95); +// 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. +const int jpeg_scale_num = config_pnmimagetypes.GetInt("jpeg-scale-num", 1); +const int jpeg_scale_denom = config_pnmimagetypes.GetInt("jpeg-scale-denom", 1); + ConfigureFn(config_pnmimagetypes) { PNMFileTypePNM::init_type(); PNMFileTypeSGI::init_type(); diff --git a/panda/src/pnmimagetypes/config_pnmimagetypes.h b/panda/src/pnmimagetypes/config_pnmimagetypes.h index 8974b87062..40ce9b0631 100644 --- a/panda/src/pnmimagetypes/config_pnmimagetypes.h +++ b/panda/src/pnmimagetypes/config_pnmimagetypes.h @@ -26,7 +26,10 @@ extern const double radiance_gamma_correction; extern const int radiance_brightness_adjustment; extern const int yuv_xsize; extern const int yuv_ysize; + extern const int jpeg_quality; +extern const int jpeg_scale_num; +extern const int jpeg_scale_denom; enum IMGHeaderType { IHT_none, diff --git a/panda/src/pnmimagetypes/pnmFileTypeJPGReader.cxx b/panda/src/pnmimagetypes/pnmFileTypeJPGReader.cxx index 7e3532f926..6230b784a3 100644 --- a/panda/src/pnmimagetypes/pnmFileTypeJPGReader.cxx +++ b/panda/src/pnmimagetypes/pnmFileTypeJPGReader.cxx @@ -41,10 +41,8 @@ Reader(PNMFileType *type, FILE *file, bool owns_file, string magic_number) : */ /* Step 4: set parameters for decompression */ - - /* In this example, we don't need to change any of the defaults set by - * jpeg_read_header(), so we do nothing here. - */ + _cinfo.scale_num = jpeg_scale_num; + _cinfo.scale_denom = jpeg_scale_denom; /* Step 5: Start decompressor */ @@ -141,6 +139,7 @@ read_data(xel *array, xelval *) { /* We can ignore the return value since suspension is not possible * with the stdio data source. + */ /* At this point you may want to check to see whether any corrupt-data * warnings occurred (test whether jerr.pub.num_warnings is nonzero). diff --git a/pandatool/src/stitchviewer/stitchImageVisualizer.cxx b/pandatool/src/stitchviewer/stitchImageVisualizer.cxx index d126406d54..718636ccf2 100644 --- a/pandatool/src/stitchviewer/stitchImageVisualizer.cxx +++ b/pandatool/src/stitchviewer/stitchImageVisualizer.cxx @@ -23,9 +23,22 @@ #include #include #include +#include + +#include StitchImageVisualizer *StitchImageVisualizer::_static_siv; +// Returns the largest power of 2 less than or equal to value. +static int +to_power_2(int value) { + int x = 1; + while ((x << 1) <= value) { + x = (x << 1); + } + return x; +} + StitchImageVisualizer::Image:: Image(StitchImage *image, int index, bool scale) : _image(image), @@ -39,11 +52,28 @@ Image(StitchImage *image, int index, bool scale) : } if (scale && image->_data != NULL) { - nout << "Scaling " << image->get_name() << "\n"; - PNMImage *n = new PNMImage(1024, 1024); - n->quick_filter_from(*image->_data); - delete image->_data; - image->_data = n; + // We have to make it a power of 2. + int old_xsize = image->_data->get_x_size(); + int old_ysize = image->_data->get_y_size(); + int new_xsize = old_xsize; + int new_ysize = old_ysize; + if (max_texture_dimension > 0) { + new_xsize = min(new_xsize, max_texture_dimension); + new_ysize = min(new_ysize, max_texture_dimension); + } + new_xsize = to_power_2(new_xsize); + new_ysize = to_power_2(new_ysize); + + if (new_xsize != old_xsize || new_ysize != old_ysize) { + nout << "Scaling " << image->get_name() << " from " + << old_xsize << " " << old_ysize << " to " + << new_xsize << " " << new_ysize << "\n"; + + PNMImage *n = new PNMImage(new_xsize, new_ysize); + n->quick_filter_from(*image->_data); + delete image->_data; + image->_data = n; + } } } @@ -214,8 +244,12 @@ toggle_viz(StitchImageVisualizer::Image &im) { void StitchImageVisualizer:: create_image_geometry(StitchImageVisualizer::Image &im) { + /* int x_verts = im._image->get_x_verts(); int y_verts = im._image->get_y_verts(); + */ + int x_verts = 2; + int y_verts = 2; TriangleMesh mesh(x_verts, y_verts); LVector3f center = LCAST(float, im._image->extrude(LPoint2d(0.5, 0.5))); @@ -223,11 +257,12 @@ create_image_geometry(StitchImageVisualizer::Image &im) { for (int xi = 0; xi < x_verts; xi++) { for (int yi = 0; yi < y_verts; yi++) { - LVector3f p = LCAST(float, im._image->get_grid_vector(xi, yi)); - LPoint2f uv = LCAST(float, im._image->get_grid_uv(xi, yi)); + LPoint2d uv = LPoint2d((double)xi / (double)(x_verts - 1), + 1.0 - (double)yi / (double)(y_verts - 1)); + LVector3d p = im._image->extrude(uv); - mesh._coords.push_back(p * scale); - mesh._texcoords.push_back(uv); + mesh._coords.push_back(LCAST(float, p) * scale); + mesh._texcoords.push_back(LCAST(float, uv)); } }