Я хочу сделать простое преобразование цвета в оттенки серого, используя java.awt.image.BufferedImage
. Я новичок в области обработки изображений, поэтому прошу простить, если что-то напутал.
Мое входное изображение представляет собой 24-битное изображение RGB (без альфа-канала), я хотел бы получить на выходе 8-битную шкалу серого BufferedImage
, что означает, что у меня есть такой класс (детали опущены для ясности):
public class GrayscaleFilter {
private BufferedImage colorFrame;
private BufferedImage grayFrame =
new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
До сих пор я успешно пробовал 2 метода преобразования, первый из которых:
private BufferedImageOp grayscaleConv =
new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null);
protected void filter() {
grayscaleConv.filter(colorFrame, grayFrame);
}
И второе существо:
protected void filter() {
WritableRaster raster = grayFrame.getRaster();
for(int x = 0; x < raster.getWidth(); x++) {
for(int y = 0; y < raster.getHeight(); y++){
int argb = colorFrame.getRGB(x,y);
int r = (argb >> 16) & 0xff;
int g = (argb >> 8) & 0xff;
int b = (argb ) & 0xff;
int l = (int) (.299 * r + .587 * g + .114 * b);
raster.setSample(x, y, 0, l);
}
}
}
Первый метод работает намного быстрее, но получаемое изображение очень темное, а это означает, что я теряю полосу пропускания, что неприемлемо (существует некоторое сопоставление преобразования цветов, используемое между оттенками серого и sRGB ColorModel
, называемое tosRGB8LUT, которое не очень хорошо работает для меня, поскольку как я могу сказать, но я не уверен, я просто предполагаю, что эти значения используются). Второй способ работает медленнее, но эффект очень приятный.
Есть ли способ объединить эти два, например. используя пользовательский индекс ColorSpace
для ColorConvertOp
? Если да, не могли бы вы привести пример?
Заранее спасибо.