diff --git a/direct/src/showbase/ShowBase.py b/direct/src/showbase/ShowBase.py index 18fa910ddd..faebae9efa 100644 --- a/direct/src/showbase/ShowBase.py +++ b/direct/src/showbase/ShowBase.py @@ -1574,7 +1574,8 @@ class ShowBase(DirectObject.DirectObject): self.camFrustumVis.removeNode() def screenshot(self, namePrefix = 'screenshot', - defaultFilename = 1, source = None): + defaultFilename = 1, source = None, + imageComment=""): """ Captures a screenshot from the main window or from the specified window or Texture and writes it to a filename in the current directory (or to a specified directory). @@ -1610,7 +1611,7 @@ class ShowBase(DirectObject.DirectObject): else: saved = source.write(filename) else: - saved = source.saveScreenshot(filename) + saved = source.saveScreenshot(filename, imageComment) # Announce to anybody that a screenshot has been taken messenger.send('screenshot', [filename]) diff --git a/panda/src/display/displayRegion.cxx b/panda/src/display/displayRegion.cxx index bd4c2fe69d..08519e005a 100644 --- a/panda/src/display/displayRegion.cxx +++ b/panda/src/display/displayRegion.cxx @@ -611,12 +611,13 @@ save_screenshot_default(const string &prefix) { // filename. Returns true on success, false on failure. //////////////////////////////////////////////////////////////////// bool DisplayRegion:: -save_screenshot(const Filename &filename) { +save_screenshot(const Filename &filename, const string &image_comment) { PNMImage image; if (!get_screenshot(image)) { return false; } + image.set_comment(image_comment); if (!image.write(filename)) { return false; } diff --git a/panda/src/display/displayRegion.h b/panda/src/display/displayRegion.h index 25a671b5b7..4995cf0e4d 100644 --- a/panda/src/display/displayRegion.h +++ b/panda/src/display/displayRegion.h @@ -111,13 +111,16 @@ PUBLISHED: void output(ostream &out) const; - static Filename make_screenshot_filename(const string &prefix = "screenshot"); + static Filename make_screenshot_filename( + const string &prefix = "screenshot"); Filename save_screenshot_default(const string &prefix = "screenshot"); - bool save_screenshot(const Filename &filename); + bool save_screenshot( + const Filename &filename, const string &image_comment = ""); bool get_screenshot(PNMImage &image); public: - INLINE void set_cull_result(CullResult *cull_result, SceneSetup *scene_setup); + INLINE void set_cull_result( + CullResult *cull_result, SceneSetup *scene_setup); INLINE CullResult *get_cull_result() const; INLINE SceneSetup *get_scene_setup() const; diff --git a/panda/src/display/graphicsOutput.I b/panda/src/display/graphicsOutput.I index ea615ca572..f30484e04d 100644 --- a/panda/src/display/graphicsOutput.I +++ b/panda/src/display/graphicsOutput.I @@ -423,11 +423,15 @@ save_screenshot_default(const string &prefix) { // Function: GraphicsOutput::save_screenshot // Access: Published // Description: Saves a screenshot of the region to the indicated -// filename. Returns true on success, false on failure. +// filename. The image comment is an optional user +// readable string that will be saved with the header +// of the image (if the file format supports embedded +// data; for example jpg allows comments). Returns +// true on success, false on failure. //////////////////////////////////////////////////////////////////// INLINE bool GraphicsOutput:: -save_screenshot(const Filename &filename) { - return _default_display_region->save_screenshot(filename); +save_screenshot(const Filename &filename, const string &image_comment) { + return _default_display_region->save_screenshot(filename, image_comment); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/display/graphicsOutput.h b/panda/src/display/graphicsOutput.h index 791762fb32..c55dbb459a 100644 --- a/panda/src/display/graphicsOutput.h +++ b/panda/src/display/graphicsOutput.h @@ -145,16 +145,20 @@ PUBLISHED: int get_num_active_display_regions() const; PT(DisplayRegion) get_active_display_region(int n) const; - GraphicsOutput *make_texture_buffer(const string &name, int x_size, int y_size, - Texture *tex = NULL, bool to_ram = false); + GraphicsOutput *make_texture_buffer( + const string &name, int x_size, int y_size, + Texture *tex = NULL, bool to_ram = false); GraphicsOutput *make_cube_map(const string &name, int size, NodePath &camera_rig, DrawMask camera_mask = DrawMask::all_on(), bool to_ram = false); - INLINE static Filename make_screenshot_filename(const string &prefix = "screenshot"); - INLINE Filename save_screenshot_default(const string &prefix = "screenshot"); - INLINE bool save_screenshot(const Filename &filename); + INLINE static Filename make_screenshot_filename( + const string &prefix = "screenshot"); + INLINE Filename save_screenshot_default( + const string &prefix = "screenshot"); + INLINE bool save_screenshot( + const Filename &filename, const string &image_comment); INLINE bool get_screenshot(PNMImage &image); NodePath get_texture_card(); diff --git a/panda/src/pnmimage/pnmImage.cxx b/panda/src/pnmimage/pnmImage.cxx index 19570a1eca..64a0ddd31d 100644 --- a/panda/src/pnmimage/pnmImage.cxx +++ b/panda/src/pnmimage/pnmImage.cxx @@ -41,6 +41,7 @@ clear() { _y_size = 0; _num_channels = 0; _maxval = 255; + _comment.clear(); _type = (PNMFileType *)NULL; } @@ -60,6 +61,7 @@ clear(int x_size, int y_size, int num_channels, _y_size = y_size; _num_channels = num_channels; _maxval = maxval; + _comment.clear(); _type = type; if (has_alpha()) { diff --git a/panda/src/pnmimage/pnmImageHeader.I b/panda/src/pnmimage/pnmImageHeader.I index 90daee6830..7b7fd5ddad 100644 --- a/panda/src/pnmimage/pnmImageHeader.I +++ b/panda/src/pnmimage/pnmImageHeader.I @@ -56,6 +56,7 @@ operator = (const PNMImageHeader ©) { _y_size = copy._y_size; _num_channels = copy._num_channels; _maxval = copy._maxval; + _comment = copy._comment; _type = copy._type; } @@ -180,6 +181,26 @@ get_y_size() const { return _y_size; } +//////////////////////////////////////////////////////////////////// +// Function: PNMImageHeader::get_comment +// Access: Published +// Description: Gets the user comment from the file. +//////////////////////////////////////////////////////////////////// +INLINE string PNMImageHeader:: +get_comment() const { + return _comment; +} + +//////////////////////////////////////////////////////////////////// +// Function: PNMImageHeader::set_comment +// Access: Published +// Description: Writes a user comment string to the image (header). +//////////////////////////////////////////////////////////////////// +INLINE void PNMImageHeader:: +set_comment(const string& comment) { + _comment = comment; +} + //////////////////////////////////////////////////////////////////// // Function: PNMImageHeader::has_type // Access: Published diff --git a/panda/src/pnmimage/pnmImageHeader.h b/panda/src/pnmimage/pnmImageHeader.h index 5bd3eebc33..addb65c472 100644 --- a/panda/src/pnmimage/pnmImageHeader.h +++ b/panda/src/pnmimage/pnmImageHeader.h @@ -72,6 +72,9 @@ PUBLISHED: INLINE int get_x_size() const; INLINE int get_y_size() const; + INLINE string get_comment() const; + INLINE void set_comment(const string &comment); + INLINE bool has_type() const; INLINE PNMFileType *get_type() const; INLINE void set_type(PNMFileType *type); @@ -128,6 +131,7 @@ protected: int _x_size, _y_size; int _num_channels; xelval _maxval; + string _comment; PNMFileType *_type; }; diff --git a/panda/src/pnmimagetypes/pnmFileTypeJPGReader.cxx b/panda/src/pnmimagetypes/pnmFileTypeJPGReader.cxx index 76306bed18..72b6bba477 100644 --- a/panda/src/pnmimagetypes/pnmFileTypeJPGReader.cxx +++ b/panda/src/pnmimagetypes/pnmFileTypeJPGReader.cxx @@ -262,7 +262,7 @@ Reader(PNMFileType *type, istream *file, bool owns_file, string magic_number) : // Hope we can putback() more than one character. for (string::reverse_iterator mi = magic_number.rbegin(); mi != magic_number.rend(); - mi++) { + ++mi) { _file->putback(*mi); } if (_file->fail()) { @@ -284,8 +284,10 @@ Reader(PNMFileType *type, istream *file, bool owns_file, string magic_number) : /* Step 2: specify data source (eg, a file) */ jpeg_istream_src(&_cinfo, file); - /* Step 3: read file parameters with jpeg_read_header() */ + /* Step 3: let lib jpeg know that we want to read the comment field */ + jpeg_save_markers(&_cinfo, JPEG_COM, 0xffff); + /* Step 4: read file parameters with jpeg_read_header() */ jpeg_read_header(&_cinfo, TRUE); /* We can ignore the return value from jpeg_read_header since * (a) suspension is not possible with the stdio data source, and @@ -293,11 +295,11 @@ Reader(PNMFileType *type, istream *file, bool owns_file, string magic_number) : * See libjpeg.doc for more info. */ - /* Step 4: set parameters for decompression */ + /* Step 6: set parameters for decompression */ _cinfo.scale_num = jpeg_scale_num; _cinfo.scale_denom = jpeg_scale_denom; - /* Step 5: Start decompressor */ + /* Step 7: Start decompressor */ jpeg_start_decompress(&_cinfo); /* We can ignore the return value since suspension is not possible diff --git a/panda/src/pnmimagetypes/pnmFileTypeJPGWriter.cxx b/panda/src/pnmimagetypes/pnmFileTypeJPGWriter.cxx index 9286be067d..e2a9b76922 100644 --- a/panda/src/pnmimagetypes/pnmFileTypeJPGWriter.cxx +++ b/panda/src/pnmimagetypes/pnmFileTypeJPGWriter.cxx @@ -201,7 +201,6 @@ Writer(PNMFileType *type, ostream *file, bool owns_file) : { } - //////////////////////////////////////////////////////////////////// // Function: PNMFileTypeJPG::Writer::write_data // Access: Public, Virtual @@ -297,6 +296,12 @@ write_data(xel *array, xelval *) { */ jpeg_start_compress(&cinfo, TRUE); + /* Write the user comment, if any */ + if (_comment.size()) { + jpeg_write_marker( + &cinfo, JPEG_COM, (JOCTET *)_comment.c_str(), strlen(_comment.c_str())); + } + /* Step 5: while (scan lines remain to be written) */ /* jpeg_write_scanlines(...); */ diff --git a/panda/src/testbed/pview.cxx b/panda/src/testbed/pview.cxx index 57cdb34ee2..df5062d2bb 100644 --- a/panda/src/testbed/pview.cxx +++ b/panda/src/testbed/pview.cxx @@ -55,7 +55,7 @@ output_screenshot(Filename &fn) framework.do_frame(); WindowFramework *wf = framework.get_window(0); - bool ok = wf->get_graphics_window()->save_screenshot(fn); + bool ok = wf->get_graphics_window()->save_screenshot(fn, "from pview"); if (!ok) { cerr << "Could not generate screenshot " << fn << "\n"; }