bool CResizeEngine::scale (CDIBSection *src, CDIBSection *dst, ILongTimeRunCallback *pCallback) { assert(src != NULL && dst != NULL); uint src_width = (uint)src->getWidth(); uint src_height = (uint)src->getHeight(); uint dst_width = (uint)dst->getWidth(); uint dst_height = (uint)dst->getHeight(); int bitcount = src->getBitCounts(); assert(dst_width > 0 && dst_height > 0); assert(bitcount == 24 || bitcount == 32); if (m_pFilter == NULL) { _FastScale(src, dst); return true; } if(dst_width * src_height <= dst_height * src_width) { CDIBSectionPtr tmp = CDIBSection::createDIBSection(dst_width, src_height, bitcount, false); if (!tmp) { return false; } if (!horizontalFilter(src, src_height, tmp.get(), 0, src_height, pCallback)) { assert(pCallback && pCallback->shouldStop()); return false; } if (!verticalFilter(tmp.get(), dst, pCallback)) { assert(pCallback && pCallback->shouldStop()); return false; } } else { CDIBSectionPtr tmp = CDIBSection::createDIBSection(src_width, dst_height, bitcount, false); if (!tmp) { return false; } if (!verticalFilter(src, tmp.get(), pCallback)) { assert(pCallback && pCallback->shouldStop()); return false; } if (!horizontalFilter(tmp.get(), dst_height, dst, 0, dst_height, pCallback)) { assert(pCallback && pCallback->shouldStop()); return false; } } return true; }
FIBITMAP* CResizeEngine::scale(FIBITMAP *src, unsigned dst_width, unsigned dst_height) { DWORD src_width = FreeImage_GetWidth(src); DWORD src_height = FreeImage_GetHeight(src); unsigned redMask = FreeImage_GetRedMask(src); unsigned greenMask = FreeImage_GetGreenMask(src); unsigned blueMask = FreeImage_GetBlueMask(src); unsigned bpp = FreeImage_GetBPP(src); FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(src); // allocate the dst image FIBITMAP *dst = FreeImage_AllocateT(image_type, dst_width, dst_height, bpp, redMask, greenMask, blueMask); if(!dst) return NULL; if(bpp == 8) { if(FreeImage_GetColorType(src) == FIC_MINISWHITE) { // build an inverted greyscale palette RGBQUAD *dst_pal = FreeImage_GetPalette(dst); for(int i = 0; i < 256; i++) { dst_pal[i].rgbRed = dst_pal[i].rgbGreen = dst_pal[i].rgbBlue = (BYTE)(255 - i); } } else { // build a greyscale palette RGBQUAD *dst_pal = FreeImage_GetPalette(dst); for(int i = 0; i < 256; i++) { dst_pal[i].rgbRed = dst_pal[i].rgbGreen = dst_pal[i].rgbBlue = (BYTE)i; } } } // decide which filtering order (xy or yx) is faster for this mapping by // counting convolution multiplies if(dst_width*src_height <= dst_height*src_width) { // xy filtering // ------------- // allocate a temporary image FIBITMAP *tmp = FreeImage_AllocateT(image_type, dst_width, src_height, bpp, redMask, greenMask, blueMask); if(!tmp) { FreeImage_Unload(dst); return NULL; } // scale source image horizontally into temporary image horizontalFilter(src, src_width, src_height, tmp, dst_width, src_height); // scale temporary image vertically into result image verticalFilter(tmp, dst_width, src_height, dst, dst_width, dst_height); // free temporary image FreeImage_Unload(tmp); } else { // yx filtering // ------------- // allocate a temporary image FIBITMAP *tmp = FreeImage_AllocateT(image_type, src_width, dst_height, bpp, redMask, greenMask, blueMask); if(!tmp) { FreeImage_Unload(dst); return NULL; } // scale source image vertically into temporary image verticalFilter(src, src_width, src_height, tmp, src_width, dst_height); // scale temporary image horizontally into result image horizontalFilter(tmp, src_width, dst_height, dst, dst_width, dst_height); // free temporary image FreeImage_Unload(tmp); } return dst; }