Alien-FreeImage

 view release on metacpan or  search on metacpan

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


			// read a pixel value from file...
			BYTE *val = cache.getBytes(file_pixel_size);

			//...and fill packet_count pixels with it

			for (int ix = 0; ix < packet_count; ix++) {
				_assignPixel<bPP>((line_bits+x), val, as24bit);
				x += pixel_size;

				if (x >= line_size) {
					x = 0;
					y++;
					line_bits = FreeImage_GetScanLine(dib, y);
				}
			}

		} else {
			// no rle commpresion

			// copy packet_count pixels from file to dib
			for (int ix = 0; ix < packet_count; ix++) {
				BYTE *val = cache.getBytes(file_pixel_size);
				_assignPixel<bPP>((line_bits+x), val, as24bit);
				x += pixel_size;

				if (x >= line_size) {
					x = 0;
					y++;
					line_bits = FreeImage_GetScanLine(dib, y);
				}
			} //< packet_count
		} //< has_rle

	} //< while height

}

// --------------------------------------------------------------------------

static FIBITMAP * DLL_CALLCONV
Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
	FIBITMAP *dib = NULL;

	if (!handle) {
		return NULL;
	}

	try {
		
		const BOOL header_only =  (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS;
				
		// remember the start offset
		long start_offset = io->tell_proc(handle);

		// remember end-of-file (used for RLE cache)
		io->seek_proc(handle, 0, SEEK_END);
		long eof = io->tell_proc(handle);
		io->seek_proc(handle, start_offset, SEEK_SET);

		// read and process the bitmap's footer

		TargaThumbnail thumbnail;
		if(isTARGA20(io, handle)) {
			TGAFOOTER footer;
			const long footer_offset = start_offset + eof - sizeof(footer);
			
			io->seek_proc(handle, footer_offset, SEEK_SET);
			io->read_proc(&footer, sizeof(tagTGAFOOTER), 1, handle);
			
#ifdef FREEIMAGE_BIGENDIAN
			SwapFooter(&footer);
#endif
			BOOL hasExtensionArea = footer.extension_offset > 0;
			if(hasExtensionArea) { 
				TGAEXTENSIONAREA extensionarea;
				io->seek_proc(handle, footer.extension_offset, SEEK_SET);
				io->read_proc(&extensionarea, sizeof(extensionarea), 1, handle);
				
#ifdef FREEIMAGE_BIGENDIAN
				SwapExtensionArea(&extensionarea);
#endif

				DWORD postage_stamp_offset = extensionarea.postage_stamp_offset;
				BOOL hasThumbnail = (postage_stamp_offset > 0) && (postage_stamp_offset < (DWORD)footer_offset);
				if(hasThumbnail) {
					io->seek_proc(handle, postage_stamp_offset, SEEK_SET);
					thumbnail.read(io, handle, footer_offset - postage_stamp_offset);
				}
			}
		}
		
		// read and process the bitmap's header

		TGAHEADER header;

		io->seek_proc(handle, start_offset, SEEK_SET);
		io->read_proc(&header, sizeof(tagTGAHEADER), 1, handle);

#ifdef FREEIMAGE_BIGENDIAN
		SwapHeader(&header);
#endif

		thumbnail.setDepth(header.is_pixel_depth);
			
		const int line = CalculateLine(header.is_width, header.is_pixel_depth);
		const int pixel_bits = header.is_pixel_depth;
		const int pixel_size = pixel_bits/8;

		int fliphoriz = (header.is_image_descriptor & 0x10) ? 1 : 0;
		int flipvert = (header.is_image_descriptor & 0x20) ? 1 : 0;

		// skip comment
		io->seek_proc(handle, header.id_length, SEEK_CUR);

		switch (header.is_pixel_depth) {
			case 8 : {
				dib = FreeImage_AllocateHeader(header_only, header.is_width, header.is_height, 8);
				
				if (dib == NULL) {
					throw FI_MSG_ERROR_DIB_MEMORY;
				}
					
				// read the palette (even if header only)

				RGBQUAD *palette = FreeImage_GetPalette(dib);

				if (header.color_map_type > 0) {
					unsigned count, csize;

					// calculate the color map size
					csize = header.cm_length * header.cm_size / 8;
					
					// read the color map
					BYTE *cmap = (BYTE*)malloc(csize * sizeof(BYTE));
					if (cmap == NULL) {
						throw FI_MSG_ERROR_DIB_MEMORY;
					}
					io->read_proc(cmap, sizeof(BYTE), csize, handle);

					// build the palette

					switch (header.cm_size) {
						case 16: {
							WORD *rgb555 = (WORD*)&cmap[0];
							unsigned start = (unsigned)header.cm_first_entry;
							unsigned stop = MIN((unsigned)256, (unsigned)header.cm_length);

							for (count = start; count < stop; count++) {
								palette[count].rgbRed   = (BYTE)((((*rgb555 & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) * 0xFF) / 0x1F);
								palette[count].rgbGreen = (BYTE)((((*rgb555 & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) * 0xFF) / 0x1F);
								palette[count].rgbBlue  = (BYTE)((((*rgb555 & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) * 0xFF) / 0x1F);
								rgb555++;



( run in 0.436 second using v1.01-cache-2.11-cpan-ceb78f64989 )