문제

PNG에서로드 한 두 개의 완충학이 있습니다. 첫 번째에는 이미지가 포함되어 있고 두 번째는 이미지의 알파 마스크입니다.

알파 마스크를 적용하여 두 가지에서 결합 된 이미지를 만들고 싶습니다. 내 Google-Fu가 실패합니다.

이미지를로드/저장하는 방법을 알고 있습니다. 오른쪽 알파 채널을 사용하여 두 개의 버퍼링이지에서 하나의 완충 지미로 이동하는 비트가 필요합니다.

도움이 되었습니까?

해결책

RGB 데이터를 한 번에 둘 이상의 픽셀로 가져와 솔루션을 개선 할 수 있습니다 ( http://java.sun.com/javase/6/docs/api/java/awt/image/bufferedimage.html), 내부 루프의 모든 반복에 세 가지 색상 객체를 생성하지 않습니다.

final int width = image.getWidth();
int[] imgData = new int[width];
int[] maskData = new int[width];

for (int y = 0; y < image.getHeight(); y++) {
    // fetch a line of data from each image
    image.getRGB(0, y, width, 1, imgData, 0, 1);
    mask.getRGB(0, y, width, 1, maskData, 0, 1);
    // apply the mask
    for (int x = 0; x < width; x++) {
        int color = imgData[x] & 0x00FFFFFF; // mask away any alpha present
        int maskColor = (maskData[x] & 0x00FF0000) << 8; // shift red into alpha bits
        color |= maskColor;
        imgData[x] = color;
    }
    // replace the data
    image.setRGB(0, y, width, 1, imgData, 0, 1);
}

다른 팁

나는이 대답에 너무 늦었지만 어쨌든 누군가에게 사용될 것입니다. 이것은 Michael Myers의 방법의 더 간단하고 효율적인 버전입니다.

public void applyGrayscaleMaskToAlpha(BufferedImage image, BufferedImage mask)
{
    int width = image.getWidth();
    int height = image.getHeight();

    int[] imagePixels = image.getRGB(0, 0, width, height, null, 0, width);
    int[] maskPixels = mask.getRGB(0, 0, width, height, null, 0, width);

    for (int i = 0; i < imagePixels.length; i++)
    {
        int color = imagePixels[i] & 0x00ffffff; // Mask preexisting alpha
        int alpha = maskPixels[i] << 24; // Shift blue to alpha
        imagePixels[i] = color | alpha;
    }

    image.setRGB(0, 0, width, height, imagePixels, 0, width);
}

모든 픽셀을 처음에는 배열로 읽으므로 하나의 루프 만 필요합니다. 또한 먼저 빨간 바이트를 마스킹 한 다음 이동하는 대신 파란색 바이트를 알파 (마스크 컬러)로 직접 이동시킵니다.

다른 방법과 마찬가지로 두 이미지 모두 동일한 크기가 있다고 가정합니다.

나는 최근 에이 것들로 조금 연주했고, 다른 것 위에 이미지를 표시하고 이미지를 회색으로 희미하게 만들었습니다.
또한 투명성이있는 마스크로 이미지를 마스킹합니다 (이 메시지의 이전 버전!).

나는 작은 테스트 프로그램을 가져 와서 원하는 결과를 얻기 위해 약간 조정했습니다.

관련 비트는 다음과 같습니다.

TestMask() throws IOException
{
    m_images = new BufferedImage[3];
    m_images[0] = ImageIO.read(new File("E:/Documents/images/map.png"));
    m_images[1] = ImageIO.read(new File("E:/Documents/images/mapMask3.png"));
    Image transpImg = TransformGrayToTransparency(m_images[1]);
    m_images[2] = ApplyTransparency(m_images[0], transpImg);
}

private Image TransformGrayToTransparency(BufferedImage image)
{
    ImageFilter filter = new RGBImageFilter()
    {
        public final int filterRGB(int x, int y, int rgb)
        {
            return (rgb << 8) & 0xFF000000;
        }
    };

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

private BufferedImage ApplyTransparency(BufferedImage image, Image mask)
{
    BufferedImage dest = new BufferedImage(
            image.getWidth(), image.getHeight(),
            BufferedImage.TYPE_INT_ARGB);
    Graphics2D g2 = dest.createGraphics();
    g2.drawImage(image, 0, 0, null);
    AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.DST_IN, 1.0F);
    g2.setComposite(ac);
    g2.drawImage(mask, 0, 0, null);
    g2.dispose();
    return dest;
}

나머지는 작은 스윙 패널에 이미지를 표시합니다.
마스크 이미지는 회색 레벨, 검은 색은 완전 투명성이되고 흰색은 불투명 해집니다.

당신은 당신의 문제를 해결했지만, 나는 그것을 공유 할 수 있지만 나는 그것을 공유 할 수 있습니다. 표준 클래스를 사용하여 이미지를 처리/필터링하는 약간 더 많은 Java-ish 방법을 사용합니다.
실제로, 내 방법은 조금 더 메모리를 사용하고 (추가 이미지를 만드는) 더 빠른지 확실하지 않지만 (각각의 성능을 측정하는 것은 흥미로울 수 있음) 약간 더 추상적입니다.
적어도, 당신은 선택이 있습니다! :-)

원본 이미지에서 알파를 사용하는 사람들을 위해.

이 코드를 Koltin에 썼습니다. 여기서 핵심 요점은 원래 이미지에 알파가 있으면이 채널을 곱해야한다는 것입니다.

콜틴 버전 :

    val width = this.width
    val imgData = IntArray(width)
    val maskData = IntArray(width)

    for(y in 0..(this.height - 1)) {

      this.getRGB(0, y, width, 1, imgData, 0, 1)
      mask.getRGB(0, y, width, 1, maskData, 0, 1)

      for (x in 0..(this.width - 1)) {

        val maskAlpha = (maskData[x] and 0x000000FF)/ 255f
        val imageAlpha = ((imgData[x] shr 24) and 0x000000FF) / 255f
        val rgb = imgData[x] and 0x00FFFFFF
        val alpha = ((maskAlpha * imageAlpha) * 255).toInt() shl 24
        imgData[x] = rgb or alpha
      }
      this.setRGB(0, y, width, 1, imgData, 0, 1)
    }

Java 버전 (Kotlin에서 방금 번역)

    int width = image.getWidth();
    int[] imgData = new int[width];
    int[] maskData = new int[width];

    for (int y = 0; y < image.getHeight(); y ++) {

        image.getRGB(0, y, width, 1, imgData, 0, 1);
        mask.getRGB(0, y, width, 1, maskData, 0, 1);

        for (int x = 0; x < image.getWidth(); x ++) {

            //Normalize (0 - 1)
            float maskAlpha = (maskData[x] & 0x000000FF)/ 255f;
            float imageAlpha = ((imgData[x] >> 24) & 0x000000FF) / 255f;

            //Image without alpha channel
            int rgb = imgData[x] & 0x00FFFFFF;

            //Multiplied alpha
            int alpha = ((int) ((maskAlpha * imageAlpha) * 255)) << 24;

            //Add alpha to image
            imgData[x] = rgb | alpha;
        }
        image.setRGB(0, y, width, 1, imgData, 0, 1);
    }

사실, 나는 그것을 알아 냈습니다. 이것은 아마도 아닐 것입니다 빠른 그렇게하는 방법이지만 작동합니다.

for (int y = 0; y < image.getHeight(); y++) {
    for (int x = 0; x < image.getWidth(); x++) {
        Color c = new Color(image.getRGB(x, y));
        Color maskC = new Color(mask.getRGB(x, y));
        Color maskedColor = new Color(c.getRed(), c.getGreen(), c.getBlue(),
            maskC.getRed());
        resultImg.setRGB(x, y, maskedColor.getRGB());
    }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top