2013-02-25 2 views
3

Я пытаюсь написать небольшой метод, который принимает изображение BufferedImage и новую ширину и высоту и масштабирует изображение, сохраняя соотношение сторон, добавляя прозрачную границу влево/вправо или сверху/снизу в зависимости от изображения. Масштабирование работает отлично, но для жизни меня я не могу получить границу прозрачной.Как масштабировать изображение Graphics2D с прозрачным дополнением

До сих пор у меня есть following code posted on pastebin.com, который хорошо масштабирует.

Я прочитал много руководств и других вопросов, безрезультатно. Я пробовал множество перестановок заливок, составных типов, типов изображений и т. Д. Иногда я получаю синий фон, иногда белый, но он никогда не кажется прозрачным.

BufferedImage newImg = new BufferedImage(newWidth, newHeight, img.getType()); 
Graphics2D g = newImg.createGraphics(); 
g.setColor(Color.WHITE); 
g.fillRect(0, 0, newWidth, newHeight); 
g.drawImage(img, x, y, x + scaledWidth, y + scaledHeight, 0, 0, 
    currentWidth, currentHeight, Color.WHITE, null); 
g.dispose(); 
return newImg; 

Любая идея, что Graphics2D позвонить мне нужно сделать, чтобы иметь Color.WHITE фон прозрачным и рисовать старое изображение над новым? Спасибо за любую помощь.

Edit:

Оказалось, что проблема у меня была в том, что я пытаюсь создать прозрачный цвет с изображением JPEG. JPEG не поддерживают прозрачность. Duh.

+0

Вы пытались установить альфа-компонент с помощью ['new Color (int r, int g, int b, int a)'] (http://docs.oracle.com/ JavaSE/7/документы/API/Java/AWT/Color.html # Цвет (интермедиат,% 20int,% 20int,% 20int))? –

+0

Я уверен, что это одна из вещей, которые я пробовал @ Eng.Fouad.Если вы можете быть более конкретным, я попробую. – Gray

+0

Что-то вроде 'new Color (0, 0, 0, 0)'. –

ответ

3

Я только что попробовал, и он работает.

Просто замените Color.WHITE на new Color(0, 0, 0, 0) и img.getType() с BufferedImage.TYPE_INT_ARGB.


BufferedImage img = ImageIO.read(new File("image.png")); 
BufferedImage outImage = scaleWithPadding(img, 300, 100); 
ImageIO.write(outImage, "png", new File("newImage.png")); 

image.png: (204x53)

enter image description here

newImage.png: (300x100)

enter image description here

+0

Спасибо за это. Какой тип изображения вы пробовали? Является ли моя проблема, что я пытаюсь преобразовать JPEG? – Gray

+1

@Gray 'PNG' изображение. 'JPEG' не может иметь прозрачности внутри него. –

+1

Это была моя проблема. Большое спасибо за помощь! – Gray

3

У меня было такое же требование, как и вы и ваш пост, и эта страница на how to make a color transparent мне очень помогла.

Вот мой окончательный код:

public BufferedImage getTransparentScaledImage(BufferedImage originalImage, int finalWidth, int finalHeight) { 
    int originalWidth = originalImage.getWidth(); 
    int originalHeight = originalImage.getHeight(); 

    int newWidth; 
    int newHeight; 
    if (originalWidth == 0 || originalHeight == 0 
      || (originalWidth == finalWidth && originalHeight == finalHeight)) { 
     return originalImage; 
    } 

    double aspectRatio = (double) originalWidth/(double) originalHeight; 
    double boundaryAspect = (double) finalWidth/(double) finalHeight; 

    if (aspectRatio > boundaryAspect) { 
     newWidth = finalWidth; 
     newHeight = (int) Math.round(newWidth/aspectRatio); 
    } else { 
     newHeight = finalHeight; 
     newWidth = (int) Math.round(aspectRatio * newHeight); 
    } 

    int xOffset = (finalWidth - newWidth)/2; 
    int yOffset = (finalHeight - newHeight)/2; 

    LoggerManager.getInstance().debug("frontoffice", 
      "Image Servlet: [" + xOffset + "] [" + yOffset + "] [" + newWidth + "] [" + newHeight + "] [" + originalWidth + "] [" + originalHeight + "] [" + finalWidth + "] [" + finalHeight + "]"); 

    BufferedImage intermediateImage = new BufferedImage(finalWidth, finalHeight, BufferedImage.TYPE_INT_RGB); 
    Graphics2D gi = intermediateImage.createGraphics(); 
    gi.setComposite(AlphaComposite.SrcOver); 
    gi.setColor(Color.WHITE); 
    gi.fillRect(0, 0, finalWidth, finalHeight); 
    gi.drawImage(originalImage, xOffset, yOffset, xOffset + newWidth, yOffset + newHeight, 0, 0, originalWidth, originalHeight, Color.WHITE, null); 
    gi.dispose(); 

    //if image from db already had a transparent background, it becomes black when drawing it onto another 
    //even if we draw it onto a transparent image 
    //so we set it to a specific color, in this case white 
    //now we have to set that white background transparent 
    Image intermediateWithTransparentPixels = makeColorTransparent(intermediateImage, Color.WHITE); 

    //finalize the transparent image 
    BufferedImage finalImage = new BufferedImage(finalWidth, finalHeight, BufferedImage.TYPE_INT_ARGB); 
    Graphics2D gf = finalImage.createGraphics(); 
    gf.setComposite(AlphaComposite.SrcOver); 
    gf.setColor(new Color(0, 0, 0, 0)); 
    gf.fillRect(0, 0, finalWidth, finalHeight); 
    gf.drawImage(intermediateWithTransparentPixels, 0, 0, finalWidth, finalHeight, new Color(0, 0, 0, 0), null); 
    gf.dispose(); 

    return finalImage; 
} 

public static Image makeColorTransparent(Image im, final Color color) { 
    ImageFilter filter = new RGBImageFilter() { 
     // the color we are looking for... Alpha bits are set to opaque 
     public int markerRGB = color.getRGB() | 0xFF000000; 

     public final int filterRGB(int x, int y, int rgb) { 
      if ((rgb | 0xFF000000) == markerRGB) { 
       // Mark the alpha bits as zero - transparent 
       return 0x00FFFFFF & rgb; 
      } else { 
       // nothing to do 
       return rgb; 
      } 
     } 
    }; 

    ImageProducer ip = new FilteredImageSource(im.getSource(), filter); 
    return Toolkit.getDefaultToolkit().createImage(ip); 
} 
+0

Спасибо, много, вы действительно решили мою проблему, которая заблокировала меня в течение длительного времени ~ –

0

Я реализовал указанные решения (или очень похоже) просто обратить внимание, если вы не используете

graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR); 
graphics2D.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY); 
graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON; 

ваши изображения будут генерироваться с очень низкое качество (из-за масштабирования)

0

У вашего оригинального метода drawImage() не было прозрачного фона, потому что использовался цвет фона. Замените следующим образом:

g.drawImage(img, x, y, x + scaledWidth, y + scaledHeight, 0, 0, currentWidth, currentHeight, null);