X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=plugins%2Fimage%2Ftga.cpp;h=88233a9af05a56ffdca7bb25df4901ee70d9977d;hb=fc8a70d5fbfc703478d25980fd151e97b19c416c;hp=6a6ac9aa85be60a711e0f8d3e074d138a3005149;hpb=12b372f89ce109a4db9d510884fbe7d05af79870;p=xonotic%2Fnetradiant.git diff --git a/plugins/image/tga.cpp b/plugins/image/tga.cpp index 6a6ac9aa..88233a9a 100644 --- a/plugins/image/tga.cpp +++ b/plugins/image/tga.cpp @@ -1,23 +1,23 @@ /* -Copyright (C) 2001-2006, William Joseph. -All Rights Reserved. + Copyright (C) 2001-2006, William Joseph. + All Rights Reserved. -This file is part of GtkRadiant. + This file is part of GtkRadiant. -GtkRadiant is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + GtkRadiant is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. -GtkRadiant is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + GtkRadiant is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with GtkRadiant; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ + You should have received a copy of the GNU General Public License + along with GtkRadiant; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ #include "tga.h" @@ -40,381 +40,377 @@ class Flip10 {}; // horizontal flip only class Flip11 {}; // both template -void image_decode(PointerInputStream& istream, PixelDecoder& decode, RGBAImage& image, const Flip00&) -{ - RGBAPixel* end = image.pixels + (image.height * image.width); - for(RGBAPixel* row = end; row != image.pixels; row -= image.width) - { - for(RGBAPixel* pixel = row - image.width; pixel != row; ++pixel) - { - decode(istream, *pixel); - } - } +void image_decode( PointerInputStream& istream, PixelDecoder& decode, RGBAImage& image, const Flip00& ){ + RGBAPixel* end = image.pixels + ( image.height * image.width ); + for ( RGBAPixel* row = end; row != image.pixels; row -= image.width ) + { + for ( RGBAPixel* pixel = row - image.width; pixel != row; ++pixel ) + { + decode( istream, *pixel ); + } + } } template -void image_decode(PointerInputStream& istream, PixelDecoder& decode, RGBAImage& image, const Flip01&) -{ - RGBAPixel* end = image.pixels + (image.height * image.width); - for(RGBAPixel* row = image.pixels; row != end; row += image.width) - { - for(RGBAPixel* pixel = row; pixel != row + image.width; ++pixel) - { - decode(istream, *pixel); - } - } +void image_decode( PointerInputStream& istream, PixelDecoder& decode, RGBAImage& image, const Flip01& ){ + RGBAPixel* end = image.pixels + ( image.height * image.width ); + for ( RGBAPixel* row = image.pixels; row != end; row += image.width ) + { + for ( RGBAPixel* pixel = row; pixel != row + image.width; ++pixel ) + { + decode( istream, *pixel ); + } + } } template -void image_decode(PointerInputStream& istream, PixelDecoder& decode, RGBAImage& image, const Flip10&) -{ - RGBAPixel* end = image.pixels + (image.height * image.width); - for(RGBAPixel* row = end; row != image.pixels; row -= image.width) - { - for(RGBAPixel* pixel = row; pixel != row - image.width;) - { - decode(istream, *--pixel); - } - } +void image_decode( PointerInputStream& istream, PixelDecoder& decode, RGBAImage& image, const Flip10& ){ + RGBAPixel* end = image.pixels + ( image.height * image.width ); + for ( RGBAPixel* row = end; row != image.pixels; row -= image.width ) + { + for ( RGBAPixel* pixel = row; pixel != row - image.width; ) + { + decode( istream, *--pixel ); + } + } } template -void image_decode(PointerInputStream& istream, PixelDecoder& decode, RGBAImage& image, const Flip11&) -{ - RGBAPixel* end = image.pixels + (image.height * image.width); - for(RGBAPixel* row = image.pixels; row != end; row += image.width) - { - for(RGBAPixel* pixel = row + image.width; pixel != row;) - { - decode(istream, *--pixel); - } - } +void image_decode( PointerInputStream& istream, PixelDecoder& decode, RGBAImage& image, const Flip11& ){ + RGBAPixel* end = image.pixels + ( image.height * image.width ); + for ( RGBAPixel* row = image.pixels; row != end; row += image.width ) + { + for ( RGBAPixel* pixel = row + image.width; pixel != row; ) + { + decode( istream, *--pixel ); + } + } } -inline void istream_read_gray(PointerInputStream& istream, RGBAPixel& pixel) -{ - istream.read(&pixel.blue, 1); - pixel.red = pixel.green = pixel.blue; - pixel.alpha = 0xff; +inline void istream_read_gray( PointerInputStream& istream, RGBAPixel& pixel ){ + istream.read( &pixel.blue, 1 ); + pixel.red = pixel.green = pixel.blue; + pixel.alpha = 0xff; } -inline void istream_read_rgb(PointerInputStream& istream, RGBAPixel& pixel) -{ - istream.read(&pixel.blue, 1); - istream.read(&pixel.green, 1); - istream.read(&pixel.red, 1); - pixel.alpha = 0xff; +inline void istream_read_rgb( PointerInputStream& istream, RGBAPixel& pixel ){ + istream.read( &pixel.blue, 1 ); + istream.read( &pixel.green, 1 ); + istream.read( &pixel.red, 1 ); + pixel.alpha = 0xff; } -inline void istream_read_rgba(PointerInputStream& istream, RGBAPixel& pixel) -{ - istream.read(&pixel.blue, 1); - istream.read(&pixel.green, 1); - istream.read(&pixel.red, 1); - istream.read(&pixel.alpha, 1); +inline void istream_read_rgba( PointerInputStream& istream, RGBAPixel& pixel ){ + istream.read( &pixel.blue, 1 ); + istream.read( &pixel.green, 1 ); + istream.read( &pixel.red, 1 ); + istream.read( &pixel.alpha, 1 ); } class TargaDecodeGrayPixel { public: - void operator()(PointerInputStream& istream, RGBAPixel& pixel) - { - istream_read_gray(istream, pixel); - } +void operator()( PointerInputStream& istream, RGBAPixel& pixel ){ + istream_read_gray( istream, pixel ); +} }; template -void targa_decode_grayscale(PointerInputStream& istream, RGBAImage& image, const Flip& flip) -{ - TargaDecodeGrayPixel decode; - image_decode(istream, decode, image, flip); +void targa_decode_grayscale( PointerInputStream& istream, RGBAImage& image, const Flip& flip ){ + TargaDecodeGrayPixel decode; + image_decode( istream, decode, image, flip ); } class TargaDecodeRGBPixel { public: - void operator()(PointerInputStream& istream, RGBAPixel& pixel) - { - istream_read_rgb(istream, pixel); - } +void operator()( PointerInputStream& istream, RGBAPixel& pixel ){ + istream_read_rgb( istream, pixel ); +} }; template -void targa_decode_rgb(PointerInputStream& istream, RGBAImage& image, const Flip& flip) -{ - TargaDecodeRGBPixel decode; - image_decode(istream, decode, image, flip); +void targa_decode_rgb( PointerInputStream& istream, RGBAImage& image, const Flip& flip ){ + TargaDecodeRGBPixel decode; + image_decode( istream, decode, image, flip ); } class TargaDecodeRGBAPixel { public: - void operator()(PointerInputStream& istream, RGBAPixel& pixel) - { - istream_read_rgba(istream, pixel); - } +void operator()( PointerInputStream& istream, RGBAPixel& pixel ){ + istream_read_rgba( istream, pixel ); +} }; template -void targa_decode_rgba(PointerInputStream& istream, RGBAImage& image, const Flip& flip) -{ - TargaDecodeRGBAPixel decode; - image_decode(istream, decode, image, flip); +void targa_decode_rgba( PointerInputStream& istream, RGBAImage& image, const Flip& flip ){ + TargaDecodeRGBAPixel decode; + image_decode( istream, decode, image, flip ); } typedef byte TargaPacket; typedef byte TargaPacketSize; -inline void targa_packet_read_istream(TargaPacket& packet, PointerInputStream& istream) -{ - istream.read(&packet, 1); +inline void targa_packet_read_istream( TargaPacket& packet, PointerInputStream& istream ){ + istream.read( &packet, 1 ); } -inline bool targa_packet_is_rle(const TargaPacket& packet) -{ - return (packet & 0x80) != 0; +inline bool targa_packet_is_rle( const TargaPacket& packet ){ + return ( packet & 0x80 ) != 0; } -inline TargaPacketSize targa_packet_size(const TargaPacket& packet) +inline TargaPacketSize targa_packet_size( const TargaPacket& packet ){ + return 1 + ( packet & 0x7f ); +} + + +class TargaDecodeGrayPixelRLE { - return 1 + (packet & 0x7f); +TargaPacketSize m_packetSize; +RGBAPixel m_pixel; +TargaPacket m_packet; +public: +TargaDecodeGrayPixelRLE() : m_packetSize( 0 ){ } +void operator()( PointerInputStream& istream, RGBAPixel& pixel ){ + if ( m_packetSize == 0 ) { + targa_packet_read_istream( m_packet, istream ); + m_packetSize = targa_packet_size( m_packet ); + + if ( targa_packet_is_rle( m_packet ) ) { + istream_read_gray( istream, m_pixel ); + } + } + + if ( targa_packet_is_rle( m_packet ) ) { + pixel = m_pixel; + } + else + { + istream_read_gray( istream, pixel ); + } + + --m_packetSize; +} +}; +template +void targa_decode_rle_grayscale( PointerInputStream& istream, RGBAImage& image, const Flip& flip ){ + TargaDecodeGrayPixelRLE decode; + image_decode( istream, decode, image, flip ); +} class TargaDecodeRGBPixelRLE { - TargaPacketSize m_packetSize; - RGBAPixel m_pixel; - TargaPacket m_packet; +TargaPacketSize m_packetSize; +RGBAPixel m_pixel; +TargaPacket m_packet; public: - TargaDecodeRGBPixelRLE() : m_packetSize(0) - { - } - void operator()(PointerInputStream& istream, RGBAPixel& pixel) - { - if(m_packetSize == 0) - { - targa_packet_read_istream(m_packet, istream); - m_packetSize = targa_packet_size(m_packet); - - if(targa_packet_is_rle(m_packet)) - { - istream_read_rgb(istream, m_pixel); - } - } - - if(targa_packet_is_rle(m_packet)) - { - pixel = m_pixel; - } - else - { - istream_read_rgb(istream, pixel); - } - - --m_packetSize; - } +TargaDecodeRGBPixelRLE() : m_packetSize( 0 ){ +} +void operator()( PointerInputStream& istream, RGBAPixel& pixel ){ + if ( m_packetSize == 0 ) { + targa_packet_read_istream( m_packet, istream ); + m_packetSize = targa_packet_size( m_packet ); + + if ( targa_packet_is_rle( m_packet ) ) { + istream_read_rgb( istream, m_pixel ); + } + } + + if ( targa_packet_is_rle( m_packet ) ) { + pixel = m_pixel; + } + else + { + istream_read_rgb( istream, pixel ); + } + + --m_packetSize; +} }; template -void targa_decode_rle_rgb(PointerInputStream& istream, RGBAImage& image, const Flip& flip) -{ +void targa_decode_rle_rgb( PointerInputStream& istream, RGBAImage& image, const Flip& flip ){ TargaDecodeRGBPixelRLE decode; - image_decode(istream, decode, image, flip); + image_decode( istream, decode, image, flip ); } class TargaDecodeRGBAPixelRLE { - TargaPacketSize m_packetSize; - RGBAPixel m_pixel; - TargaPacket m_packet; +TargaPacketSize m_packetSize; +RGBAPixel m_pixel; +TargaPacket m_packet; public: - TargaDecodeRGBAPixelRLE() : m_packetSize(0) - { - } - void operator()(PointerInputStream& istream, RGBAPixel& pixel) - { - if(m_packetSize == 0) - { - targa_packet_read_istream(m_packet, istream); - m_packetSize = targa_packet_size(m_packet); - - if(targa_packet_is_rle(m_packet)) - { - istream_read_rgba(istream, m_pixel); - } - } - - if(targa_packet_is_rle(m_packet)) - { - pixel = m_pixel; - } - else - { - istream_read_rgba(istream, pixel); - } - - --m_packetSize; - } +TargaDecodeRGBAPixelRLE() : m_packetSize( 0 ){ +} +void operator()( PointerInputStream& istream, RGBAPixel& pixel ){ + if ( m_packetSize == 0 ) { + targa_packet_read_istream( m_packet, istream ); + m_packetSize = targa_packet_size( m_packet ); + + if ( targa_packet_is_rle( m_packet ) ) { + istream_read_rgba( istream, m_pixel ); + } + } + + if ( targa_packet_is_rle( m_packet ) ) { + pixel = m_pixel; + } + else + { + istream_read_rgba( istream, pixel ); + } + + --m_packetSize; +} }; template -void targa_decode_rle_rgba(PointerInputStream& istream, RGBAImage& image, const Flip& flip) -{ +void targa_decode_rle_rgba( PointerInputStream& istream, RGBAImage& image, const Flip& flip ){ TargaDecodeRGBAPixelRLE decode; - image_decode(istream, decode, image, flip); + image_decode( istream, decode, image, flip ); } struct TargaHeader { - unsigned char id_length, colormap_type, image_type; - unsigned short colormap_index, colormap_length; - unsigned char colormap_size; - unsigned short x_origin, y_origin, width, height; - unsigned char pixel_size, attributes; + unsigned char id_length, colormap_type, image_type; + unsigned short colormap_index, colormap_length; + unsigned char colormap_size; + unsigned short x_origin, y_origin, width, height; + unsigned char pixel_size, attributes; }; -inline void targa_header_read_istream(TargaHeader& targa_header, PointerInputStream& istream) -{ - targa_header.id_length = istream_read_byte(istream); - targa_header.colormap_type = istream_read_byte(istream); - targa_header.image_type = istream_read_byte(istream); - - targa_header.colormap_index = istream_read_int16_le(istream); - targa_header.colormap_length = istream_read_int16_le(istream); - targa_header.colormap_size = istream_read_byte(istream); - targa_header.x_origin = istream_read_int16_le(istream); - targa_header.y_origin = istream_read_int16_le(istream); - targa_header.width = istream_read_int16_le(istream); - targa_header.height = istream_read_int16_le(istream); - targa_header.pixel_size = istream_read_byte(istream); - targa_header.attributes = istream_read_byte(istream); - - if (targa_header.id_length != 0) - istream.seek(targa_header.id_length); // skip TARGA image comment +inline void targa_header_read_istream( TargaHeader& targa_header, PointerInputStream& istream ){ + targa_header.id_length = istream_read_byte( istream ); + targa_header.colormap_type = istream_read_byte( istream ); + targa_header.image_type = istream_read_byte( istream ); + + targa_header.colormap_index = istream_read_int16_le( istream ); + targa_header.colormap_length = istream_read_int16_le( istream ); + targa_header.colormap_size = istream_read_byte( istream ); + targa_header.x_origin = istream_read_int16_le( istream ); + targa_header.y_origin = istream_read_int16_le( istream ); + targa_header.width = istream_read_int16_le( istream ); + targa_header.height = istream_read_int16_le( istream ); + targa_header.pixel_size = istream_read_byte( istream ); + targa_header.attributes = istream_read_byte( istream ); + + if ( targa_header.id_length != 0 ) { + istream.seek( targa_header.id_length ); // skip TARGA image comment + } } template class ScopeDelete { - Type* m_value; - ScopeDelete(const ScopeDelete&); - ScopeDelete& operator=(const ScopeDelete&); +Type* m_value; +ScopeDelete( const ScopeDelete& ); +ScopeDelete& operator=( const ScopeDelete& ); public: - ScopeDelete(Type* value) : m_value(value) - { - } - ~ScopeDelete() - { - delete m_value; - } - Type* get_pointer() const - { - return m_value; - } +ScopeDelete( Type* value ) : m_value( value ){ +} +~ScopeDelete(){ + delete m_value; +} +Type* get_pointer() const { + return m_value; +} }; template -Image* Targa_decodeImageData(const TargaHeader& targa_header, PointerInputStream& istream, const Flip& flip) -{ - RGBAImage* image = new RGBAImage(targa_header.width, targa_header.height); - - if (targa_header.image_type == 2 || targa_header.image_type == 3) - { - switch (targa_header.pixel_size) - { - case 8: - targa_decode_grayscale(istream, *image, flip); - break; - case 24: - targa_decode_rgb(istream, *image, flip); - break; - case 32: - targa_decode_rgba(istream, *image, flip); - break; - default: - globalErrorStream() << "LoadTGA: illegal pixel_size '" << targa_header.pixel_size << "'\n"; - image->release(); - return 0; - } - } - else if (targa_header.image_type == 10) - { - switch (targa_header.pixel_size) - { - case 24: - targa_decode_rle_rgb(istream, *image, flip); - break; - case 32: - targa_decode_rle_rgba(istream, *image, flip); - break; - default: - globalErrorStream() << "LoadTGA: illegal pixel_size '" << targa_header.pixel_size << "'\n"; - image->release(); - return 0; - } - } - - return image; +Image* Targa_decodeImageData( const TargaHeader& targa_header, PointerInputStream& istream, const Flip& flip ){ + RGBAImage* image = new RGBAImage( targa_header.width, targa_header.height ); + + if ( targa_header.image_type == 2 || targa_header.image_type == 3 ) { + switch ( targa_header.pixel_size ) + { + case 8: + targa_decode_grayscale( istream, *image, flip ); + break; + case 24: + targa_decode_rgb( istream, *image, flip ); + break; + case 32: + targa_decode_rgba( istream, *image, flip ); + break; + default: + globalErrorStream() << "LoadTGA: illegal pixel_size '" << targa_header.pixel_size << "'\n"; + image->release(); + return 0; + } + } + else if ( targa_header.image_type == 10 || targa_header.image_type == 11 ) { + switch ( targa_header.pixel_size ) + { + case 8: + targa_decode_rle_grayscale( istream, *image, flip ); + break; + case 24: + targa_decode_rle_rgb( istream, *image, flip ); + break; + case 32: + targa_decode_rle_rgba( istream, *image, flip ); + break; + default: + globalErrorStream() << "LoadTGA: illegal pixel_size '" << targa_header.pixel_size << "'\n"; + image->release(); + return 0; + } + } + + return image; } const unsigned int TGA_FLIP_HORIZONTAL = 0x10; const unsigned int TGA_FLIP_VERTICAL = 0x20; -Image* LoadTGABuff(const byte* buffer) -{ - PointerInputStream istream(buffer); - TargaHeader targa_header; - - targa_header_read_istream(targa_header, istream); - - if (targa_header.image_type != 2 && targa_header.image_type != 10 && targa_header.image_type != 3) - { - globalErrorStream() << "LoadTGA: TGA type " << targa_header.image_type << " not supported\n"; - globalErrorStream() << "LoadTGA: Only type 2 (RGB), 3 (gray), and 10 (RGB) TGA images supported\n"; - return 0; - } - - if (targa_header.colormap_type != 0) - { - globalErrorStream() << "LoadTGA: colormaps not supported\n"; - return 0; - } - - if ((targa_header.pixel_size != 32 && targa_header.pixel_size != 24) - && targa_header.image_type != 3) - { - globalErrorStream() << "LoadTGA: Only 32 or 24 bit images supported\n"; - return 0; - } - - if(!bitfield_enabled(targa_header.attributes, TGA_FLIP_HORIZONTAL) - && !bitfield_enabled(targa_header.attributes, TGA_FLIP_VERTICAL)) - { - return Targa_decodeImageData(targa_header, istream, Flip00()); - } - if(!bitfield_enabled(targa_header.attributes, TGA_FLIP_HORIZONTAL) - && bitfield_enabled(targa_header.attributes, TGA_FLIP_VERTICAL)) - { - return Targa_decodeImageData(targa_header, istream, Flip01()); - } - if(bitfield_enabled(targa_header.attributes, TGA_FLIP_HORIZONTAL) - && !bitfield_enabled(targa_header.attributes, TGA_FLIP_VERTICAL)) - { - return Targa_decodeImageData(targa_header, istream, Flip10()); - } - if(bitfield_enabled(targa_header.attributes, TGA_FLIP_HORIZONTAL) - && bitfield_enabled(targa_header.attributes, TGA_FLIP_VERTICAL)) - { - return Targa_decodeImageData(targa_header, istream, Flip11()); - } - - // unreachable - return 0; +Image* LoadTGABuff( const byte* buffer ){ + PointerInputStream istream( buffer ); + TargaHeader targa_header; + + targa_header_read_istream( targa_header, istream ); + + if ( targa_header.image_type != 2 && targa_header.image_type != 10 && targa_header.image_type != 3 && targa_header.image_type != 11 ) { + globalErrorStream() << "LoadTGA: TGA type " << targa_header.image_type << " not supported\n"; + globalErrorStream() << "LoadTGA: Only type 2 (RGB), 3 (gray), 10 (RGB), and 11 (gray) TGA images supported\n"; + return 0; + } + + if ( targa_header.colormap_type != 0 ) { + globalErrorStream() << "LoadTGA: colormaps not supported\n"; + return 0; + } + + if ( ( ( targa_header.image_type == 2 || targa_header.image_type == 10 ) && targa_header.pixel_size != 32 && targa_header.pixel_size != 24 ) || + ( ( targa_header.image_type == 3 || targa_header.image_type == 11 ) && targa_header.pixel_size != 8 ) ) { + globalErrorStream() << "LoadTGA: Only 32, 24 or 8 bit images supported\n"; + return 0; + } + + if ( !bitfield_enabled( targa_header.attributes, TGA_FLIP_HORIZONTAL ) + && !bitfield_enabled( targa_header.attributes, TGA_FLIP_VERTICAL ) ) { + return Targa_decodeImageData( targa_header, istream, Flip00() ); + } + if ( !bitfield_enabled( targa_header.attributes, TGA_FLIP_HORIZONTAL ) + && bitfield_enabled( targa_header.attributes, TGA_FLIP_VERTICAL ) ) { + return Targa_decodeImageData( targa_header, istream, Flip01() ); + } + if ( bitfield_enabled( targa_header.attributes, TGA_FLIP_HORIZONTAL ) + && !bitfield_enabled( targa_header.attributes, TGA_FLIP_VERTICAL ) ) { + return Targa_decodeImageData( targa_header, istream, Flip10() ); + } + if ( bitfield_enabled( targa_header.attributes, TGA_FLIP_HORIZONTAL ) + && bitfield_enabled( targa_header.attributes, TGA_FLIP_VERTICAL ) ) { + return Targa_decodeImageData( targa_header, istream, Flip11() ); + } + + // unreachable + return 0; } -Image* LoadTGA(ArchiveFile& file) -{ - ScopedArchiveBuffer buffer(file); - return LoadTGABuff(buffer.buffer); -} +Image* LoadTGA( ArchiveFile& file ){ + ScopedArchiveBuffer buffer( file ); + return LoadTGABuff( buffer.buffer ); +} \ No newline at end of file