Пример #1
0
void testRGBAChannels(FREE_IMAGE_TYPE image_type, unsigned width, unsigned height, BOOL bUseAlpha) {
	BOOL bResult = FALSE;

	// create a test image
	FIBITMAP *src = FreeImage_AllocateT(image_type, width, height);
	assert(src != NULL);

	// test get/set channel
	// -------------------------	
	{
		FIBITMAP *channel = FreeImage_GetChannel(src, FICC_GREEN);
		assert(channel != NULL);
		bResult = FreeImage_SetChannel(src, channel, FICC_GREEN);
		assert(bResult);	
		FreeImage_Unload(channel);
	}
	
	if(bUseAlpha) {
		FIBITMAP *alpha = FreeImage_GetChannel(src, FICC_ALPHA);
		assert(alpha != NULL);
		bResult = FreeImage_SetChannel(src, alpha, FICC_ALPHA);
		assert(bResult);	
		FreeImage_Unload(alpha);
	}

	FreeImage_Unload(src);
}
int DLL_CALLCONV
FIA_ReplaceColourPlanes (FIBITMAP **src, FIBITMAP *R, FIBITMAP *G, FIBITMAP *B)
{

	if (FreeImage_HasPixels(R) && FIA_Is8Bit(R)) {
		if (*src==NULL)
			*src = FreeImage_Allocate (FreeImage_GetWidth(R), FreeImage_GetHeight(R), 24);
		FIA_SetGreyLevelPalette (R);
		FreeImage_SetChannel(*src, R, FICC_RED);
	}
	
	if (FreeImage_HasPixels(G) && FIA_Is8Bit(G)) {
		if (*src==NULL)
			*src = FreeImage_Allocate (FreeImage_GetWidth(G), FreeImage_GetHeight(G), 24);
		FIA_SetGreyLevelPalette (G);
		FreeImage_SetChannel(*src, G, FICC_GREEN);
	}
	
	if (FreeImage_HasPixels(B) && FIA_Is8Bit(B)) {
		if (*src==NULL)
			*src = FreeImage_Allocate (FreeImage_GetWidth(B), FreeImage_GetHeight(B), 24);
		FIA_SetGreyLevelPalette (B);
		FreeImage_SetChannel(*src, B, FICC_BLUE);
	}
		
	return FIA_SUCCESS;
}
Пример #3
0
BOOL fipImage::setChannel(fipImage& image, FREE_IMAGE_COLOR_CHANNEL channel) {
	if(_dib) {
		_bHasChanged = TRUE;
		return FreeImage_SetChannel(_dib, image._dib, channel);
	}
	return FALSE;
}
Пример #4
0
void test32BitsChannels(unsigned width, unsigned height) {
	BOOL bResult = FALSE;

	// create a test 8-bit image
	FIBITMAP *src = createZonePlateImage(width, height, 128);
	if(src != NULL) {
		// convert to 32-bit
		FIBITMAP *tmp = FreeImage_ConvertTo32Bits(src);
		FreeImage_Unload(src);
		src = tmp;
	}
	assert(src != NULL);

	// save for further examination
	bResult = FreeImage_Save(FIF_PNG, src, "zoneplate.png", PNG_DEFAULT);
	assert(bResult);

	// test get/set channel
	// -------------------------	
	FIBITMAP *channel = FreeImage_GetChannel(src, FICC_ALPHA);
	assert(channel != NULL);
	bResult = FreeImage_SetChannel(src, channel, FICC_ALPHA);
	assert(bResult);	
	FreeImage_Unload(channel);

	FreeImage_Unload(src);
}
Пример #5
0
BOOL fipImage::combineChannels(fipImage& red, fipImage& green, fipImage& blue) {
	if(!_dib) {
		int width = red.getWidth();
		int height = red.getHeight();
		_dib = FreeImage_Allocate(width, height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
	}

	if(_dib) {
		BOOL bResult = TRUE;
		bResult &= FreeImage_SetChannel(_dib, red._dib, FICC_RED);
		bResult &= FreeImage_SetChannel(_dib, green._dib, FICC_GREEN);
		bResult &= FreeImage_SetChannel(_dib, blue._dib, FICC_BLUE);

		_bHasChanged = TRUE;

		return bResult;
	}
	return FALSE;
}
Пример #6
0
FIBITMAP *loadDIB(const std::string &url) {
	// figure out if the file exists
	if(!fs::exists(url)) {
		printf("poImage: image file not found (%s)\n", url.c_str());
		return NULL;
	}
	
	loadFreeImageIfNeeded();

	FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
	fif = FreeImage_GetFileType(url.c_str());
//	if(fif == FIF_UNKNOWN)
//		fif = FreeImage_GetFIFFromFilename(url.c_str());
	if(fif == FIF_UNKNOWN) {
		printf("poImage: image isn't a supported file type (%s)\n", url.c_str());
		return NULL;
	}
	
	FIBITMAP *dib = NULL;
	if(FreeImage_FIFSupportsReading(fif))
		dib = FreeImage_Load(fif, url.c_str());
	if(!dib) {
		printf("poImage: image file not found (%s)\n", url.c_str());
		return NULL;
	}

	unsigned bpp = FreeImage_GetBPP(dib);
	if(bpp == 24 || bpp == 32) {
		// there has got to be a more efficient way of doing this
		FIBITMAP *red = FreeImage_GetChannel(dib,FICC_RED);
		FIBITMAP *blue = FreeImage_GetChannel(dib,FICC_BLUE);
		
		FreeImage_SetChannel(dib,red,FICC_BLUE);
		FreeImage_SetChannel(dib,blue,FICC_RED);
		
		FreeImage_Unload(red);
		FreeImage_Unload(blue);
	}
	
	return dib;
}
/**
 Creates a 32-bit transparent image using the black channel of the source image
 @param src Source image
 @return Returns a 32-bit transparent image
*/
FIBITMAP* CreateAlphaFromLightness(FIBITMAP *src) {
	// create a 32-bit image from the source
	FIBITMAP *dst = FreeImage_ConvertTo32Bits(src);

	// create a 8-bit mask
	FreeImage_Invert(src);
	FIBITMAP *mask = FreeImage_ConvertTo8Bits(src);
	FreeImage_Invert(src);

	// insert the mask as an alpha channel
	FreeImage_SetChannel(dst, mask, FICC_ALPHA);

	// free the mask and return
	FreeImage_Unload(mask);

	return dst;
}
Пример #8
0
/**
   Load a FIBITMAP from a MNG or a JNG stream
   @param format_id ID of the caller
   @param io Stream i/o functions
   @param handle Stream handle
   @param Offset Start of the first chunk
   @param flags Loading flags
   @return Returns a dib if successful, returns NULL otherwise
*/
FIBITMAP*
mng_ReadChunks(int format_id, FreeImageIO *io, fi_handle handle, long Offset, int flags = 0) {
    DWORD mLength = 0;
    BYTE mChunkName[5];
    BYTE *mChunk = NULL;
    DWORD crc_file;
    long LastOffset;
    long mOrigPos;
    BYTE *PLTE_file_chunk = NULL;   // whole PLTE chunk (lentgh, name, array, crc)
    DWORD PLTE_file_size = 0;       // size of PLTE chunk

    BOOL m_HasGlobalPalette = FALSE; // may turn to TRUE in PLTE chunk
    unsigned m_TotalBytesOfChunks = 0;
    FIBITMAP *dib = NULL;
    FIBITMAP *dib_alpha = NULL;

    FIMEMORY *hJpegMemory = NULL;
    FIMEMORY *hPngMemory = NULL;
    FIMEMORY *hIDATMemory = NULL;

    // ---
    DWORD jng_width = 0;
    DWORD jng_height = 0;
    BYTE jng_color_type = 0;
    BYTE jng_image_sample_depth = 0;
    BYTE jng_image_compression_method = 0;

    BYTE jng_alpha_sample_depth = 0;
    BYTE jng_alpha_compression_method = 0;
    BYTE jng_alpha_filter_method = 0;
    BYTE jng_alpha_interlace_method = 0;

    DWORD mng_frame_width = 0;
    DWORD mng_frame_height = 0;
    DWORD mng_ticks_per_second = 0;
    DWORD mng_nominal_layer_count = 0;
    DWORD mng_nominal_frame_count = 0;
    DWORD mng_nominal_play_time = 0;
    DWORD mng_simplicity_profile = 0;


    DWORD res_x = 2835; // 72 dpi
    DWORD res_y = 2835; // 72 dpi
    RGBQUAD rgbBkColor = {0, 0, 0, 0};
    WORD bk_red, bk_green, bk_blue;
    BOOL hasBkColor = FALSE;
    BOOL mHasIDAT = FALSE;

    tEXtMAP key_value_pair;

    // ---

    BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS;

    // get the file size
    const long mLOF = mng_LOF(io, handle);
    // go to the first chunk
    io->seek_proc(handle, Offset, SEEK_SET);

    try {
        BOOL mEnd = FALSE;

        while(mEnd == FALSE) {
            // start of the chunk
            LastOffset = io->tell_proc(handle);
            // read length
            mLength = 0;
            io->read_proc(&mLength, 1, sizeof(mLength), handle);
            mng_SwapLong(&mLength);
            // read name
            io->read_proc(&mChunkName[0], 1, 4, handle);
            mChunkName[4] = '\0';

            if(mLength > 0) {
                mChunk = (BYTE*)realloc(mChunk, mLength);
                if(!mChunk) {
                    FreeImage_OutputMessageProc(format_id, "Error while parsing %s chunk: out of memory", mChunkName);
                    throw (const char*)NULL;
                }
                Offset = io->tell_proc(handle);
                if(Offset + (long)mLength > mLOF) {
                    FreeImage_OutputMessageProc(format_id, "Error while parsing %s chunk: unexpected end of file", mChunkName);
                    throw (const char*)NULL;
                }
                // read chunk
                io->read_proc(mChunk, 1, mLength, handle);
            }
            // read crc
            io->read_proc(&crc_file, 1, sizeof(crc_file), handle);
            mng_SwapLong(&crc_file);
            // check crc
            DWORD crc_check = FreeImage_ZLibCRC32(0, &mChunkName[0], 4);
            crc_check = FreeImage_ZLibCRC32(crc_check, mChunk, mLength);
            if(crc_check != crc_file) {
                FreeImage_OutputMessageProc(format_id, "Error while parsing %s chunk: bad CRC", mChunkName);
                throw (const char*)NULL;
            }

            switch( mng_GetChunckType(mChunkName) ) {
                case MHDR:
                    // The MHDR chunk is always first in all MNG datastreams except for those
                    // that consist of a single PNG or JNG datastream with a PNG or JNG signature.
                    if(mLength == 28) {
                        memcpy(&mng_frame_width, &mChunk[0], 4);
                        memcpy(&mng_frame_height, &mChunk[4], 4);
                        memcpy(&mng_ticks_per_second, &mChunk[8], 4);
                        memcpy(&mng_nominal_layer_count, &mChunk[12], 4);
                        memcpy(&mng_nominal_frame_count, &mChunk[16], 4);
                        memcpy(&mng_nominal_play_time, &mChunk[20], 4);
                        memcpy(&mng_simplicity_profile, &mChunk[24], 4);

                        mng_SwapLong(&mng_frame_width);
                        mng_SwapLong(&mng_frame_height);
                        mng_SwapLong(&mng_ticks_per_second);
                        mng_SwapLong(&mng_nominal_layer_count);
                        mng_SwapLong(&mng_nominal_frame_count);
                        mng_SwapLong(&mng_nominal_play_time);
                        mng_SwapLong(&mng_simplicity_profile);

                    } else {
                        FreeImage_OutputMessageProc(format_id, "Error while parsing %s chunk: size is %d instead of 28", mChunkName, mLength);
                    }
                    break;

                case MEND:
                    mEnd = TRUE;
                    break;

                case LOOP:
                case ENDL:
                    break;
                case DEFI:
                    break;
                case SAVE:
                case SEEK:
                case TERM:
                    break;
                case BACK:
                    break;

                    // Global "PLTE" and "tRNS" (if any).  PNG "PLTE" will be of 0 byte, as it uses global data.
                case PLTE:  // Global
                    m_HasGlobalPalette = TRUE;
                    PLTE_file_size = mLength + 12; // (lentgh, name, array, crc) = (4, 4, mLength, 4)
                    PLTE_file_chunk = (BYTE*)realloc(PLTE_file_chunk, PLTE_file_size);
                    if(!PLTE_file_chunk) {
                        FreeImage_OutputMessageProc(format_id, "Error while parsing %s chunk: out of memory", mChunkName);
                        throw (const char*)NULL;
                    } else {
                        mOrigPos = io->tell_proc(handle);
                        // seek to the start of the chunk
                        io->seek_proc(handle, LastOffset, SEEK_SET);
                        // load the whole chunk
                        io->read_proc(PLTE_file_chunk, 1, PLTE_file_size, handle);
                        // go to the start of the next chunk
                        io->seek_proc(handle, mOrigPos, SEEK_SET);
                    }
                    break;

                case tRNS:  // Global
                    break;

                case IHDR:
                    Offset = LastOffset;
                    // parse the PNG file and get its file size
                    if(mng_CountPNGChunks(io, handle, Offset, &m_TotalBytesOfChunks) == FALSE) {
                        // reach an unexpected end of file
                        mEnd = TRUE;
                        FreeImage_OutputMessageProc(format_id, "Error while parsing %s chunk: unexpected end of PNG file", mChunkName);
                        break;
                    }

                    // wrap the { IHDR, ..., IEND } chunks as a PNG stream
                    if(hPngMemory == NULL) {
                        hPngMemory = FreeImage_OpenMemory();
                    }

                    mOrigPos = io->tell_proc(handle);

                    // write PNG file signature
                    FreeImage_SeekMemory(hPngMemory, 0, SEEK_SET);
                    FreeImage_WriteMemory(g_png_signature, 1, 8, hPngMemory);

                    mChunk = (BYTE*)realloc(mChunk, m_TotalBytesOfChunks);
                    if(!mChunk) {
                        FreeImage_OutputMessageProc(format_id, "Error while parsing %s chunk: out of memory", mChunkName);
                        throw (const char*)NULL;
                    }

                    // on calling CountPNGChunks earlier, we were in Offset pos,
                    // go back there
                    io->seek_proc(handle, Offset, SEEK_SET);
                    io->read_proc(mChunk, 1, m_TotalBytesOfChunks, handle);
                    // Put back to original pos
                    io->seek_proc(handle, mOrigPos, SEEK_SET);
                    // write the PNG chunks
                    FreeImage_WriteMemory(mChunk, 1, m_TotalBytesOfChunks, hPngMemory);

                    // plug in global PLTE if local PLTE exists
                    if(m_HasGlobalPalette) {
                        // ensure we remove some local chunks, so that global
                        // "PLTE" can be inserted right before "IDAT".
                        mng_RemoveChunk(hPngMemory, mng_PLTE);
                        mng_RemoveChunk(hPngMemory, mng_tRNS);
                        mng_RemoveChunk(hPngMemory, mng_bKGD);
                        // insert global "PLTE" chunk in its entirety before "IDAT"
                        mng_InsertChunk(hPngMemory, mng_IDAT, PLTE_file_chunk, PLTE_file_size);
                    }

                    if(dib) FreeImage_Unload(dib);
                    dib = mng_LoadFromMemoryHandle(hPngMemory, flags);

                    // stop after the first image
                    mEnd = TRUE;
                    break;

                case JHDR:
                    if(mLength == 16) {
                        memcpy(&jng_width, &mChunk[0], 4);
                        memcpy(&jng_height, &mChunk[4], 4);
                        mng_SwapLong(&jng_width);
                        mng_SwapLong(&jng_height);

                        jng_color_type = mChunk[8];
                        jng_image_sample_depth = mChunk[9];
                        jng_image_compression_method = mChunk[10];
                        //BYTE jng_image_interlace_method = mChunk[11]; // for debug only

                        jng_alpha_sample_depth = mChunk[12];
                        jng_alpha_compression_method = mChunk[13];
                        jng_alpha_filter_method = mChunk[14];
                        jng_alpha_interlace_method = mChunk[15];
                    } else {
                        FreeImage_OutputMessageProc(format_id, "Error while parsing %s chunk: invalid chunk length", mChunkName);
                        throw (const char*)NULL;
                    }
                    break;

                case JDAT:
                    if(hJpegMemory == NULL) {
                        hJpegMemory = FreeImage_OpenMemory();
                    }
                    // as there may be several JDAT chunks, concatenate them
                    FreeImage_WriteMemory(mChunk, 1, mLength, hJpegMemory);
                    break;

                case IDAT:
                    if(!header_only && (jng_alpha_compression_method == 0)) {
                        // PNG grayscale IDAT format
                        if(hIDATMemory == NULL) {
                            hIDATMemory = FreeImage_OpenMemory();
                            mHasIDAT = TRUE;
                        }
                        // as there may be several IDAT chunks, concatenate them
                        FreeImage_WriteMemory(mChunk, 1, mLength, hIDATMemory);
                    }
                    break;

                case IEND:
                    if(!hJpegMemory) {
                        mEnd = TRUE;
                        break;
                    }
                    // load the JPEG
                    if(dib) {
                        FreeImage_Unload(dib);
                    }
                    dib = mng_LoadFromMemoryHandle(hJpegMemory, flags);

                    // load the PNG alpha layer
                    if(mHasIDAT) {
                        BYTE *data = NULL;
                        DWORD size_in_bytes = 0;

                        // get a pointer to the IDAT buffer
                        FreeImage_AcquireMemory(hIDATMemory, &data, &size_in_bytes);
                        if(data && size_in_bytes) {
                            // wrap the IDAT chunk as a PNG stream
                            if(hPngMemory == NULL) {
                                hPngMemory = FreeImage_OpenMemory();
                            }
                            mng_WritePNGStream(jng_width, jng_height, jng_alpha_sample_depth, data, size_in_bytes, hPngMemory);
                            // load the PNG
                            if(dib_alpha) {
                                FreeImage_Unload(dib_alpha);
                            }
                            dib_alpha = mng_LoadFromMemoryHandle(hPngMemory, flags);
                        }
                    }
                    // stop the parsing
                    mEnd = TRUE;
                    break;

                case JDAA:
                    break;

                case gAMA:
                    break;

                case pHYs:
                    // unit is pixels per meter
                    memcpy(&res_x, &mChunk[0], 4);
                    mng_SwapLong(&res_x);
                    memcpy(&res_y, &mChunk[4], 4);
                    mng_SwapLong(&res_y);
                    break;

                case bKGD:
                    memcpy(&bk_red, &mChunk[0], 2);
                    mng_SwapShort(&bk_red);
                    rgbBkColor.rgbRed = (BYTE)bk_red;
                    memcpy(&bk_green, &mChunk[2], 2);
                    mng_SwapShort(&bk_green);
                    rgbBkColor.rgbGreen = (BYTE)bk_green;
                    memcpy(&bk_blue, &mChunk[4], 2);
                    mng_SwapShort(&bk_blue);
                    rgbBkColor.rgbBlue = (BYTE)bk_blue;
                    hasBkColor = TRUE;
                    break;

                case tEXt:
                    mng_SetMetadata_tEXt(key_value_pair, mChunk, mLength);
                    break;

                case UNKNOWN_CHUNCK:
                default:
                    break;


            } // switch( GetChunckType )
        } // while(!mEnd)

        FreeImage_CloseMemory(hJpegMemory);
        FreeImage_CloseMemory(hPngMemory);
        FreeImage_CloseMemory(hIDATMemory);
        free(mChunk);
        free(PLTE_file_chunk);

        // convert to 32-bit if a transparent layer is available
        if(!header_only && dib_alpha) {
            FIBITMAP *dst = FreeImage_ConvertTo32Bits(dib);
            if((FreeImage_GetBPP(dib_alpha) == 8) && (FreeImage_GetImageType(dib_alpha) == FIT_BITMAP)) {
                FreeImage_SetChannel(dst, dib_alpha, FICC_ALPHA);
            } else {
                FIBITMAP *dst_alpha = FreeImage_ConvertTo8Bits(dib_alpha);
                FreeImage_SetChannel(dst, dst_alpha, FICC_ALPHA);
                FreeImage_Unload(dst_alpha);
            }
            FreeImage_Unload(dib);
            dib = dst;
        }
        FreeImage_Unload(dib_alpha);

        if(dib) {
            // set metadata
            FreeImage_SetDotsPerMeterX(dib, res_x);
            FreeImage_SetDotsPerMeterY(dib, res_y);
            if(hasBkColor) {
                FreeImage_SetBackgroundColor(dib, &rgbBkColor);
            }
            if(key_value_pair.size()) {
                for(tEXtMAP::iterator j = key_value_pair.begin(); j != key_value_pair.end(); j++) {
                    std::string key = (*j).first;
                    std::string value = (*j).second;
                    mng_SetKeyValue(FIMD_COMMENTS, dib, key.c_str(), value.c_str());
                }
            }
        }

        return dib;

    } catch(const char *text) {
        FreeImage_CloseMemory(hJpegMemory);
        FreeImage_CloseMemory(hPngMemory);
        FreeImage_CloseMemory(hIDATMemory);
        free(mChunk);
        free(PLTE_file_chunk);
        FreeImage_Unload(dib);
        FreeImage_Unload(dib_alpha);
        if(text) {
            FreeImage_OutputMessageProc(format_id, text);
        }
        return NULL;
    }
}