Alien-FreeImage

 view release on metacpan or  search on metacpan

src/Source/FreeImage/PluginTARGA.cpp  view on Meta::CPAN

// ==========================================================
// TARGA Loader and Writer
//
// Design and implementation by
// - Floris van den Berg (flvdberg@wxs.nl)
// - Jani Kajala (janik@remedy.fi)
// - Martin Weber (martweb@gmx.net)
// - Machiel ten Brinke (brinkem@uni-one.nl)
// - Peter Lemmens (peter.lemmens@planetinternet.be)
// - Hervé Drolon (drolon@infonie.fr)
// - Mihail Naydenov (mnaydenov@users.sourceforge.net)
//
// This file is part of FreeImage 3
//
// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
// THIS DISCLAIMER.
//
// Use at your own risk!
// ==========================================================

#include "FreeImage.h"
#include "Utilities.h"

// ----------------------------------------------------------
//   Constants + headers
// ----------------------------------------------------------

#ifdef _WIN32
#pragma pack(push, 1)
#else
#pragma pack(1)
#endif

typedef struct tagTGAHEADER {
	BYTE id_length;				//! length of the image ID field
	BYTE color_map_type;		//! whether a color map is included
	BYTE image_type;			//! compression and color types

	WORD cm_first_entry;		//! first entry index (offset into the color map table)
	WORD cm_length;				//! color map length (number of entries)
	BYTE cm_size;				//! color map entry size, in bits (number of bits per pixel)

	WORD is_xorigin;			//! X-origin of image (absolute coordinate of lower-left corner for displays where origin is at the lower left)
	WORD is_yorigin;			//! Y-origin of image (as for X-origin)
	WORD is_width;				//! image width
	WORD is_height;				//! image height
	BYTE is_pixel_depth;		//! bits per pixel
	BYTE is_image_descriptor;	//! image descriptor, bits 3-0 give the alpha channel depth, bits 5-4 give direction
} TGAHEADER;

typedef struct tagTGAEXTENSIONAREA {
	WORD extension_size;		// Size in bytes of the extension area, always 495
	char author_name[41];		// Name of the author. If not used, bytes should be set to NULL (\0) or spaces
	char author_comments[324];	// A comment, organized as four lines, each consisting of 80 characters plus a NULL
	WORD datetime_stamp[6];		// Date and time at which the image was created
	char job_name[41];			// Job ID
	WORD job_time[3];			// Hours, minutes and seconds spent creating the file (for billing, etc.)
	char software_id[41];		// The application that created the file
	BYTE software_version[3];
	DWORD key_color;
	WORD pixel_aspect_ratio[2];
	WORD gamma_value[2];
	DWORD color_correction_offset;	// Number of bytes from the beginning of the file to the color correction table if present
	DWORD postage_stamp_offset;		// Number of bytes from the beginning of the file to the postage stamp image if present
	DWORD scan_line_offset;			// Number of bytes from the beginning of the file to the scan lines table if present
	BYTE attributes_type;			// Specifies the alpha channel
} TGAEXTENSIONAREA;

typedef struct tagTGAFOOTER {
	DWORD extension_offset;	// extension area offset : offset in bytes from the beginning of the file
	DWORD developer_offset;	// developer directory offset : offset in bytes from the beginning of the file
	char signature[18];		// signature string : contains "TRUEVISION-XFILE.\0"
} TGAFOOTER;

#ifdef _WIN32
#pragma pack(pop)
#else
#pragma pack()
#endif

static const char *FI_MSG_ERROR_CORRUPTED = "Image data corrupted";

// ----------------------------------------------------------
// Image type
//
#define TGA_NULL		0	// no image data included
#define TGA_CMAP		1	// uncompressed, color-mapped image
#define TGA_RGB			2	// uncompressed, true-color image
#define TGA_MONO		3	// uncompressed, black-and-white image
#define TGA_RLECMAP		9	// run-length encoded, color-mapped image
#define TGA_RLERGB		10	// run-length encoded, true-color image
#define TGA_RLEMONO		11	// run-length encoded, black-and-white image
#define TGA_CMPCMAP		32	// compressed (Huffman/Delta/RLE) color-mapped image (e.g., VDA/D) - Obsolete
#define TGA_CMPCMAP4	33	// compressed (Huffman/Delta/RLE) color-mapped four pass image (e.g., VDA/D) - Obsolete

// ==========================================================
// Thumbnail functions
// ==========================================================

class TargaThumbnail
{
public:
	TargaThumbnail() : _w(0), _h(0), _depth(0), _data(NULL) { 
	}

src/Source/FreeImage/PluginTARGA.cpp  view on Meta::CPAN

	BOOL isNull() { return _begin == NULL;}
	
	inline
	BYTE getByte() {
		if (_ptr >= _end) {
			// need refill
			_ptr = _begin;
			_io->read_proc(_ptr, sizeof(BYTE), (unsigned)_size, _handle);	//### EOF - no problem?
		}

		BYTE result = *_ptr;

		_ptr++;

		return result;
	}
	
	inline
	BYTE* getBytes(size_t count /*must be < _size!*/) {
		if (_ptr + count >= _end) {
			
			// need refill

			// 'count' bytes might span two cache bounds,
			// SEEK back to add the remains of the current cache again into the new one

			long read = long(_ptr - _begin);
			long remaining = long(_size - read);

			_io->seek_proc(_handle, -remaining, SEEK_CUR);

			_ptr = _begin;
			_io->read_proc(_ptr, sizeof(BYTE), (unsigned)_size, _handle);	//### EOF - no problem?
		}

		BYTE *result = _ptr;

		_ptr += count;

		return result;
	}

private:
	IOCache& operator=(const IOCache& src); // deleted
	IOCache(const IOCache& other); // deleted

private:
	BYTE *_ptr;
	BYTE *_begin;
	BYTE *_end;
	const size_t _size;
	const FreeImageIO *_io;	
	const fi_handle _handle;	
};

#ifdef FREEIMAGE_BIGENDIAN
static void
SwapHeader(TGAHEADER *header) {
	SwapShort(&header->cm_first_entry);
	SwapShort(&header->cm_length);
	SwapShort(&header->is_xorigin);
	SwapShort(&header->is_yorigin);
	SwapShort(&header->is_width);
	SwapShort(&header->is_height);
}

static void
SwapExtensionArea(TGAEXTENSIONAREA *ex) {
	SwapShort(&ex->extension_size);
	SwapShort(&ex->datetime_stamp[0]);
	SwapShort(&ex->datetime_stamp[1]);
	SwapShort(&ex->datetime_stamp[2]);
	SwapShort(&ex->datetime_stamp[3]);
	SwapShort(&ex->datetime_stamp[4]);
	SwapShort(&ex->datetime_stamp[5]);
	SwapShort(&ex->job_time[0]);
	SwapShort(&ex->job_time[1]);
	SwapShort(&ex->job_time[2]);
	SwapLong (&ex->key_color);
	SwapShort(&ex->pixel_aspect_ratio[0]);
	SwapShort(&ex->pixel_aspect_ratio[1]);
	SwapShort(&ex->gamma_value[0]);
	SwapShort(&ex->gamma_value[1]);
	SwapLong (&ex->color_correction_offset);
	SwapLong (&ex->postage_stamp_offset);
	SwapLong (&ex->scan_line_offset);
}

static void
SwapFooter(TGAFOOTER *footer) {
	SwapLong(&footer->extension_offset);
	SwapLong(&footer->developer_offset);
}

#endif // FREEIMAGE_BIGENDIAN

// ==========================================================
// Plugin Interface
// ==========================================================

static int s_format_id;

// ==========================================================
// Plugin Implementation
// ==========================================================

static const char * DLL_CALLCONV
Format() {
	return "TARGA";
}

static const char * DLL_CALLCONV
Description() {
	return "Truevision Targa";
}

static const char * DLL_CALLCONV
Extension() {
	return "tga,targa";
}

static const char * DLL_CALLCONV

src/Source/FreeImage/PluginTARGA.cpp  view on Meta::CPAN

			} else {

				// no rle

				if(has_rle) {
					// flush rle packet

					// include current pixel first
					assert(packet_count < max_packet_size);
					++packet_count;

					flushPacket(line, pixel_size, packet_begin, packet, packet_count, has_rle);

					// start anew on the next pixel
					continue;

				} else {

					writeToPacket(packet, current, pixel_size);
					packet += pixel_size;
				}

			}

			// increase counter on every pixel

			++packet_count;

			if(packet_count == max_packet_size) {
				flushPacket(line, pixel_size, packet_begin, packet, packet_count, has_rle);
			}

		}//for width

		// write line to disk
		io->write_proc(line_begin, 1, (unsigned)(line - line_begin), handle);

	}//for height

	free(line_begin);
	free(packet_begin);
	free(current);
	free(next);
}

static BOOL DLL_CALLCONV
Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
	if ((dib == NULL) || (handle == NULL)) {
		return FALSE;
	}

	RGBQUAD *palette = FreeImage_GetPalette(dib);
	const unsigned bpp = FreeImage_GetBPP(dib);

	// write the file header

	TGAHEADER header;

	header.id_length = 0;
	header.cm_first_entry = 0;
	header.is_xorigin = 0;
	header.is_yorigin = 0;
	header.is_width = (WORD)FreeImage_GetWidth(dib);
	header.is_height = (WORD)FreeImage_GetHeight(dib);
	header.is_pixel_depth = (BYTE)bpp;
	header.is_image_descriptor = (bpp == 32 ? 8 : 0);

	if (palette) {
		header.color_map_type = 1;
		header.image_type = (TARGA_SAVE_RLE & flags) ? TGA_RLECMAP : TGA_CMAP;
		header.cm_length = (WORD)(1 << bpp);

		if (FreeImage_IsTransparent(dib)) {
			header.cm_size = 32;
		} else {
			header.cm_size = 24;
		}

	} else {
		header.color_map_type = 0;
		header.image_type = (TARGA_SAVE_RLE & flags) ? TGA_RLERGB : TGA_RGB;
		header.cm_length = 0;
		header.cm_size = 0;
	}

	// write the header

#ifdef FREEIMAGE_BIGENDIAN
	SwapHeader(&header);
#endif

	io->write_proc(&header, sizeof(header), 1, handle);

#ifdef FREEIMAGE_BIGENDIAN
	SwapHeader(&header);
#endif

	// write the palette

	if (palette) {
		if (FreeImage_IsTransparent(dib)) {
			FILE_BGRA *bgra_pal = (FILE_BGRA*)malloc(header.cm_length * sizeof(FILE_BGRA));

			// get the transparency table
			BYTE *trns = FreeImage_GetTransparencyTable(dib);

			for (unsigned i = 0; i < header.cm_length; i++) {
				bgra_pal[i].b = palette[i].rgbBlue;
				bgra_pal[i].g = palette[i].rgbGreen;
				bgra_pal[i].r = palette[i].rgbRed;
				bgra_pal[i].a = trns[i];
			}

			io->write_proc(bgra_pal, sizeof(FILE_BGRA), header.cm_length, handle);

			free(bgra_pal);

		} else {
			FILE_BGR *bgr_pal = (FILE_BGR*)malloc(header.cm_length * sizeof(FILE_BGR));

			for (unsigned i = 0; i < header.cm_length; i++) {
				bgr_pal[i].b = palette[i].rgbBlue;



( run in 0.468 second using v1.01-cache-2.11-cpan-5623c5533a1 )