X-Git-Url: http://git.xonotic.org/?p=xonotic%2Fnetradiant.git;a=blobdiff_plain;f=plugins%2Fimage%2Fbmp.cpp;h=4b27227bffac4964d6483160df57e75224698126;hp=63ce4a053ebc5896b7dda02d17b8bc55b4b689b0;hb=9dfae1c9b270ee369c6362903a9205b30751b95f;hpb=0a6d5683b0cfa1a0bd7ef64bada105dbe4ddd6e1 diff --git a/plugins/image/bmp.cpp b/plugins/image/bmp.cpp index 63ce4a05..4b27227b 100644 --- a/plugins/image/bmp.cpp +++ b/plugins/image/bmp.cpp @@ -30,166 +30,168 @@ typedef unsigned char byte; typedef unsigned char PaletteEntry[4]; -typedef struct -{ - char id[2]; - unsigned long fileSize; - unsigned long reserved0; - unsigned long bitmapDataOffset; - unsigned long bitmapHeaderSize; - unsigned long width; - unsigned long height; - unsigned short planes; - unsigned short bitsPerPixel; - unsigned long compression; - unsigned long bitmapDataSize; - unsigned long hRes; - unsigned long vRes; - unsigned long colors; - unsigned long importantColors; - PaletteEntry palette[256]; +typedef struct { + char id[2]; + unsigned long fileSize; + unsigned long reserved0; + unsigned long bitmapDataOffset; + unsigned long bitmapHeaderSize; + unsigned long width; + unsigned long height; + unsigned short planes; + unsigned short bitsPerPixel; + unsigned long compression; + unsigned long bitmapDataSize; + unsigned long hRes; + unsigned long vRes; + unsigned long colors; + unsigned long importantColors; + PaletteEntry palette[256]; } BMPHeader_t; -class ReadPixel8 -{ -PaletteEntry* m_palette; +class ReadPixel8 { + PaletteEntry *m_palette; public: -ReadPixel8( PaletteEntry* palette ) : m_palette( palette ){ -} -void operator()( PointerInputStream& inputStream, byte*& pixbuf ) const { - byte palIndex; - inputStream.read( &palIndex, 1 ); - *pixbuf++ = m_palette[palIndex][2]; - *pixbuf++ = m_palette[palIndex][1]; - *pixbuf++ = m_palette[palIndex][0]; - *pixbuf++ = 0xff; -} + ReadPixel8(PaletteEntry *palette) : m_palette(palette) + { + } + + void operator()(PointerInputStream &inputStream, byte *&pixbuf) const + { + byte palIndex; + inputStream.read(&palIndex, 1); + *pixbuf++ = m_palette[palIndex][2]; + *pixbuf++ = m_palette[palIndex][1]; + *pixbuf++ = m_palette[palIndex][0]; + *pixbuf++ = 0xff; + } }; -class ReadPixel16 -{ +class ReadPixel16 { public: -void operator()( PointerInputStream& inputStream, byte*& pixbuf ) const { - unsigned short shortPixel; - inputStream.read( reinterpret_cast( &shortPixel ), sizeof( unsigned short ) ); //!\todo Is this endian safe? - *pixbuf++ = static_cast( shortPixel & ( 31 << 10 ) ) >> 7; - *pixbuf++ = static_cast( shortPixel & ( 31 << 5 ) ) >> 2; - *pixbuf++ = static_cast( shortPixel & ( 31 ) ) << 3; - *pixbuf++ = 0xff; -} + void operator()(PointerInputStream &inputStream, byte *&pixbuf) const + { + unsigned short shortPixel; + inputStream.read(reinterpret_cast( &shortPixel ), sizeof(unsigned short)); //!\todo Is this endian safe? + *pixbuf++ = static_cast( shortPixel & (31 << 10)) >> 7; + *pixbuf++ = static_cast( shortPixel & (31 << 5)) >> 2; + *pixbuf++ = static_cast( shortPixel & (31)) << 3; + *pixbuf++ = 0xff; + } }; -class ReadPixel24 -{ +class ReadPixel24 { public: -void operator()( PointerInputStream& inputStream, byte*& pixbuf ) const { - byte bgr[3]; - inputStream.read( bgr, 3 ); - *pixbuf++ = bgr[2]; - *pixbuf++ = bgr[1]; - *pixbuf++ = bgr[0]; - *pixbuf++ = 255; -} + void operator()(PointerInputStream &inputStream, byte *&pixbuf) const + { + byte bgr[3]; + inputStream.read(bgr, 3); + *pixbuf++ = bgr[2]; + *pixbuf++ = bgr[1]; + *pixbuf++ = bgr[0]; + *pixbuf++ = 255; + } }; -class ReadPixel32 -{ +class ReadPixel32 { public: -void operator()( PointerInputStream& inputStream, byte*& pixbuf ) const { - byte bgra[4]; - inputStream.read( bgra, 4 ); - *pixbuf++ = bgra[2]; - *pixbuf++ = bgra[1]; - *pixbuf++ = bgra[0]; - *pixbuf++ = bgra[3]; -} + void operator()(PointerInputStream &inputStream, byte *&pixbuf) const + { + byte bgra[4]; + inputStream.read(bgra, 4); + *pixbuf++ = bgra[2]; + *pixbuf++ = bgra[1]; + *pixbuf++ = bgra[0]; + *pixbuf++ = bgra[3]; + } }; template -void ReadBMP( PointerInputStream& inputStream, byte* bmpRGBA, int rows, int columns, ReadPixel readPixel ){ - for ( int row = rows - 1; row >= 0; row-- ) - { - byte* pixbuf = bmpRGBA + row * columns * 4; - - for ( int column = 0; column < columns; column++ ) - { - readPixel( inputStream, pixbuf ); - } - } +void ReadBMP(PointerInputStream &inputStream, byte *bmpRGBA, int rows, int columns, ReadPixel readPixel) +{ + for (int row = rows - 1; row >= 0; row--) { + byte *pixbuf = bmpRGBA + row * columns * 4; + + for (int column = 0; column < columns; column++) { + readPixel(inputStream, pixbuf); + } + } } -Image* LoadBMPBuff( PointerInputStream& inputStream, std::size_t length ){ - BMPHeader_t bmpHeader; - inputStream.read( reinterpret_cast( bmpHeader.id ), 2 ); - bmpHeader.fileSize = istream_read_uint32_le( inputStream ); - bmpHeader.reserved0 = istream_read_uint32_le( inputStream ); - bmpHeader.bitmapDataOffset = istream_read_uint32_le( inputStream ); - bmpHeader.bitmapHeaderSize = istream_read_uint32_le( inputStream ); - bmpHeader.width = istream_read_uint32_le( inputStream ); - bmpHeader.height = istream_read_uint32_le( inputStream ); - bmpHeader.planes = istream_read_uint16_le( inputStream ); - bmpHeader.bitsPerPixel = istream_read_uint16_le( inputStream ); - bmpHeader.compression = istream_read_uint32_le( inputStream ); - bmpHeader.bitmapDataSize = istream_read_uint32_le( inputStream ); - bmpHeader.hRes = istream_read_uint32_le( inputStream ); - bmpHeader.vRes = istream_read_uint32_le( inputStream ); - bmpHeader.colors = istream_read_uint32_le( inputStream ); - bmpHeader.importantColors = istream_read_uint32_le( inputStream ); - - if ( bmpHeader.bitsPerPixel == 8 ) { - int paletteSize = bmpHeader.colors * 4; - inputStream.read( reinterpret_cast( bmpHeader.palette ), paletteSize ); - } - - if ( bmpHeader.id[0] != 'B' && bmpHeader.id[1] != 'M' ) { - globalErrorStream() << "LoadBMP: only Windows-style BMP files supported\n"; - return 0; - } - if ( bmpHeader.fileSize != length ) { - globalErrorStream() << "LoadBMP: header size does not match file size (" << Unsigned( bmpHeader.fileSize ) << " vs. " << Unsigned( length ) << ")\n"; - return 0; - } - if ( bmpHeader.compression != 0 ) { - globalErrorStream() << "LoadBMP: only uncompressed BMP files supported\n"; - return 0; - } - if ( bmpHeader.bitsPerPixel < 8 ) { - globalErrorStream() << "LoadBMP: monochrome and 4-bit BMP files not supported\n"; - return 0; - } - - int columns = bmpHeader.width; - int rows = bmpHeader.height; - if ( rows < 0 ) { - rows = -rows; - } - - RGBAImage* image = new RGBAImage( columns, rows ); - - switch ( bmpHeader.bitsPerPixel ) - { - case 8: - ReadBMP( inputStream, image->getRGBAPixels(), rows, columns, ReadPixel8( bmpHeader.palette ) ); - break; - case 16: - ReadBMP( inputStream, image->getRGBAPixels(), rows, columns, ReadPixel16() ); - break; - case 24: - ReadBMP( inputStream, image->getRGBAPixels(), rows, columns, ReadPixel24() ); - break; - case 32: - ReadBMP( inputStream, image->getRGBAPixels(), rows, columns, ReadPixel32() ); - break; - default: - globalErrorStream() << "LoadBMP: illegal pixel_size '" << bmpHeader.bitsPerPixel << "'\n"; - image->release(); - return 0; - } - return image; +Image *LoadBMPBuff(PointerInputStream &inputStream, std::size_t length) +{ + BMPHeader_t bmpHeader; + inputStream.read(reinterpret_cast( bmpHeader.id ), 2); + bmpHeader.fileSize = istream_read_uint32_le(inputStream); + bmpHeader.reserved0 = istream_read_uint32_le(inputStream); + bmpHeader.bitmapDataOffset = istream_read_uint32_le(inputStream); + bmpHeader.bitmapHeaderSize = istream_read_uint32_le(inputStream); + bmpHeader.width = istream_read_uint32_le(inputStream); + bmpHeader.height = istream_read_uint32_le(inputStream); + bmpHeader.planes = istream_read_uint16_le(inputStream); + bmpHeader.bitsPerPixel = istream_read_uint16_le(inputStream); + bmpHeader.compression = istream_read_uint32_le(inputStream); + bmpHeader.bitmapDataSize = istream_read_uint32_le(inputStream); + bmpHeader.hRes = istream_read_uint32_le(inputStream); + bmpHeader.vRes = istream_read_uint32_le(inputStream); + bmpHeader.colors = istream_read_uint32_le(inputStream); + bmpHeader.importantColors = istream_read_uint32_le(inputStream); + + if (bmpHeader.bitsPerPixel == 8) { + int paletteSize = bmpHeader.colors * 4; + inputStream.read(reinterpret_cast( bmpHeader.palette ), paletteSize); + } + + if (bmpHeader.id[0] != 'B' && bmpHeader.id[1] != 'M') { + globalErrorStream() << "LoadBMP: only Windows-style BMP files supported\n"; + return 0; + } + if (bmpHeader.fileSize != length) { + globalErrorStream() << "LoadBMP: header size does not match file size (" << Unsigned(bmpHeader.fileSize) + << " vs. " << Unsigned(length) << ")\n"; + return 0; + } + if (bmpHeader.compression != 0) { + globalErrorStream() << "LoadBMP: only uncompressed BMP files supported\n"; + return 0; + } + if (bmpHeader.bitsPerPixel < 8) { + globalErrorStream() << "LoadBMP: monochrome and 4-bit BMP files not supported\n"; + return 0; + } + + int columns = bmpHeader.width; + int rows = bmpHeader.height; + if (rows < 0) { + rows = -rows; + } + + RGBAImage *image = new RGBAImage(columns, rows); + + switch (bmpHeader.bitsPerPixel) { + case 8: + ReadBMP(inputStream, image->getRGBAPixels(), rows, columns, ReadPixel8(bmpHeader.palette)); + break; + case 16: + ReadBMP(inputStream, image->getRGBAPixels(), rows, columns, ReadPixel16()); + break; + case 24: + ReadBMP(inputStream, image->getRGBAPixels(), rows, columns, ReadPixel24()); + break; + case 32: + ReadBMP(inputStream, image->getRGBAPixels(), rows, columns, ReadPixel32()); + break; + default: + globalErrorStream() << "LoadBMP: illegal pixel_size '" << bmpHeader.bitsPerPixel << "'\n"; + image->release(); + return 0; + } + return image; } -Image* LoadBMP( ArchiveFile& file ){ - ScopedArchiveBuffer buffer( file ); - PointerInputStream inputStream( buffer.buffer ); - return LoadBMPBuff( inputStream, buffer.length ); +Image *LoadBMP(ArchiveFile &file) +{ + ScopedArchiveBuffer buffer(file); + PointerInputStream inputStream(buffer.buffer); + return LoadBMPBuff(inputStream, buffer.length); }