1
0
forked from 0ad/0ad
0ad/source/lib/tex/tex_bmp.cpp
janwas 4663ac0fe7 split debug_assert into ENSURE and ASSERT as discussed in a previous meeting.
the old debug_assert always ran and tested the expression, which slows
down release builds. wrapping them in #ifndef NDEBUG is clumsy. the new
ASSERT behaves like assert and ENSURE like the old debug_assert. Let's
change any time-critical but not-super-important ENSURE to ASSERT to
speed up release builds. (already done in bits.h and unique_range.h)

This was SVN commit r9362.
2011-04-30 13:01:45 +00:00

162 lines
4.0 KiB
C++

/* Copyright (c) 2010 Wildfire Games
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Windows BMP codec
*/
#include "precompiled.h"
#include "lib/byte_order.h"
#include "tex_codec.h"
#pragma pack(push, 1)
struct BmpHeader
{
// BITMAPFILEHEADER
u16 bfType; // "BM"
u32 bfSize; // of file
u16 bfReserved1;
u16 bfReserved2;
u32 bfOffBits; // offset to image data
// BITMAPINFOHEADER
u32 biSize;
i32 biWidth;
i32 biHeight;
u16 biPlanes;
u16 biBitCount;
u32 biCompression;
u32 biSizeImage;
// the following are unused and zeroed when writing:
i32 biXPelsPerMeter;
i32 biYPelsPerMeter;
u32 biClrUsed;
u32 biClrImportant;
};
#pragma pack(pop)
#define BI_RGB 0 // biCompression
static LibError bmp_transform(Tex* UNUSED(t), size_t UNUSED(transforms))
{
return INFO::TEX_CODEC_CANNOT_HANDLE;
}
static bool bmp_is_hdr(const u8* file)
{
// check header signature (bfType == "BM"?).
// we compare single bytes to be endian-safe.
return (file[0] == 'B' && file[1] == 'M');
}
static bool bmp_is_ext(const OsPath& extension)
{
return extension == L".bmp";
}
static size_t bmp_hdr_size(const u8* file)
{
const size_t hdr_size = sizeof(BmpHeader);
if(file)
{
BmpHeader* hdr = (BmpHeader*)file;
const u32 ofs = read_le32(&hdr->bfOffBits);
ENSURE(ofs >= hdr_size && "bmp_hdr_size invalid");
return ofs;
}
return hdr_size;
}
// requirements: uncompressed, direct colour, bottom up
static LibError bmp_decode(DynArray* RESTRICT da, Tex* RESTRICT t)
{
u8* file = da->base;
const BmpHeader* hdr = (const BmpHeader*)file;
const long w = (long)read_le32(&hdr->biWidth);
const long h_ = (long)read_le32(&hdr->biHeight);
const u16 bpp = read_le16(&hdr->biBitCount);
const u32 compress = read_le32(&hdr->biCompression);
const long h = abs(h_);
size_t flags = 0;
flags |= (h_ < 0)? TEX_TOP_DOWN : TEX_BOTTOM_UP;
if(bpp > 16)
flags |= TEX_BGR;
if(bpp == 32)
flags |= TEX_ALPHA;
// sanity checks
if(compress != BI_RGB)
WARN_RETURN(ERR::TEX_COMPRESSED);
t->w = w;
t->h = h;
t->bpp = bpp;
t->flags = flags;
return INFO::OK;
}
static LibError bmp_encode(Tex* RESTRICT t, DynArray* RESTRICT da)
{
const size_t hdr_size = sizeof(BmpHeader); // needed for BITMAPFILEHEADER
const size_t img_size = tex_img_size(t);
const size_t file_size = hdr_size + img_size;
const i32 h = (t->flags & TEX_TOP_DOWN)? -(i32)t->h : (i32)t->h;
size_t transforms = t->flags;
transforms &= ~TEX_ORIENTATION; // no flip needed - we can set top-down bit.
transforms ^= TEX_BGR; // BMP is native BGR.
const BmpHeader hdr =
{
// BITMAPFILEHEADER
0x4D42, // bfType = 'B','M'
(u32)file_size, // bfSize
0, 0, // bfReserved1,2
hdr_size, // bfOffBits
// BITMAPINFOHEADER
40, // biSize = sizeof(BITMAPINFOHEADER)
(i32)t->w,
h,
1, // biPlanes
(u16)t->bpp,
BI_RGB, // biCompression
(u32)img_size, // biSizeImage
0, 0, 0, 0 // unused (bi?PelsPerMeter, biClr*)
};
return tex_codec_write(t, transforms, &hdr, hdr_size, da);
}
TEX_CODEC_REGISTER(bmp);