📄 openbmp.cpp
字号:
memset(pixels, 0, h.width * h.height);
// we read the image from the bottom down, and then flip it when
// we're done
int x = 0;
int y = 0;
const byte* in = raster_data;
while (in - raster_data < h.image_size - 1) {
byte n = *in++;
byte c = *in++;
if (n == 0) { // escape code
if (c == 0) { // end of line
x = 0;
//++y; // XXXaegis uhhh... uhhh... :) it works this way...
if (y >= h.height) {
// did we go too far?
break;
}
} else if (c == 1) { // end of bitmap
break;
} else if (c == 2) { // delta
// do we have enough space?
if (in - raster_data >= h.image_size - 1) {
break;
}
// I have no idea how I'm supposed to do this...
// Let's take a guess!
int dx = *in++;
int dy = *in++;
x = (x + dx) % h.width;
y += dy + (x + dx) / h.width;
if (y >= h.height) {
// if we went too far, stop now
break;
}
} else { // read uncompressed
// the input raster data is padded on DWORD boundaries
// c == num_pixels
int num_bytes = (c + 3) / 4 * 2;
// make sure we have enough space
if (in - raster_data > h.image_size - num_bytes) {
break;
}
// nasty decoding loop...
int i = 0;
int j = 0;
while (true) {
byte l = (in[j] & 0xF0) >> 4;
byte r = (in[j] & 0x0F);
++j;
pixels[y * h.width + x] = l;
if (!advance(x, y, h) || ++i >= c) {
break;
}
pixels[y * h.width + x] = r;
if (!advance(x, y, h) || ++i >= c) {
break;
}
}
// make SURE we move forward the right number of bytes
in += num_bytes;
}
} else {
// a less nasty decoding loop...
byte lc = (c & 0xF0) >> 4;
byte rc = c & 0x0F;
int i = 0;
while (true) {
pixels[y * h.width + x] = lc;
if (!advance(x, y, h) || ++i >= n) {
break;
}
pixels[y * h.width + x] = rc;
if (!advance(x, y, h) || ++i >= n) {
break;
}
}
} // end if
} // end while
// flippy flippy!
int pitch = h.width;
auto_array<byte> row(new byte[pitch]);
for (int i = 0; i < h.height / 2; ++i) {
int j = h.height - i - 1;
memcpy((byte*)row, pixels + i * pitch, pitch);
memcpy(pixels + i * pitch, pixels + j * pitch, pitch);
memcpy(pixels + j * pitch, (byte*)row, pitch);
}
return new SimpleImage(h.width, h.height, PF_I8, pixels.release(),
(byte*)palette.release(), 256, PF_B8G8R8);
}
Image* ReadBitmap8(const byte* raster_data, const Header& h) {
auto_array<byte> pixels(new byte[h.width * h.height]);
auto_array<BGR> palette(new BGR[256]);
memset(palette, 0, 256 * sizeof(BGR));
memcpy(palette, h.palette, h.palette_size * sizeof(BGR));
for (int i = 0; i < h.height; ++i) {
const byte* in = raster_data + i * h.pitch;
byte* out = pixels + (h.height - i - 1) * h.width;
for (int j = 0; j < h.width; ++j) {
*out++ = *in++;
}
}
return new SimpleImage(h.width, h.height, PF_I8, pixels.release(),
(byte*)palette.release(), 256, PF_B8G8R8);
}
Image* ReadBitmapRLE8(const byte* raster_data, const Header& h) {
auto_array<byte> pixels(new byte[h.width * h.height]);
auto_array<BGR> palette(new BGR[256]);
memset(palette, 0, 256 * sizeof(BGR));
memcpy(palette, h.palette, h.palette_size * sizeof(BGR));
// by default, we have an empty bitmap
memset(pixels, 0, h.width * h.height);
// we read the image from the bottom down, and then flip it when
// we're done
int x = 0;
int y = 0;
const byte* in = raster_data;
while (in - raster_data < h.image_size - 1) {
byte n = *in++;
byte c = *in++;
if (n == 0) { // escape code
if (c == 0) { // end of line
x = 0;
//++y; // XXXaegis uhhh... uhhh... :) it works this way...
if (y >= h.height) {
// did we go too far?
break;
}
} else if (c == 1) { // end of bitmap
break;
} else if (c == 2) { // delta
// do we have enough space?
if (in - raster_data >= h.image_size - 1) {
break;
}
// I have no idea how I'm supposed to do this...
// Let's take a guess!
int dx = *in++;
int dy = *in++;
x = (x + dx) % h.width;
y += dy + (x + dx) / h.width;
if (y >= h.height) {
// if we went too far, stop now
break;
}
} else { // read uncompressed
// c == num_pixels
int num_bytes = (c + 1) / 2 * 2;
// make sure we have enough space
if (in - raster_data > h.image_size - num_bytes) {
break;
}
// decoding loop...
int i = 0;
int j = 0;
while (true) {
pixels[y * h.width + x] = in[j++];
if (!advance(x, y, h) || ++i >= c) {
break;
}
}
// make SURE we move forward the right number of bytes
in += num_bytes;
}
} else {
int i = 0;
while (true) {
pixels[y * h.width + x] = c;
if (!advance(x, y, h) || ++i >= n) {
break;
}
}
} // end if
} // end while
// flippy flippy!
int pitch = h.width;
auto_array<byte> row(new byte[pitch]);
for (int i = 0; i < h.height / 2; ++i) {
int j = h.height - i - 1;
memcpy((byte*)row, pixels + i * pitch, pitch);
memcpy(pixels + i * pitch, pixels + j * pitch, pitch);
memcpy(pixels + j * pitch, (byte*)row, pitch);
}
return new SimpleImage(h.width, h.height, PF_I8, pixels.release(),
(byte*)palette.release(), 256, PF_B8G8R8);
}
Image* ReadBitmap16(const byte* raster_data, const Header& h) {
auto_array<RGB> pixels(new RGB[h.width * h.height]);
for (int i = 0; i < h.height; ++i) {
const byte* in = raster_data + i * h.pitch;
RGB* out = pixels + (h.height - i - 1) * h.width;
for (int j = 0; j < h.width; ++j) {
int clr = read16_le(in);
in += 2;
#define C16(C) \
(byte)( ((clr & h.bf_##C##_mask) >> h.bf_##C##_shift) << h.bf_##C##_rshift);
out->red = C16(red);
out->green = C16(green);
out->blue = C16(blue);
++out;
#undef C16
}
}
return new SimpleImage(h.width, h.height, PF_R8G8B8,
(byte*)pixels.release());
}
Image* ReadBitmap24(const byte* raster_data, const Header& h) {
auto_array<BGR> pixels(new BGR[h.width * h.height]);
for (int i = 0; i < h.height; ++i) {
const byte* in = raster_data + i * h.pitch;
BGR* out = pixels + (h.height - i - 1) * h.width;
for (int j = 0; j < h.width; ++j) {
out->blue = *in++;
out->green = *in++;
out->red = *in++;
++out;
}
}
return new SimpleImage(h.width, h.height, PF_B8G8R8,
(byte*)pixels.release());
}
Image* ReadBitmap32(const byte* raster_data, const Header& h) {
auto_array<RGB> pixels(new RGB[h.width * h.height]);
for (int i = 0; i < h.height; ++i) {
const byte* in = raster_data + i * h.pitch;
RGB* out = pixels + (h.height - i - 1) * h.width;
for (int j = 0; j < h.width; ++j) {
u32 pixel = read32_le(in);
in += 4;
out->red = (byte)((pixel & h.bf_red_mask) >> h.bf_red_shift);
out->green = (byte)((pixel & h.bf_green_mask) >> h.bf_green_shift);
out->blue = (byte)((pixel & h.bf_blue_mask) >> h.bf_blue_shift);
++out;
}
}
return new SimpleImage(h.width, h.height, PF_R8G8B8,
(byte*)pixels.release());
}
Image* DecodeBitmap(File* file, const Header& h) {
if (!file->seek(h.data_offset, File::BEGIN)) {
return 0;
}
// the raster data stored in the file
auto_array<byte> raster_data(new byte[h.image_size]);
if (file->read(raster_data, h.image_size) != h.image_size) {
return 0;
}
// the output pixel buffer (parameter to new SimpleImage)
auto_array<byte> pixels(new byte[h.width * h.height * 3]);
typedef Image* (*Decoder)(const byte* raster_data, const Header& h);
Decoder decoder = 0;
if (h.bpp == 1 && h.compression == 0) { decoder = ReadBitmap1; }
else if (h.bpp == 4 && h.compression == 0) { decoder = ReadBitmap4; }
else if (h.bpp == 4 && h.compression == 2) { decoder = ReadBitmapRLE4; }
else if (h.bpp == 8 && h.compression == 0) { decoder = ReadBitmap8; }
else if (h.bpp == 8 && h.compression == 1) { decoder = ReadBitmapRLE8; }
else if (h.bpp == 16 && (h.compression == 0 ||
h.compression == 3)) { decoder = ReadBitmap16; }
else if (h.bpp == 24 && h.compression == 0) { decoder = ReadBitmap24; }
else if (h.bpp == 32 && (h.compression == 0 ||
h.compression == 3)) { decoder = ReadBitmap32; }
if (decoder) {
return decoder(raster_data.get(), h);
} else {
return 0;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -