【问题标题】:Custom method to rescale a PNG loses transparency调整PNG大小的自定义方法失去透明度
【发布时间】:2011-03-13 02:55:43
【问题描述】:

大家好,我正在为支持 java 的手机开发一款 j2ME 游戏。我正在尝试使用以下方法缩放透明 PNG:

// 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);
}

它正确缩放图像,不幸的是我似乎失去了该方法返回的图像的透明度。我对这些概念相当陌生,任何帮助将不胜感激!请注意,为了在任何支持 java 的移动设备上正确显示,重新缩放需要在代码中完成,而不是在任何类型的图像编辑器中。

提前致谢!

【问题讨论】:

    标签: java png transparency java-me image-scaling


    【解决方案1】:

    感谢所有一直在寻找解决这个看似广泛且未解决的问题的方法的人。我设法在http://willperone.net/Code/codescaling.php找到了一个很好的解决方案

    您只需将 createRGBImage 参数中的“false”更改为 true。这将方法标记为将每个像素的高位处理为 alpha 值。这是我的实现,与上面的原始链接没有太大变化。

    XRatio 和 YRatio 在画布初始化时被声明为常量,其中 XRatio = this.getWidth()(当前手机的屏幕宽度)除以您的原始背景图像宽度,YRatio 与 getHeight() / 原始背景图像高度.

    // 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);
    }
    

    【讨论】:

      【解决方案2】:

      这可能是因为您没有区分像素值中的 alpha。您可以做的是添加一个额外的例程来处理带有 alpha 的那些,以便它们保持可能的 alpha 值。

      基本上它会检查每个像素,看看它是否有 alpha,如果有,检查它是否会在调整大小的图像上,如果是,则使用它的 alpha 应用它,如果没有,则丢弃它。

      【讨论】:

      • 谢谢 Yonathan。我正在尝试使用 Image.GetRGB() 和 Image.createRGBImage() 以及缩放算法来操纵两者之间的 ARGB 数组。祝我好运:)
      • ARGB 方法的更新:它工作得很好,除了缩放比例通常不是整数,这使得纯像素数组操作更加困难。
      【解决方案3】:

      也许是 Image 类的方法:

      Image   getScaledInstance(int width, int height, int hints) 
      

      非常适合您的需要..?

      发件人:http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/api/java/awt/Image.html

      【讨论】:

      • 我认为J2ME不支持这种方法,不过还是谢谢你的回复!
      • 我的错误,将发布另一个答案。
      猜你喜欢
      • 2010-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-15
      • 2013-01-02
      • 2010-09-21
      • 1970-01-01
      相关资源
      最近更新 更多