Из JavaDoc BufferedImage.setRGB()
"Устанавливает для пикселя в этом BufferedImage указанное значение RGB. Предполагается, что пиксель находится в цветовой модели RGB по умолчанию, TYPE_INT_ARGB и цветовом пространстве sRGB по умолчанию. Для изображений с IndexColorModel индекс с индексом выбран ближайший цвет. "
Чтобы решить эту проблему, создайте новый BufferedImage с требуемым цветовым пространством, такими же размерами, что и исходное изображение, и запишите в него пиксели, а не обратно в исходный BufferedImage.
BufferedImage targetImage = new BufferedImage(img.getWidth(),
img.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
вместо этого запишите пиксели к этому изображению ...
targetImage.setRGB(x, y, p);
затем сохраните это новое изображение ..
ImageIO.write(targetImage, "jpg", f);
Как примечание, более точный способ преобразования цветного изображения в шкалу серого состоит в преобразовании пикселей RGB в цветовое пространство YUV и последующем использовании значения яркости, а не среднего значения RGB. Это потому, что яркость R G и B взвешены по-разному.