2010-07-08 2 views
5

Привет, ребята, я работаю над игрой j2ME для мобильных телефонов, поддерживающих Java. Я пытаюсь масштабировать прозрачный PNG с помощью следующего метода:Пользовательский метод масштабирования 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,, перемасштабирование должно выполняться в коде, а не в каком-либо редакторе изображений.

Заранее благодарен!

ответ

4

Спасибо всем, кто искал решения этой, казалось бы, широко распространенной и нерешенной проблемы. Мне удалось найти отличное решение на http://willperone.net/Code/codescaling.php

Вы просто изменяете «false» в параметре createRGBImage на true. Это означает, что метод обрабатывает старшие биты каждого пикселя как альфа-значения. Вот моя реализация, немного изменившаяся от исходной ссылки выше.

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

Может быть, класс 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

+0

Я не думаю, что этот метод поддерживается в J2ME, спасибо за ответ, хотя! – jbabey

+0

Моя ошибка, опубликует другой ответ. –

1

Это возможно потому, что вы не различают альфа в пиксельных значений. Что вы можете сделать, так это добавить дополнительную рутину для обработки альфа, чтобы они сохраняли свои альфа-значения.

В основном это проверка каждого пикселя, если у него есть альфа, если он есть, проверьте, будет ли оно на изображении с измененным размером, если это так, примените его там, где есть альфа, если нет, отбросьте его.

+0

Спасибо Yonathan. Я пытаюсь использовать Image.GetRGB() и Image.createRGBImage() вместе с алгоритмом масштабирования для управления массивом ARGB между ними. Желаем мне удачи :) – jbabey

+0

Обновление по ARGB-подходу: он работает достаточно хорошо, за исключением того факта, что коэффициенты масштабирования обычно не являются целыми числами, что делает манипуляции с массивами с использованием пиксельных элементов немного сложнее. – jbabey

Смежные вопросы