Как преобразовать растровое изображение в градациях серого в альфа-маску?

У меня есть изображение JPG в оттенках серого, и я хочу загрузить его в растровое изображение формата Bitmap.Config.ALPHA_8. Возможно ли это, как я могу это сделать?

Легко загрузить альфа-канал из PNG (который может иметь пустые каналы R, G, B), но я бы хотел использовать JPG для сжатия.

Это дополнительный вопрос к как объединить два непрозрачные растровые изображения в один с альфа-каналом?


person Pēteris Caune    schedule 24.02.2011    source источник


Ответы (1)


ColorMatrix на помощь!

Цитируя документы Android, ColorMatrix:

Матрица 5x4 для преобразования цветных и альфа-компонентов растрового изображения. Матрица хранится в одном массиве и обрабатывается следующим образом: [ a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t ] При применении к цвету [r, g, b, a] результирующий цвет вычисляется как (после фиксации) R' = aR + bG + cВ + дА + е; G' = fR + gG + hB + iA + j; B' = kR + lG + mB + nA + o; А' = pR + qG + rB + sA + t;

Настройте цветовую матрицу, которая берет альфа-значение из красного канала (или зеленого, или синего, не имеет значения для оттенков серого...), затем используйте его в Paint.setColorFilter(). Вот более-менее полный пример:

final BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
options.inScaled = false;

// Load source grayscale bitmap
Bitmap grayscale = BitmapFactory.decodeResource(getResources(), R.drawable.my_grayscale_mask, options);
// Place for  alpha mask. It's specifically ARGB_8888 not ALPHA_8, 
// ALPHA_8 for some reason didn't work out for me. 
Bitmap alpha = Bitmap.createBitmap(grayscale.getWidth(), grayscale.getHeight(),
        Bitmap.Config.ARGB_8888);
float[] matrix = new float[] {
        0, 0, 0, 0, 0,
        0, 0, 0, 0, 0,
        0, 0, 0, 0, 0,
        1, 0, 0, 0, 0};
Paint grayToAlpha = new Paint();
grayToAlpha.setColorFilter(new ColorMatrixColorFilter(new ColorMatrix(matrix)));
Canvas alphaCanvas = new Canvas(alpha);
// Make sure nothing gets scaled during drawing
alphaCanvas.setDensity(Bitmap.DENSITY_NONE);
// Draw grayscale bitmap on to alpha canvas, using color filter that
// takes alpha from red channel
alphaCanvas.drawBitmap(grayscale, 0, 0, grayToAlpha);
// Bitmap alpha now has usable alpha channel!
person Pēteris Caune    schedule 25.02.2011
comment
Разве эта матрица не заберет из маски только красный канал? Это должно работать, конечно, если источник действительно в градациях серого. Как будет выглядеть мактикс для обычного RGB? В нижней строке 0.333, 0.333, 0.334, 0, 0 я думаю. Это правильно? - person Hermann Klecker; 23.02.2015