xoreos  0.0.5
screenshot.cpp
Go to the documentation of this file.
1 /* xoreos - A reimplementation of BioWare's Aurora engine
2  *
3  * xoreos is the legal property of its developers, whose names
4  * can be found in the AUTHORS file distributed with this source
5  * distribution.
6  *
7  * xoreos is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 3
10  * of the License, or (at your option) any later version.
11  *
12  * xoreos is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with xoreos. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
25 #include "src/common/scopedptr.h"
26 #include "src/common/ustring.h"
27 #include "src/common/writefile.h"
28 #include "src/common/filepath.h"
29 #include "src/common/threads.h"
30 #include "src/common/datetime.h"
31 
32 #include "src/graphics/types.h"
33 
35 
36 namespace Graphics {
37 
39  try {
41  } catch (...) {
42  return false;
43  }
44 
45  filename = Common::FilePath::getUserDataFile(filename);
46  if (Common::FilePath::isRegularFile(filename))
47  // We already did a screenshot this second
48  return false;
49 
50  return true;
51 }
52 
53 static bool writeBMP(const Common::UString &filename, const byte *data,
54  int width, int height) {
55 
56  if ((width <= 0) || (height <= 0) || !data)
57  return false;
58 
59  Common::WriteFile file;
60  if (!file.open(filename))
61  return false;
62 
63  // The pitch of the output has to be divisible by 4, so
64  // we output zeroes to make the pitch that far.
65  int extraDataSize = width & 3;
66  int imageSize = height * (width + extraDataSize) * 3;
67 
68  // Main bitmap header
69  file.writeByte('B');
70  file.writeByte('M');
71  file.writeUint32LE(14 + 40 + imageSize); // Size
72  file.writeUint32LE(0); // reserved
73  file.writeUint32LE(14 + 40); // Image offset after both headers
74 
75  // v3 header
76  file.writeUint32LE(40);
77  file.writeUint32LE(width);
78  file.writeUint32LE(height);
79  file.writeUint16LE(1);
80  file.writeUint16LE(24);
81  file.writeUint32LE(0);
82  file.writeUint32LE(imageSize);
83  file.writeUint32LE(72);
84  file.writeUint32LE(72);
85  file.writeUint32LE(0);
86  file.writeUint32LE(0);
87 
88  if (extraDataSize != 0) {
89  // Dump, making sure the pitch is correct
90  while (height--) {
91  file.write(data, width * 3);
92 
93  // Ensure we're on a 4-byte boundary
94  for (int i = 0; i < extraDataSize; i++)
95  file.writeByte(0);
96 
97  data += width * 3;
98  }
99  } else {
100  // Dump directly (can do all at once here because the data
101  // is already good for BMP output)
102  file.write(data, width * height * 3);
103  }
104 
105  file.flush();
106  file.close();
107  return true;
108 }
109 
112 
113  Common::UString filename;
114  if (!constructFilename(filename))
115  return true;
116 
117  GLint m_viewport[4];
118 
119  glGetIntegerv(GL_VIEWPORT, m_viewport);
120 
121  if ((m_viewport[2] <= 0) || (m_viewport[3] <= 0))
122  return false;
123 
124  Common::ScopedArray<byte> screen(new byte[3 * m_viewport[2] * m_viewport[3]]);
125 
126  glReadPixels(0, 0, m_viewport[2], m_viewport[3], GL_BGR, GL_UNSIGNED_BYTE, screen.get());
127  const bool success = writeBMP(filename, screen.get(), m_viewport[2], m_viewport[3]);
128 
129  if (success) {
130  status("Screenshot taken: %s", filename.c_str());
131  return true;
132  }
133 
134  warning("Failed to take screenshot");
135  return false;
136 }
137 
138 } // End of namespace Graphics
bool takeScreenshot()
Saves a screenshot to a file.
Definition: screenshot.cpp:110
size_t write(const void *dataPtr, size_t dataSize)
Write data into the stream.
Definition: writefile.cpp:91
A class holding an UTF-8 string.
Definition: ustring.h:48
A date/time object, storing a specific point in time.
Definition: datetime.h:36
UString formatDateTimeISO(uint32 sep=0, uint32 sepDate=0, uint32 sepTime=0) const
Return a string representation of the date and time in ISO 8601 format.
Definition: datetime.cpp:79
Screenshot writing.
Basic graphics types.
static bool writeBMP(const Common::UString &filename, const byte *data, int width, int height)
Definition: screenshot.cpp:53
bool constructFilename(Common::UString &filename)
Definition: screenshot.cpp:38
A simple scoped smart pointer template.
Utility functions for manipulating date and time.
Threading system helpers.
const char * c_str() const
Return the (utf8 encoded) string data.
Definition: ustring.cpp:249
static UString getUserDataFile(UString file)
Return a path suitable for writing into.
Definition: filepath.cpp:383
bool open(const UString &fileName)
Try to open the file with the given fileName.
Definition: writefile.cpp:50
static bool isRegularFile(const UString &p)
Does specified path exist and is it a regular file?
Definition: filepath.cpp:52
void writeUint16LE(uint16 value)
Definition: writestream.h:98
void writeByte(byte value)
Definition: writestream.h:88
void warning(const char *s,...)
Definition: util.cpp:33
void flush()
Commit any buffered data to the underlying channel or storage medium; unbuffered streams can use the ...
Definition: writefile.cpp:83
Unicode string handling.
PointerType get() const
Returns the plain pointer value.
Definition: scopedptr.h:96
void close()
Close the file, if open.
Definition: writefile.cpp:69
void enforceMainThread()
Throws an Exception if called from a non-main thread.
Definition: threads.cpp:60
Coordinated Universal Time (UTC).
Definition: datetime.h:39
void status(const char *s,...)
Definition: util.cpp:52
Implementing the stream writing interfaces for files.
A simple streaming file writing class.
Definition: writefile.h:40
void writeUint32LE(uint32 value)
Definition: writestream.h:104
Utility class for manipulating file paths.
uint8 byte
Definition: types.h:209