Проблема (по крайней мере, с png к jpg преобразованию) состоит в том, что цветовая схема не является тем же, потому что jpg не поддерживает прозрачность.
то, Что мы сделали успешно, является чем-то вдоль этих строк (это вытягивают от различных битов кода - поэтому простите грубость форматирования):
File file = new File("indexed_test.gif");
BufferedImage image = ImageIO.read(file);
int width = image.getWidth();
int height = image.getHeight();
BufferedImage jpgImage;
//you can probably do this without the headless check if you just use the first block
if (GraphicsEnvironment.isHeadless()) {
if (image.getType() == BufferedImage.TYPE_CUSTOM) {
//coerce it to TYPE_INT_ARGB and cross fingers -- PNGs give a TYPE_CUSTOM and that doesn't work with
//trying to create a new BufferedImage
jpgImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_ARGB);
} else {
jpgImage = new BufferedImage(width, height, image.getType());
}
} else {
jgpImage = GraphicsEnvironment.getLocalGraphicsEnvironment().
getDefaultScreenDevice().getDefaultConfiguration().
createCompatibleImage(width, height, image.getTransparency());
}
//copy the original to the new image
Graphics2D g2 = null;
try {
g2 = jpg.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2.drawImage(image, 0, 0, width, height, null);
}
finally {
if (g2 != null) {
g2.dispose();
}
}
File f = new File("indexed_test.jpg");
ImageIO.write(jpgImage, "jpg", f);
Это работает на png к jpg и gif к jpg. И у Вас будет белый фон, где прозрачные биты были. Можно измениться, это при наличии g2 заполняет изображение другим цветом перед вызовом drawImage.
Как уже упомянуто в ОБНОВЛЕНИИ вопроса я реализовал более простой способ заменить прозрачные пиксели предопределенным цветом:
public static BufferedImage fillTransparentPixels( BufferedImage image,
Color fillColor ) {
int w = image.getWidth();
int h = image.getHeight();
BufferedImage image2 = new BufferedImage(w, h,
BufferedImage.TYPE_INT_RGB);
Graphics2D g = image2.createGraphics();
g.setColor(fillColor);
g.fillRect(0,0,w,h);
g.drawRenderedImage(image, null);
g.dispose();
return image2;
}
и я называю этот метод прежде jpeg преобразование таким образом:
if( inputImage.getColorModel().getTransparency() != Transparency.OPAQUE) {
inputImage = fillTransparentPixels(inputImage, Color.WHITE);
}
JPEG не имеет никакой поддержки прозрачности. Таким образом, даже когда Вы получаете круговой цвет правильно, у Вас все еще будет черный или белый фон, в зависимости от Вашего кодера и/или рендерера.
с опозданием на 3 месяца, но у меня очень похожая проблема (хотя я даже не загружаю гифку, а просто генерирую прозрачное изображение - скажем, без фона, цветную форму - где при сохранении в jpeg, перепутаны все цвета, не только фон)
Нашел этот фрагмент кода в этой довольно старой ветке списка интересов java2d , подумал, что поделюсь, потому что после быстрого теста , оно намного более производительно, чем ваше решение:
final WritableRaster raster = img.getRaster();
final WritableRaster newRaster = raster.createWritableChild(0, 0, img.getWidth(), img.getHeight(), 0, 0, new int[]{0, 1, 2});
// create a ColorModel that represents the one of the ARGB except the alpha channel
final DirectColorModel cm = (DirectColorModel) img.getColorModel();
final DirectColorModel newCM = new DirectColorModel(cm.getPixelSize(), cm.getRedMask(), cm.getGreenMask(), cm.getBlueMask());
// now create the new buffer that we'll use to write the image
return new BufferedImage(newCM, newRaster, false, null);
К сожалению, я не могу сказать, что понимаю в точности , что оно делает;)
Для Java 6 (и, я думаю, 5 тоже):
BufferedImage bufferedImage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB);
g = bufferedImage.createGraphics();
//Color.WHITE estes the background to white. You can use any other color
g.drawImage(image, 0, 0, bufferedImage.getWidth(), bufferedImage.getHeight(), Color.WHITE, null);