سؤال

ولقد اثنين من BufferedImages حملت في من ملفات PNG. أول يحتوي على صورة، والثاني قناع ألفا للصورة.

وأريد لخلق صورة جنبا إلى جنب من اثنين، من خلال تطبيق قناع ألفا. بلدي جوجل فو فشل لي.

وأنا أعرف كيفية تحميل / حفظ الصور، أنا فقط بحاجة بت أين أذهب من اثنين BufferedImages إلى BufferedImage واحد مع قناة ألفا الصحيحة.

هل كانت مفيدة؟

المحلول

ويمكن تحسين الحل الخاص بك عن طريق جلب بيانات RGB بكسل أكثر من واحد في وقت واحد (انظر <لأ href = "http://java.sun.com/javase/6/docs/api/java/awt/image /BufferedImage.html "يختلط =" noreferrer "> 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);
}

نصائح أخرى

وأنا في وقت متأخر جدا مع هذا الجواب، ولكن ربما هو استخدام لشخص ما على أي حال. هذا هو نسخة أكثر بساطة وأكثر كفاءة من طريقة مايكل مايرز:

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

والباقي مجرد عرض الصور في لوحة سوينغ قليلا.
لاحظ أن صورة القناع مستويات الرمادي والأسود يصبح الشفافية الكاملة، أبيض تصبح مبهمة كامل.

وعلى الرغم من أنك قد حل مشكلتك، على الرغم من أنني يمكن أن تشارك احملوا على ذلك. ويستخدم أكثر قليلا طريقة جافا العش، باستخدام الفئات القياسية لمعالجة الصور / فلتر.
في الواقع، يستخدم أسلوب بلدي أكثر قليلا الذاكرة (صنع صورة إضافية) وأنا لست متأكدا من أنه هو أسرع (قياس أداء كل منها يمكن أن تكون مثيرة للاهتمام)، لكنه أكثر قليلا مجردة.
على الأقل، لديك خيار! : -)

وبالنسبة لأولئك الذين يستخدمون ألفا في الصورة الأصلية.

ولقد كتبت هذا الرمز في Koltin، والنقطة الأساسية هنا هي أنه إذا كان لديك ألفا على الصورة الأصلية تحتاج إلى مضاعفة هذه القنوات.

و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)
    }

وجافا إصدار (ترجمة فقط من 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