FIBITMAP* DLL_CALLCONV FIA_ComplexImageToRealValued(FIBITMAP *src) { 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_DOUBLE, width, height, 32, 0, 0, 0); if(!dst) return NULL; FICOMPLEX *src_bits; double *dst_bits; for(y = 0; y < height; y++) { src_bits = (FICOMPLEX *) FreeImage_GetScanLine(src, y); dst_bits = (double *) FreeImage_GetScanLine(dst, y); for(x=0; x < width; x++) { dst_bits[x] = (double) src_bits[x].r; } } return dst; }
template<class Tsrc> FIBITMAP* CONVERT_TO_COMPLEX<Tsrc>::convert(FIBITMAP *src) { FIBITMAP *dst = NULL; unsigned width = FreeImage_GetWidth(src); unsigned height = FreeImage_GetHeight(src); // allocate dst image dst = FreeImage_AllocateT(FIT_COMPLEX, width, height); if(!dst) return NULL; // convert from src_type to FIT_COMPLEX for(unsigned y = 0; y < height; y++) { const Tsrc *src_bits = reinterpret_cast<Tsrc*>(FreeImage_GetScanLine(src, y)); FICOMPLEX *dst_bits = (FICOMPLEX *)FreeImage_GetScanLine(dst, y); for(unsigned x = 0; x < width; x++) { dst_bits[x].r = (double)src_bits[x]; dst_bits[x].i = 0; } } return dst; }
template<class Tdst, class Tsrc> FIBITMAP* CONVERT_TYPE<Tdst, Tsrc>::convert(FIBITMAP *src, FREE_IMAGE_TYPE dst_type) { FIBITMAP *dst = NULL; unsigned width = FreeImage_GetWidth(src); unsigned height = FreeImage_GetHeight(src); unsigned bpp = FreeImage_GetBPP(src); // allocate dst image dst = FreeImage_AllocateT(dst_type, width, height, bpp, FreeImage_GetRedMask(src), FreeImage_GetGreenMask(src), FreeImage_GetBlueMask(src)); if(!dst) return NULL; // convert from src_type to dst_type for(unsigned y = 0; y < height; y++) { const Tsrc *src_bits = reinterpret_cast<Tsrc*>(FreeImage_GetScanLine(src, y)); Tdst *dst_bits = reinterpret_cast<Tdst*>(FreeImage_GetScanLine(dst, y)); for(unsigned x = 0; x < width; x++) { *dst_bits++ = static_cast<Tdst>(*src_bits++); } } return dst; }
/** @brief Inverts each pixel data. @param src Input image to be processed. @return Returns TRUE if successful, FALSE otherwise. */ BOOL DLL_CALLCONV FreeImage_Invert(FIBITMAP *src) { unsigned i, x, y, k; BYTE *bits; if (!src) return FALSE; int bpp = FreeImage_GetBPP(src); switch(bpp) { case 1 : case 4 : case 8 : { // if the dib has a colormap, just invert it // else, keep the linear grayscale if (FreeImage_GetColorType(src) == FIC_PALETTE) { RGBQUAD *pal = FreeImage_GetPalette(src); for(i = 0; i < FreeImage_GetColorsUsed(src); i++) { pal[i].rgbRed = 255 - pal[i].rgbRed; pal[i].rgbGreen = 255 - pal[i].rgbGreen; pal[i].rgbBlue = 255 - pal[i].rgbBlue; } } else { for(y = 0; y < FreeImage_GetHeight(src); y++) { bits = FreeImage_GetScanLine(src, y); for (x = 0; x < FreeImage_GetLine(src); x++) { bits[x] = ~bits[x]; } } } break; } case 24 : case 32 : { unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); for(y = 0; y < FreeImage_GetHeight(src); y++) { bits = FreeImage_GetScanLine(src, y); for(x = 0; x < FreeImage_GetWidth(src); x++) { for(k = 0; k < bytespp; k++) { bits[k] = ~bits[k]; } bits += bytespp; } } break; } } return TRUE; }
/** Solution of the model problem on the coarsest grid, where h = 1/2 . The right-hand side is input in rhs[0..2][0..2] and the solution is returned in u[0..2][0..2]. */ static void fmg_solve(FIBITMAP *U, FIBITMAP *RHS) { // fill U with zeros fmg_fillArrayWithZeros(U); // calculate U(1, 1) = -h*h*RHS(1, 1)/4.0 where h = 1/2 float *u_scan = (float*)FreeImage_GetScanLine(U, 1); const float *rhs_scan = (float*)FreeImage_GetScanLine(RHS, 1); u_scan[1] = -rhs_scan[1] / 16; }
/** @brief Retrieves the red, green, blue or alpha channel of a 24- or 32-bit BGR[A] image. @param src Input image to be processed. @param channel Color channel to extract @return Returns the extracted channel if successful, returns NULL otherwise. */ FIBITMAP * DLL_CALLCONV FreeImage_GetChannel(FIBITMAP *src, FREE_IMAGE_COLOR_CHANNEL channel) { int c; if(!src) return NULL; unsigned bpp = FreeImage_GetBPP(src); if((bpp == 24) || (bpp == 32)) { // select the channel to extract switch(channel) { case FICC_BLUE: c = FI_RGBA_BLUE; break; case FICC_GREEN: c = FI_RGBA_GREEN; break; case FICC_RED: c = FI_RGBA_RED; break; case FICC_ALPHA: if(bpp != 32) return NULL; c = FI_RGBA_ALPHA; break; default: return NULL; } // allocate a 8-bit dib unsigned width = FreeImage_GetWidth(src); unsigned height = FreeImage_GetHeight(src); FIBITMAP *dst = FreeImage_Allocate(width, height, 8) ; if(!dst) return NULL; // build a greyscale palette RGBQUAD *pal = FreeImage_GetPalette(dst); for(int i = 0; i < 256; i++) { pal[i].rgbBlue = pal[i].rgbGreen = pal[i].rgbRed = i; } // perform extraction int bytespp = bpp / 8; // bytes / pixel for(unsigned y = 0; y < height; y++) { BYTE *src_bits = FreeImage_GetScanLine(src, y); BYTE *dst_bits = FreeImage_GetScanLine(dst, y); for(unsigned x = 0; x < width; x++) { dst_bits[x] = src_bits[c]; src_bits += bytespp; } } return dst; } return NULL; }
/** Save using EXR_LC compression (works only with RGB[A]F images) */ static BOOL SaveAsEXR_LC(C_OStream& ostream, FIBITMAP *dib, Imf::Header& header, int width, int height) { int x, y; Imf::RgbaChannels rgbaChannels; try { FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); // convert from float to half Imf::Array2D<Imf::Rgba> pixels(height, width); switch(image_type) { case FIT_RGBF: rgbaChannels = Imf::WRITE_YC; for(y = 0; y < height; y++) { FIRGBF *src_bits = (FIRGBF*)FreeImage_GetScanLine(dib, height - 1 - y); for(x = 0; x < width; x++) { Imf::Rgba &dst_bits = pixels[y][x]; dst_bits.r = src_bits[x].red; dst_bits.g = src_bits[x].green; dst_bits.b = src_bits[x].blue; } } break; case FIT_RGBAF: rgbaChannels = Imf::WRITE_YCA; for(y = 0; y < height; y++) { FIRGBAF *src_bits = (FIRGBAF*)FreeImage_GetScanLine(dib, height - 1 - y); for(x = 0; x < width; x++) { Imf::Rgba &dst_bits = pixels[y][x]; dst_bits.r = src_bits[x].red; dst_bits.g = src_bits[x].green; dst_bits.b = src_bits[x].blue; dst_bits.a = src_bits[x].alpha; } } break; default: THROW (Iex::IoExc, "Bad image type"); break; } // write the data Imf::RgbaOutputFile file(ostream, header, rgbaChannels); file.setFrameBuffer (&pixels[0][0], 1, width); file.writePixels (height); return TRUE; } catch(Iex::BaseExc & e) { FreeImage_OutputMessageProc(s_format_id, e.what()); return FALSE; } }
/* dt of 2d function using squared distance */ static void dt2d (FIBITMAP * src) { int width = FreeImage_GetWidth (src); int height = FreeImage_GetHeight (src); float *f = new float[MAX (width, height)]; register int x, y; register float *src_ptr; // transform along columns for(x = 0; x < width; x++) { for(y = 0; y < height; y++) { src_ptr = (float *) FreeImage_GetScanLine (src, y); f[y] = src_ptr[x]; } float *d = dt (f, height); for(y = 0; y < height; y++) { src_ptr = (float *) FreeImage_GetScanLine (src, y); src_ptr[x] = d[y]; } delete[]d; } // transform along rows for(y = 0; y < height; y++) { src_ptr = (float *) FreeImage_GetScanLine (src, y); for(x = 0; x < width; x++) { f[x] = src_ptr[x]; } float *d = dt (f, width); for(x = 0; x < width; x++) { src_ptr[x] = d[x]; } delete[]d; } delete f; }
/** @brief Insert a 8-bit dib into a 24- or 32-bit image. Both src and dst must have the same width and height. @param dst Image to modify (24- or 32-bit) @param src Input 8-bit image to insert @param channel Color channel to modify @return Returns TRUE if successful, FALSE otherwise. */ BOOL DLL_CALLCONV FreeImage_SetChannel(FIBITMAP *dst, FIBITMAP *src, FREE_IMAGE_COLOR_CHANNEL channel) { int c; if(!src || !dst) return FALSE; // src image should be grayscale, dst image should be 24- or 32-bit unsigned src_bpp = FreeImage_GetBPP(src); unsigned dst_bpp = FreeImage_GetBPP(dst); if((src_bpp != 8) || (dst_bpp != 24) && (dst_bpp != 32)) return FALSE; // src and dst images should have the same width and height unsigned src_width = FreeImage_GetWidth(src); unsigned src_height = FreeImage_GetHeight(src); unsigned dst_width = FreeImage_GetWidth(dst); unsigned dst_height = FreeImage_GetHeight(dst); if((src_width != dst_width) || (src_height != dst_height)) return FALSE; // select the channel to modify switch(channel) { case FICC_BLUE: c = FI_RGBA_BLUE; break; case FICC_GREEN: c = FI_RGBA_GREEN; break; case FICC_RED: c = FI_RGBA_RED; break; case FICC_ALPHA: if(dst_bpp != 32) return FALSE; c = FI_RGBA_ALPHA; break; default: return FALSE; } // perform insertion int bytespp = dst_bpp / 8; // bytes / pixel for(unsigned y = 0; y < dst_height; y++) { BYTE *src_bits = FreeImage_GetScanLine(src, y); BYTE *dst_bits = FreeImage_GetScanLine(dst, y); for(unsigned x = 0; x < dst_width; x++) { dst_bits[c] = src_bits[x]; dst_bits += bytespp; } } return TRUE; }
/** Convert a processed raw image to a FIBITMAP @param image Processed raw image @return Returns the converted dib if successfull, returns NULL otherwise @see libraw_LoadEmbeddedPreview */ static FIBITMAP * libraw_ConvertProcessedImageToDib(libraw_processed_image_t *image) { FIBITMAP *dib = NULL; try { unsigned width = image->width; unsigned height = image->height; unsigned bpp = image->bits; if(bpp == 16) { // allocate output dib dib = FreeImage_AllocateT(FIT_RGB16, width, height); if(!dib) { throw FI_MSG_ERROR_DIB_MEMORY; } // write data WORD *raw_data = (WORD*)image->data; for(unsigned y = 0; y < height; y++) { FIRGB16 *output = (FIRGB16*)FreeImage_GetScanLine(dib, height - 1 - y); for(unsigned x = 0; x < width; x++) { output[x].red = raw_data[0]; output[x].green = raw_data[1]; output[x].blue = raw_data[2]; raw_data += 3; } } } else if(bpp == 8) { // allocate output dib dib = FreeImage_AllocateT(FIT_BITMAP, width, height, 24); if(!dib) { throw FI_MSG_ERROR_DIB_MEMORY; } // write data BYTE *raw_data = (BYTE*)image->data; for(unsigned y = 0; y < height; y++) { RGBTRIPLE *output = (RGBTRIPLE*)FreeImage_GetScanLine(dib, height - 1 - y); for(unsigned x = 0; x < width; x++) { output[x].rgbtRed = raw_data[0]; output[x].rgbtGreen = raw_data[1]; output[x].rgbtBlue = raw_data[2]; raw_data += 3; } } } return dib; } catch(const char *text) { FreeImage_Unload(dib); FreeImage_OutputMessageProc(s_format_id, text); return NULL; } }
static FIBITMAP* ConvertComplexImageToAbsoluteValued(FIBITMAP *src, bool squared) { FIBITMAP *dst = NULL; unsigned x, y; unsigned width = FreeImage_GetWidth(src); unsigned height = FreeImage_GetHeight(src); // Allocate a double bit dib dst = FreeImage_AllocateT(FIT_DOUBLE, width, height, 32, 0, 0, 0); if(!dst) return NULL; FICOMPLEX *src_bits, *src_bit; double *dst_bits; if(squared) { for(y = 0; y < height; y++) { src_bits = (FICOMPLEX *) FreeImage_GetScanLine(src, y); dst_bits = (double *) FreeImage_GetScanLine(dst, y); for(x=0; x < width; x++) { src_bit = src_bits + x; *(dst_bits + x) = (double) ((src_bit->r * src_bit->r) + (src_bit->i * src_bit->i)); } } } else { for(y = 0; y < height; y++) { src_bits = (FICOMPLEX *) FreeImage_GetScanLine(src, y); dst_bits = (double *) FreeImage_GetScanLine(dst, y); for(x=0; x < width; x++) { src_bit = src_bits + x; *(dst_bits + x) = sqrt((double) ((src_bit->r * src_bit->r) + (src_bit->i * src_bit->i))); } } } return dst; }
/** Returns minus the residual for the model problem. Input quantities are u[0..n-1][0..n-1] and rhs[0..n-1][0..n-1], while res[0..n-1][0..n-1] is returned. */ static void fmg_residual(FIBITMAP *RES, FIBITMAP *U, FIBITMAP *RHS, int n) { int row, col; const float h = 1.0F / (n-1); const float h2i = 1.0F / (h*h); const int res_pitch = FreeImage_GetPitch(RES) / sizeof(float); const int u_pitch = FreeImage_GetPitch(U) / sizeof(float); const int rhs_pitch = FreeImage_GetPitch(RHS) / sizeof(float); float *res_bits = (float*)FreeImage_GetBits(RES); const float *u_bits = (float*)FreeImage_GetBits(U); const float *rhs_bits = (float*)FreeImage_GetBits(RHS); // interior points { float *res_scan = res_bits + res_pitch; const float *u_scan = u_bits + u_pitch; const float *rhs_scan = rhs_bits + rhs_pitch; for (row = 1; row < n-1; row++) { for (col = 1; col < n-1; col++) { // calculate RES(row, col) = // -h2i * [ U(row+1, col) + U(row-1, col) + U(row, col+1) + U(row, col-1) - 4 * U(row, col) ] + RHS(row, col); float *res_center = res_scan + col; const float *u_center = u_scan + col; const float *rhs_center = rhs_scan + col; *res_center = *(u_center + u_pitch) + *(u_center - u_pitch) + *(u_center + 1) + *(u_center - 1) - 4 * *u_center; *res_center *= -h2i; *res_center += *rhs_center; } res_scan += res_pitch; u_scan += u_pitch; rhs_scan += rhs_pitch; } } // boundary points { memset(FreeImage_GetScanLine(RES, 0), 0, FreeImage_GetPitch(RES)); memset(FreeImage_GetScanLine(RES, n-1), 0, FreeImage_GetPitch(RES)); float *left = res_bits; float *right = res_bits + (n-1); for(int k = 0; k < n; k++) { *left = 0; *right = 0; left += res_pitch; right += res_pitch; } } }
static inline void CopyImageRow (FIBITMAP * src, int src_row, int row_start, int count) { int pitch = FreeImage_GetPitch (src); BYTE *src_bits, *dst_bits; src_bits = FreeImage_GetScanLine (src, src_row); for(int y = row_start; y < (row_start + count); y++) { dst_bits = FreeImage_GetScanLine (src, y); memcpy (dst_bits, src_bits, pitch); } }
/* dt of binary image using squared distance */ FIBITMAP *DLL_CALLCONV FIA_DistanceTransform (FIBITMAP * src) { int width = FreeImage_GetWidth (src); int height = FreeImage_GetHeight (src); float *out_ptr; unsigned char *src_ptr; FIBITMAP *out = FIA_ConvertToGreyscaleFloatType (src, FIT_FLOAT); for(register int y = 0; y < height; y++) { src_ptr = (unsigned char *) FreeImage_GetScanLine (src, y); out_ptr = (float *) FreeImage_GetScanLine (out, y); for(register int x = 0; x < width; x++) { if (src_ptr[x] == 0) { out_ptr[x] = 0.0f; } else { out_ptr[x] = INF; } } } dt2d (out); // take square roots for(register int y = 0; y < height; y++) { out_ptr = (float *) FreeImage_GetScanLine (out, y); for(register int x = 0; x < width; x++) { out_ptr[x] = sqrt (out_ptr[x]); } } FIBITMAP *ret = FreeImage_ConvertToStandardType (out, 1); FreeImage_Unload (out); return ret; }
bool LoadImage(FIBITMAP* image, Graphics::TBitmap* picture) { picture->FreeImage(); picture->PixelFormat = pf32bit; picture->Width = FreeImage_GetWidth(image); picture->Height = FreeImage_GetHeight(image); RGBQUAD *row1, *row2; for(int i(0); i < picture->Height; ++i) { row1 = (RGBQUAD *)FreeImage_GetScanLine(image,i); row2 = (RGBQUAD *)picture->ScanLine[picture->Height-1-i]; if(!row1 || !row2) return false; for(int j(0); j < picture->Width; ++j) { row2[j].rgbRed = row1[j].rgbRed; row2[j].rgbGreen = row1[j].rgbGreen; row2[j].rgbBlue = row1[j].rgbBlue; } } return true; }
void write_image(const string& file, const SampleBuffer& buffer) { const float samples = static_cast<float>(buffer.samples()); FIBITMAP* dib = FreeImage_Allocate(buffer.width(), buffer.height(), 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); const unsigned int BYTESPP = FreeImage_GetLine(dib) / FreeImage_GetWidth(dib); for (unsigned int y = 0; y < FreeImage_GetHeight(dib); ++y) { BYTE* bits = FreeImage_GetScanLine(dib, y); for (unsigned int x = 0; x < FreeImage_GetWidth(dib); ++x) { vec3 c = gamma_correct(buffer.get(x, y) / samples) * 255.0f; bits[FI_RGBA_RED] = static_cast<BYTE>(c.r); bits[FI_RGBA_GREEN] = static_cast<BYTE>(c.g); bits[FI_RGBA_BLUE] = static_cast<BYTE>(c.b); bits[FI_RGBA_ALPHA] = 255; bits += BYTESPP; } } if (!FreeImage_Save(FIF_PNG, dib, file.c_str(), 0)) { string err = "Failed to save screenshot to file '"; err += file; err += '\''; throw err; } FreeImage_Unload(dib); }
void poImage::setPixel(poPoint p, poColor c) { if(p.x < 0 || p.y < 0 || p.x >= getWidth() || p.y >=getHeight()) return; uint x = p.x; uint y = p.y; BYTE *bits = FreeImage_GetScanLine(bitmap, y); switch(getChannels()) { case 1: bits[x] = (((0.21*c.R) + (0.71*c.G) + (0.07*c.B)) * c.A) * 255; break; case 2: bits[x*2] = ((0.21*c.R) + (0.71*c.G) + (0.07*c.B)) * 255; bits[x*2+1] = c.A * 255; break; case 3: bits[x*3] = c.R * c.A * 255; bits[x*3+1] = c.G * c.A * 255; bits[x*3+2] = c.B * c.A * 255; break; case 4: bits[x*4] = c.R * 255; bits[x*4+1] = c.G * 255; bits[x*4+2] = c.B * 255; bits[x*4+3] = c.A * 255; break; } }
bool RGBAImage::WriteToFile(const char* filename) { const FREE_IMAGE_FORMAT fileType = FreeImage_GetFIFFromFilename(filename); if(FIF_UNKNOWN == fileType) { printf("Can't save to unknown filetype %s\n", filename); return false; } FIBITMAP* bitmap = FreeImage_Allocate(Width, Height, 32, 0x000000ff, 0x0000ff00, 0x00ff0000); if(!bitmap) { printf("Failed to create freeimage for %s\n", filename); return false; } const unsigned int* source = Data; for( int y=0; y < Height; y++, source += Width ) { unsigned int* scanline = (unsigned int*)FreeImage_GetScanLine(bitmap, Height - y - 1 ); memcpy(scanline, source, sizeof(source[0]) * Width); } FreeImage_SetTransparent(bitmap, true); FIBITMAP* converted = FreeImage_ConvertTo24Bits(bitmap); const bool result = !!FreeImage_Save(fileType, converted, filename); if(!result) printf("Failed to save to %s\n", filename); FreeImage_Unload(converted); FreeImage_Unload(bitmap); return result; }
/** Used for all 32 and 24 bit loading of uncompressed images */ static void loadTrueColor(FIBITMAP* dib, int width, int height, int file_pixel_size, FreeImageIO* io, fi_handle handle, BOOL as24bit) { const int pixel_size = as24bit ? 3 : file_pixel_size; // input line cache BYTE* file_line = (BYTE*)malloc( width * file_pixel_size); if (!file_line) { throw FI_MSG_ERROR_MEMORY; } for (int y = 0; y < height; y++) { BYTE *bits = FreeImage_GetScanLine(dib, y); io->read_proc(file_line, file_pixel_size, width, handle); BYTE *bgra = file_line; for (int x = 0; x < width; x++) { bits[FI_RGBA_BLUE] = bgra[0]; bits[FI_RGBA_GREEN] = bgra[1]; bits[FI_RGBA_RED] = bgra[2]; if (!as24bit) { bits[FI_RGBA_ALPHA] = bgra[3]; } bgra += file_pixel_size; bits += pixel_size; } } free(file_line); }
FIBITMAP* TargaThumbnail::toFIBITMAP() { if(isNull() || _depth == 0) { return NULL; } const unsigned line_size = _depth * _w / 8; FIBITMAP* dib = FreeImage_Allocate(_w, _h, _depth); if(!dib) { return NULL; } const BYTE* line = _data; const BYTE height = _h; for (BYTE h = 0; h < height; ++h, line += line_size) { BYTE* dst_line = FreeImage_GetScanLine(dib, height - 1 - h); memcpy(dst_line, line, line_size); } #ifdef FREEIMAGE_BIGENDIAN swapShortPixels(dib); #endif #if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB SwapRedBlue32(dib); #endif return dib; }
/** Invert only color components, skipping Alpha/Black (Can be useful as public/utility function) */ static BOOL invertColor(FIBITMAP* dib) { FREE_IMAGE_TYPE type = FreeImage_GetImageType(dib); const unsigned Bpp = FreeImage_GetBPP(dib)/8; if((type == FIT_BITMAP && Bpp == 4) || type == FIT_RGBA16) { const unsigned width = FreeImage_GetWidth(dib); const unsigned height = FreeImage_GetHeight(dib); BYTE *line_start = FreeImage_GetScanLine(dib, 0); const unsigned pitch = FreeImage_GetPitch(dib); const unsigned triBpp = Bpp - (Bpp == 4 ? 1 : 2); for(unsigned y = 0; y < height; y++) { BYTE *line = line_start; for(unsigned x = 0; x < width; x++) { for(unsigned b=0; b < triBpp; ++b) { line[b] = ~line[b]; } line += Bpp; } line_start += pitch; } return TRUE; } else { return FreeImage_Invert(dib); } }
poColor poImage::getPixel(poPoint p) const { if(!isValid() || p.x < 0 || p.y < 0 || p.x >= getWidth() || p.y >=getHeight()) return poColor(); uint x = p.x; uint y = p.y; BYTE* bits = FreeImage_GetScanLine(bitmap, y); poColor ret; switch(getChannels()) { case 1: ret.set255(bits[x], bits[x], bits[x], 255); break; case 2: ret.set255(bits[x*2], bits[x*2], bits[x*2], bits[x*2+1]); break; case 3: ret.set255(bits[x*3+0], bits[x*3+1], bits[x*3+2], 255); break; case 4: ret.set255(bits[x*4+0], bits[x*4+1], bits[x*4+2], bits[x*4+3]); break; default: ; } return ret; }
static BOOL DLL_CALLCONV Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) { if(!dib) return FALSE; if(FreeImage_GetImageType(dib) != FIT_RGBF) return FALSE; unsigned width = FreeImage_GetWidth(dib); unsigned height = FreeImage_GetHeight(dib); // write the header rgbeHeaderInfo header_info; memset(&header_info, 0, sizeof(rgbeHeaderInfo)); // fill the header with correct gamma and exposure rgbe_WriteMetadata(dib, &header_info); // fill a comment sprintf(header_info.comment, "# Made with FreeImage %s", FreeImage_GetVersion()); if(!rgbe_WriteHeader(io, handle, width, height, &header_info)) { return FALSE; } // write each scanline for(unsigned y = 0; y < height; y++) { FIRGBF *scanline = (FIRGBF*)FreeImage_GetScanLine(dib, height - 1 - y); if(!rgbe_WritePixels_RLE(io, handle, scanline, width, 1)) { return FALSE; } } return TRUE; }
/** Pre-multiplies a 32-bit image's red-, green- and blue channels with it's alpha channel for to be used with e.g. the Windows GDI function AlphaBlend(). The transformation changes the red-, green- and blue channels according to the following equation: channel(x, y) = channel(x, y) * alpha_channel(x, y) / 255 @param dib Input/Output dib to be premultiplied @return Returns TRUE on success, FALSE otherwise (e.g. when the bitdepth of the source dib cannot be handled). */ BOOL DLL_CALLCONV FreeImage_PreMultiplyWithAlpha(FIBITMAP *dib) { if (!FreeImage_HasPixels(dib)) return FALSE; if ((FreeImage_GetBPP(dib) != 32) || (FreeImage_GetImageType(dib) != FIT_BITMAP)) { return FALSE; } int width = FreeImage_GetWidth(dib); int height = FreeImage_GetHeight(dib); for(int y = 0; y < height; y++) { BYTE *bits = FreeImage_GetScanLine(dib, y); for (int x = 0; x < width; x++, bits += 4) { const BYTE alpha = bits[FI_RGBA_ALPHA]; // slightly faster: care for two special cases if(alpha == 0x00) { // special case for alpha == 0x00 // color * 0x00 / 0xFF = 0x00 bits[FI_RGBA_BLUE] = 0x00; bits[FI_RGBA_GREEN] = 0x00; bits[FI_RGBA_RED] = 0x00; } else if(alpha == 0xFF) { // nothing to do for alpha == 0xFF // color * 0xFF / 0xFF = color continue; } else { bits[FI_RGBA_BLUE] = (BYTE)( (alpha * (WORD)bits[FI_RGBA_BLUE] + 127) / 255 ); bits[FI_RGBA_GREEN] = (BYTE)( (alpha * (WORD)bits[FI_RGBA_GREEN] + 127) / 255 ); bits[FI_RGBA_RED] = (BYTE)( (alpha * (WORD)bits[FI_RGBA_RED] + 127) / 255 ); } } } return TRUE; }
/** Load uncompressed image pixels for 1-, 4-, 8-, 16-, 24- and 32-bit dib @param io FreeImage IO @param handle FreeImage IO handle @param dib Image to be loaded @param height Image height @param pitch Image pitch @param bit_count Image bit-depth (1-, 4-, 8-, 16-, 24- or 32-bit) @return Returns TRUE if successful, returns FALSE otherwise */ static BOOL LoadPixelData(FreeImageIO *io, fi_handle handle, FIBITMAP *dib, int height, unsigned pitch, unsigned bit_count) { unsigned count = 0; // Load pixel data // NB: height can be < 0 for BMP data if (height > 0) { count = io->read_proc((void *)FreeImage_GetBits(dib), height * pitch, 1, handle); if(count != 1) { return FALSE; } } else { int positiveHeight = abs(height); for (int c = 0; c < positiveHeight; ++c) { count = io->read_proc((void *)FreeImage_GetScanLine(dib, positiveHeight - c - 1), pitch, 1, handle); if(count != 1) { return FALSE; } } } // swap as needed #ifdef FREEIMAGE_BIGENDIAN if (bit_count == 16) { for(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) { WORD *pixel = (WORD *)FreeImage_GetScanLine(dib, y); for(unsigned x = 0; x < FreeImage_GetWidth(dib); x++) { SwapShort(pixel); pixel++; } } } #endif #if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB if (bit_count == 24 || bit_count == 32) { for(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) { BYTE *pixel = FreeImage_GetScanLine(dib, y); for(unsigned x = 0; x < FreeImage_GetWidth(dib); x++) { INPLACESWAP(pixel[0], pixel[2]); pixel += (bit_count >> 3); } } } #endif return TRUE; }
/** @brief Set the real or imaginary part of a complex image. Both src and dst must have the same width and height. @param dst Image to modify (image of type FIT_COMPLEX) @param src Input image of type FIT_DOUBLE @param channel Channel to modify @return Returns TRUE if successful, FALSE otherwise. */ BOOL DLL_CALLCONV FreeImage_SetComplexChannel(FIBITMAP *dst, FIBITMAP *src, FREE_IMAGE_COLOR_CHANNEL channel) { unsigned x, y; double *src_bits = NULL; FICOMPLEX *dst_bits = NULL; if(!src || !dst) return FALSE; // src image should be of type FIT_DOUBLE, dst image should be of type FIT_COMPLEX FREE_IMAGE_TYPE src_type = FreeImage_GetImageType(src); FREE_IMAGE_TYPE dst_type = FreeImage_GetImageType(dst); if((src_type != FIT_DOUBLE) || (dst_type != FIT_COMPLEX)) return FALSE; // src and dst images should have the same width and height unsigned src_width = FreeImage_GetWidth(src); unsigned src_height = FreeImage_GetHeight(src); unsigned dst_width = FreeImage_GetWidth(dst); unsigned dst_height = FreeImage_GetHeight(dst); if((src_width != dst_width) || (src_height != dst_height)) return FALSE; // select the channel to modify switch(channel) { case FICC_REAL: // real part for(y = 0; y < dst_height; y++) { src_bits = (double *)FreeImage_GetScanLine(src, y); dst_bits = (FICOMPLEX *)FreeImage_GetScanLine(dst, y); for(x = 0; x < dst_width; x++) { dst_bits[x].r = src_bits[x]; } } break; case FICC_IMAG: // imaginary part for(y = 0; y < dst_height; y++) { src_bits = (double *)FreeImage_GetScanLine(src, y); dst_bits = (FICOMPLEX *)FreeImage_GetScanLine(dst, y); for(x = 0; x < dst_width; x++) { dst_bits[x].i = src_bits[x]; } } break; } return TRUE; }
static FIBITMAP * DLL_CALLCONV Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { FIBITMAP *dib = NULL; if(!handle) { return NULL; } BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; try { rgbeHeaderInfo header_info; unsigned width, height; // Read the header if(rgbe_ReadHeader(io, handle, &width, &height, &header_info) == FALSE) { return NULL; } // allocate a RGBF image dib = FreeImage_AllocateHeaderT(header_only, FIT_RGBF, width, height); if(!dib) { throw FI_MSG_ERROR_MEMORY; } // set the metadata as comments rgbe_ReadMetadata(dib, &header_info); if(header_only) { // header only mode return dib; } // read the image pixels and fill the dib for(unsigned y = 0; y < height; y++) { FIRGBF *scanline = (FIRGBF*)FreeImage_GetScanLine(dib, height - 1 - y); if(!rgbe_ReadPixels_RLE(io, handle, scanline, width, 1)) { FreeImage_Unload(dib); return NULL; } } } catch(const char *text) { if(dib != NULL) { FreeImage_Unload(dib); } FreeImage_OutputMessageProc(s_format_id, text); } return dib; }
/** check and adapt scanline */ void Vt2IsoImageFreeImage_c::checkUpdateScanline( unsigned int aui_y ) { if ( i_curScanLineY != int(aui_y) ) { // read scanline for given y // ( FreeImage library documentation states, that first scanline in memory is // bottommost -> i.e. upsidedown in relation to other modellings // -> change direction back to usual with ( ui_height - aui_y ) ) scanline = FreeImage_GetScanLine(bitmap, ( (ui_height - 1) - aui_y ) ); i_curScanLineY = aui_y; } }
int DLL_CALLCONV FIA_ReplaceColourPlanesHSV (FIBITMAP **src, FIBITMAP *H, FIBITMAP *S, FIBITMAP *V) { // HSV source images must all be the same size FIBITMAP *R=NULL, *G=NULL, *B=NULL; int x, y; double h, s, v; // Check we have valid images if (!FreeImage_HasPixels(H) || !FIA_Is8Bit(H) || !FreeImage_HasPixels(S) || !FIA_Is8Bit(S) || !FreeImage_HasPixels(V) || !FIA_Is8Bit(V)) { return FIA_ERROR; } // alloc RGB to something the same size as the source images R = FreeImage_Clone(H); G = FreeImage_Clone(H); B = FreeImage_Clone(H); // Convert the HSV values to RGB and store for(y = 0; y < FreeImage_GetHeight(H); y++) { BYTE *src_h = FreeImage_GetScanLine(H, y); BYTE *src_s = FreeImage_GetScanLine(S, y); BYTE *src_v = FreeImage_GetScanLine(V, y); BYTE *dst_r = FreeImage_GetScanLine(R, y); BYTE *dst_g = FreeImage_GetScanLine(G, y); BYTE *dst_b = FreeImage_GetScanLine(B, y); for(x = 0; x < FreeImage_GetWidth(H); x++) { // Red, Green and Blue are between 0 and 255 // Hue varies between 0 and 360 // Satuation between 0 and 1 // Value between 0 and 1 h = ((double)(*src_h))/255.0 * 360.0; s = ((double)(*src_s))/255.0; v = ((double)(*src_v))/255.0; FIA_HSVToRGB (h, s, v, dst_r, dst_g, dst_b); // jump to next pixel src_h ++; src_s ++; src_v ++; dst_r ++; dst_g ++; dst_b ++; } } FIA_ReplaceColourPlanes (src, R, G, B); FreeImage_Unload(R); FreeImage_Unload(G); FreeImage_Unload(B); return FIA_SUCCESS; }
/** * Clears the image to the chosen color. Returns 0 if there is no image loaded. * For ::IND_LUMINANCE image type, the 'color' value is taken from the pA parameter. Other parameters are ignored * @param pR Byte R (Red). * @param pG Byte G (Green). * @param pB Byte B (Blue). * @param pA Byte A (Transparency). */ bool IND_Image::clear(BYTE pR, BYTE pG, BYTE pB, BYTE pA) { // No image loaded if (!isImageLoaded() || !FreeImage_HasPixels(getFreeImageHandle())) return false; FIBITMAP* dib = getFreeImageHandle(); FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); int bpp (getBpp()); int bytespp = bpp/8; int colorFormat = getFormatInt(); //Interprets differently depending on image type switch(image_type) { case FIT_BITMAP: //LOOP - Y coords for(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) { BYTE *bits = FreeImage_GetScanLine(dib, y); //LOOP - X coords for(unsigned x = 0; x < FreeImage_GetWidth(dib); x++) { // Set pixel color to total transparency, if color matches given colorkey //RGBx color format if(IND_COLOUR_INDEX != colorFormat && IND_LUMINANCE != colorFormat) { bits[FI_RGBA_RED] = pR; bits[FI_RGBA_GREEN] = pG; bits[FI_RGBA_BLUE] = pB; } else if (IND_COLOUR_INDEX == colorFormat) { //TODO } else if (IND_LUMINANCE == colorFormat) { assert (8 == bpp); //The bpp for IND_LUMINANCE should be 8 for this image type *bits = pA; } if (IND_RGBA == colorFormat) { bits[FI_RGBA_ALPHA] = pA; } // jump to next pixel bits += bytespp; }//LOOP END }//LOOP END break; //TODO: OTHER IMAGE TYPES default: break; } return true; }