unsigned int LoadTexture(const char* a_szTexture, unsigned int a_uiFormat /* = GL_RGBA */, unsigned int* a_uiWidth /* = nullptr */, unsigned int* a_uiHeight /* = nullptr */, unsigned int* a_uiBPP /* = nullptr*/) { FIBITMAP* pBitmap = nullptr; // check the file signature and deduce its format and load it FREE_IMAGE_FORMAT fif = FreeImage_GetFileType(a_szTexture, 0); if (fif != FIF_UNKNOWN && FreeImage_FIFSupportsReading(fif)) { pBitmap = FreeImage_Load(fif, a_szTexture); } if (pBitmap == nullptr) { printf("Error: Failed to load image '%s'!\n", a_szTexture); return 0; } // optionally get the image width and height if (a_uiWidth != nullptr) *a_uiWidth = FreeImage_GetWidth(pBitmap); if (a_uiHeight != nullptr) *a_uiHeight = FreeImage_GetHeight(pBitmap); // force the image to RGBA unsigned int bpp = FreeImage_GetBPP(pBitmap); if( a_uiBPP != nullptr ) *a_uiBPP = bpp/8; FREE_IMAGE_COLOR_TYPE fi_colourType = FreeImage_GetColorType(pBitmap); if (fi_colourType != FIC_RGBALPHA ) { FIBITMAP* ndib = FreeImage_ConvertTo32Bits(pBitmap); FreeImage_Unload(pBitmap); pBitmap = ndib; bpp = FreeImage_GetBPP(pBitmap); fi_colourType = FreeImage_GetColorType(pBitmap); } // get the pixel data BYTE* pData = FreeImage_GetBits(pBitmap); // try to determine data type of file (bytes/floats) FREE_IMAGE_TYPE fit = FreeImage_GetImageType(pBitmap); GLenum eType = (fit == FIT_RGBF || fit == FIT_FLOAT) ? GL_FLOAT:GL_UNSIGNED_BYTE; // create GL texture GLuint textureID; glGenTextures( 1, &textureID ); glBindTexture( GL_TEXTURE_2D, textureID ); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, FreeImage_GetWidth(pBitmap), FreeImage_GetHeight(pBitmap), 0, a_uiFormat, eType, pData); //CREATING A GL BUFFER GLuint VBO; glGenBuffers(1, &VBO); glBindBuffer( GL_Array_Buffer, VBO); // specify default filtering and wrapping glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); // unbind texture glBindTexture( GL_TEXTURE_2D, 0 ); // delete data FreeImage_Unload(pBitmap); //DELETING THE GL BUFFER MADE ABOVE glDeleteBuffers(1, &VBO); return textureID; }
/** Encode a FIBITMAP to a WebP image @param hmem Memory output stream, containing on return the encoded image @param dib The FIBITMAP to encode @param flags FreeImage save flags @return Returns TRUE if successfull, returns FALSE otherwise */ static BOOL EncodeImage(FIMEMORY *hmem, FIBITMAP *dib, int flags) { WebPPicture picture; // Input buffer WebPConfig config; // Coding parameters BOOL bIsFlipped = FALSE; try { const unsigned width = FreeImage_GetWidth(dib); const unsigned height = FreeImage_GetHeight(dib); const unsigned bpp = FreeImage_GetBPP(dib); const unsigned pitch = FreeImage_GetPitch(dib); // check image type FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); if( !((image_type == FIT_BITMAP) && ((bpp == 24) || (bpp == 32))) ) { throw FI_MSG_ERROR_UNSUPPORTED_FORMAT; } // check format limits if(MAX(width, height) > WEBP_MAX_DIMENSION) { FreeImage_OutputMessageProc(s_format_id, "Unsupported image size: width x height = %d x %d", width, height); return FALSE; } // Initialize output I/O if(WebPPictureInit(&picture) == 1) { picture.writer = WebP_MemoryWriter; picture.custom_ptr = hmem; picture.width = (int)width; picture.height = (int)height; } else { throw "Couldn't initialize WebPPicture"; } // --- Set encoding parameters --- // Initialize encoding parameters to default values WebPConfigInit(&config); // quality/speed trade-off (0=fast, 6=slower-better) config.method = 6; if((flags & WEBP_LOSSLESS) == WEBP_LOSSLESS) { // lossless encoding config.lossless = 1; picture.use_argb = 1; } else if((flags & 0x7F) > 0) { // lossy encoding config.lossless = 0; // quality is between 1 (smallest file) and 100 (biggest) - default to 75 config.quality = (float)(flags & 0x7F); if(config.quality > 100) { config.quality = 100; } } // validate encoding parameters if(WebPValidateConfig(&config) == 0) { throw "Failed to initialize encoder"; } // --- Perform encoding --- // Invert dib scanlines bIsFlipped = FreeImage_FlipVertical(dib); // convert dib buffer to output stream const BYTE *bits = FreeImage_GetBits(dib); #if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR switch(bpp) { case 24: WebPPictureImportBGR(&picture, bits, pitch); break; case 32: WebPPictureImportBGRA(&picture, bits, pitch); break; } #else switch(bpp) { case 24: WebPPictureImportRGB(&picture, bits, pitch); break; case 32: WebPPictureImportRGBA(&picture, bits, pitch); break; } #endif // FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR if(!WebPEncode(&config, &picture)) { throw "Failed to encode image"; } WebPPictureFree(&picture); if(bIsFlipped) { // invert dib scanlines FreeImage_FlipVertical(dib); } return TRUE; } catch (const char* text) { WebPPictureFree(&picture); if(bIsFlipped) { // invert dib scanlines FreeImage_FlipVertical(dib); } if(NULL != text) { FreeImage_OutputMessageProc(s_format_id, text); } } return FALSE; }
void Engine::TextureCube::loadFromFiles( const CHAR *posx, const CHAR *negx, const CHAR *posy, const CHAR *negy, const CHAR *posz, const CHAR *negz) { UINT i; FIBITMAP *image[6]; FIBITMAP *tmp; ID3D11Texture2D *texture; const CHAR *tex[] = { posx, negx, negy, posy, posz, negz }; image[0] = FreeImage_Load(FreeImage_GetFileType(tex[0]), tex[0]); image[1] = FreeImage_Load(FreeImage_GetFileType(tex[1]), tex[1]); image[2] = FreeImage_Load(FreeImage_GetFileType(tex[2]), tex[2]); image[3] = FreeImage_Load(FreeImage_GetFileType(tex[3]), tex[3]); image[4] = FreeImage_Load(FreeImage_GetFileType(tex[4]), tex[4]); image[5] = FreeImage_Load(FreeImage_GetFileType(tex[5]), tex[5]); if (_pShaderResourceView) _pShaderResourceView->Release(); if (_pSamplerState) _pSamplerState->Release(); D3D11_TEXTURE2D_DESC descTexture; descTexture.Width = FreeImage_GetWidth(image[0]); descTexture.Height = FreeImage_GetHeight(image[0]); descTexture.MipLevels = 1; descTexture.ArraySize = 6; descTexture.Format = DXGI_FORMAT_B8G8R8A8_UNORM; descTexture.SampleDesc.Count = 1; descTexture.SampleDesc.Quality = 0; descTexture.Usage = D3D11_USAGE_IMMUTABLE; descTexture.BindFlags = D3D11_BIND_SHADER_RESOURCE; descTexture.CPUAccessFlags = 0; descTexture.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE; D3D11_SUBRESOURCE_DATA data[6]; for (i = 0; i < 6; i++) { if (image[i] == NULL) { std::string text = "Error while loading image: "; text.append(tex[i]); MessageBoxA(NULL, text.c_str(), __FILE__, MB_OK); exit(1); } tmp = image[i]; image[i] = FreeImage_ConvertTo32Bits(image[i]); FreeImage_Unload(tmp); data[i].pSysMem = FreeImage_GetBits(image[i]); data[i].SysMemPitch = 4 * descTexture.Width; data[i].SysMemSlicePitch = 0; } Device->CreateTexture2D(&descTexture, data, &texture); D3D11_SHADER_RESOURCE_VIEW_DESC descShaderResourceView; descShaderResourceView.Format = descTexture.Format; descShaderResourceView.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; descShaderResourceView.TextureCube.MostDetailedMip = 0; descShaderResourceView.TextureCube.MipLevels = descTexture.MipLevels; Device->CreateShaderResourceView(texture, &descShaderResourceView, &_pShaderResourceView); D3D11_SAMPLER_DESC descSampler; descSampler.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; descSampler.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; descSampler.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; descSampler.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; descSampler.ComparisonFunc = D3D11_COMPARISON_NEVER; descSampler.MipLODBias = 0.0f; descSampler.MaxAnisotropy = 1; descSampler.BorderColor[0] = 0.0f; descSampler.BorderColor[1] = 0.0f; descSampler.BorderColor[2] = 0.0f; descSampler.BorderColor[3] = 0.0f; descSampler.MinLOD = 0; descSampler.MaxLOD = D3D11_FLOAT32_MAX; Device->CreateSamplerState(&descSampler, &_pSamplerState); texture->Release(); }
//--------------------------------------------------------------------- Codec::DecodeResult FreeImageCodec::decode(DataStreamPtr& input) const { // Set error handler FreeImage_SetOutputMessage(FreeImageLoadErrorHandler); // Buffer stream into memory (TODO: override IO functions instead?) MemoryDataStream memStream(input, true); FIMEMORY* fiMem = FreeImage_OpenMemory(memStream.getPtr(), static_cast<DWORD>(memStream.size())); FIBITMAP* fiBitmap = FreeImage_LoadFromMemory( (FREE_IMAGE_FORMAT)mFreeImageType, fiMem); if (!fiBitmap) { OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Error decoding image", "FreeImageCodec::decode"); } ImageData* imgData = OGRE_NEW ImageData(); MemoryDataStreamPtr output; imgData->depth = 1; // only 2D formats handled by this codec imgData->width = FreeImage_GetWidth(fiBitmap); imgData->height = FreeImage_GetHeight(fiBitmap); imgData->num_mipmaps = 0; // no mipmaps in non-DDS imgData->flags = 0; // Must derive format first, this may perform conversions FREE_IMAGE_TYPE imageType = FreeImage_GetImageType(fiBitmap); FREE_IMAGE_COLOR_TYPE colourType = FreeImage_GetColorType(fiBitmap); unsigned bpp = FreeImage_GetBPP(fiBitmap); switch(imageType) { case FIT_UNKNOWN: case FIT_COMPLEX: case FIT_UINT32: case FIT_INT32: case FIT_DOUBLE: default: OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Unknown or unsupported image format", "FreeImageCodec::decode"); break; case FIT_BITMAP: // Standard image type // Perform any colour conversions for greyscale if (colourType == FIC_MINISWHITE || colourType == FIC_MINISBLACK) { FIBITMAP* newBitmap = FreeImage_ConvertToGreyscale(fiBitmap); // free old bitmap and replace FreeImage_Unload(fiBitmap); fiBitmap = newBitmap; // get new formats bpp = FreeImage_GetBPP(fiBitmap); colourType = FreeImage_GetColorType(fiBitmap); } // Perform any colour conversions for RGB else if (bpp < 8 || colourType == FIC_PALETTE || colourType == FIC_CMYK) { FIBITMAP* newBitmap = FreeImage_ConvertTo24Bits(fiBitmap); // free old bitmap and replace FreeImage_Unload(fiBitmap); fiBitmap = newBitmap; // get new formats bpp = FreeImage_GetBPP(fiBitmap); colourType = FreeImage_GetColorType(fiBitmap); } // by this stage, 8-bit is greyscale, 16/24/32 bit are RGB[A] switch(bpp) { case 8: imgData->format = PF_L8; break; case 16: // Determine 555 or 565 from green mask // cannot be 16-bit greyscale since that's FIT_UINT16 if(FreeImage_GetGreenMask(fiBitmap) == FI16_565_GREEN_MASK) { imgData->format = PF_R5G6B5; } else { // FreeImage doesn't support 4444 format so must be 1555 imgData->format = PF_A1R5G5B5; } break; case 24: // FreeImage differs per platform // PF_BYTE_BGR[A] for little endian (== PF_ARGB native) // PF_BYTE_RGB[A] for big endian (== PF_RGBA native) #if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB imgData->format = PF_BYTE_RGB; #else imgData->format = PF_BYTE_BGR; #endif break; case 32: #if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB imgData->format = PF_BYTE_RGBA; #else imgData->format = PF_BYTE_BGRA; #endif break; }; break; case FIT_UINT16: case FIT_INT16: // 16-bit greyscale imgData->format = PF_L16; break; case FIT_FLOAT: // Single-component floating point data imgData->format = PF_FLOAT32_R; break; case FIT_RGB16: imgData->format = PF_SHORT_RGB; break; case FIT_RGBA16: imgData->format = PF_SHORT_RGBA; break; case FIT_RGBF: imgData->format = PF_FLOAT32_RGB; break; case FIT_RGBAF: imgData->format = PF_FLOAT32_RGBA; break; }; unsigned char* srcData = FreeImage_GetBits(fiBitmap); unsigned srcPitch = FreeImage_GetPitch(fiBitmap); // Final data - invert image and trim pitch at the same time size_t dstPitch = imgData->width * PixelUtil::getNumElemBytes(imgData->format); imgData->size = dstPitch * imgData->height; // Bind output buffer output.bind(OGRE_NEW MemoryDataStream(imgData->size)); uchar* pSrc; uchar* pDst = output->getPtr(); for (size_t y = 0; y < imgData->height; ++y) { pSrc = srcData + (imgData->height - y - 1) * srcPitch; memcpy(pDst, pSrc, dstPitch); pDst += dstPitch; } FreeImage_Unload(fiBitmap); FreeImage_CloseMemory(fiMem); DecodeResult ret; ret.first = output; ret.second = CodecDataPtr(imgData); return ret; }
Int32 loadTexture(Texture *out_texture, const char *fileAddress) { __BLITZ_ASSERT(out_texture); __BLITZ_ASSERT(fileAddress); auto existingTexture = textureList.find(std::string(fileAddress)); if (existingTexture != textureList.end()) { *out_texture = existingTexture->second; return 0; } FREE_IMAGE_FORMAT freeImageFormat; freeImageFormat = FreeImage_GetFileType(fileAddress, 0); if (freeImageFormat == FIF_UNKNOWN) { freeImageFormat = FreeImage_GetFIFFromFilename(fileAddress); } if (freeImageFormat == FIF_UNKNOWN) { __BLITZ_THROW_ERROR("Failed to load image \"" + std::string(fileAddress) + "\" : Image format is not supported."); return 1; } Bool loadAlphaChannel = 0; switch (freeImageFormat) { case FIF_BMP: case FIF_GIF: case FIF_JPEG: loadAlphaChannel = 0; break; case FIF_DDS: case FIF_PNG: case FIF_TARGA: loadAlphaChannel = 1; break; } if (FreeImage_FIFSupportsReading(freeImageFormat) == 0) { __BLITZ_THROW_ERROR("Failed to load image \"" + std::string(fileAddress) + "\" : Reading from this image format is not supported."); return 1; } FIBITMAP *freeImageBitmap = FreeImage_Load(freeImageFormat, fileAddress, 0); if (freeImageBitmap == 0) { __BLITZ_THROW_ERROR("Failed to load image \"" + std::string(fileAddress) + "\" : Failed to load image file."); return 1; } BYTE *imageData = FreeImage_GetBits(freeImageBitmap); if (imageData == 0) { __BLITZ_THROW_ERROR("Failed to load image \"" + std::string(fileAddress) + "\" : Failed to get image data."); return 1; } Int32 imageWidth = FreeImage_GetWidth(freeImageBitmap), imageHeight = FreeImage_GetHeight(freeImageBitmap); if (imageWidth <= 0 || imageHeight <= 0) { __BLITZ_THROW_ERROR("Failed to load image \"" + std::string(fileAddress) + "\" : Image dimensions are invalid."); return 1; } glGenTextures(1, out_texture); glBindTexture(GL_TEXTURE_2D, *out_texture); GLint imageFormat = loadAlphaChannel ? GL_BGRA : GL_BGR; glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, imageWidth, imageHeight, 0, imageFormat, GL_UNSIGNED_BYTE, imageData); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glBindTexture(GL_TEXTURE_2D, 0); FreeImage_Unload(freeImageBitmap); std::pair<std::string, Texture> newPair = std::pair<std::string, Texture>(fileAddress, *out_texture); textureList.insert(newPair); blitz::__debug::throwMessage("Image \"" + std::string(fileAddress) + "\" loaded."); return 0; }
Texture* FreeImageImageCodec::load(const RawDataContainer& data, Texture* result) { int len = (int)data.getSize(); FIMEMORY *mem = 0; FIBITMAP *img = 0; Texture *retval = 0; try { mem = FreeImage_OpenMemory(static_cast<BYTE*>(const_cast<std::uint8_t*>(data.getDataPtr())), len); if (mem == 0) throw MemoryException("Unable to open memory stream, FreeImage_OpenMemory failed"); FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeFromMemory(mem, len); if (fif == FIF_UNKNOWN) // it may be that it's TARGA or MNG { fif = FIF_TARGA; img = FreeImage_LoadFromMemory(fif, mem, 0); if (img == 0) { fif = FIF_MNG; img = FreeImage_LoadFromMemory(fif, mem, 0); } } else img = FreeImage_LoadFromMemory(fif, mem, 0); if (img == 0) throw GenericException("Unable to load image, FreeImage_LoadFromMemory failed"); FIBITMAP *newImg = FreeImage_ConvertTo32Bits(img); if (newImg == 0) throw GenericException("Unable to convert image, FreeImage_ConvertTo32Bits failed"); FreeImage_Unload(img); img = newImg; newImg = 0; // FreeImage pixel format for little-endian architecture (which CEGUI // supports) is like BGRA. We need to convert that to RGBA. // // It is now: // RED_MASK 0x00FF0000 // GREEN_MASK 0x0000FF00 // BLUE_MASK 0x000000FF // ALPHA_MASK 0xFF000000 // // It should be: // RED_MASK 0x000000FF // GREEN_MASK 0x0000FF00 // BLUE_MASK 0x00FF0000 // ALPHA_MASK 0xFF000000 unsigned int pitch = FreeImage_GetPitch(img); unsigned int height = FreeImage_GetHeight(img); unsigned int width = FreeImage_GetWidth(img); std::uint8_t *rawBuf = new std::uint8_t[width * height << 2]; // convert the bitmap to raw bits (top-left pixel first) FreeImage_ConvertToRawBits(rawBuf, img, pitch, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK, true); // We need to convert pixel format a little // NB: little endian only - I think(!) #if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR for (unsigned int i = 0; i < height; ++i) { for (unsigned int j = 0; j < width; ++j) { unsigned int p = *(((unsigned int*)(rawBuf + i * pitch)) + j); unsigned int r = (p >> 16) & 0x000000FF; unsigned int b = (p << 16) & 0x00FF0000; p &= 0xFF00FF00; p |= r | b; // write the adjusted pixel back *(((unsigned int*)(rawBuf + i * pitch)) + j) = p; } } #endif FreeImage_Unload(img); img = 0; result->loadFromMemory(rawBuf, Sizef(width, height), Texture::PF_RGBA); delete [] rawBuf; retval = result; } catch (Exception&) { } if (img != 0) FreeImage_Unload(img); if (mem != 0) FreeImage_CloseMemory(mem); return retval; }
static void *bg_new_img(void *data) { /* so we can poll for it */ block_usr1_signal(); struct imv_loader *ldr = data; char path[PATH_MAX] = "-"; pthread_mutex_lock(&ldr->lock); int from_stdin = !strncmp(path, ldr->path, 2); if(!from_stdin) { (void)snprintf(path, PATH_MAX, "%s", ldr->path); } pthread_mutex_unlock(&ldr->lock); FREE_IMAGE_FORMAT fmt; if (from_stdin) { pthread_mutex_lock(&ldr->lock); ldr->fi_buffer = FreeImage_OpenMemory(ldr->buffer, ldr->buffer_size); fmt = FreeImage_GetFileTypeFromMemory(ldr->fi_buffer, 0); pthread_mutex_unlock(&ldr->lock); } else { fmt = FreeImage_GetFileType(path, 0); } if(fmt == FIF_UNKNOWN) { if (from_stdin) { pthread_mutex_lock(&ldr->lock); FreeImage_CloseMemory(ldr->fi_buffer); pthread_mutex_unlock(&ldr->lock); } error_occurred(ldr); return NULL; } int num_frames = 1; FIMULTIBITMAP *mbmp = NULL; FIBITMAP *bmp = NULL; int width, height; int raw_frame_time = 100; /* default to 100 */ if(fmt == FIF_GIF) { if(from_stdin) { pthread_mutex_lock(&ldr->lock); mbmp = FreeImage_LoadMultiBitmapFromMemory(FIF_GIF, ldr->fi_buffer, GIF_LOAD256); pthread_mutex_unlock(&ldr->lock); } else { mbmp = FreeImage_OpenMultiBitmap(FIF_GIF, path, /* don't create file */ 0, /* read only */ 1, /* keep in memory */ 1, /* flags */ GIF_LOAD256); } if(!mbmp) { error_occurred(ldr); return NULL; } num_frames = FreeImage_GetPageCount(mbmp); FIBITMAP *frame = FreeImage_LockPage(mbmp, 0); width = FreeImage_GetWidth(frame); height = FreeImage_GetHeight(frame); bmp = FreeImage_ConvertTo32Bits(frame); /* get duration of first frame */ FITAG *tag = NULL; FreeImage_GetMetadata(FIMD_ANIMATION, frame, "FrameTime", &tag); if(FreeImage_GetTagValue(tag)) { raw_frame_time = *(int*)FreeImage_GetTagValue(tag); } FreeImage_UnlockPage(mbmp, frame, 0); } else { /* Future TODO: If we load image line-by-line we could stop loading large * ones before wasting much more time/memory on them. */ int flags = (fmt == FIF_JPEG) ? JPEG_EXIFROTATE : 0; FIBITMAP *image; if(from_stdin) { pthread_mutex_lock(&ldr->lock); image = FreeImage_LoadFromMemory(fmt, ldr->fi_buffer, flags); pthread_mutex_unlock(&ldr->lock); } else { image = FreeImage_Load(fmt, path, flags); } if(!image) { error_occurred(ldr); pthread_mutex_lock(&ldr->lock); FreeImage_CloseMemory(ldr->fi_buffer); ldr->fi_buffer = NULL; pthread_mutex_unlock(&ldr->lock); return NULL; } /* Check for cancellation before we convert pixel format */ if(is_thread_cancelled()) { FreeImage_Unload(image); return NULL; } width = FreeImage_GetWidth(bmp); height = FreeImage_GetHeight(bmp); bmp = FreeImage_ConvertTo32Bits(image); FreeImage_Unload(image); } /* now update the loader */ pthread_mutex_lock(&ldr->lock); /* check for cancellation before finishing */ if(is_thread_cancelled()) { if(mbmp) { FreeImage_CloseMultiBitmap(mbmp, 0); } if(bmp) { FreeImage_Unload(bmp); } pthread_mutex_unlock(&ldr->lock); return NULL; } if(ldr->mbmp) { FreeImage_CloseMultiBitmap(ldr->mbmp, 0); } if(ldr->bmp) { FreeImage_Unload(ldr->bmp); } ldr->mbmp = mbmp; ldr->bmp = bmp; if(ldr->out_bmp) { FreeImage_Unload(ldr->out_bmp); } ldr->out_bmp = FreeImage_Clone(bmp); ldr->out_is_new_image = 1; ldr->width = width; ldr->height = height; ldr->cur_frame = 0; ldr->next_frame = 1; ldr->num_frames = num_frames; ldr->frame_time = (double)raw_frame_time * 0.0001; pthread_mutex_unlock(&ldr->lock); return NULL; }
bool Texture::loadTexture(const char* path, bool generateMipMaps, bool defaultParameters) { printf("Reading image %s\n", path); FREE_IMAGE_FORMAT format = FIF_UNKNOWN; FIBITMAP* dib(0); format = FreeImage_GetFileType(path, 0); // Check the file signature and deduce its format if (format == FIF_UNKNOWN) // If still unknown, try to guess the file format from the file extension format = FreeImage_GetFIFFromFilename(path); if (format == FIF_UNKNOWN) // If still unkown, return failure { printf("Failure(1)\n"); return false; } // Check if the plugin has reading capabilities and load the file if (FreeImage_FIFSupportsReading(format)) dib = FreeImage_Load(format, path); if (!dib) { printf("Failure(2)\n"); return false; } BYTE* dataPointer = FreeImage_GetBits(dib); // Retrieve image data int width = FreeImage_GetWidth(dib); // Get the image width and height int height = FreeImage_GetHeight(dib); int BPP = FreeImage_GetBPP(dib); // bytes per pixel // If somehow one of these failed (they shouldn't), return failure if (dataPointer == NULL || width == 0 || height == 0) { printf("Failure(3)\n"); return false; } glGenTextures(1, &textureID); glBindTexture(GL_TEXTURE_2D, textureID); int texFormat = BPP == 24 ? GL_BGR : BPP == 8 ? GL_LUMINANCE : 0; //int internalFormat = BPP == 24 ? GL_RGB : GL_DEPTH_COMPONENT; glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, texFormat, GL_UNSIGNED_BYTE, dataPointer); FreeImage_Unload(dib); if (defaultParameters) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); } if (generateMipMaps) { glGenerateMipmap(GL_TEXTURE_2D); mipMapsGenerated = generateMipMaps; } return true; }
Texture* TextureManager::addTexture( const std::string& filename ) { Texture* ret = nullptr; FREE_IMAGE_FORMAT fif = FIF_UNKNOWN; FIBITMAP* dib = nullptr; // TODO This name is nonsense, change it // Find format from file signature fif = FreeImage_GetFileType( filename.c_str(), 0 ); if ( FIF_UNKNOWN == fif ) { // Find format from file extension fif = FreeImage_GetFIFFromFilename( filename.c_str() ); } if ( FIF_UNKNOWN == fif ) { // Still unknown std::string error = "Cannot determine " + filename + " image format."; LOG( logERROR ) << error; CORE_ASSERT( 0, error.c_str() ); return nullptr; } if ( FreeImage_FIFSupportsReading( fif ) ) { dib = FreeImage_Load( fif, filename.c_str() ); } std::string error = "Something went wrong while trying to load " + filename + "."; //CORE_ASSERT(dib, error.c_str()); if ( nullptr == dib ) { LOG( logERROR ) << error; return nullptr; } ret = new Texture( filename, GL_TEXTURE_2D ); unsigned char* data = FreeImage_GetBits( dib ); int bpp = FreeImage_GetBPP( dib ); int format = ( bpp == 24 ? GL_BGR : 0 ); // TODO Handle other formats int internal = ( bpp == 24 ? GL_RGB : 0 ); // TODO Handle other formats int w = FreeImage_GetWidth( dib ); int h = FreeImage_GetHeight( dib ); // FIXME(Charly): Use VLOG instead of the check if ( m_verbose ) { LOG( logINFO ) << "Image stats (" << filename << ") :\n" << "\tBPP : 0x" << std::hex << bpp << std::dec << std::endl << "\tFormat : 0x" << std::hex << format << std::dec << std::endl << "\tSize : " << w << ", " << h; } CORE_ASSERT( data, "Data is null" ); ret->initGL( internal, w, h, format, GL_UNSIGNED_BYTE, data ); ret->genMipmap( GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR ); m_textures.insert( TexturePair( filename, ret ) ); FreeImage_Unload( dib ); return ret; }
unsigned DLL_CALLCONV FreeImage_GetDIBSize(FIBITMAP *dib) { return (dib) ? sizeof(BITMAPINFOHEADER) + (FreeImage_GetColorsUsed(dib) * sizeof(RGBQUAD)) + (FreeImage_GetPitch(dib) * FreeImage_GetHeight(dib)) : 0; }
FIBITMAP * DLL_CALLCONV FreeImage_ConvertToUINT16(FIBITMAP *dib) { FIBITMAP *src = NULL; FIBITMAP *dst = NULL; if(!FreeImage_HasPixels(dib)) return NULL; const FREE_IMAGE_TYPE src_type = FreeImage_GetImageType(dib); // check for allowed conversions switch(src_type) { case FIT_BITMAP: { // convert to greyscale if needed if((FreeImage_GetBPP(dib) == 8) && (FreeImage_GetColorType(dib) == FIC_MINISBLACK)) { src = dib; } else { src = FreeImage_ConvertToGreyscale(dib); if(!src) return NULL; } break; } case FIT_UINT16: // UINT16 type : clone the src return FreeImage_Clone(dib); break; case FIT_RGB16: // allow conversion from 48-bit RGB src = dib; break; case FIT_RGBA16: // allow conversion from 64-bit RGBA (ignore the alpha channel) src = dib; break; default: return NULL; } // allocate dst image const unsigned width = FreeImage_GetWidth(src); const unsigned height = FreeImage_GetHeight(src); dst = FreeImage_AllocateT(FIT_UINT16, width, height); if(!dst) return NULL; // copy metadata from src to dst FreeImage_CloneMetadata(dst, src); // convert from src type to UINT16 switch(src_type) { case FIT_BITMAP: { for(unsigned y = 0; y < height; y++) { const BYTE *src_bits = (BYTE*)FreeImage_GetScanLine(src, y); WORD *dst_bits = (WORD*)FreeImage_GetScanLine(dst, y); for(unsigned x = 0; x < width; x++) { dst_bits[x] = src_bits[x] << 8; } } } break; case FIT_RGB16: { for(unsigned y = 0; y < height; y++) { const FIRGB16 *src_bits = (FIRGB16*)FreeImage_GetScanLine(src, y); WORD *dst_bits = (WORD*)FreeImage_GetScanLine(dst, y); for(unsigned x = 0; x < width; x++) { // convert to grey dst_bits[x] = (WORD)LUMA_REC709(src_bits[x].red, src_bits[x].green, src_bits[x].blue); } } } break; case FIT_RGBA16: { for(unsigned y = 0; y < height; y++) { const FIRGBA16 *src_bits = (FIRGBA16*)FreeImage_GetScanLine(src, y); WORD *dst_bits = (WORD*)FreeImage_GetScanLine(dst, y); for(unsigned x = 0; x < width; x++) { // convert to grey dst_bits[x] = (WORD)LUMA_REC709(src_bits[x].red, src_bits[x].green, src_bits[x].blue); } } } break; default: break; } if(src != dib) { FreeImage_Unload(src); } return dst; }
FREE_IMAGE_COLOR_TYPE DLL_CALLCONV FreeImage_GetColorType(FIBITMAP *dib) { RGBQUAD *rgb; const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); // special bitmap type if(image_type != FIT_BITMAP) { switch(image_type) { case FIT_RGB16: case FIT_RGBF: return FIC_RGB; case FIT_RGBA16: case FIT_RGBAF: return FIC_RGBALPHA; } return FIC_MINISBLACK; } // standard image type switch (FreeImage_GetBPP(dib)) { case 1: { rgb = FreeImage_GetPalette(dib); if ((rgb->rgbRed == 0) && (rgb->rgbGreen == 0) && (rgb->rgbBlue == 0)) { rgb++; if ((rgb->rgbRed == 255) && (rgb->rgbGreen == 255) && (rgb->rgbBlue == 255)) return FIC_MINISBLACK; } if ((rgb->rgbRed == 255) && (rgb->rgbGreen == 255) && (rgb->rgbBlue == 255)) { rgb++; if ((rgb->rgbRed == 0) && (rgb->rgbGreen == 0) && (rgb->rgbBlue == 0)) return FIC_MINISWHITE; } return FIC_PALETTE; } case 4: case 8: // Check if the DIB has a color or a greyscale palette { int ncolors = FreeImage_GetColorsUsed(dib); int minisblack = 1; rgb = FreeImage_GetPalette(dib); for (int i = 0; i < ncolors; i++) { if ((rgb->rgbRed != rgb->rgbGreen) || (rgb->rgbRed != rgb->rgbBlue)) return FIC_PALETTE; // The DIB has a color palette if the greyscale isn't a linear ramp // Take care of reversed grey images if (rgb->rgbRed != i) { if ((ncolors-i-1) != rgb->rgbRed) return FIC_PALETTE; else minisblack = 0; } rgb++; } return minisblack ? FIC_MINISBLACK : FIC_MINISWHITE; } case 16: case 24: return FIC_RGB; case 32: { if (FreeImage_GetICCProfile(dib)->flags & FIICC_COLOR_IS_CMYK) return FIC_CMYK; for (unsigned y = 0; y < FreeImage_GetHeight(dib); y++) { rgb = (RGBQUAD *)FreeImage_GetScanLine(dib, y); for (unsigned x = 0; x < FreeImage_GetWidth(dib); x++) if (rgb[x].rgbReserved != 0xFF) return FIC_RGBALPHA; } return FIC_RGB; } default : return FIC_MINISBLACK; } }
FIBITMAP * DLL_CALLCONV FreeImage_Clone(FIBITMAP *dib) { if(!dib) return NULL; unsigned width = FreeImage_GetWidth(dib); unsigned height = FreeImage_GetHeight(dib); unsigned bpp = FreeImage_GetBPP(dib); // check for pixel availability ... BOOL header_only = FreeImage_HasPixels(dib) ? FALSE : TRUE; // allocate a new dib FIBITMAP *new_dib = FreeImage_AllocateHeaderT(header_only, FreeImage_GetImageType(dib), width, height, bpp, FreeImage_GetRedMask(dib), FreeImage_GetGreenMask(dib), FreeImage_GetBlueMask(dib)); if (new_dib) { // save ICC profile links FIICCPROFILE *src_iccProfile = FreeImage_GetICCProfile(dib); FIICCPROFILE *dst_iccProfile = FreeImage_GetICCProfile(new_dib); // save metadata links METADATAMAP *src_metadata = ((FREEIMAGEHEADER *)dib->data)->metadata; METADATAMAP *dst_metadata = ((FREEIMAGEHEADER *)new_dib->data)->metadata; // calculate the size of a FreeImage image // align the palette and the pixels on a FIBITMAP_ALIGNMENT bytes alignment boundary // palette is aligned on a 16 bytes boundary // pixels are aligned on a 16 bytes boundary size_t dib_size = FreeImage_GetImageSizeHeader(header_only, width, height, bpp); // copy the bitmap + internal pointers (remember to restore new_dib internal pointers later) memcpy(new_dib->data, dib->data, dib_size); // reset ICC profile link for new_dib memset(dst_iccProfile, 0, sizeof(FIICCPROFILE)); // restore metadata link for new_dib ((FREEIMAGEHEADER *)new_dib->data)->metadata = dst_metadata; // reset thumbnail link for new_dib ((FREEIMAGEHEADER *)new_dib->data)->thumbnail = NULL; // copy possible ICC profile FreeImage_CreateICCProfile(new_dib, src_iccProfile->data, src_iccProfile->size); dst_iccProfile->flags = src_iccProfile->flags; // copy metadata models for(METADATAMAP::iterator i = (*src_metadata).begin(); i != (*src_metadata).end(); i++) { int model = (*i).first; TAGMAP *src_tagmap = (*i).second; if(src_tagmap) { // create a metadata model TAGMAP *dst_tagmap = new(std::nothrow) TAGMAP(); if(dst_tagmap) { // fill the model for(TAGMAP::iterator j = src_tagmap->begin(); j != src_tagmap->end(); j++) { std::string dst_key = (*j).first; FITAG *dst_tag = FreeImage_CloneTag( (*j).second ); // assign key and tag value (*dst_tagmap)[dst_key] = dst_tag; } // assign model and tagmap (*dst_metadata)[model] = dst_tagmap; } } } // copy the thumbnail FreeImage_SetThumbnail(new_dib, FreeImage_GetThumbnail(dib)); return new_dib; } return NULL; }
int main(int argc, char *argv[]) { printf("%s Starting...\n\n", argv[0]); try { std::string sFilename; char *filePath = sdkFindFilePath("Lena.pgm", argv[0]); if (filePath) { sFilename = filePath; } else { printf("Error unable to find Lena.pgm\n"); exit(EXIT_FAILURE); } // set your own FreeImage error handler FreeImage_SetOutputMessage(FreeImageErrorHandler); cudaDeviceInit(argc, (const char **)argv); // Min spec is SM 1.0 devices if (printfNPPinfo(argc, argv, 1, 0) == false) { cudaDeviceReset(); exit(EXIT_SUCCESS); } if (argc > 1) { sFilename = argv[1]; } // if we specify the filename at the command line, then we only test sFilename // otherwise we will check both sFilename[0,1] int file_errors = 0; std::ifstream infile(sFilename.data(), std::ifstream::in); if (infile.good()) { std::cout << "freeImageInteropNPP opened: <" << sFilename.data() << "> successfully!" << std::endl; file_errors = 0; infile.close(); } else { std::cout << "freeImageInteropNPP unable to open: <" << sFilename.data() << ">" << std::endl; file_errors++; infile.close(); } if (file_errors > 0) { exit(EXIT_FAILURE); } std::string sResultFilename = sFilename; std::string::size_type dot = sResultFilename.rfind('.'); if (dot != std::string::npos) { sResultFilename = sResultFilename.substr(0, dot); } sResultFilename += "_boxFilterFII.pgm"; if (argc >= 3) { sResultFilename = argv[2]; } FREE_IMAGE_FORMAT eFormat = FreeImage_GetFileType(sFilename.c_str()); // no signature? try to guess the file format from the file extension if (eFormat == FIF_UNKNOWN) { eFormat = FreeImage_GetFIFFromFilename(sFilename.c_str()); } NPP_ASSERT(eFormat != FIF_UNKNOWN); // check that the plugin has reading capabilities ... FIBITMAP *pBitmap; if (FreeImage_FIFSupportsReading(eFormat)) { pBitmap = FreeImage_Load(eFormat, sFilename.c_str()); } NPP_ASSERT(pBitmap != 0); // Dump the bitmap information to the console std::cout << (*pBitmap) << std::endl; // make sure this is an 8-bit single channel image NPP_ASSERT(FreeImage_GetColorType(pBitmap) == FIC_MINISBLACK); NPP_ASSERT(FreeImage_GetBPP(pBitmap) == 8); unsigned int nImageWidth = FreeImage_GetWidth(pBitmap); unsigned int nImageHeight = FreeImage_GetHeight(pBitmap); unsigned int nSrcPitch = FreeImage_GetPitch(pBitmap); unsigned char *pSrcData = FreeImage_GetBits(pBitmap); int nSrcPitchCUDA; Npp8u *pSrcImageCUDA = nppiMalloc_8u_C1(nImageWidth, nImageHeight, &nSrcPitchCUDA); NPP_ASSERT_NOT_NULL(pSrcImageCUDA); // copy image loaded via FreeImage to into CUDA device memory, i.e. // transfer the image-data up to the GPU's video-memory NPP_CHECK_CUDA(cudaMemcpy2D(pSrcImageCUDA, nSrcPitchCUDA, pSrcData, nSrcPitch, nImageWidth, nImageHeight, cudaMemcpyHostToDevice)); // define size of the box filter const NppiSize oMaskSize = {7, 7}; const NppiPoint oMaskAchnor = {0, 0}; // compute maximal result image size const NppiSize oSizeROI = {nImageWidth - (oMaskSize.width - 1), nImageHeight - (oMaskSize.height - 1) }; // allocate result image memory int nDstPitchCUDA; Npp8u *pDstImageCUDA = nppiMalloc_8u_C1(oSizeROI.width, oSizeROI.height, &nDstPitchCUDA); NPP_ASSERT_NOT_NULL(pDstImageCUDA); NPP_CHECK_NPP(nppiFilterBox_8u_C1R(pSrcImageCUDA, nSrcPitchCUDA, pDstImageCUDA, nDstPitchCUDA, oSizeROI, oMaskSize, oMaskAchnor)); // create the result image storage using FreeImage so we can easily // save FIBITMAP *pResultBitmap = FreeImage_Allocate(oSizeROI.width, oSizeROI.height, 8 /* bits per pixel */); NPP_ASSERT_NOT_NULL(pResultBitmap); unsigned int nResultPitch = FreeImage_GetPitch(pResultBitmap); unsigned char *pResultData = FreeImage_GetBits(pResultBitmap); NPP_CHECK_CUDA(cudaMemcpy2D(pResultData, nResultPitch, pDstImageCUDA, nDstPitchCUDA, oSizeROI.width, oSizeROI.height, cudaMemcpyDeviceToHost)); // now save the result image bool bSuccess; bSuccess = FreeImage_Save(FIF_PGM, pResultBitmap, sResultFilename.c_str(), 0) == TRUE; NPP_ASSERT_MSG(bSuccess, "Failed to save result image."); //free nppiImage nppiFree(pSrcImageCUDA); nppiFree(pDstImageCUDA); cudaDeviceReset(); exit(EXIT_SUCCESS); } catch (npp::Exception &rException) { std::cerr << "Program error! The following exception occurred: \n"; std::cerr << rException << std::endl; std::cerr << "Aborting." << std::endl; exit(EXIT_FAILURE); } catch (...) { std::cerr << "Program error! An unknow type of exception occurred. \n"; std::cerr << "Aborting." << std::endl; exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); }
unsigned fipImage::getHeight() const { return FreeImage_GetHeight(_dib); }
mng_ptr mymnggetcanvasline(mng_handle mng, mng_uint32 line) { FIBITMAP *bitmap = ((mngstuff *)mng_get_userdata(mng))->bitmap; return FreeImage_GetScanLine(bitmap, FreeImage_GetHeight(bitmap) - line - 1); }
BYTE* fipImage::getScanLine(unsigned scanline) const { if(scanline < FreeImage_GetHeight(_dib)) { return FreeImage_GetScanLine(_dib, scanline); } return NULL; }
void load_image(const char *fname) { // active only for static linking #ifdef FREEIMAGE_LIB FreeImage_Initialise(); #endif FIBITMAP *bitmap; // Get the format of the image file FREE_IMAGE_FORMAT fif =FreeImage_GetFileType(fname, 0); // If the format can't be determined, try to guess the format from the file name if(fif == FIF_UNKNOWN) { fif = FreeImage_GetFIFFromFilename(fname); } // Load the data in bitmap if possible if(fif != FIF_UNKNOWN && FreeImage_FIFSupportsReading(fif)) { bitmap = FreeImage_Load(fif, fname); } else { bitmap = NULL; } // PROCESS IMAGE if bitmap was successfully initialized if(bitmap) { unsigned int w = FreeImage_GetWidth(bitmap); unsigned int h = FreeImage_GetHeight(bitmap); unsigned pixel_size = FreeImage_GetBPP(bitmap); // Get a pointer to the pixel data BYTE *data = (BYTE*)FreeImage_GetBits(bitmap); // Process only RGB and RGBA images if(pixel_size == 24) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_BGR, GL_UNSIGNED_BYTE, (GLvoid*)data); } else if (pixel_size == 32) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid*)data); } else { std::cerr << "pixel size = " << pixel_size << " don't know how to process this case. I'm out!" << std::endl; exit(-1); } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } else { std::cerr << "Unable to load the image file " << fname << " I'm out!" << std::endl; exit(-1); } // Clean bitmap; FreeImage_Unload(bitmap); // active only for static linking #ifdef FREEIMAGE_LIB FreeImage_DeInitialise(); #endif }
bool CPicture::Load(tstring sFilePathName) { bool bResult = false; bIsIcon = false; lpIcons = NULL; //CFile PictureFile; //CFileException e; FreePictureData(); // Important - Avoid Leaks... // No-op if no file specified if (sFilePathName.empty()) return true; // Load & initialize the GDI+ library if available HMODULE hGdiPlusLib = AtlLoadSystemLibraryUsingFullPath(_T("gdiplus.dll")); if (hGdiPlusLib && GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL) == Ok) { bHaveGDIPlus = true; } // Since we loaded the gdiplus.dll only to check if it's available, we // can safely free the library here again - GdiplusStartup() loaded it too // and reference counting will make sure that it stays loaded until GdiplusShutdown() // is called. FreeLibrary(hGdiPlusLib); // Attempt to load using GDI+ if available if (bHaveGDIPlus) { pBitmap = new Bitmap(sFilePathName.c_str(), FALSE); GUID guid; pBitmap->GetRawFormat(&guid); if (pBitmap->GetLastStatus() != Ok) { delete pBitmap; pBitmap = NULL; } // gdiplus only loads the first icon found in an icon file // so we have to handle icon files ourselves :( // Even though gdiplus can load icons, it can't load the new // icons from Vista - in Vista, the icon format changed slightly. // But the LoadIcon/LoadImage API still can load those icons, // at least those dimensions which are also used on pre-Vista // systems. // For that reason, we don't rely on gdiplus telling us if // the image format is "icon" or not, we also check the // file extension for ".ico". std::transform(sFilePathName.begin(), sFilePathName.end(), sFilePathName.begin(), ::tolower); bIsIcon = (guid == ImageFormatIcon) || (wcsstr(sFilePathName.c_str(), L".ico") != NULL) || (wcsstr(sFilePathName.c_str(), L".cur") != NULL); bIsTiff = (guid == ImageFormatTIFF) || (_tcsstr(sFilePathName.c_str(), _T(".tiff")) != NULL); m_Name = sFilePathName; if (bIsIcon) { // Icon file, get special treatment... if (pBitmap) { // Cleanup first... delete (pBitmap); pBitmap = NULL; bIsIcon = true; } CAutoFile hFile = CreateFile(sFilePathName.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile) { BY_HANDLE_FILE_INFORMATION fileinfo; if (GetFileInformationByHandle(hFile, &fileinfo)) { lpIcons = new BYTE[fileinfo.nFileSizeLow]; DWORD readbytes; if (ReadFile(hFile, lpIcons, fileinfo.nFileSizeLow, &readbytes, NULL)) { // we have the icon. Now gather the information we need later if (readbytes >= sizeof(ICONDIR)) { // we are going to open same file second time so we have to close the file now hFile.CloseHandle(); LPICONDIR lpIconDir = (LPICONDIR)lpIcons; if ((lpIconDir->idCount) && ((lpIconDir->idCount * sizeof(ICONDIR)) <= fileinfo.nFileSizeLow)) { try { bResult = false; nCurrentIcon = 0; hIcons = new HICON[lpIconDir->idCount]; // check that the pointers point to data that we just loaded if (((BYTE*)lpIconDir->idEntries > (BYTE*)lpIconDir) && (((BYTE*)lpIconDir->idEntries) + (lpIconDir->idCount * sizeof(ICONDIRENTRY)) < ((BYTE*)lpIconDir) + fileinfo.nFileSizeLow)) { m_Width = lpIconDir->idEntries[0].bWidth; m_Height = lpIconDir->idEntries[0].bHeight; bResult = true; for (int i=0; i<lpIconDir->idCount; ++i) { hIcons[i] = (HICON)LoadImage(NULL, sFilePathName.c_str(), IMAGE_ICON, lpIconDir->idEntries[i].bWidth, lpIconDir->idEntries[i].bHeight, LR_LOADFROMFILE); if (hIcons[i] == NULL) { // if the icon couldn't be loaded, the data is most likely corrupt delete [] lpIcons; lpIcons = NULL; bResult = false; break; } } } } catch (...) { delete [] lpIcons; lpIcons = NULL; bResult = false; } } else { delete [] lpIcons; lpIcons = NULL; bResult = false; } } else { delete [] lpIcons; lpIcons = NULL; bResult = false; } } else { delete [] lpIcons; lpIcons = NULL; } } } } else if (pBitmap) // Image loaded successfully with GDI+ { m_Height = pBitmap->GetHeight(); m_Width = pBitmap->GetWidth(); bResult = true; } // If still failed to load the file... if (!bResult) { // Attempt to load the FreeImage library as an optional DLL to support additional formats // NOTE: Currently just loading via FreeImage & using GDI+ for drawing. // It might be nice to remove this dependency in the future. HMODULE hFreeImageLib = LoadLibrary(_T("FreeImage.dll")); // FreeImage DLL functions typedef const char* (__stdcall *FreeImage_GetVersion_t)(void); typedef int (__stdcall *FreeImage_GetFileType_t)(const TCHAR *filename, int size); typedef int (__stdcall *FreeImage_GetFIFFromFilename_t)(const TCHAR *filename); typedef void* (__stdcall *FreeImage_Load_t)(int format, const TCHAR *filename, int flags); typedef void (__stdcall *FreeImage_Unload_t)(void* dib); typedef int (__stdcall *FreeImage_GetColorType_t)(void* dib); typedef unsigned (__stdcall *FreeImage_GetWidth_t)(void* dib); typedef unsigned (__stdcall *FreeImage_GetHeight_t)(void* dib); typedef void (__stdcall *FreeImage_ConvertToRawBits_t)(BYTE *bits, void *dib, int pitch, unsigned bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask, BOOL topdown); //FreeImage_GetVersion_t FreeImage_GetVersion = NULL; FreeImage_GetFileType_t FreeImage_GetFileType = NULL; FreeImage_GetFIFFromFilename_t FreeImage_GetFIFFromFilename = NULL; FreeImage_Load_t FreeImage_Load = NULL; FreeImage_Unload_t FreeImage_Unload = NULL; //FreeImage_GetColorType_t FreeImage_GetColorType = NULL; FreeImage_GetWidth_t FreeImage_GetWidth = NULL; FreeImage_GetHeight_t FreeImage_GetHeight = NULL; FreeImage_ConvertToRawBits_t FreeImage_ConvertToRawBits = NULL; if (hFreeImageLib) { bool exportsValid = true; //FreeImage_GetVersion = (FreeImage_GetVersion_t)s_GetProcAddressEx(hFreeImageLib, "_FreeImage_GetVersion@0", valid); FreeImage_GetWidth = (FreeImage_GetWidth_t)s_GetProcAddressEx(hFreeImageLib, "_FreeImage_GetWidth@4", exportsValid); FreeImage_GetHeight = (FreeImage_GetHeight_t)s_GetProcAddressEx(hFreeImageLib, "_FreeImage_GetHeight@4", exportsValid); FreeImage_Unload = (FreeImage_Unload_t)s_GetProcAddressEx(hFreeImageLib, "_FreeImage_Unload@4", exportsValid); FreeImage_ConvertToRawBits = (FreeImage_ConvertToRawBits_t)s_GetProcAddressEx(hFreeImageLib, "_FreeImage_ConvertToRawBits@32", exportsValid); #ifdef UNICODE FreeImage_GetFileType = (FreeImage_GetFileType_t)s_GetProcAddressEx(hFreeImageLib, "_FreeImage_GetFileTypeU@8", exportsValid); FreeImage_GetFIFFromFilename = (FreeImage_GetFIFFromFilename_t)s_GetProcAddressEx(hFreeImageLib, "_FreeImage_GetFIFFromFilenameU@4", exportsValid); FreeImage_Load = (FreeImage_Load_t)s_GetProcAddressEx(hFreeImageLib, "_FreeImage_LoadU@12", exportsValid); #else FreeImage_GetFileType = (FreeImage_GetFileType_t)s_GetProcAddressEx(hFreeImageLib, "_FreeImage_GetFileType@8", exportsValid); FreeImage_GetFIFFromFilename = (FreeImage_GetFIFFromFilename_t)s_GetProcAddressEx(hFreeImageLib, "_FreeImage_GetFIFFromFilename@4", exportsValid); FreeImage_Load = (FreeImage_Load_t)s_GetProcAddressEx(hFreeImageLib, "_FreeImage_Load@12", exportsValid); #endif //const char* version = FreeImage_GetVersion(); // Check the DLL is using compatible exports if (exportsValid) { // Derive file type from file header. int fileType = FreeImage_GetFileType(sFilePathName.c_str(), 0); if (fileType < 0) { // No file header available, attempt to parse file name for extension. fileType = FreeImage_GetFIFFromFilename(sFilePathName.c_str()); } // If we have a valid file type if (fileType >= 0) { void* dib = FreeImage_Load(fileType, sFilePathName.c_str(), 0); if (dib) { unsigned width = FreeImage_GetWidth(dib); unsigned height = FreeImage_GetHeight(dib); // Create a GDI+ bitmap to load into... pBitmap = new Bitmap(width, height, PixelFormat32bppARGB); if (pBitmap && pBitmap->GetLastStatus() == Ok) { // Write & convert the loaded data into the GDI+ Bitmap Rect rect(0, 0, width, height); BitmapData bitmapData; if (pBitmap->LockBits(&rect, ImageLockModeWrite, PixelFormat32bppARGB, &bitmapData) == Ok) { FreeImage_ConvertToRawBits((BYTE*)bitmapData.Scan0, dib, bitmapData.Stride, 32, 0xff << RED_SHIFT, 0xff << GREEN_SHIFT, 0xff << BLUE_SHIFT, FALSE); pBitmap->UnlockBits(&bitmapData); m_Width = width; m_Height = height; bResult = true; } else // Failed to lock the destination Bitmap { delete pBitmap; pBitmap = NULL; } } else // Bitmap allocation failed { delete pBitmap; pBitmap = NULL; } FreeImage_Unload(dib); dib = NULL; } } } FreeLibrary(hFreeImageLib); hFreeImageLib = NULL; } } }
FIBITMAP * DLL_CALLCONV FreeImage_ConvertToFloat(FIBITMAP *dib) { FIBITMAP *src = NULL; FIBITMAP *dst = NULL; if(!FreeImage_HasPixels(dib)) return NULL; FREE_IMAGE_TYPE src_type = FreeImage_GetImageType(dib); // check for allowed conversions switch(src_type) { case FIT_BITMAP: { // allow conversion from 8-bit if((FreeImage_GetBPP(dib) == 8) && (FreeImage_GetColorType(dib) == FIC_MINISBLACK)) { src = dib; } else { src = FreeImage_ConvertToGreyscale(dib); if(!src) return NULL; } break; } case FIT_UINT16: case FIT_RGB16: case FIT_RGBA16: case FIT_RGBF: case FIT_RGBAF: src = dib; break; case FIT_FLOAT: // float type : clone the src return FreeImage_Clone(dib); default: return NULL; } // allocate dst image const unsigned width = FreeImage_GetWidth(src); const unsigned height = FreeImage_GetHeight(src); dst = FreeImage_AllocateT(FIT_FLOAT, width, height); if(!dst) { if(src != dib) { FreeImage_Unload(src); } return NULL; } // copy metadata from src to dst FreeImage_CloneMetadata(dst, src); // convert from src type to float const unsigned src_pitch = FreeImage_GetPitch(src); const unsigned dst_pitch = FreeImage_GetPitch(dst); const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src); BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst); switch(src_type) { case FIT_BITMAP: { for(unsigned y = 0; y < height; y++) { const BYTE *src_pixel = (BYTE*)src_bits; float *dst_pixel = (float*)dst_bits; for(unsigned x = 0; x < width; x++) { // convert and scale to the range [0..1] dst_pixel[x] = (float)(src_pixel[x]) / 255; } src_bits += src_pitch; dst_bits += dst_pitch; } } break; case FIT_UINT16: { for(unsigned y = 0; y < height; y++) { const WORD *src_pixel = (WORD*)src_bits; float *dst_pixel = (float*)dst_bits; for(unsigned x = 0; x < width; x++) { // convert and scale to the range [0..1] dst_pixel[x] = (float)(src_pixel[x]) / 65535; } src_bits += src_pitch; dst_bits += dst_pitch; } } break; case FIT_RGB16: { for(unsigned y = 0; y < height; y++) { const FIRGB16 *src_pixel = (FIRGB16*)src_bits; float *dst_pixel = (float*)dst_bits; for(unsigned x = 0; x < width; x++) { // convert and scale to the range [0..1] dst_pixel[x] = LUMA_REC709(src_pixel[x].red, src_pixel[x].green, src_pixel[x].blue) / 65535.0F; } src_bits += src_pitch; dst_bits += dst_pitch; } } break; case FIT_RGBA16: { for(unsigned y = 0; y < height; y++) { const FIRGBA16 *src_pixel = (FIRGBA16*)src_bits; float *dst_pixel = (float*)dst_bits; for(unsigned x = 0; x < width; x++) { // convert and scale to the range [0..1] dst_pixel[x] = LUMA_REC709(src_pixel[x].red, src_pixel[x].green, src_pixel[x].blue) / 65535.0F; } src_bits += src_pitch; dst_bits += dst_pitch; } } break; case FIT_RGBF: { for(unsigned y = 0; y < height; y++) { const FIRGBF *src_pixel = (FIRGBF*)src_bits; float *dst_pixel = (float*)dst_bits; for(unsigned x = 0; x < width; x++) { // convert (assume pixel values are in the range [0..1]) dst_pixel[x] = LUMA_REC709(src_pixel[x].red, src_pixel[x].green, src_pixel[x].blue); } src_bits += src_pitch; dst_bits += dst_pitch; } } break; case FIT_RGBAF: { for(unsigned y = 0; y < height; y++) { const FIRGBAF *src_pixel = (FIRGBAF*)src_bits; float *dst_pixel = (float*)dst_bits; for(unsigned x = 0; x < width; x++) { // convert (assume pixel values are in the range [0..1]) dst_pixel[x] = LUMA_REC709(src_pixel[x].red, src_pixel[x].green, src_pixel[x].blue); } src_bits += src_pitch; dst_bits += dst_pitch; } } break; } if(src != dib) { FreeImage_Unload(src); } return dst; }
static void *bg_next_frame(void *data) { struct imv_loader *ldr = data; pthread_mutex_lock(&ldr->lock); int num_frames = ldr->num_frames; if(num_frames < 2) { pthread_mutex_unlock(&ldr->lock); return NULL; } FITAG *tag = NULL; char disposal_method = 0; int frame_time = 0; short top = 0; short left = 0; ldr->cur_frame = ldr->next_frame; ldr->next_frame = (ldr->cur_frame + 1) % ldr->num_frames; FIBITMAP *frame = FreeImage_LockPage(ldr->mbmp, ldr->cur_frame); FIBITMAP *frame32 = FreeImage_ConvertTo32Bits(frame); /* First frame is always going to use the raw frame */ if(ldr->cur_frame > 0) { FreeImage_GetMetadata(FIMD_ANIMATION, frame, "DisposalMethod", &tag); if(FreeImage_GetTagValue(tag)) { disposal_method = *(char*)FreeImage_GetTagValue(tag); } } FreeImage_GetMetadata(FIMD_ANIMATION, frame, "FrameLeft", &tag); if(FreeImage_GetTagValue(tag)) { left = *(short*)FreeImage_GetTagValue(tag); } FreeImage_GetMetadata(FIMD_ANIMATION, frame, "FrameTop", &tag); if(FreeImage_GetTagValue(tag)) { top = *(short*)FreeImage_GetTagValue(tag); } FreeImage_GetMetadata(FIMD_ANIMATION, frame, "FrameTime", &tag); if(FreeImage_GetTagValue(tag)) { frame_time = *(int*)FreeImage_GetTagValue(tag); } /* some gifs don't provide a frame time at all */ if(frame_time == 0) { frame_time = 100; } ldr->frame_time += frame_time * 0.001; FreeImage_UnlockPage(ldr->mbmp, frame, 0); /* If this frame is inset, we need to expand it for compositing */ if(ldr->width != (int)FreeImage_GetWidth(frame32) || ldr->height != (int)FreeImage_GetHeight(frame32)) { FIBITMAP *expanded = FreeImage_Allocate(ldr->width, ldr->height, 32, 0,0,0); FreeImage_Paste(expanded, frame32, left, top, 255); FreeImage_Unload(frame32); frame32 = expanded; } switch(disposal_method) { case 0: /* nothing specified, fall through to compositing */ case 1: /* composite over previous frame */ if(ldr->bmp && ldr->cur_frame > 0) { FIBITMAP *bg_frame = FreeImage_ConvertTo24Bits(ldr->bmp); FreeImage_Unload(ldr->bmp); FIBITMAP *comp = FreeImage_Composite(frame32, 1, NULL, bg_frame); FreeImage_Unload(bg_frame); FreeImage_Unload(frame32); ldr->bmp = comp; } else { /* No previous frame, just render directly */ if(ldr->bmp) { FreeImage_Unload(ldr->bmp); } ldr->bmp = frame32; } break; case 2: /* TODO - set to background, composite over that */ if(ldr->bmp) { FreeImage_Unload(ldr->bmp); } ldr->bmp = frame32; break; case 3: /* TODO - restore to previous content */ if(ldr->bmp) { FreeImage_Unload(ldr->bmp); } ldr->bmp = frame32; break; } if(ldr->out_bmp) { FreeImage_Unload(ldr->out_bmp); } ldr->out_bmp = FreeImage_Clone(ldr->bmp); pthread_mutex_unlock(&ldr->lock); return NULL; }
CImageDataLoader::CImageData::CImageData(IDataStream* pData) { if(pData->IsValid()) { static bool init = false; if(!init) { init = true; TLS_data backup = *TLS::getData(); TLS::getData()->domain_ptr = nullptr; TLS::getData()->domain_guid = guidNull; FreeImage_Initialise(); *TLS::getData() = backup; } TLS_data backup = *TLS::getData(); TLS::getData()->domain_ptr = nullptr; TLS::getData()->domain_guid = guidNull; FIBITMAP* fibitmap = FreeImage_LoadFromHandle(FIF_PNG,&ImageLoaderIO,(fi_handle)pData); *TLS::getData() = backup; if(fibitmap) { _Width = FreeImage_GetWidth(fibitmap); _Height = FreeImage_GetHeight(fibitmap); _Format = R8G8B8A8; _Data = new u8[_Width*_Height*sizeof(u32)]; for(int iy =0; iy < _Height; ++iy) for(int ix =0; ix < _Width; ++ix) { RGBQUAD color; FreeImage_GetPixelColor(fibitmap,ix,iy,&color); ((u32*)_Data)[iy*_Width+ix] = ((u32)color.rgbRed << 0) | ((u32)color.rgbGreen << 8) | ((u32)color.rgbBlue << 16) | ((u32)0xff << 24); } TLS_data backup = *TLS::getData(); TLS::getData()->domain_ptr = nullptr; TLS::getData()->domain_guid = guidNull; FreeImage_Unload(fibitmap); *TLS::getData() = backup; _Levels = 1; return; } pData->Seek(0,IDataStream::ORIGIN_BEGINNING); if(TryLoadBLP(pData)) return; pData->Seek(0,IDataStream::ORIGIN_BEGINNING); /* SparseVirtualTextureFile hsvt; if(hsvt.Open(pData)) { _Width = 5120; _Height = 5120; _Format = R8G8B8A8; _Levels = 1; _Data = new u8[_Width*_Height*sizeof(u32)]; hsvt.ReadImageFromVirtualTexture(0,0,_Width,_Height,_Data,6); return; } pData->Seek(0,IDataStream::ORIGIN_BEGINNING);*/ } // loading failed _Width = 256; _Height = 256; _Format = R8G8B8A8; _Levels = 1; _Data = new u8[_Width*_Height*sizeof(u32)]; for(int iy =0; iy < _Height; ++iy) for(int ix =0; ix < _Width; ++ix) ((u32*)_Data)[iy*_Width+ix] = ((1-((iy/64)+(ix/64))%2) * 0x00ffffff) | 0xff000000; }
static BOOL DLL_CALLCONV Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) { png_structp png_ptr = nullptr; png_infop info_ptr; png_colorp palette = NULL; png_uint_32 width, height; BOOL has_alpha_channel = FALSE; RGBQUAD *pal; // pointer to dib palette int bit_depth, pixel_depth; // pixel_depth = bit_depth * channels int palette_entries; int interlace_type; fi_ioStructure fio; fio.s_handle = handle; fio.s_io = io; if ((dib) && (handle)) { try { // create the chunk manage structure png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, error_handler, warning_handler); if (!png_ptr) { return FALSE; } // allocate/initialize the image information data. info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, (png_infopp)NULL); return FALSE; } // Set error handling. REQUIRED if you aren't supplying your own // error handling functions in the png_create_write_struct() call. if (setjmp(png_jmpbuf(png_ptr))) { // if we get here, we had a problem reading the file png_destroy_write_struct(&png_ptr, &info_ptr); return FALSE; } // init the IO png_set_write_fn(png_ptr, &fio, _WriteProc, _FlushProc); // set physical resolution png_uint_32 res_x = (png_uint_32)FreeImage_GetDotsPerMeterX(dib); png_uint_32 res_y = (png_uint_32)FreeImage_GetDotsPerMeterY(dib); if ((res_x > 0) && (res_y > 0)) { png_set_pHYs(png_ptr, info_ptr, res_x, res_y, PNG_RESOLUTION_METER); } // Set the image information here. Width and height are up to 2^31, // bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on // the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY, // PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB, // or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or // PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST // currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED width = FreeImage_GetWidth(dib); height = FreeImage_GetHeight(dib); pixel_depth = FreeImage_GetBPP(dib); BOOL bInterlaced = FALSE; if( (flags & PNG_INTERLACED) == PNG_INTERLACED) { interlace_type = PNG_INTERLACE_ADAM7; bInterlaced = TRUE; } else { interlace_type = PNG_INTERLACE_NONE; } // set the ZLIB compression level or default to PNG default compression level (ZLIB level = 6) int zlib_level = flags & 0x0F; if((zlib_level >= 1) && (zlib_level <= 9)) { png_set_compression_level(png_ptr, zlib_level); } else if((flags & PNG_Z_NO_COMPRESSION) == PNG_Z_NO_COMPRESSION) { png_set_compression_level(png_ptr, Z_NO_COMPRESSION); } // filtered strategy works better for high color images if(pixel_depth >= 16){ png_set_compression_strategy(png_ptr, Z_FILTERED); png_set_filter(png_ptr, 0, PNG_FILTER_NONE|PNG_FILTER_SUB|PNG_FILTER_PAETH); } else { png_set_compression_strategy(png_ptr, Z_DEFAULT_STRATEGY); } FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); if(image_type == FIT_BITMAP) { // standard image type bit_depth = (pixel_depth > 8) ? 8 : pixel_depth; } else { // 16-bit greyscale or 16-bit RGB(A) bit_depth = 16; } // check for transparent images BOOL bIsTransparent = (image_type == FIT_BITMAP) && FreeImage_IsTransparent(dib) && (FreeImage_GetTransparencyCount(dib) > 0) ? TRUE : FALSE; switch (FreeImage_GetColorType(dib)) { case FIC_MINISWHITE: if(!bIsTransparent) { // Invert monochrome files to have 0 as black and 1 as white (no break here) png_set_invert_mono(png_ptr); } // (fall through) case FIC_MINISBLACK: if(!bIsTransparent) { png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, PNG_COLOR_TYPE_GRAY, interlace_type, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); break; } // If a monochrome image is transparent, save it with a palette // (fall through) case FIC_PALETTE: { png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, PNG_COLOR_TYPE_PALETTE, interlace_type, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); // set the palette palette_entries = 1 << bit_depth; palette = (png_colorp)png_malloc(png_ptr, palette_entries * sizeof (png_color)); pal = FreeImage_GetPalette(dib); for (int i = 0; i < palette_entries; i++) { palette[i].red = pal[i].rgbRed; palette[i].green = pal[i].rgbGreen; palette[i].blue = pal[i].rgbBlue; } png_set_PLTE(png_ptr, info_ptr, palette, palette_entries); // You must not free palette here, because png_set_PLTE only makes a link to // the palette that you malloced. Wait until you are about to destroy // the png structure. break; } case FIC_RGBALPHA : has_alpha_channel = TRUE; png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, PNG_COLOR_TYPE_RGBA, interlace_type, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); #if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR // flip BGR pixels to RGB if(image_type == FIT_BITMAP) { png_set_bgr(png_ptr); } #endif break; case FIC_RGB: png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, PNG_COLOR_TYPE_RGB, interlace_type, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); #if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR // flip BGR pixels to RGB if(image_type == FIT_BITMAP) { png_set_bgr(png_ptr); } #endif break; case FIC_CMYK: break; } // write possible ICC profile FIICCPROFILE *iccProfile = FreeImage_GetICCProfile(dib); if (iccProfile->size && iccProfile->data) { png_set_iCCP(png_ptr, info_ptr, "Embedded Profile", 0, (png_const_bytep)iccProfile->data, iccProfile->size); } // write metadata WriteMetadata(png_ptr, info_ptr, dib); // Optional gamma chunk is strongly suggested if you have any guess // as to the correct gamma of the image. // png_set_gAMA(png_ptr, info_ptr, gamma); // set the transparency table if (bIsTransparent) { png_set_tRNS(png_ptr, info_ptr, FreeImage_GetTransparencyTable(dib), FreeImage_GetTransparencyCount(dib), NULL); } // set the background color if(FreeImage_HasBackgroundColor(dib)) { png_color_16 image_background; RGBQUAD rgbBkColor; FreeImage_GetBackgroundColor(dib, &rgbBkColor); memset(&image_background, 0, sizeof(png_color_16)); image_background.blue = rgbBkColor.rgbBlue; image_background.green = rgbBkColor.rgbGreen; image_background.red = rgbBkColor.rgbRed; image_background.index = rgbBkColor.rgbReserved; png_set_bKGD(png_ptr, info_ptr, &image_background); } // Write the file header information. png_write_info(png_ptr, info_ptr); // write out the image data #ifndef FREEIMAGE_BIGENDIAN if (bit_depth == 16) { // turn on 16 bit byte swapping png_set_swap(png_ptr); } #endif int number_passes = 1; if (bInterlaced) { number_passes = png_set_interlace_handling(png_ptr); } if ((pixel_depth == 32) && (!has_alpha_channel)) { BYTE *buffer = (BYTE *)malloc(width * 3); // transparent conversion to 24-bit // the number of passes is either 1 for non-interlaced images, or 7 for interlaced images for (int pass = 0; pass < number_passes; pass++) { for (png_uint_32 k = 0; k < height; k++) { FreeImage_ConvertLine32To24(buffer, FreeImage_GetScanLine(dib, height - k - 1), width); png_write_row(png_ptr, buffer); } } free(buffer); } else { // the number of passes is either 1 for non-interlaced images, or 7 for interlaced images for (int pass = 0; pass < number_passes; pass++) { for (png_uint_32 k = 0; k < height; k++) { png_write_row(png_ptr, FreeImage_GetScanLine(dib, height - k - 1)); } } } // It is REQUIRED to call this to finish writing the rest of the file // Bug with png_flush png_write_end(png_ptr, info_ptr); // clean up after the write, and free any memory allocated if (palette) { png_free(png_ptr, palette); } png_destroy_write_struct(&png_ptr, &info_ptr); return TRUE; } catch (const char *text) { if(png_ptr) { png_destroy_write_struct(&png_ptr, &info_ptr); } FreeImage_OutputMessageProc(s_format_id, text); } } return FALSE; }
/** Write a FIBITMAP to a JNG stream @param format_id ID of the caller @param io Stream i/o functions @param dib Image to be saved @param handle Stream handle @param flags Saving flags @return Returns TRUE if successful, returns FALSE otherwise */ BOOL mng_WriteJNG(int format_id, FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int flags) { DWORD jng_width = 0; DWORD jng_height = 0; BYTE jng_color_type = 0; BYTE jng_image_sample_depth = 8; BYTE jng_image_compression_method = 8; // 8: ISO-10918-1 Huffman-coded baseline JPEG. BYTE jng_image_interlace_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; BYTE buffer[16]; FIMEMORY *hJngMemory = NULL; FIMEMORY *hJpegMemory = NULL; FIMEMORY *hPngMemory = NULL; FIBITMAP *dib_rgb = NULL; FIBITMAP *dib_alpha = NULL; if(!dib || (FreeImage_GetImageType(dib) != FIT_BITMAP)) { return FALSE; } unsigned bpp = FreeImage_GetBPP(dib); switch(bpp) { case 8: if(FreeImage_GetColorType(dib) == FIC_MINISBLACK) { dib_rgb = dib; jng_color_type = MNG_COLORTYPE_JPEGGRAY; } else { // JPEG plugin will convert other types (FIC_MINISWHITE, FIC_PALETTE) to 24-bit on the fly //dib_rgb = FreeImage_ConvertTo24Bits(dib); dib_rgb = dib; jng_color_type = MNG_COLORTYPE_JPEGCOLOR; } break; case 24: dib_rgb = dib; jng_color_type = MNG_COLORTYPE_JPEGCOLOR; break; case 32: dib_rgb = FreeImage_ConvertTo24Bits(dib); jng_color_type = MNG_COLORTYPE_JPEGCOLORA; jng_alpha_sample_depth = 8; break; default: return FALSE; } jng_width = (DWORD)FreeImage_GetWidth(dib); jng_height = (DWORD)FreeImage_GetHeight(dib); try { hJngMemory = FreeImage_OpenMemory(); // --- write JNG file signature --- FreeImage_WriteMemory(g_jng_signature, 1, 8, hJngMemory); // --- write a JHDR chunk --- SwapLong(&jng_width); SwapLong(&jng_height); memcpy(&buffer[0], &jng_width, 4); memcpy(&buffer[4], &jng_height, 4); SwapLong(&jng_width); SwapLong(&jng_height); buffer[8] = jng_color_type; buffer[9] = jng_image_sample_depth; buffer[10] = jng_image_compression_method; buffer[11] = jng_image_interlace_method; buffer[12] = jng_alpha_sample_depth; buffer[13] = jng_alpha_compression_method; buffer[14] = jng_alpha_filter_method; buffer[15] = jng_alpha_interlace_method; mng_WriteChunk(mng_JHDR, &buffer[0], 16, hJngMemory); // --- write a sequence of JDAT chunks --- hJpegMemory = FreeImage_OpenMemory(); flags |= JPEG_BASELINE; if(!FreeImage_SaveToMemory(FIF_JPEG, dib_rgb, hJpegMemory, flags)) { throw (const char*)NULL; } if(dib_rgb != dib) { FreeImage_Unload(dib_rgb); dib_rgb = NULL; } { BYTE *jpeg_data = NULL; DWORD size_in_bytes = 0; // get a pointer to the stream buffer FreeImage_AcquireMemory(hJpegMemory, &jpeg_data, &size_in_bytes); // write chunks for(DWORD k = 0; k < size_in_bytes;) { DWORD bytes_left = size_in_bytes - k; DWORD chunk_size = MIN(JPEG_CHUNK_SIZE, bytes_left); mng_WriteChunk(mng_JDAT, &jpeg_data[k], chunk_size, hJngMemory); k += chunk_size; } } FreeImage_CloseMemory(hJpegMemory); hJpegMemory = NULL; // --- write alpha layer as a sequence of IDAT chunk --- if((bpp == 32) && (jng_color_type == MNG_COLORTYPE_JPEGCOLORA)) { dib_alpha = FreeImage_GetChannel(dib, FICC_ALPHA); hPngMemory = FreeImage_OpenMemory(); if(!FreeImage_SaveToMemory(FIF_PNG, dib_alpha, hPngMemory, PNG_DEFAULT)) { throw (const char*)NULL; } FreeImage_Unload(dib_alpha); dib_alpha = NULL; // get the IDAT chunk { BOOL bResult = FALSE; DWORD start_pos = 0; DWORD next_pos = 0; long offset = 8; do { // find the next IDAT chunk from 'offset' position bResult = mng_FindChunk(hPngMemory, mng_IDAT, offset, &start_pos, &next_pos); if(!bResult) break; BYTE *png_data = NULL; DWORD size_in_bytes = 0; // get a pointer to the stream buffer FreeImage_AcquireMemory(hPngMemory, &png_data, &size_in_bytes); // write the IDAT chunk mng_WriteChunk(mng_IDAT, &png_data[start_pos+8], next_pos - start_pos - 12, hJngMemory); offset = next_pos; } while(bResult); } FreeImage_CloseMemory(hPngMemory); hPngMemory = NULL; } // --- write a IEND chunk --- mng_WriteChunk(mng_IEND, NULL, 0, hJngMemory); // write the JNG on output stream { BYTE *jng_data = NULL; DWORD size_in_bytes = 0; FreeImage_AcquireMemory(hJngMemory, &jng_data, &size_in_bytes); io->write_proc(jng_data, 1, size_in_bytes, handle); } FreeImage_CloseMemory(hJngMemory); FreeImage_CloseMemory(hJpegMemory); FreeImage_CloseMemory(hPngMemory); return TRUE; } catch(const char *text) { FreeImage_CloseMemory(hJngMemory); FreeImage_CloseMemory(hJpegMemory); FreeImage_CloseMemory(hPngMemory); if(dib_rgb && (dib_rgb != dib)) { FreeImage_Unload(dib_rgb); } FreeImage_Unload(dib_alpha); if(text) { FreeImage_OutputMessageProc(format_id, text); } return FALSE; } }
static BOOL DLL_CALLCONV Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) { const char *channel_name[4] = { "R", "G", "B", "A" }; BOOL bIsFlipped = FALSE; half *halfData = NULL; if(!dib || !handle) return FALSE; try { // check for EXR_LC compression and verify that the format is RGB if((flags & EXR_LC) == EXR_LC) { FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); if(((image_type != FIT_RGBF) && (image_type != FIT_RGBAF)) || ((flags & EXR_FLOAT) == EXR_FLOAT)) { THROW (Iex::IoExc, "EXR_LC compression is only available with RGB[A]F images"); } if((FreeImage_GetWidth(dib) % 2) || (FreeImage_GetHeight(dib) % 2)) { THROW (Iex::IoExc, "EXR_LC compression only works when the width and height are a multiple of 2"); } } // wrap the FreeImage IO stream C_OStream ostream(io, handle); // compression Imf::Compression compress; if((flags & EXR_NONE) == EXR_NONE) { // no compression compress = Imf::NO_COMPRESSION; } else if((flags & EXR_ZIP) == EXR_ZIP) { // zlib compression, in blocks of 16 scan lines compress = Imf::ZIP_COMPRESSION; } else if((flags & EXR_PIZ) == EXR_PIZ) { // piz-based wavelet compression compress = Imf::PIZ_COMPRESSION; } else if((flags & EXR_PXR24) == EXR_PXR24) { // lossy 24-bit float compression compress = Imf::PXR24_COMPRESSION; } else if((flags & EXR_B44) == EXR_B44) { // lossy 44% float compression compress = Imf::B44_COMPRESSION; } else { // default value compress = Imf::PIZ_COMPRESSION; } // create the header int width = FreeImage_GetWidth(dib); int height = FreeImage_GetHeight(dib); int dx = 0, dy = 0; Imath::Box2i dataWindow (Imath::V2i (0, 0), Imath::V2i (width - 1, height - 1)); Imath::Box2i displayWindow (Imath::V2i (-dx, -dy), Imath::V2i (width - dx - 1, height - dy - 1)); Imf::Header header = Imf::Header(displayWindow, dataWindow, 1, Imath::V2f(0,0), 1, Imf::INCREASING_Y, compress); // handle thumbnail SetPreviewImage(dib, header); // check for EXR_LC compression if((flags & EXR_LC) == EXR_LC) { return SaveAsEXR_LC(ostream, dib, header, width, height); } // output pixel type Imf::PixelType pixelType; if((flags & EXR_FLOAT) == EXR_FLOAT) { pixelType = Imf::FLOAT; // save as float data type } else { // default value pixelType = Imf::HALF; // save as half data type } // check the data type and number of channels int components = 0; FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); switch(image_type) { case FIT_FLOAT: components = 1; // insert luminance channel header.channels().insert ("Y", Imf::Channel(pixelType)); break; case FIT_RGBF: components = 3; for(int c = 0; c < components; c++) { // insert R, G and B channels header.channels().insert (channel_name[c], Imf::Channel(pixelType)); } break; case FIT_RGBAF: components = 4; for(int c = 0; c < components; c++) { // insert R, G, B and A channels header.channels().insert (channel_name[c], Imf::Channel(pixelType)); } break; default: THROW (Iex::ArgExc, "Cannot save: invalid data type.\nConvert the image to float before saving as OpenEXR."); } // build a frame buffer (i.e. what we have on input) Imf::FrameBuffer frameBuffer; BYTE *bits = NULL; // pointer to our pixel buffer size_t bytespp = 0; // size of our pixel in bytes size_t bytespc = 0; // size of our pixel component in bytes unsigned pitch = 0; // size of our yStride in bytes if(pixelType == Imf::HALF) { // convert from float to half halfData = new(std::nothrow) half[width * height * components]; if(!halfData) THROW (Iex::NullExc, FI_MSG_ERROR_MEMORY); for(int y = 0; y < height; y++) { float *src_bits = (float*)FreeImage_GetScanLine(dib, height - 1 - y); half *dst_bits = halfData + y * width * components; for(int x = 0; x < width; x++) { for(int c = 0; c < components; c++) { dst_bits[c] = src_bits[c]; } src_bits += components; dst_bits += components; } } bits = (BYTE*)halfData; bytespc = sizeof(half); bytespp = sizeof(half) * components; pitch = sizeof(half) * width * components; } else if(pixelType == Imf::FLOAT) { // invert dib scanlines bIsFlipped = FreeImage_FlipVertical(dib); bits = FreeImage_GetBits(dib); bytespc = sizeof(float); bytespp = sizeof(float) * components; pitch = FreeImage_GetPitch(dib); } if(image_type == FIT_FLOAT) { frameBuffer.insert ("Y", // name Imf::Slice (pixelType, // type (char*)(bits), // base bytespp, // xStride pitch)); // yStride } else if((image_type == FIT_RGBF) || (image_type == FIT_RGBAF)) { for(int c = 0; c < components; c++) { char *channel_base = (char*)(bits) + c*bytespc; frameBuffer.insert (channel_name[c],// name Imf::Slice (pixelType, // type channel_base, // base bytespp, // xStride pitch)); // yStride } } // write the data Imf::OutputFile file (ostream, header); file.setFrameBuffer (frameBuffer); file.writePixels (height); if(halfData != NULL) delete[] halfData; if(bIsFlipped) { // invert dib scanlines FreeImage_FlipVertical(dib); } return TRUE; } catch(Iex::BaseExc & e) { if(halfData != NULL) delete[] halfData; if(bIsFlipped) { // invert dib scanlines FreeImage_FlipVertical(dib); } FreeImage_OutputMessageProc(s_format_id, e.what()); return FALSE; } }
void putBmpIntoPixels(FIBITMAP * bmp, ofPixels_<PixelType> &pix, bool swapForLittleEndian = true) { // convert to correct type depending on type of input bmp and PixelType FIBITMAP* bmpConverted = nullptr; FREE_IMAGE_TYPE imgType = FreeImage_GetImageType(bmp); if(sizeof(PixelType)==1 && (FreeImage_GetColorType(bmp) == FIC_PALETTE || FreeImage_GetBPP(bmp) < 8 || imgType!=FIT_BITMAP)) { if(FreeImage_IsTransparent(bmp)) { bmpConverted = FreeImage_ConvertTo32Bits(bmp); } else { bmpConverted = FreeImage_ConvertTo24Bits(bmp); } bmp = bmpConverted; }else if(sizeof(PixelType)==2 && imgType!=FIT_UINT16 && imgType!=FIT_RGB16 && imgType!=FIT_RGBA16){ if(FreeImage_IsTransparent(bmp)) { bmpConverted = FreeImage_ConvertToType(bmp,FIT_RGBA16); } else { bmpConverted = FreeImage_ConvertToType(bmp,FIT_RGB16); } bmp = bmpConverted; }else if(sizeof(PixelType)==4 && imgType!=FIT_FLOAT && imgType!=FIT_RGBF && imgType!=FIT_RGBAF){ if(FreeImage_IsTransparent(bmp)) { bmpConverted = FreeImage_ConvertToType(bmp,FIT_RGBAF); } else { bmpConverted = FreeImage_ConvertToType(bmp,FIT_RGBF); } bmp = bmpConverted; } unsigned int width = FreeImage_GetWidth(bmp); unsigned int height = FreeImage_GetHeight(bmp); unsigned int bpp = FreeImage_GetBPP(bmp); unsigned int channels = (bpp / sizeof(PixelType)) / 8; unsigned int pitch = FreeImage_GetPitch(bmp); ofPixelFormat pixFormat; if(channels==1) pixFormat=OF_PIXELS_GRAY; #ifdef TARGET_LITTLE_ENDIAN if(swapForLittleEndian){ if(channels==3) pixFormat=OF_PIXELS_BGR; if(channels==4) pixFormat=OF_PIXELS_BGRA; }else{ if(channels==3) pixFormat=OF_PIXELS_RGB; if(channels==4) pixFormat=OF_PIXELS_RGBA; } #else if(channels==3) pixFormat=OF_PIXELS_RGB; if(channels==4) pixFormat=OF_PIXELS_RGBA; #endif // ofPixels are top left, FIBITMAP is bottom left FreeImage_FlipVertical(bmp); unsigned char* bmpBits = FreeImage_GetBits(bmp); if(bmpBits != nullptr) { pix.setFromAlignedPixels((PixelType*) bmpBits, width, height, pixFormat, pitch); } else { ofLogError("ofImage") << "putBmpIntoPixels(): unable to set ofPixels from FIBITMAP"; } if(bmpConverted != nullptr) { FreeImage_Unload(bmpConverted); } #ifdef TARGET_LITTLE_ENDIAN if(swapForLittleEndian && sizeof(PixelType) == 1 && channels >=3 ) { pix.swapRgb(); } #endif }
bool Engine::gameLoop() { // set a variable to pass into the texture whatever //unsigned int texID; camera = Camera(); // loop that will load all shaders for (int i = 0; i < texFiles.size(); i++) { // LOAD BEFORE GAME LOOP // this variable holds the texture file char* textureFile = texFiles[i]; FIBITMAP* image = FreeImage_Load(FreeImage_GetFileType(textureFile, 0), textureFile); // check if load failed if (image == nullptr) { return false; } // convert the original image into a 32bit bmp FIBITMAP* image32Bit = FreeImage_ConvertTo32Bits(image); // unload the image from memory FreeImage_Unload(image); // generate and bind a new texture glGenTextures(1, &texIDs[i]); glBindTexture(GL_TEXTURE_2D, texIDs[i]); // upload the texture bytes glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB_ALPHA, FreeImage_GetWidth(image32Bit), FreeImage_GetHeight(image32Bit), 0, GL_BGRA, GL_UNSIGNED_BYTE, (void*)FreeImage_GetBits(image32Bit)); // set min filter to linear glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // unload the image from RAM FreeImage_Unload(image32Bit); // unbind the texture when done glBindTexture(GL_TEXTURE_2D, 0); } int counter = 0; // values that will hold the mouse's position double mouseX; double mouseY; vec3 unit; // loop until the window is closed by the user while (!glfwWindowShouldClose(GLFWwindowPtr)) { // update the game time prevFrameTime = currTime; currTime = glfwGetTime(); deltaTime = currTime - prevFrameTime; // clear the canvas glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // this will apply an initial force whenever the cueball stops, representing the pool stick striking it float mag; vec3 mousePos; vec3 force; // calculate lighting vec3 lightLoc = vec3(0, 0, 4); // pass in the light to the shaders glUniform3f(5, lightLoc.x, lightLoc.y, lightLoc.z); glUniform3f(6, camera.transform.loc.x, camera.transform.loc.y, camera.transform.loc.z); // if the cue ball is not already moving or in play, then allow the player to move it if (keyIsDown[GLFW_MOUSE_BUTTON_LEFT] && !keyWasDown[GLFW_MOUSE_BUTTON_LEFT] && inPlay == false) { // reset the friction counter frictionCounter = 0; // gets the mouse location double mouseX; double mouseY; // method that gets the cursor location glfwGetCursorPos(GLFWwindowPtr, &mouseX, &mouseY); int width, height; glfwGetWindowSize(GLFWwindowPtr, &width, &height); //cout << mouseX << ", " << mouseY << endl; mouseX = (mouseX / 400) - 1; mouseY = (mouseY / 300) - 1; //cout << mouseX << ", " << mouseY << endl; // this is the vector that will hold the vector connecting the cue ball to the mouse vec3 ballToMouse = vec3(mouseX - objects[1].transform.loc.x, -mouseY - objects[1].transform.loc.y, 0); // find the magnitude mag = sqrt((pow(ballToMouse.x, 2)) + (pow(ballToMouse.y, 2))); // find the unit vector unit = vec3(ballToMouse.x / mag, ballToMouse.y / mag, 0); // this is the initial force force = vec3(unit.x * FORCE, unit.y * FORCE, 0); // multiply the initial force by that to find the final force vector objects[1].calcForces(force, deltaTime); // set the in Play attribute to true inPlay = true; } if (inPlay == true) { // calculate a frictional force //vec3 forceFriction = vec3(unit.x * FORCE_FRICTION, unit.y * FORCE_FRICTION, 0); for (int i = 1; i < objects.size(); i++) { objects[i].friction(deltaTime); } //cout << objects[1].getRigidBody().vel.x << " " << objects[1].getRigidBody().vel.y << endl; // set a counter //frictionCounter += FORCE_FRICTION; // a boolean that will check if all objects have stopped //bool allStopped = true; // //// if all objects have stopped, then set inPlay to false //for (int i = 1; i < objects.size(); i++) //{ // // if one object isn't stopped then set the boolean to false // if (objects[i].rigidBody.vel != vec3(0, 0, 0)) // { // allStopped = false; // } //} // //if (allStopped == false) //{ // inPlay = false; //} } // check for collisions // for the purpose of checking collisions, object 1 is the cue ball for (int i = 1; i < objects.size(); i++) { for (int j = i + 1; j < objects.size(); j++) { if (objects[i].collidesWith(objects[j])) { objects[i].calculateCollision(objects[j]); cout << "Ball " << i << " is colliding with ball " << j << endl; break; } } for (int h = 0; h < pockets.size(); h++) { if (pocketCollision(pockets[h], objects[i])) { cout << "Ball " << i << " is colliding with pocket " << h << endl; } } // if the object goes off of the screen if (objects[i].transform.loc.x > 1) { objects[i].transform.loc.x = -1; } if (objects[i].transform.loc.x < -1) { objects[i].transform.loc.x = 1; } if (objects[i].transform.loc.y > 1) { objects[i].transform.loc.y = -1; } if (objects[i].transform.loc.y < -1) { objects[i].transform.loc.y = 1; } // actually move the object objects[i].move(deltaTime); } //cout << objects[1].transform.loc.x << endl; // update the camera //camera.update(vec3(), deltaTime); for (int i = 0; i < objects.size(); i++) { // call the current objects draw method objects[i].draw(); // render the game objects if (i == 0) { models[0].render(); } else { models[1].render(); } glBindVertexArray(0); glBindTexture(GL_TEXTURE_2D, texIDs[i]); // unbind after drawing } camera.update(vec3(0, 0, 0), deltaTime); glfwSwapBuffers(GLFWwindowPtr); // process queued window, mouse/keyboard callback events //keyWasDown = keyIsDown; glfwPollEvents(); if (keyIsDown[GLFW_KEY_LEFT]) { //cout << "Left" << endl; camera.update(vec3(-40, 0, 0), deltaTime); } else { camera.stop(); } if (keyIsDown[GLFW_KEY_RIGHT]) { //cout << "Right" << endl; camera.update(vec3(40, 0, 0), deltaTime); } else { camera.stop(); } if (keyIsDown[GLFW_KEY_UP]) { //cout << "Up" << endl; camera.update(vec3(0, 40, 0), deltaTime); } else { camera.stop(); } if (keyIsDown[GLFW_KEY_DOWN]) { //cout << "Down" << endl; camera.update(vec3(0, -40, 0), deltaTime); } else { camera.stop(); } // check to see if escape key is pressed if (keyIsDown[GLFW_KEY_ESCAPE]) { glfwSetWindowShouldClose(GLFWwindowPtr, GL_TRUE); } } for (int i = 0; i < texIDs.size(); i++) { glDeleteTextures(1, &texIDs[i]); } glfwTerminate(); return true; }
bool FreeImage::onLoad() { switch ( this -> loadingType ) { case LoadingType::EMPTY: { this -> freeImage = FreeImage_Allocate( this -> size.x, this -> size.y, this -> BPP, 0, 0, 0 ); break; } case LoadingType::FILE: { // Check the file signature and deduce its format. #ifdef WIN32 FREE_IMAGE_FORMAT imageFormat = FreeImage_GetFileTypeU( fileNameW.toCString(), 0 ); #else FREE_IMAGE_FORMAT imageFormat = FreeImage_GetFileType( fileName.toCString(), 0 ); #endif // If still unknown, try to guess the file format from the file extension. if ( imageFormat == FIF_UNKNOWN ) { #ifdef WIN32 imageFormat = FreeImage_GetFIFFromFilenameU( fileNameW.toCString() ); #else imageFormat = FreeImage_GetFIFFromFilename( fileName.toCString() ); #endif } // If still unknown, return failure. if ( imageFormat == FIF_UNKNOWN ) { error( String( "Free Image was unable to detect the file format : " ) << fileName ); return false; } // Check that the plugin has reading capabilities and load the file. if ( FreeImage_FIFSupportsReading( imageFormat ) ) { #ifdef WIN32 this -> freeImage = FreeImage_LoadU( imageFormat, fileNameW.toCString() ); #else this -> freeImage = FreeImage_Load( imageFormat, fileName.toCString() ); #endif } if ( this -> freeImage == NULL ) { error( String( "Free Image was unable to load the picture : " ) << fileName ); return false; } if ( this -> size.x == 0 || this -> size.y == 0 ) { this -> size.x = FreeImage_GetWidth( this -> freeImage ); this -> size.y = FreeImage_GetHeight( this -> freeImage ); } if ( this -> loadingFormat == Format::UNDEFINED ) { switch ( FreeImage_GetColorType( this -> freeImage ) ) { case FIC_PALETTE: _updateFormat( Format::R ); break; case FIC_RGB: _updateFormat( Format::RGB ); break; default: _updateFormat( Format::RGBA ); break; } } log( this -> fileName << this -> size << " has been loaded successfully !" ); break; } } //if we have to flip vertically. if ( this -> invertY ) FreeImage_FlipVertical( this -> freeImage ); //Change BPP if ( this -> BPP != FreeImage_GetBPP( this -> freeImage ) ) _updateBPP(); //resize if ( this -> size != Math::Vec2<Size>( FreeImage_GetWidth( this -> freeImage ), FreeImage_GetHeight( this -> freeImage ) ) ) _updateSize(); this -> stride = FreeImage_GetPitch( this -> freeImage ); return true; }
void Image::_load(string sFilename) { errlog << "Load " << sFilename << endl; //image format FREE_IMAGE_FORMAT fif = FIF_UNKNOWN; //pointer to the image, once loaded FIBITMAP *dib(0); //pointer to the image data BYTE* bits(0); //image width and height unsigned int width(0), height(0); //check the file signature and deduce its format fif = FreeImage_GetFileType(sFilename.c_str(), 0); //if still unknown, try to guess the file format from the file extension if(fif == FIF_UNKNOWN) fif = FreeImage_GetFIFFromFilename(sFilename.c_str()); //if still unkown, return failure if(fif == FIF_UNKNOWN) { errlog << "Unknown image type for file " << sFilename << endl; return; } //check that the plugin has reading capabilities and load the file if(FreeImage_FIFSupportsReading(fif)) dib = FreeImage_Load(fif, sFilename.c_str()); else errlog << "File " << sFilename << " doesn't support reading." << endl; //if the image failed to load, return failure if(!dib) { errlog << "Error loading image " << sFilename.c_str() << endl; return; } //retrieve the image data //get the image width and height width = FreeImage_GetWidth(dib); height = FreeImage_GetHeight(dib); int w = power_of_two(width); int h = power_of_two(height); int mode, modeflip; if(FreeImage_GetBPP(dib) == 24) // RGB 24bit { mode = GL_RGB; modeflip = GL_BGR; } else if(FreeImage_GetBPP(dib) == 32) // RGBA 32bit { mode = GL_RGBA; modeflip = GL_BGRA; } FIBITMAP *bitmap2 = FreeImage_Allocate(w, h, FreeImage_GetBPP(dib)); FreeImage_Paste(bitmap2, dib, 0, 0, 255); FreeImage_FlipVertical(bitmap2); //Apparently, FreeImage handles this strangely. Flipping beforehand doesn't work right. FreeImage_Unload(dib); bits = FreeImage_GetBits(bitmap2); //if this somehow one of these failed (they shouldn't), return failure if((bits == 0) || (width == 0) || (height == 0)) { errlog << "Something went terribly horribly wrong with getting image bits; just sit and wait for the singularity" << endl; return; } //generate an OpenGL texture ID for this texture m_iWidth = width; m_iHeight = height; m_iRealWidth = w; m_iRealHeight = h; glGenTextures(1, &m_hTex); //bind to the new texture ID glBindTexture(GL_TEXTURE_2D, m_hTex); //store the texture data for OpenGL use glTexImage2D(GL_TEXTURE_2D, 0, mode, w, h, 0, modeflip, GL_UNSIGNED_BYTE, bits); //Free FreeImage's copy of the data FreeImage_Unload(bitmap2); }
template<class Tsrc> FIBITMAP* CONVERT_TO_BYTE<Tsrc>::convert(FIBITMAP *src, BOOL scale_linear) { FIBITMAP *dst = NULL; unsigned x, y; unsigned width = FreeImage_GetWidth(src); unsigned height = FreeImage_GetHeight(src); // allocate a 8-bit dib dst = FreeImage_AllocateT(FIT_BITMAP, width, height, 8, 0, 0, 0); if(!dst) return NULL; // build a greyscale palette RGBQUAD *pal = FreeImage_GetPalette(dst); for(int i = 0; i < 256; i++) { pal[i].rgbRed = (BYTE)i; pal[i].rgbGreen = (BYTE)i; pal[i].rgbBlue = (BYTE)i; } // convert the src image to dst // (FIBITMAP are stored upside down) if(scale_linear) { Tsrc max, min; double scale; // find the min and max value of the image Tsrc l_min, l_max; min = 255, max = 0; for(y = 0; y < height; y++) { Tsrc *bits = reinterpret_cast<Tsrc*>(FreeImage_GetScanLine(src, y)); MAXMIN(bits, width, l_max, l_min); if(l_max > max) max = l_max; if(l_min < min) min = l_min; } if(max == min) { max = 255; min = 0; } // compute the scaling factor scale = 255 / (double)(max - min); // scale to 8-bit for(y = 0; y < height; y++) { Tsrc *src_bits = reinterpret_cast<Tsrc*>(FreeImage_GetScanLine(src, y)); BYTE *dst_bits = FreeImage_GetScanLine(dst, y); for(x = 0; x < width; x++) { dst_bits[x] = (BYTE)( scale * (src_bits[x] - min) + 0.5); } } } else { for(y = 0; y < height; y++) { Tsrc *src_bits = reinterpret_cast<Tsrc*>(FreeImage_GetScanLine(src, y)); BYTE *dst_bits = FreeImage_GetScanLine(dst, y); for(x = 0; x < width; x++) { // rounding int q = int(src_bits[x] + 0.5); dst_bits[x] = (BYTE) MIN(255, MAX(0, q)); } } } return dst; }