1//============================================================================
2//
3// SSSS tt lll lll
4// SS SS tt ll ll
5// SS tttttt eeee ll ll aaaa
6// SSSS tt ee ee ll ll aa
7// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
8// SS SS tt ee ll ll aa aa
9// SSSS ttt eeeee llll llll aaaaa
10//
11// Copyright (c) 1995-2019 by Bradford W. Mott, Stephen Anthony
12// and the Stella Team
13//
14// See the file "License.txt" for information on usage and redistribution of
15// this file, and for a DISCLAIMER OF ALL WARRANTIES.
16//============================================================================
17
18#if defined(PNG_SUPPORT)
19
20#ifndef PNGLIBRARY_HXX
21#define PNGLIBRARY_HXX
22
23#include <png.h>
24
25class OSystem;
26class FrameBuffer;
27class FBSurface;
28class Properties;
29
30#include "bspf.hxx"
31
32/**
33 This class implements a thin wrapper around the libpng library, and
34 abstracts all the irrelevant details other loading and saving an
35 actual image.
36
37 @author Stephen Anthony
38*/
39class PNGLibrary
40{
41 public:
42 explicit PNGLibrary(OSystem& osystem);
43
44 /**
45 Read a PNG image from the specified file into a FBSurface structure,
46 scaling the image to the surface bounds.
47
48 @param filename The filename to load the PNG image
49 @param surface The FBSurface into which to place the PNG data
50
51 @post On success, the FBSurface containing image data, otherwise a
52 runtime_error is thrown containing a more detailed
53 error message.
54 */
55 void loadImage(const string& filename, FBSurface& surface);
56
57 /**
58 Save the current FrameBuffer image to a PNG file. Note that in most
59 cases this will be a TIA image, but it could actually be used for
60 *any* mode.
61
62 @param filename The filename to save the PNG image
63 @param comments The text comments to add to the PNG image
64
65 @post On success, the PNG file has been saved to 'filename',
66 otherwise a runtime_error is thrown containing a
67 more detailed error message.
68 */
69 void saveImage(const string& filename,
70 const VariantList& comments = EmptyVarList);
71
72 /**
73 Save the given surface to a PNG file.
74
75 @param filename The filename to save the PNG image
76 @param surface The surface data for the PNG image
77 @param rect The area of the surface to use
78 @param comments The text comments to add to the PNG image
79
80 @post On success, the PNG file has been saved to 'filename',
81 otherwise a runtime_error is thrown containing a
82 more detailed error message.
83 */
84 void saveImage(const string& filename, const FBSurface& surface,
85 const Common::Rect& rect = Common::EmptyRect,
86 const VariantList& comments = EmptyVarList);
87
88 /**
89 Called at regular intervals, and used to determine whether a
90 continuous snapshot is due to be taken.
91
92 @param time The current time in microseconds
93 */
94 void updateTime(uInt64 time);
95
96 /**
97 Answer whether continuous snapshot mode is enabled.
98 */
99 bool continuousSnapEnabled() const { return mySnapInterval > 0; }
100
101 /**
102 Enable/disable continuous snapshot mode.
103
104 @param perFrame Toggle snapshots every frame, or that specified by
105 'ssinterval' setting.
106 */
107 void toggleContinuousSnapshots(bool perFrame);
108
109 /**
110 Set the number of seconds between taking a snapshot in
111 continuous snapshot mode. Setting an interval of 0 disables
112 continuous snapshots.
113
114 @param interval Interval in seconds between snapshots
115 */
116 void setContinuousSnapInterval(uInt32 interval);
117
118 /**
119 NOTE: This method will be made private soon, so all calls from
120 external code should be refactored
121
122 Create a new snapshot based on the name of the ROM, and also
123 optionally using the number given as a parameter.
124
125 @param number Optional number to append to the snapshot name
126 */
127 void takeSnapshot(uInt32 number = 0);
128
129 private:
130 // Global OSystem object
131 OSystem& myOSystem;
132
133 // Used for continuous snapshot mode
134 uInt32 mySnapInterval;
135 uInt32 mySnapCounter;
136
137 // The following data remains between invocations of allocateStorage,
138 // and is only changed when absolutely necessary.
139 struct ReadInfoType {
140 ByteBuffer buffer;
141 unique_ptr<png_bytep[]> row_pointers;
142 png_uint_32 width, height, pitch;
143 uInt32 buffer_size, row_size;
144 };
145 static ReadInfoType ReadInfo;
146
147 /**
148 Allocate memory for PNG read operations. This is used to provide a
149 basic memory manager, so that we don't constantly allocate and deallocate
150 memory for each image loaded.
151
152 The method fills the 'ReadInfo' struct with valid memory locations
153 dependent on the given dimensions. If memory has been previously
154 allocated and it can accommodate the given dimensions, it is used directly.
155
156 @param iwidth The width of the PNG image
157 @param iheight The height of the PNG image
158 */
159 bool allocateStorage(png_uint_32 iwidth, png_uint_32 iheight);
160
161 /** The actual method which saves a PNG image.
162
163 @param out The output stream for writing PNG data
164 @param rows Pointer into PNG RGB data for each row
165 @param width The width of the PNG image
166 @param height The height of the PNG image
167 @param comments The text comments to add to the PNG image
168 */
169 void saveImageToDisk(ofstream& out, const unique_ptr<png_bytep[]>& rows,
170 png_uint_32 width, png_uint_32 height,
171 const VariantList& comments);
172
173 /**
174 Load the PNG data from 'ReadInfo' into the FBSurface. The surface
175 is resized as necessary to accommodate the data.
176
177 @param surface The FBSurface into which to place the PNG data
178 */
179 void loadImagetoSurface(FBSurface& surface);
180
181 /**
182 Write PNG tEXt chunks to the image.
183 */
184 void writeComments(png_structp png_ptr, png_infop info_ptr,
185 const VariantList& comments);
186
187 /** PNG library callback functions */
188 static void png_read_data(png_structp ctx, png_bytep area, png_size_t size);
189 static void png_write_data(png_structp ctx, png_bytep area, png_size_t size);
190 static void png_io_flush(png_structp ctx);
191 [[noreturn]] static void png_user_warn(png_structp ctx, png_const_charp str);
192 [[noreturn]] static void png_user_error(png_structp ctx, png_const_charp str);
193
194 private:
195 // Following constructors and assignment operators not supported
196 PNGLibrary(const PNGLibrary&) = delete;
197 PNGLibrary(PNGLibrary&&) = delete;
198 PNGLibrary& operator=(const PNGLibrary&) = delete;
199 PNGLibrary& operator=(PNGLibrary&&) = delete;
200};
201
202#endif
203
204#endif // PNG_SUPPORT
205