add some hacky code to allow passing sfc files with -b
[openc2e.git] / c16Image.cpp
blob8ed335fabb7c23f3ab9823879c46024794fc4014
1 /*
2 * c16Image.cpp
3 * openc2e
5 * Created by Alyssa Milburn on Sat May 22 2004.
6 * Copyright (c) 2004 Alyssa Milburn. All rights reserved.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
20 #include "c16Image.h"
21 #include "openc2e.h"
23 void c16Image::readHeader(std::istream &in) {
24 uint32 flags; uint16 spritecount;
25 in.read((char *)&flags, 4); flags = swapEndianLong(flags);
26 is_565 = (flags & 0x01);
27 assert(flags & 0x02);
28 in.read((char *)&spritecount, 2); m_numframes = swapEndianShort(spritecount);
30 widths = new unsigned short[m_numframes];
31 heights = new unsigned short[m_numframes];
32 lineoffsets = new unsigned int *[m_numframes];
34 // first, read the headers.
35 for (unsigned int i = 0; i < m_numframes; i++) {
36 uint32 offset;
37 in.read((char *)&offset, 4); offset = swapEndianLong(offset);
38 in.read((char *)&widths[i], 2); widths[i] = swapEndianShort(widths[i]);
39 in.read((char *)&heights[i], 2); heights[i] = swapEndianShort(heights[i]);
40 lineoffsets[i] = new unsigned int[heights[i]];
41 lineoffsets[i][0] = offset;
42 for (unsigned int j = 1; j < heights[i]; j++) {
43 in.read((char *)&lineoffsets[i][j], 4); lineoffsets[i][j] = swapEndianLong(lineoffsets[i][j]);
48 shared_ptr<creaturesImage> c16Image::mutableCopy() {
49 s16Image *img = new s16Image();
51 img->imgformat = if_16bit;
52 img->is_565 = is_565;
53 img->m_numframes = m_numframes;
54 img->offsets = 0;
55 img->widths = new unsigned short[m_numframes];
56 memcpy(img->widths, widths, m_numframes * sizeof(unsigned short));
57 img->heights = new unsigned short[m_numframes];
58 memcpy(img->heights, heights, m_numframes * sizeof(unsigned short));
59 img->buffers = new void *[m_numframes];
60 for (unsigned int i = 0; i < m_numframes; i++) {
61 img->buffers[i] = new char[widths[i] * heights[i] * 2];
62 memcpy(img->buffers[i], buffers[i], widths[i] * heights[i] * 2);
65 return shared_ptr<creaturesImage>(img);
68 shared_ptr<creaturesImage> s16Image::mutableCopy() {
69 s16Image *img = new s16Image();
71 img->imgformat = if_16bit;
72 img->is_565 = is_565;
73 img->m_numframes = m_numframes;
74 img->offsets = 0;
75 img->widths = new unsigned short[m_numframes];
76 memcpy(img->widths, widths, m_numframes * sizeof(unsigned short));
77 img->heights = new unsigned short[m_numframes];
78 memcpy(img->heights, heights, m_numframes * sizeof(unsigned short));
79 img->buffers = new void *[m_numframes];
80 for (unsigned int i = 0; i < m_numframes; i++) {
81 img->buffers[i] = new char[widths[i] * heights[i] * 2];
82 memcpy(img->buffers[i], buffers[i], widths[i] * heights[i] * 2);
85 return shared_ptr<creaturesImage>(img);
88 c16Image::c16Image(mmapifstream *in, std::string n) : creaturesImage(n) {
89 stream = in;
90 imgformat = if_16bit;
92 readHeader(*in);
94 buffers = new void *[m_numframes];
96 // then, read the files. this involves seeking around, and is hence immensely ghey
97 // todo: we assume the file format is valid here. we shouldn't.
98 for (unsigned int i = 0; i < m_numframes; i++) {
99 buffers[i] = new char[widths[i] * heights[i] * 2];
100 uint16 *bufferpos = (uint16 *)buffers[i];
101 for (unsigned int j = 0; j < heights[i]; j++) {
102 in->seekg(lineoffsets[i][j], std::ios::beg);
103 while (true) {
104 uint16 tag; in->read((char *)&tag, 2); tag = swapEndianShort(tag);
105 if (tag == 0) break;
106 bool transparentrun = ((tag & 0x0001) == 0);
107 uint16 runlength = (tag & 0xFFFE) >> 1;
108 if (transparentrun)
109 memset((char *)bufferpos, 0, (runlength * 2));
110 else {
111 in->read((char *)bufferpos, (runlength * 2));
112 for (unsigned int k = 0; k < runlength; k++) {
113 bufferpos[k] = swapEndianShort(bufferpos[k]);
116 bufferpos += runlength;
119 delete[] lineoffsets[i];
121 delete[] lineoffsets;
124 void s16Image::readHeader(std::istream &in) {
125 uint32 flags; uint16 spritecount;
126 in.read((char *)&flags, 4); flags = swapEndianLong(flags);
127 is_565 = (flags & 0x01);
128 in.read((char *)&spritecount, 2); m_numframes = swapEndianShort(spritecount);
130 widths = new unsigned short[m_numframes];
131 heights = new unsigned short[m_numframes];
132 offsets = new unsigned int[m_numframes];
134 // first, read the headers.
135 for (unsigned int i = 0; i < m_numframes; i++) {
136 in.read((char *)&offsets[i], 4); offsets[i] = swapEndianLong(offsets[i]);
137 in.read((char *)&widths[i], 2); widths[i] = swapEndianShort(widths[i]);
138 in.read((char *)&heights[i], 2); heights[i] = swapEndianShort(heights[i]);
142 void s16Image::writeHeader(std::ostream &s) {
143 unsigned int dw; unsigned short w;
145 dw = (is_565 ? 1 : 0);
146 dw = swapEndianLong(dw); s.write((char *)&dw, 4);
147 w = m_numframes;
148 w = swapEndianShort(w); s.write((char *)&w, 2);
150 for (unsigned int i = 0; i < m_numframes; i++) {
151 dw = offsets[i];
152 dw = swapEndianLong(dw); s.write((char *)&dw, 4);
153 w = widths[i];
154 w = swapEndianShort(w); s.write((char *)&w, 2);
155 w = heights[i];
156 w = swapEndianShort(w); s.write((char *)&w, 2);
160 bool s16Image::transparentAt(unsigned int frame, unsigned int x, unsigned int y) {
161 unsigned int offset = (y * widths[frame]) + x;
162 unsigned short *buffer = (unsigned short *)buffers[frame];
163 return (buffer[offset] == 0);
166 bool c16Image::transparentAt(unsigned int frame, unsigned int x, unsigned int y) {
167 unsigned int offset = (y * widths[frame]) + x;
168 unsigned short *buffer = (unsigned short *)buffers[frame];
169 return (buffer[offset] == 0);
172 s16Image::s16Image(mmapifstream *in, std::string n) : creaturesImage(n) {
173 stream = in;
174 imgformat = if_16bit;
176 readHeader(*in);
178 buffers = new void *[m_numframes];
180 for (unsigned int i = 0; i < m_numframes; i++)
181 buffers[i] = in->map + offsets[i];
183 delete[] offsets;
186 s16Image::~s16Image() {
187 delete[] widths;
188 delete[] heights;
189 if (!stream) { // make sure this isn't a damn mmapifstream..
190 for (unsigned int i = 0; i < m_numframes; i++)
191 delete[] (uint16 *)buffers[i];
193 delete[] buffers;
194 // TODO: we should never have 'offsets' left over here, but .. we should check
197 c16Image::~c16Image() {
198 delete[] widths;
199 delete[] heights;
200 for (unsigned int i = 0; i < m_numframes; i++)
201 delete[] (uint16 *)buffers[i];
202 delete[] buffers;
203 // TODO: we should never have 'offsets' left over here, but .. we should check
206 void s16Image::tint(unsigned char r, unsigned char g, unsigned char b, unsigned char rotation, unsigned char swap) {
207 assert(!stream); // this only works on duplicated images
209 if (128 == r && 128 == g && 128 == b && 128 == rotation && 128 == swap) return; // duh
212 * CDN:
213 * if rotation >= 128
214 * absRot = rotation-128
215 * else
216 * absRot = 128 - rotation
217 * endif
218 * invRot = 127-absRot
220 int absRot;
221 if (rotation >= 128)
222 absRot = (int)rotation - 128;
223 else
224 absRot = 128 - (int)rotation;
225 int invRot = 127 - absRot;
228 * CDN:
229 * if swap >= 128
230 * absSwap = swap - 128
231 * else
232 * absSwap = 128 - swap
233 * endif
234 * invSwap = 127-absSwap
236 int absSwap;
237 if (swap >= 128)
238 absSwap = (int)swap - 128;
239 else
240 absSwap = 128 - (int)swap;
241 int invSwap = 127 - absSwap;
244 * CDN:
245 * redTint = red-128
246 * greenTint = green-128
247 * blueTint = blue-128
250 int redTint = (int)r - 128;
251 int greenTint = (int)g - 128;
252 int blueTint = (int)b - 128;
254 for (unsigned int i = 0; i < m_numframes; i++) {
255 for (unsigned int j = 0; j < heights[i]; j++) {
256 for (unsigned int k = 0; k < widths[i]; k++) {
257 unsigned short v = ((unsigned short *)buffers[i])[(j * widths[i]) + k];
258 if (v == 0) continue;
261 * CDN:
262 * tempRed = RedValue + redTint;
263 * tempGreen = GreenValue + greenTint;
264 * tempBlue = BlueValue + blueTint;
266 int red = (((uint32)(v) & 0xf800) >> 8) + redTint;
267 if (red < 0) red = 0; else if (red > 255) red = 255;
268 int green = (((uint32)(v) & 0x07e0) >> 3) + greenTint;
269 if (green < 0) green = 0; else if (green > 255) green = 255;
270 int blue = (((uint32)(v) & 0x001f) << 3) + blueTint;
271 if (blue < 0) blue = 0; else if (blue > 255) blue = 255;
274 * CDN:
275 * if (rotation < 128)
276 * rotRed = ((absRot * tempBlue) + (invRot * tempRed)) / 256
277 * rotGreen = ((absRot * tempRed) + (invRot * tempGreen)) / 256
278 * rotBlue = ((absRot * tempGreen) + (invRot * tempBlue)) / 256
279 * endif
282 int rotRed, rotGreen, rotBlue;
283 rotRed = ((blue * absRot) + (red * invRot)) / 128;
284 rotGreen = ((red * absRot) + (green * invRot)) / 128;
285 rotBlue = ((green * absRot) + (blue * invRot)) / 128;
289 * CDN:
290 * swappedRed = ((absSwap * rotBlue) + (invSwap * rotRed))/256
291 * swappedBlue = ((absSwap * rotRed) + (invSwap * rotBlue))/256
293 * fuzzie notes that this doesn't seem to be a no-op for swap=128..
295 int swappedRed = ((absSwap * blue) + (invSwap * red)) / 128;
296 int swappedBlue = ((absSwap * red) + (invSwap * blue)) / 128;
299 * SetColour(definedcolour to (swappedRed,rotGreen,swappedBlue))
301 swappedRed = (swappedRed << 8) & 0xf800;
302 rotGreen = (rotGreen << 3) & 0x7e0;
303 swappedBlue = (swappedBlue >> 3) & 0x1f;
304 v = (swappedRed | rotGreen | swappedBlue);
306 * if definedcolour ==0 SetColour(definedcolour to (1,1,1))
308 if (v == 0)
309 v = (1 << 11 | 1 << 5 | 1);
310 ((unsigned short *)buffers[i])[(j * widths[i]) + k] = v;
316 /* vim: set noet: */