X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=plugins%2Fimage%2Fbmp.cpp;h=63ce4a053ebc5896b7dda02d17b8bc55b4b689b0;hb=HEAD;hp=4b27227bffac4964d6483160df57e75224698126;hpb=02a51890a3d97a0e937fbb11071cf7c41cc00aa9;p=xonotic%2Fnetradiant.git diff --git a/plugins/image/bmp.cpp b/plugins/image/bmp.cpp index 4b27227b..63ce4a05 100644 --- a/plugins/image/bmp.cpp +++ b/plugins/image/bmp.cpp @@ -30,168 +30,166 @@ 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 ); }