Alien-FreeImage

 view release on metacpan or  search on metacpan

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

		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
		icon_dib = FreeImage_Clone(dib);
		vPages.push_back(icon_dib);
		icon_header->idCount++;

		// write the header
		io->seek_proc(handle, 0, SEEK_SET);
#ifdef FREEIMAGE_BIGENDIAN
		SwapIconHeader(icon_header);
#endif
		io->write_proc(icon_header, sizeof(ICONHEADER), 1, handle);
#ifdef FREEIMAGE_BIGENDIAN
		SwapIconHeader(icon_header);
#endif

		// write all icons
		// ...
		
		// save the icon descriptions

		ICONDIRENTRY *icon_list = (ICONDIRENTRY *)malloc(icon_header->idCount * sizeof(ICONDIRENTRY));
		if(!icon_list) {
			throw FI_MSG_ERROR_MEMORY;
		}
		memset(icon_list, 0, icon_header->idCount * sizeof(ICONDIRENTRY));

		for(k = 0; k < icon_header->idCount; k++) {
			icon_dib = (FIBITMAP*)vPages[k];

			// convert internal format to ICONDIRENTRY
			// take into account Vista icons whose size is 256x256
			const BITMAPINFOHEADER *bmih = FreeImage_GetInfoHeader(icon_dib);
			icon_list[k].bWidth			= (bmih->biWidth > 255)  ? 0 : (BYTE)bmih->biWidth;
			icon_list[k].bHeight		= (bmih->biHeight > 255) ? 0 : (BYTE)bmih->biHeight;
			icon_list[k].bReserved		= 0;
			icon_list[k].wPlanes		= bmih->biPlanes;
			icon_list[k].wBitCount		= bmih->biBitCount;
			if( (icon_list[k].wPlanes * icon_list[k].wBitCount) >= 8 ) {
				icon_list[k].bColorCount = 0;
			} else {
				icon_list[k].bColorCount = (BYTE)(1 << (icon_list[k].wPlanes * icon_list[k].wBitCount));
			}
			// initial guess (correct only for standard icons)
			icon_list[k].dwBytesInRes	= CalculateImageSize(icon_dib);
			icon_list[k].dwImageOffset = CalculateImageOffset(vPages, k);
		}

		// make a room for icon dir entries, until later update
		const long directory_start = io->tell_proc(handle);
		io->write_proc(icon_list, sizeof(ICONDIRENTRY) * icon_header->idCount, 1, handle);

		// write the image bits for each image
		
		DWORD dwImageOffset = (DWORD)io->tell_proc(handle);

		for(k = 0; k < icon_header->idCount; k++) {
			icon_dib = (FIBITMAP*)vPages[k];
			
			if((icon_list[k].bWidth == 0) && (icon_list[k].bHeight == 0)) {
				// Vista icon support
				FreeImage_SaveToHandle(FIF_PNG, icon_dib, io, handle, PNG_DEFAULT);
			}
			else {
				// standard icon support
				// see http://msdn.microsoft.com/en-us/library/ms997538.aspx
				SaveStandardIcon(io, icon_dib, handle);
			}

			// update ICONDIRENTRY members			
			DWORD dwBytesInRes = (DWORD)io->tell_proc(handle) - dwImageOffset;
			icon_list[k].dwImageOffset = dwImageOffset;
			icon_list[k].dwBytesInRes  = dwBytesInRes;
			dwImageOffset += dwBytesInRes;
		}

		// update the icon descriptions
		const long current_pos = io->tell_proc(handle);
		io->seek_proc(handle, directory_start, SEEK_SET);
#ifdef FREEIMAGE_BIGENDIAN
		SwapIconDirEntries(icon_list, icon_header->idCount);
#endif
		io->write_proc(icon_list, sizeof(ICONDIRENTRY) * icon_header->idCount, 1, handle);
		io->seek_proc(handle, current_pos, SEEK_SET);

		free(icon_list);

		// free the vector class
		for(k = 0; k < icon_header->idCount; k++) {
			icon_dib = (FIBITMAP*)vPages[k];
			FreeImage_Unload(icon_dib);
		}

		return TRUE;

	} catch(const char *text) {
		// free the vector class
		for(size_t k = 0; k < vPages.size(); k++) {
			FIBITMAP *icon_dib = (FIBITMAP*)vPages[k];
			FreeImage_Unload(icon_dib);
		}
		FreeImage_OutputMessageProc(s_format_id, text);
		return FALSE;
	}



( run in 0.591 second using v1.01-cache-2.11-cpan-411bb0df24b )