Alien-FreeImage

 view release on metacpan or  search on metacpan

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

#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
	if (bit_count == 24) {
		FILE_BGR bgr;
		for(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) {
			BYTE *line = FreeImage_GetScanLine(dib, y);
			for(unsigned x = 0; x < FreeImage_GetWidth(dib); x++) {
				RGBTRIPLE *triple = ((RGBTRIPLE *)line)+x;
				bgr.b = triple->rgbtBlue;
				bgr.g = triple->rgbtGreen;
				bgr.r = triple->rgbtRed;
				if (io->write_proc(&bgr, sizeof(FILE_BGR), 1, handle) != 1)
					return FALSE;
			}
		}
	} else if (bit_count == 32) {
		FILE_BGRA bgra;
		for(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) {
			BYTE *line = FreeImage_GetScanLine(dib, y);
			for(unsigned x = 0; x < FreeImage_GetWidth(dib); x++) {
				RGBQUAD *quad = ((RGBQUAD *)line)+x;
				bgra.b = quad->rgbBlue;
				bgra.g = quad->rgbGreen;
				bgra.r = quad->rgbRed;
				bgra.a = quad->rgbReserved;
				if (io->write_proc(&bgra, sizeof(FILE_BGRA), 1, handle) != 1)
					return FALSE;
			}
		}
	} else
#endif
#if defined(FREEIMAGE_BIGENDIAN) || FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
	{
#endif
		BYTE *xor_mask = FreeImage_GetBits(dib);
		io->write_proc(xor_mask, size_xor, 1, handle);
#if defined(FREEIMAGE_BIGENDIAN) || FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
	}
#endif
	// AND mask
	BYTE *and_mask = (BYTE*)malloc(size_and);
	if(!and_mask) {
		return FALSE;
	}

	if(FreeImage_IsTransparent(dib)) {

		if(bit_count == 32) {
			// create the AND mask from the alpha channel

			int width_and  = WidthBytes(width);
			BYTE *and_bits = and_mask;

			// clear the mask
			memset(and_mask, 0, size_and);

			for(int y = 0; y < height; y++) {
				RGBQUAD *bits = (RGBQUAD*)FreeImage_GetScanLine(dib, y);

				for(int x = 0; x < width; x++) {
					if(bits[x].rgbReserved != 0xFF) {
						// set any transparent color to full transparency
						and_bits[x >> 3] |= (0x80 >> (x & 0x7)); 
					}
				}

				and_bits += width_and;
			}
		} 
		else if(bit_count <= 8) {
			// create the AND mask from the transparency table

			BYTE *trns = FreeImage_GetTransparencyTable(dib);

			int width_and  = WidthBytes(width);
			BYTE *and_bits = and_mask;

			// clear the mask
			memset(and_mask, 0, size_and);

			switch(FreeImage_GetBPP(dib)) {
				case 1:
				{
					for(int y = 0; y < height; y++) {
						BYTE *bits = (BYTE*)FreeImage_GetScanLine(dib, y);
						for(int x = 0; x < width; x++) {
							// get pixel at (x, y)
							BYTE index = (bits[x >> 3] & (0x80 >> (x & 0x07))) != 0;
							if(trns[index] != 0xFF) {
								// set any transparent color to full transparency
								and_bits[x >> 3] |= (0x80 >> (x & 0x7)); 
							}
						}
						and_bits += width_and;
					}
				}
				break;

				case 4:
				{
					for(int y = 0; y < height; y++) {
						BYTE *bits = (BYTE*)FreeImage_GetScanLine(dib, y);
						for(int x = 0; x < width; x++) {
							// get pixel at (x, y)
							BYTE shift = (BYTE)((1 - x % 2) << 2);
							BYTE index = (bits[x >> 1] & (0x0F << shift)) >> shift;
							if(trns[index] != 0xFF) {
								// set any transparent color to full transparency
								and_bits[x >> 3] |= (0x80 >> (x & 0x7)); 
							}
						}
						and_bits += width_and;
					}
				}
				break;

				case 8:
				{
					for(int y = 0; y < height; y++) {
						BYTE *bits = (BYTE*)FreeImage_GetScanLine(dib, y);
						for(int x = 0; x < width; x++) {
							// get pixel at (x, y)
							BYTE index = bits[x];
							if(trns[index] != 0xFF) {
								// set any transparent color to full transparency
								and_bits[x >> 3] |= (0x80 >> (x & 0x7)); 
							}
						}
						and_bits += width_and;
					}
				}
				break;

			}
		}
	}
	else {
		// empty AND mask
		memset(and_mask, 0, size_and);
	}

	io->write_proc(and_mask, size_and, 1, handle);
	free(and_mask);

	return TRUE;
}

static BOOL DLL_CALLCONV
Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
	ICONHEADER *icon_header = NULL;
	std::vector<FIBITMAP*> vPages;
	int k;

	if(!dib || !handle || !data) {
		return FALSE;
	}

	// check format limits
	unsigned w = FreeImage_GetWidth(dib);
	unsigned h = FreeImage_GetHeight(dib);
	if((w < 16) || (w > 256) || (h < 16) || (h > 256) || (w != h)) {
		FreeImage_OutputMessageProc(s_format_id, "Unsupported icon size: width x height = %d x %d", w, h);
		return FALSE;
	}

	if (page == -1) {
		page = 0;
	}
	
	// get the icon header
	icon_header = (ICONHEADER*)data;

	try {
		FIBITMAP *icon_dib = NULL;

		// load all icons
		for(k = 0; k < icon_header->idCount; k++) {
			icon_dib = Load(io, handle, k, flags, data);
			if(!icon_dib) {
				throw FI_MSG_ERROR_DIB_MEMORY;
			}
			vPages.push_back(icon_dib);
		}

		// add the page



( run in 0.622 second using v1.01-cache-2.11-cpan-787462296c9 )