xoreos  0.0.5
winiconimage.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/util.h"
27 #include "src/common/readstream.h"
28 #include "src/common/error.h"
29 
31 
32 namespace Graphics {
33 
34 WinIconImage::WinIconImage(Common::SeekableReadStream &cur) : _hotspotX(0), _hotspotY(0) {
35  _compressed = false;
36  _hasAlpha = true;
38 
39  load(cur);
40 }
41 
43 }
44 
46  try {
47 
48  readHeader(cur);
49  readData (cur);
50 
51  } catch (Common::Exception &e) {
52  e.add("Failed reading CUR file");
53  throw;
54  }
55 }
56 
58  cur.seek(0);
59 
60  if (cur.readUint16LE() != 0)
61  throw Common::Exception("Reserved bytes != 0");
62 
63  _iconType = cur.readUint16LE();
64  if (_iconType != 1 && _iconType != 2)
65  throw Common::Exception("CUR/ICO resource is not a cursor/icon");
66 
67  _imageCount = cur.readUint16LE();
68 
69  if (!_imageCount)
70  throw Common::Exception("No image count");
71 }
72 
74  // For now, use the last image (which should be the highest quality)
75  // TODO: Detection of which image to use
76  cur.skip((_imageCount - 1) * 16);
77 
78  uint width = cur.readByte();
79  uint height = cur.readByte();
80  /* byte colorDepth = */ cur.readByte();
81 
82  // Not terrible to handle, but whatever :P
83  if (width & 3)
84  throw Common::Exception("Non-divisible-by-4 images not handled");
85 
86  if (width == 0)
87  width = 256;
88  if (height == 0)
89  height = 256;
90 
91  if (cur.readByte() != 0)
92  throw Common::Exception("Reserved byte != 0");
93 
94  if (_iconType == 2) {
95  _hotspotX = cur.readUint16LE();
96  _hotspotY = cur.readUint16LE();
97  } else {
98  // Icons have a 'planes' field and a 'bits per pixel' pixel
99  // field, but both are unused.
100  cur.readUint16LE();
101  cur.readUint16LE();
102  }
103 
104  /* uint32 size = */ cur.readUint32LE();
105  uint32 offset = cur.readUint32LE();
106 
107  // Welcome to the cursor data. Let's ride through the Win bitmap header v3
108  cur.seek(offset);
109 
110  /* uint32 headerSize = */ cur.readUint32LE();
111  /* uint32 bitmapWidth = */ cur.readUint32LE();
112  /* uint32 bitmapHeight = */ cur.readUint32LE();
113  /* uint16 planes = */ cur.readUint16LE();
114  uint16 bitsPerPixel = cur.readUint16LE();
115  /* uint32 compression = */ cur.readUint32LE();
116  /* uint32 imageSize = */ cur.readUint32LE();
117  cur.skip(16); // Skip the rest
118 
119  // We're only using 8bpp/24bpp for now. If more is required, DrMcCoy will
120  // volunteer to add it.
121  if (bitsPerPixel != 8 && bitsPerPixel != 24)
122  throw Common::Exception("Unhandled bpp %d", bitsPerPixel);
123 
124  const int pitch = width * (bitsPerPixel / 8);
125 
126  // Now we're at the palette. Read it in for 8bpp
127  byte palette[256 * 4];
128 
129  if (bitsPerPixel == 8)
130  cur.read(palette, 256 * 4);
131 
132  // The XOR map
133  Common::ScopedArray<byte> xorMap(new byte[pitch * height]);
134  if (cur.read(xorMap.get(), pitch * height) != (pitch * height))
136 
137  // The AND map
138  const uint32 andWidth = (width + 7) / 8;
139  Common::ScopedArray<byte> andMap(new byte[andWidth * height]);
140  if (cur.read(andMap.get(), andWidth * height) != (andWidth * height))
142 
145 
146  _mipMaps.push_back(new MipMap(this));
147 
148  _mipMaps[0]->width = width;
149  _mipMaps[0]->height = height;
150  _mipMaps[0]->size = width * height * 4;
151 
152  _mipMaps[0]->data.reset(new byte[_mipMaps[0]->size]);
153 
154  const byte *xorSrc = xorMap.get();
155  byte *dst = _mipMaps[0]->data.get();
156 
157  for (uint32 y = 0; y < height; y++) {
158  const byte *andSrc = andMap.get() + andWidth * y;
159 
160  for (uint32 x = 0; x < width; x++) {
161  if (bitsPerPixel == 8) {
162  const byte pixel = *xorSrc++;
163 
164  *dst++ = palette[pixel * 4];
165  *dst++ = palette[pixel * 4 + 1];
166  *dst++ = palette[pixel * 4 + 2];
167  } else {
168  *dst++ = *xorSrc++;
169  *dst++ = *xorSrc++;
170  *dst++ = *xorSrc++;
171  }
172 
173  *dst++ = (andSrc[x / 8] & (1 << (7 - x % 8))) ? 0 : 0xff;
174  }
175  }
176 }
177 
179  return _hotspotX;
180 }
181 
183  return _hotspotY;
184 }
185 
186 } // End of namespace Graphics
uint16 readUint16LE()
Read an unsigned 16-bit word stored in little endian (LSB first) order from the stream and return it...
Definition: readstream.h:122
void add(const char *s,...) GCC_PRINTF(2
Definition: error.cpp:58
uint32 readUint32LE()
Read an unsigned 32-bit word stored in little endian (LSB first) order from the stream and return it...
Definition: readstream.h:133
virtual size_t seek(ptrdiff_t offset, Origin whence=kOriginBegin)=0
Sets the stream position indicator for the stream.
PixelDataType _dataType
Definition: decoder.h:124
Exception that provides a stack of explanations.
Definition: error.h:36
A simple scoped smart pointer template.
Basic exceptions to throw.
uint16_t uint16
Definition: types.h:202
PixelFormat _format
Definition: decoder.h:122
Utility templates and functions.
virtual size_t skip(ptrdiff_t offset)
Skip the specified number of bytes, adding that offset to the current position in the stream...
Definition: readstream.h:317
PixelFormatRaw _formatRaw
Definition: decoder.h:123
virtual size_t read(void *dataPtr, size_t dataSize)=0
Read data from the stream.
StackException Exception
Definition: error.h:59
const Exception kReadError("Read error")
Exception when reading from a stream failed.
Definition: error.h:62
Basic reading stream interfaces.
void load(Common::SeekableReadStream &cur)
PointerType get() const
Returns the plain pointer value.
Definition: scopedptr.h:96
uint32_t uint32
Definition: types.h:204
Decoding Windows icon and cursor files (.ICO and .CUR).
WinIconImage(Common::SeekableReadStream &cur)
void readData(Common::SeekableReadStream &cur)
Interface for a seekable & readable data stream.
Definition: readstream.h:265
void readHeader(Common::SeekableReadStream &cur)
byte readByte()
Read an unsigned byte from the stream and return it.
Definition: readstream.h:92
uint8 byte
Definition: types.h:209
unsigned int uint
Definition: types.h:211