Изменить альфа-значение BufferedImage? - PullRequest
7 голосов
/ 19 марта 2009

Как изменить глобальное альфа-значение BufferedImage в Java? (Т.е. сделать так, чтобы каждый пиксель в изображении, имеющий альфа-значение 100, имел альфа-значение 80)

Ответы [ 6 ]

9 голосов
/ 18 апреля 2009

@ Нил Коффи: Спасибо, я тоже искал это; однако, Ваш код работал не очень хорошо для меня (белый фон стал черным).

Я кодировал что-то вроде этого, и оно отлично работает:

public void setAlpha(byte alpha) {       
    alpha %= 0xff; 
    for (int cx=0;cx<obj_img.getWidth();cx++) {          
        for (int cy=0;cy<obj_img.getHeight();cy++) {
            int color = obj_img.getRGB(cx, cy);

            int mc = (alpha << 24) | 0x00ffffff;
            int newcolor = color & mc;
            obj_img.setRGB(cx, cy, newcolor);            

        }

    }
}

Где obj_img - BufferedImage.TYPE_INT_ARGB.

Я меняю альфу с помощью setAlpha ((byte) 125); альфа-диапазон теперь 0-255.

Надеюсь, кто-нибудь найдет это полезным.

4 голосов
/ 11 апреля 2012

Это старый вопрос, поэтому я отвечаю не ради ОП, а для таких, как я, которые найдут этот вопрос позже.

AlphaComposite

Как уже упоминалось в превосходном наброске @ Michael, операция AlphaComposite может изменить альфа-канал. Но только определенными способами, которые мне несколько сложны для понимания:

enter image description here

- это формула для того, как операция «over» влияет на альфа-канал. Более того, это также влияет на каналы RGB, поэтому, если у вас есть данные о цвете, которые необходимо изменить, AlphaComposite не является ответом.

BufferedImageOps

LookupOp

Существует несколько разновидностей BufferedImageOp (см. 4.10.6 здесь ). В более общем случае задача OP может быть выполнена с помощью LookupOp , который требует построения массивов поиска. Чтобы изменить только альфа-канал, укажите массив идентификаторов (массив где table [i] = i) для каналов RGB и отдельный массив для альфа-канала. Заполните последний массив table[i] = f(i), где f() - это функция, с помощью которой вы хотите отобразить старое альфа-значение на новое. Например. если вы хотите, чтобы «каждый пиксель в изображении, имеющий альфа-значение 100, имело альфа-значение 80», установите table[100] = 80. (Полный диапазон от 0 до 255.) См. , как увеличить непрозрачность при размытии по Гауссу для примера кода.

RescaleOp

Но для подмножества этих случаев есть более простой способ сделать это, не требующий настройки таблицы поиска. Если f() - простая линейная функция, используйте RescaleOp . Например, если вы хотите установить newAlpha = oldAlpha - 20, используйте RescaleOp с scaleFactor, равным 1, и смещением -20. Если вы хотите установить newAlpha = oldAlpha * 0.8, используйте scaleFactor, равный 0,8, и смещение, равное 0. В любом случае вам снова нужно предоставить фиктивные scaleFactor и смещения для каналов RGB:

new RescaleOp({1.0f, 1.0f, 1.0f, /* alpha scaleFactor */ 0.8f},
              {0f, 0f, 0f, /* alpha offset */ -20f}, null)

Снова см. 4.10.6 здесь для некоторых примеров, которые хорошо иллюстрируют принципы, но не относятся к альфа-каналу.

Обе RescaleOp и LookupOp позволяют изменять BufferedImage на месте.

4 голосов
/ 19 марта 2009

Я не верю, что есть одна простая команда, чтобы сделать это. Несколько вариантов:

Первый - самый простой для реализации, ИМО.

3 голосов
/ 07 мая 2014

для более привлекательного эффекта альфа-изменения вы можете использовать относительное альфа-изменение на пиксель (вместо статического набора или линейного отсечения)

public static void modAlpha(BufferedImage modMe, double modAmount) {
        //
    for (int x = 0; x < modMe.getWidth(); x++) {          
        for (int y = 0; y < modMe.getHeight(); y++) {
                //
            int argb = modMe.getRGB(x, y); //always returns TYPE_INT_ARGB
            int alpha = (argb >> 24) & 0xff;  //isolate alpha

            alpha *= modAmount; //similar distortion to tape saturation (has scrunching effect, eliminates clipping)
            alpha &= 0xff;      //keeps alpha in 0-255 range

            argb &= 0x00ffffff; //remove old alpha info
            argb |= (alpha << 24);  //add new alpha info
            modMe.setRGB(x, y, argb);            
        }
    }
}
1 голос
/ 19 марта 2009

Я на 99% уверен, что методы, которые утверждают, что имеют дело со значением "RGB", упакованным в int, действительно имеют дело с ARGB. Таким образом, вы должны быть в состоянии сделать что-то вроде:

for (all x,y values of image) {
  int argb = img.getRGB(x, y);
  int oldAlpha = (argb >>> 24);
  if (oldAlpha == 100) {
    argb = (80 << 24) | (argb & 0xffffff);
    img.setRGB(x, y, argb);
  }
}

Для скорости вы можете использовать методы для получения блоков значений пикселей.

0 голосов
/ 18 марта 2018

Может потребоваться сначала скопировать BufferedImage на изображение типа BufferedImage.TYPE_INT_ARGB. Если ваше изображение имеет тип, скажем, BufferedImage.TYPE_INT_RGB, то альфа-компонент не будет установлен правильно. Если ваш BufferedImage имеет тип BufferedImage.TYPE_INT_ARGB, то код ниже работает. /** * Modifies each pixel of the BufferedImage so that the selected component (R, G, B, or A) * is adjusted by delta. Note: the BufferedImage must be of type BufferedImage.TYPE_INT_ARGB. * @param src BufferedImage of type BufferedImage.TYPE_INT_ARGB. * @param colorIndex 0=red, 1=green, 2=blue, 3= alpha * @param delta amount to change component * @return */ public static BufferedImage adjustAColor(BufferedImage src,int colorIndex, int delta) { int w = src.getWidth(); int h = src.getHeight(); assert(src.getType()==BufferedImage.TYPE_INT_ARGB); for (int y = 0; y < h; y++) for (int x = 0; x < w; x++) { int rgb = src.getRGB(x,y); java.awt.Color color= new java.awt.Color(rgb,true); int red=color.getRed(); int green=color.getGreen(); int blue=color.getBlue(); int alpha=color.getAlpha(); switch (colorIndex) { case 0: red=adjustColor(red,delta); break; case 1: green=adjustColor(green,delta); break; case 2: blue=adjustColor(blue,delta); break; case 3: alpha=adjustColor(alpha,delta); break; default: throw new IllegalStateException(); } java.awt.Color adjustedColor=new java.awt.Color(red,green,blue,alpha); src.setRGB(x,y,adjustedColor.getRGB()); int gottenColorInt=src.getRGB(x,y); java.awt.Color gottenColor=new java.awt.Color(gottenColorInt,true); assert(gottenColor.getRed()== red); assert(gottenColor.getGreen()== green); assert(gottenColor.getBlue()== blue); assert(gottenColor.getAlpha()== alpha); } return src; } private static int adjustColor(int value255, int delta) { value255+= delta; if (value255<0) { value255=0; } else if (value255>255) { value255=255; } return value255; }

...