CreateDIBSection + 16 bit system color - winapi

This code works perfect on 32 bit system color (Windows 7),
but it doesn't work on 16 bit color - menu bitmaps not transparent!!!:
...
HBITMAP rv = rgb(hsrc, 16);
...
HBITMAP rgb(HBITMAP hsrc, WORD wBitsPixel) {
HBITMAP hold = NULL;
HDC hdcsrc = NULL, hdc = NULL;
BITMAP bmp = {0};
HBITMAP dib = NULL;
UCHAR *dst = NULL, *src = NULL, *tmp = NULL;
UCHAR alpha;
int bpl;
ULONG x, y;
DWORD bmp_size = 0;
HANDLE hdib = NULL;
char *lpbitmap = NULL;
int rv = 0;
hdc = GetDC(m_hMainDlg);
hdcsrc = CreateCompatibleDC(hdc);
hold = (HBITMAP)SelectObject(hdcsrc, hsrc);
rv = GetObject(hsrc, sizeof(BITMAP), &bmp);
BITMAPINFOHEADER bi = {0};
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bmp.bmWidth;;
bi.biHeight = bmp.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = wBitsPixel;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
bmp_size = ((bmp.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmp.bmHeight;
hdib = GlobalAlloc(GHND, bmp_size);
lpbitmap = (char *)GlobalLock(hdib);
/* Get bits of source bitmap. */
GetDIBits(hdcsrc, hsrc, 0, bmp.bmHeight, lpbitmap, (BITMAPINFO *)&bi, DIB_RGB_COLORS);
/* For destination bitmap */
BITMAPINFO bmi = {0};
bmi.bmiHeader.biSize = sizeof(BITMAPINFO);
bmi.bmiHeader.biWidth = bmp.bmWidth;
bmi.bmiHeader.biHeight = bmp.bmHeight;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = wBitsPixel;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = 0;
bmi.bmiHeader.biXPelsPerMeter = 0;
bmi.bmiHeader.biYPelsPerMeter = 0;
bmi.bmiHeader.biClrUsed = 0;
bmi.bmiHeader.biClrImportant = 0;
dib = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, (void **)&dst, NULL, 0);
bpl = 4 * bmp.bmWidth; /* bytes per line */
src = (UCHAR *)lpbitmap;
for (y = 0; y < bmp.bmHeight; y++, src += bpl) {
tmp = src;
for (x = 0; x < bmp.bmWidth; x++) {
alpha = tmp[3];
dst[0] = tmp[0] * alpha / 255;
dst[1] = tmp[1] * alpha / 255;
dst[2] = tmp[2] * alpha / 255;
dst[3] = alpha;
dst += 4;
tmp += 4;
}
}
// free resources
ReleaseDC(m_hMainDlg, hdc);
SelectObject(hdcsrc, hold);
DeleteDC(hdcsrc);
GlobalUnlock(hdib);
GlobalFree(hdib);
return dib;
}

Related

Reading EXR file

I'm trying to create a IWICBitmap from an EXR file (error checks removed).
#pragma pack(push,1)
struct fl
{
float r, g, b, a;
};
#pragma pack(pop)
HRESULT Open(const char* f,IWICBitmap** d)
{
exr_context_initializer_t ctxtinit = EXR_DEFAULT_CONTEXT_INITIALIZER;
exr_context_t myfile = {};
exr_result_t rv = exr_start_read(&myfile, f, &ctxtinit);
int part_index = 0;
const exr_attr_chlist_t* chl = 0;
exr_get_channels(myfile, part_index, &chl);
int32_t ck = 0;
rv = exr_get_chunk_count(myfile, part_index, &ck);
int32_t sl = 0;
rv = exr_get_scanlines_per_chunk(myfile, part_index, &sl);
int y = 0;
int wi = 0;
int he = 0;
std::vector<fl> data; // put here the floats
exr_decode_pipeline_t dec = {};
for (int32_t cuk = 0; cuk < ck; cuk++)
{
exr_chunk_info_t ch = {};
exr_read_scanline_chunk_info(myfile, part_index, y, &ch);
wi = ch.width;
he += ch.height;
y += sl;
bool first = 0;
if (dec.decompress_fn == 0)
{
rv = exr_decoding_initialize(myfile, part_index, &ch, &dec);
rv = exr_decoding_choose_default_routines(myfile, part_index, &dec);
first = 1;
}
if (!first)
rv = exr_decoding_update(myfile, part_index,&ch,&dec);
rv = exr_decoding_run(myfile, part_index, &dec);
int NumPixels = (wi * ch.height);
auto BytesPerPixel = ch.unpacked_size / NumPixels;
if (true)
{
// RGB(A)
if (chl->entries[0].pixel_type == EXR_PIXEL_HALF)
{
if (BytesPerPixel == chl->num_channels * 2)
{
auto ds = data.size();
data.resize(ds + NumPixels);
auto p = data.data() + ds;
char* x = (char*)dec.unpacked_buffer;
for (int j = 0; j < NumPixels; j++)
{
uint16_t* u = (uint16_t*)x;
p->a = 1.0f;
for (int jH = 0; jH < chl->num_channels; jH++)
{
half ha(Imath_3_2::half::FromBits,*u);
ha.setBits(*u);
if (strcmp(chl->entries[jH].name.str, "R") == 0) p->r = ha.operator float();
if (strcmp(chl->entries[jH].name.str, "G") == 0) p->g = ha.operator float();
if (strcmp(chl->entries[jH].name.str, "B") == 0) p->b = ha.operator float();
if (strcmp(chl->entries[jH].name.str, "A") == 0) p->a = ha.operator float();
u++;
}
x += BytesPerPixel;
p++;
}
}
else
break;
}
if (chl->entries[0].pixel_type == EXR_PIXEL_FLOAT)
{
// code removed for simplicity, I guess the same issue happens here unless it's a problem of the half-float
}
}
}
rv = exr_decoding_destroy(myfile, &dec);
exr_finish(&myfile);
CComPtr<IWICImagingFactory2> wbfact = 0;
CoCreateInstance(CLSID_WICImagingFactory2, 0, CLSCTX_INPROC_SERVER,
__uuidof(IWICImagingFactory2), (void**)&wbfact);
return wbfact->CreateBitmapFromMemory(wi, he, GUID_WICPixelFormat128bppPRGBAFloat, wi * 16,(UINT)data.size()*16, (BYTE*)data.data(), d);
}
What am I doing wrong? The pixel number I'm reading is correct (in this image 800x800).
My result:
Photoshop:
Is there a problem with the half-float? I'm just using the OpenEXR's IMath implementation.

Windows.h GDI - BITMAPINFO alloca indicates failure

I want to create an image from the desktop and set it to gray using BITMAPINFO, but it keeps showing me the warning, "Warning C6255 _alloca indicates failure by raising a stack overflow exception. Consider using _malloca instead".
I would appreciate any advice.
HBITMAP CreateGreyscaleBitmap(int cx, int cy)
{
BITMAPINFO* pbmi = (BITMAPINFO*)alloca(sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256);
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbmi->bmiHeader.biWidth = cx;
pbmi->bmiHeader.biHeight = cy;
pbmi->bmiHeader.biPlanes = 1;
pbmi->bmiHeader.biBitCount = 8;
pbmi->bmiHeader.biCompression = BI_RGB;
pbmi->bmiHeader.biSizeImage = 0;
pbmi->bmiHeader.biXPelsPerMeter = 14173;
pbmi->bmiHeader.biYPelsPerMeter = 14173;
pbmi->bmiHeader.biClrUsed = 0;
pbmi->bmiHeader.biClrImportant = 0;
for (int i = 0; i < 256; i++)
{
pbmi->bmiColors[i].rgbRed = i;
pbmi->bmiColors[i].rgbGreen = i;
pbmi->bmiColors[i].rgbBlue = i;
pbmi->bmiColors[i].rgbReserved = 0;
}
PVOID pv;
return CreateDIBSection(NULL, pbmi, DIB_RGB_COLORS, &pv, NULL, 0);
}

Creating 24-bit BITMAP in Winapi

I'm using the following code in order to convert my ImageMagick image to 32-bit HBITMAP:
BITMAP bitmap;
std::memset(&bitmap, 0, sizeof(bitmap));
bitmap.bmType = 0;
bitmap.bmWidth = image->image()->columns;
bitmap.bmHeight = image->image()->rows;
bitmap.bmWidthBytes = 4 * bitmap.bmWidth;
bitmap.bmPlanes = 1;
bitmap.bmBitsPixel = 32;
bitmap.bmBits = NULL;
const size_t size = bitmap.bmWidthBytes * bitmap.bmHeight;
auto buffer = (HANDLE)GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, size);
RGBQUAD *bitmap_bits = (RGBQUAD *) GlobalLock((HGLOBAL) buffer);
register RGBQUAD *q = bitmap_bits;
for (size_t y = 0; y < image->image()->rows; y++)
{
register auto p = GetVirtualPixels(image->image(), 0, y, image->image()->columns, 1, exception);
if (!p) break;
for (size_t x = 0; x < image->image()->columns; x++)
{
q->rgbRed = ScaleQuantumToChar(GetPixelRed(image->image(), p));
q->rgbGreen = ScaleQuantumToChar(GetPixelGreen(image->image(), p));
q->rgbBlue = ScaleQuantumToChar(GetPixelBlue(image->image(), p));
q->rgbReserved = 0;
p += GetPixelChannels(image->image());
q++;
}
}
bitmap.bmBits = bitmap_bits;
HBITMAP hbmp = CreateBitmapIndirect(&bitmap);
It works well, but I'd like to save some memory by using images with lower depth. Unfortunately I'm not even able to make it work with 24-bit images. I modified my code to look like this:
BITMAP bitmap;
std::memset(&bitmap, 0, sizeof(bitmap));
bitmap.bmType = 0;
bitmap.bmWidth = image->image()->columns;
bitmap.bmHeight = image->image()->rows;
bitmap.bmWidthBytes = ((bitmap.bmWidth * 24 + 31) / 32) * 4;
bitmap.bmPlanes = 1;
bitmap.bmBitsPixel = 24;
bitmap.bmBits = NULL;
const size_t length = bitmap.bmWidthBytes * bitmap.bmHeight;
auto buffer = (HANDLE)GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, length);
RGBTRIPLE *bitmap_bits = (RGBTRIPLE *) GlobalLock((HGLOBAL) buffer);
register RGBTRIPLE *q = bitmap_bits;
for (size_t y = 0; y < image->image()->rows; y++)
{
register auto p = GetVirtualPixels(image->image(), 0, y, image->image()->columns, 1, exception);
if (!p) break;
for (size_t x = 0; x < image->image()->columns; x++)
{
q->rgbtRed = ScaleQuantumToChar(GetPixelRed(image->image(), p));
q->rgbtGreen = ScaleQuantumToChar(GetPixelGreen(image->image(), p));
q->rgbtBlue = ScaleQuantumToChar(GetPixelBlue(image->image(), p));
p += GetPixelChannels(image->image());
q++;
}
}
bitmap.bmBits = bitmap_bits;
HBITMAP hbmp = CreateBitmapIndirect(&bitmap);
But it seems that this code cannot produce valid bitmap. What am I doing wrong?
You are not taking the stride/alignment into account. Each row needs to be DWORD aligned.
Calculating Surface Stride
In an uncompressed bitmap, the stride is the number of bytes needed to go from the start of one row of pixels to the start of the next row. The image format defines a minimum stride for an image. In addition, the graphics hardware might require a larger stride for the surface that contains the image.
For uncompressed RGB formats, the minimum stride is always the image width in bytes, rounded up to the nearest DWORD. You can use the following formula to calculate the stride:
stride = ((((biWidth * biBitCount) + 31) & ~31) >> 3)
You need to fix the way you access the RGBTRIPLEs in the buffer.
Before the "x loop" you should do something like q = (RGBTRIPLE*) (((char*)bitmap_bits) + (y * bitmap.bmWidthBytes));
CreateBitmapIndirect creates a DDB which is perhaps not the best choice, create a DIB instead:
#define CalcStride(w, bpp) ( ((((w) * (bpp)) + 31) & ~31) >> 3 )
static void SetPixel24(UINT w, void*bits, UINT x, UINT y, COLORREF cr)
{
RGBTRIPLE*p = ((RGBTRIPLE*) ( ((char*)bits) + (y * CalcStride(w, 24)) )) + x;
p->rgbtRed = GetRValue(cr);
p->rgbtGreen = GetGValue(cr);
p->rgbtBlue = GetBValue(cr);
}
void Silly24BPPExample()
{
HWND hWnd = CreateWindowEx(WS_EX_APPWINDOW, WC_STATIC, 0, WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_OVERLAPPEDWINDOW|SS_BITMAP|SS_REALSIZECONTROL, 0, 0, 99, 99, 0, 0, 0, 0);
const INT w = 4, h = 4, bpp = 24;
BITMAPINFO bi;
ZeroMemory(&bi, sizeof(bi));
BITMAPINFOHEADER&bih = bi.bmiHeader;
bih.biSize = sizeof(BITMAPINFOHEADER);
bih.biWidth = w, bih.biHeight = -h;
bih.biPlanes = 1, bih.biBitCount = bpp;
bih.biCompression = BI_RGB;
void*bits;
HBITMAP hBmp = CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, &bits, NULL, 0);
for (UINT x = 0; x < w; ++x)
for (UINT y = 0; y < h; ++y)
SetPixel24(w, bits, x, y, RGB(255, 0, 0)); // All red
SetPixel24(w, bits, 0, 0, RGB(0, 0, 255)); // except one blue
SendMessage(hWnd, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM) hBmp);
for (MSG msg; IsWindow(hWnd) && GetMessage(&msg, 0, 0, 0); ) DispatchMessage(&msg);
// DeleteObject(...)
}

C++ convert 32 bit bmp image to 24 bit bmp and 16 bit bmp

Trying to convert 32 bit image B8R8G8A8 to 24bit image R8G8B8 and 16bit R5G5B5.
But result is very strange, maybe I do not understand how to convert image properly. How to do it properly and fix colors?
Input image:
After Convert32to16():
After Convert32to24():
stdafx.h
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#pragma once
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
#include <iostream>
#include <fstream>
#include <windows.h>
// TODO: reference additional headers your program requires here
ImageConverter.cpp
#include "stdafx.h"
using std::cout;
using std::endl;
using std::ofstream;
using std::ifstream;
void Convert32to24(void* B8G8R8A8, BYTE* R8G8B8, int width, int height)
{
long B8G8R8A8Size = (width * height * 4);
long j = 0;
for (long i = 0; i < (B8G8R8A8Size - 3); i = i + 4)
{
BYTE Red = ((PBYTE)B8G8R8A8)[i + 2];
BYTE Green = ((PBYTE)B8G8R8A8)[i + 1];
BYTE Blue = ((PBYTE)B8G8R8A8)[i];
BYTE Alpha = ((PBYTE)B8G8R8A8)[i + 3];
R8G8B8[j] = Red;
R8G8B8[j + 1] = Green;
R8G8B8[j + 2] = Blue;
j = j + 3;
}
}
void Convert32to16(void* B8G8R8A8, BYTE* R5G5B5, int width, int height)
{
long B8G8R8A8Size = (width * height * 4);
long j = 0;
for (long i = 0; i < (B8G8R8A8Size - 3); i = i + 4)
{
BYTE Red = ((PBYTE)B8G8R8A8)[i + 2] >> 3;
BYTE Green = ((PBYTE)B8G8R8A8)[i + 1] >> 3;
BYTE Blue = ((PBYTE)B8G8R8A8)[i] >> 3;
BYTE Alpha = ((PBYTE)B8G8R8A8)[i + 3];
uint16_t RGB565 = ((Red >> 3) << 11) | ((Green >> 2) << 5) | (Blue >> 3);
R5G5B5[j] = RGB565 >> 8;
R5G5B5[j + 1] = RGB565 & 0xFF;
j = j + 2;
}
}
void WriteDataToBmp(const WCHAR *filename, void *imageData, int width, int height, int BitCount, int bytesPerPixel)
{
HANDLE hdl = INVALID_HANDLE_VALUE;
DWORD bytesWritten;
BITMAPFILEHEADER fileHeader;
BITMAPINFOHEADER fileInfo;
fileInfo.biSize = sizeof(BITMAPINFOHEADER);
fileInfo.biBitCount = BitCount;
fileInfo.biCompression = BI_RGB;
fileInfo.biWidth = width;
fileInfo.biHeight = 0 - height;
fileInfo.biPlanes = 1;
fileInfo.biSizeImage = (width * height * bytesPerPixel);
fileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + fileInfo.biSizeImage;
fileHeader.bfType = 'MB';
fileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
hdl = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
if (hdl == INVALID_HANDLE_VALUE)
{
return;
}
WriteFile(hdl, &fileHeader, sizeof(fileHeader), &bytesWritten, NULL);
WriteFile(hdl, &fileInfo, sizeof(fileInfo), &bytesWritten, NULL);
WriteFile(hdl, imageData, fileInfo.biSizeImage, &bytesWritten, NULL);
CloseHandle(hdl);
}
unsigned char* ReadDataFromBmp(char* filename)
{
FILE* f = fopen(filename, "rb");
unsigned char info[54];
fread(info, sizeof(unsigned char), 54, f);
int width = *(int*)&info[18];
int height = *(int*)&info[22];
int size = abs(4 * width * height);
unsigned char* data = new unsigned char[size];
fread(data, sizeof(unsigned char), size, f);
fclose(f);
return data;
}
int main(int args, char** cat) {
int width = 1440;
int height = 900;
int bytesOnPixel;
BYTE *OutputImage24Bit = new BYTE[width * height * 3];
BYTE *OutputImage16Bit = new BYTE[width * height * 2];
unsigned char* inputImage32Bit = ReadDataFromBmp((char*)"E:/TestImage.bmp");
bytesOnPixel = 2;
Convert32to16(inputImage32Bit, OutputImage16Bit, width, height);
WriteDataToBmp(L"E:/TestImage16bit.bmp", OutputImage16Bit, width, height, 8 * bytesOnPixel, bytesOnPixel);
bytesOnPixel = 3;
Convert32to24(inputImage32Bit, OutputImage24Bit, width, height);
WriteDataToBmp(L"E:/TestImage24bit.bmp", OutputImage24Bit, width, height, 8 * bytesOnPixel, bytesOnPixel);
return 1;
}
fileInfo.biCompression = BI_RGB;
16-bit bitmap uses BI_BITFIELDS compression. In addition 16-bit bitmap has to populate the color table to show if it is using 555 format, 565 format, or a different format.
24-bit and 16-bit bitmap need padding. Albeit, that's not an issue if the width in bytes is a multiple of 4. In general you cannot read/write pixel after pixel because the padding can throw everything off. Instead make 2 loops to go through the height and width. Pixel size would also depend on padding.
Note that you can do the same with or GDI+ or WIC. You can change the bitmap to different formats PixelFormat16bppRGB555, PixelFormat16bppRGB565, PixelFormat16bppARGB1555, PixelFormat24bppRGB...
GDI+ example:
int main()
{
Gdiplus::GdiplusStartupInput tmp;
ULONG_PTR token;
Gdiplus::GdiplusStartup(&token, &tmp, NULL);
auto *source = Gdiplus::Bitmap::FromFile(L"test.bmp");
auto *destination = source->Clone(0, 0, source->GetWidth(), source->GetHeight(),
PixelFormat16bppRGB565);
CLSID clsid_bmp;
CLSIDFromString(L"{557cf400-1a04-11d3-9a73-0000f81ef32e}", &clsid_bmp);
destination->Save(L"copy.bmp", &clsid_bmp);
delete destination;
delete source;
Gdiplus::GdiplusShutdown(token);
return 0;
}
Home made version: (using std::vector for memory, instead of new/delete)
void Convert32to24(const wchar_t* file, std::vector<BYTE> &src, int width, int height)
{
int width_in_bytes_32 = width * 4;
int width_in_bytes_24 = ((width * 24 + 31) / 32) * 4;
DWORD size = width_in_bytes_24 * height;
std::vector<BYTE> dst(size);
for(int h = 0; h < height; h++)
for(int w = 0; w < width; w++)
{
int i = h * width_in_bytes_32 + w * 4;
int j = h * width_in_bytes_24 + w * 3;
dst[j + 0] = src[i + 0];
dst[j + 1] = src[i + 1];
dst[j + 2] = src[i + 2];
}
BITMAPFILEHEADER bf = { 'MB', 54 + size, 0, 0, 54 };
BITMAPINFOHEADER bi = { sizeof(bi), width, height, 1, 24, BI_RGB };
std::ofstream fout(file, std::ios::binary);
fout.write((char*)&bf, sizeof(bf));
fout.write((char*)&bi, sizeof(bi));
fout.write((char*)&dst[0], size);
}
void Convert32to16(const wchar_t* file, std::vector<BYTE> &src, int width, int height)
{
int width_in_bytes_32 = width * 4;
int width_in_bytes_16 = ((width * 16 + 31) / 32) * 4;
DWORD size = width_in_bytes_16 * height;
std::vector<BYTE> dst(size);
for(int h = 0; h < height; h++)
for(int w = 0; w < width; w++)
{
int i = h * width_in_bytes_32 + w * 4;
int j = h * width_in_bytes_16 + w * 2;
//555 format, each color is from 0 to 32, instead of 0 to 256
uint16_t blu = (uint16_t)(src[i + 0] * 31.f / 255.f);
uint16_t grn = (uint16_t)(src[i + 1] * 31.f / 255.f);
uint16_t red = (uint16_t)(src[i + 2] * 31.f / 255.f);
uint16_t sum = (red) | (grn << 5) | (blu << 10);
memcpy(&dst[j], &sum, 2);
}
BITMAPFILEHEADER bf = { 'MB', 54 + size, 0, 0, 54 };
BITMAPINFOHEADER bi = { sizeof(bi), width, height, 1, 16, BI_BITFIELDS };
std::ofstream fout(file, std::ios::binary);
fout.write((char*)&bf, sizeof(bf));
fout.write((char*)&bi, sizeof(bi));
//555 format
COLORREF color[]{
0b0000000000011111,//31
0b0000001111100000,//31 << 5
0b0111110000000000 //31 << 10
};
fout.write((char*)&color, sizeof(color));
fout.write((char*)&dst[0], size);
}
int main()
{
const wchar_t* file_32 = L"E:\\TestImage.bmp";
const wchar_t* file_16 = L"E:\\OutputImage16Bit.bmp";
const wchar_t* file_24 = L"E:\\OutputImage24Bit.bmp";
BITMAPFILEHEADER bh;
BITMAPINFOHEADER bi;
std::ifstream fin(file_32, std::ios::binary);
if(!fin)
return 0;
fin.read((char*)&bh, sizeof(bh));
fin.read((char*)&bi, sizeof(bi));
if(bi.biBitCount != 32)
return 0;
std::vector<BYTE> source(bh.bfSize);
fin.read((char*)&source[0], bh.bfSize);
Convert32to16(file_16, source, bi.biWidth, bi.biHeight);
Convert32to24(file_24, source, bi.biWidth, bi.biHeight);
return 0;
}

Rescaling image in J2ME

I'm resizing a bird image using the following code:
private Image resizeImage(Image src) {
int srcWidth = src.getWidth();
int srcHeight = src.getHeight();
int screenWidth=getWidth()/3;
int screenHeight=getHeight()/3;
Image tmp = Image.createImage(screenWidth, srcHeight);
Graphics g = tmp.getGraphics();
int ratio = (srcWidth << 16) / screenWidth;
int pos = ratio/2;
//Horizontal Resize
for (int x = 0; x < screenWidth; x++) {
g.setClip(x, 0, 1, srcHeight);
g.drawImage(src, x - (pos >> 16), 0, Graphics.LEFT | Graphics.TOP);
pos += ratio;
}
Image resizedImage = Image.createImage(screenWidth, screenHeight);
g = resizedImage.getGraphics();
ratio = (srcHeight << 16) / screenHeight;
pos = ratio/2;
//Vertical resize
for (int y = 0; y < screenHeight; y++) {
g.setClip(0, y, screenWidth, 1);
g.drawImage(tmp, 0, y - (pos >> 16), Graphics.LEFT | Graphics.TOP);
pos += ratio;
}
return resizedImage;
}
The image is resized but it has white background along with it as shown. How to get only resized image with transparent background..?
Here is an Image scaling function I've been using. Includes transparency. Found here: http://willperone.net/Code/codescaling.php
public Image scale(Image original, int newWidth, int newHeight) {
int[] rawInput = new int[original.getHeight() * original.getWidth()];
original.getRGB(rawInput, 0, original.getWidth(), 0, 0, original.getWidth(), original.getHeight());
int[] rawOutput = new int[newWidth * newHeight];
// YD compensates for the x loop by subtracting the width back out
int YD = (original.getHeight() / newHeight) * original.getWidth() - original.getWidth();
int YR = original.getHeight() % newHeight;
int XD = original.getWidth() / newWidth;
int XR = original.getWidth() % newWidth;
int outOffset = 0;
int inOffset = 0;
for (int y = newHeight, YE = 0; y > 0; y--) {
for (int x = newWidth, XE = 0; x > 0; x--) {
rawOutput[outOffset++] = rawInput[inOffset];
inOffset += XD;
XE += XR;
if (XE >= newWidth) {
XE -= newWidth;
inOffset++;
}
}
inOffset += YD;
YE += YR;
if (YE >= newHeight) {
YE -= newHeight;
inOffset += original.getWidth();
}
}
rawInput = null;
return Image.createRGBImage(rawOutput, newWidth, newHeight, true);
}

Resources