Основная проблема с вашим кодом состоит в том, что он не будет l oop, потому что вы инициализируете i, j
в width, height
, что уже больше, чем условие выхода из циклов for
(i < width, j < height
) , Начните итерацию с 0, инициализируя i
и j
до 0
, и ваш код будет работать так, как задумано.
Для повышения производительности вы также хотите изменить порядок циклов. Поскольку BufferedImage
s хранятся в виде непрерывного массива, строка за строкой, вы будете использовать кэш ЦП гораздо лучше, если вы поместите l oop по оси x (строка) во внутренней l oop.
Примечание: я также предлагаю переименовать i
и j
в x
и y
для лучшей читаемости.
Наконец, ваш метод преобразования RGB в серый путем усреднения цветов будет работать, но это не самый распространенный способ преобразования в оттенки серого, поскольку человеческий глаз не воспринимает интенсивности цветов как одинаковые , См. Википедия по преобразованию серой шкалы для лучшего понимания правильного преобразования и теории, лежащей в основе.
Тем не менее, все это сказано для изображений JPEG, хранящихся как YCbCr (наиболее распространенный способ хранения JPEG), существует гораздо более быстрый, эффективный для памяти и более простой способ преобразования изображения в шкалу серого, а именно простое считывание канала Y (яркости) JPEG и непосредственное использование его в качестве шкалы серого.
Используя Java и ImageIO, вы можете сделать это следующим образом:
public class GrayJPEG {
public static void main(String[] args) throws IOException {
try (ImageInputStream stream = ImageIO.createImageInputStream(new File(args[0]))) {
ImageReader reader = ImageIO.getImageReaders(stream).next(); // Will throw exception if no reader available
try {
reader.setInput(stream);
ImageReadParam param = reader.getDefaultReadParam();
// The QnD way, just specify the gray type directly
//param.setDestinationType(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_GRAY));
// The very correct way, query the reader if it supports gray, and use that
Iterator<ImageTypeSpecifier> types = reader.getImageTypes(0);
while (types.hasNext()) {
ImageTypeSpecifier type = types.next();
if (type.getColorModel().getColorSpace().getType() == ColorSpace.TYPE_GRAY) {
param.setDestinationType(type);
break;
}
}
BufferedImage image = reader.read(0, param);
ImageIO.write(image, "JPEG", new File(args[0] + "_gray.jpg"));
}
finally {
reader.dispose();
}
}
}
}