2010-07-08 20 views
5

Hola amigos, estoy trabajando en un juego j2ME para teléfonos celulares habilitados para Java. Estoy tratando de escalar un PNG transparente con el siguiente método:El método personalizado para cambiar la escala de un archivo PNG pierde transparencia

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

Escala la imagen correctamente, por desgracia, me parece estar perdiendo la transparencia con la imagen que devuelve el método. Soy bastante nuevo en estos conceptos, ¡y cualquier ayuda sería muy apreciada! Tenga en cuenta que para mostrarse correctamente en cualquier dispositivo móvil compatible con Java, el cambio de escala debe hacerse en código, no en ningún tipo de editor de imágenes.

¡Gracias de antemano!

Respuesta

4

Gracias a todos los que han estado buscando soluciones a este problema aparentemente muy extendido y sin resolver. Logré encontrar una gran solución en http://willperone.net/Code/codescaling.php

Usted acaba de cambiar el "falso" en el parámetro createRGBImage a un verdadero. Esto indica el método para procesar los bits de orden superior de cada píxel como valores alfa. Aquí está mi implementación, no hay muchos cambios desde el enlace original anterior.

XRatio y YRatio se declaran como constantes cuando se inicializa el lienzo, donde XRatio = this.getWidth() (el ancho de la pantalla del teléfono actual) dividido por el ancho original de su imagen de fondo, y YRatio con getHeight()/original background image altura.

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

Es posiblemente porque no distinguen alfa en los valores de los píxeles. Lo que puede hacer es agregar una rutina extra para manejar las que tienen alfa, de modo que conserven sus posibles valores alfa.

Básicamente está comprobando cada píxel, mira si tiene alfa, si tiene, comprueba si estará en la imagen redimensionada, si es así, aplícala allí con su alfa, si no, descártala.

+0

Gracias Yonathan. Estoy intentando usar Image.GetRGB() e Image.createRGBImage() junto con un algoritmo de escala para manipular la matriz ARGB en el medio. Desearme suerte :) – jbabey

+0

Actualización sobre el enfoque ARGB: Funciona bastante bien, excepto por el hecho de que las proporciones de escalado generalmente no son números enteros, lo que hace que la manipulación pura de arreglos de píxeles sea un poco más difícil. – jbabey

Cuestiones relacionadas