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.
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);
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
++) {
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
;
53 img
->m_numframes
= m_numframes
;
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
;
73 img
->m_numframes
= m_numframes
;
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
) {
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
);
104 uint16 tag
; in
->read((char *)&tag
, 2); tag
= swapEndianShort(tag
);
106 bool transparentrun
= ((tag
& 0x0001) == 0);
107 uint16 runlength
= (tag
& 0xFFFE) >> 1;
109 memset((char *)bufferpos
, 0, (runlength
* 2));
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);
148 w
= swapEndianShort(w
); s
.write((char *)&w
, 2);
150 for (unsigned int i
= 0; i
< m_numframes
; i
++) {
152 dw
= swapEndianLong(dw
); s
.write((char *)&dw
, 4);
154 w
= swapEndianShort(w
); s
.write((char *)&w
, 2);
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
) {
174 imgformat
= if_16bit
;
178 buffers
= new void *[m_numframes
];
180 for (unsigned int i
= 0; i
< m_numframes
; i
++)
181 buffers
[i
] = in
->map
+ offsets
[i
];
186 s16Image::~s16Image() {
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
];
194 // TODO: we should never have 'offsets' left over here, but .. we should check
197 c16Image::~c16Image() {
200 for (unsigned int i
= 0; i
< m_numframes
; i
++)
201 delete[] (uint16
*)buffers
[i
];
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
214 * absRot = rotation-128
216 * absRot = 128 - rotation
218 * invRot = 127-absRot
222 absRot
= (int)rotation
- 128;
224 absRot
= 128 - (int)rotation
;
225 int invRot
= 127 - absRot
;
230 * absSwap = swap - 128
232 * absSwap = 128 - swap
234 * invSwap = 127-absSwap
238 absSwap
= (int)swap
- 128;
240 absSwap
= 128 - (int)swap
;
241 int invSwap
= 127 - absSwap
;
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;
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;
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
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;
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))
309 v
= (1 << 11 | 1 << 5 | 1);
310 ((unsigned short *)buffers
[i
])[(j
* widths
[i
]) + k
] = v
;