Hey folks, I am working on a j2ME game for java-capable cell phones. I am attempting to scale a transparent PNG with the following method:
// method derived from a Snippet from http://snippets.dzone.com/posts/show/3257
// scales an image according to the ratios given as parameters
private Image rescaleImage(Image image, double XRatio, double YRatio)
{
// the old height and width
int sourceWidth = image.getWidth();
int sourceHeight = image.getHeight();
// what the new height and width should be
int newWidth = (int)(XRatio * sourceWidth);
int newHeight = (int)(YRatio * sourceHeight);
Image newImage = Image.createImage(newWidth, newHeight);
Graphics g = newImage.getGraphics();
for (int y = 0; y < newHeight; y++)
{
for (int x = 0; x < newWidth; x++)
{
g.setClip(x, y, 1, 1);
int dx = (x * sourceWidth) / newWidth;
int dy = (y * sourceHeight) / newHeight;
g.drawImage(image, (x - dx), (y - dy), Graphics.LEFT | Graphics.TOP);
}
}
return Image.createImage(newImage);
}
It scales the image correctly, unfortunately I seem to be losing the transparency with the image returned by the method. I am fairly new to these concepts, and any help would be greatly appreciated! Please note that in order to be properly displayed on any java-capable mobile device, the rescaling needs to be done in code, not in any sort of image editor.
Thanks in advance!
Remember that GIF and JPEG codecs are “lossy,” meaning some resolution will be lost when scaling images. PNG files, on the other hand, will not degrade in quality. Note that the quality can be lost when resizing or re-formatting bitmap files such as GIF, JPEG, and even some PNGs.
Another way to resize an image without losing quality is to use a program like Microsoft Paint. With Paint, you can resize an image without losing quality by using the "Resize and Skew" dialog box. In the "Resize and Skew" dialog box, you can change the width and height of the image.
You may be used to saving image files for web use as JPEGs, but JPEGs don't support transparent backgrounds. So, instead, you'll need to use a format such as GIF, TIF or, ideally, PNG. The PNG file is small enough for use online but still delivers high quality with transparency as well.
Thanks to everyone who has been looking for solutions to this seemingly wide-spread and unsolved problem. I managed to find a great solution at http://willperone.net/Code/codescaling.php
You just change the "false" in the createRGBImage parameter to a true. This flags the method to process the high-order bits of each pixel as alpha values. Here is my implementation, not much change from the original link above.
XRatio and YRatio are declared as constants when the canvas is initialized, where XRatio = this.getWidth() (the current phone's screen width) divided by your original background image width, and YRatio with getHeight() / original background image height.
// RESCALEIMAGE
// scales an image according to the ratios given as parameters
// derived from http://willperone.net/Code/codescaling.php
public static Image rescaleImage(Image original, double XRatio, double YRatio)
{
// the original width and height
int originalWidth = original.getWidth();
int originalHeight = original.getHeight();
// the target width and height
int newWidth = (int)(XRatio * originalWidth);
int newHeight = (int)(YRatio * originalHeight);
// create and fill the pixel array from the original image
int[] rawInput = new int[originalHeight * originalWidth];
original.getRGB(rawInput, 0, originalWidth, 0, 0, originalWidth, originalHeight);
// pixel array for the target image
int[] rawOutput = new int[newWidth*newHeight];
// YD compensates for the x loop by subtracting the width back out
int YD = (originalHeight / newHeight) * originalWidth - originalWidth;
int YR = originalHeight % newHeight;
int XD = originalWidth / newWidth;
int XR = originalWidth % 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 += originalWidth;
}
}
return Image.createRGBImage(rawOutput, newWidth, newHeight, true);
}
It is possibly because you don't distinguish alpha in the pixel values. What you can do is add an extra routine to handle the ones with alpha so they keep their possible alpha values.
Basically it's checking every pixel, see if it has alpha, if it has, check if it will be on the resized image, if so, apply it there with it's alpha, if not, discard it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With