¿Girar JPEG sin pérdidas (90/180/270 grados) en Java?
Pregunta
¿Existe una biblioteca Java para rotar archivos JPEG en incrementos de 90 grados, sin incurrir en degradación de la imagen?
Otros consejos
Sobre la base de la respuesta de Henry, he aquí un ejemplo de cómo usar MediaUtil para llevar a cabo la rotación sin pérdida JPEG basado en los datos EXIF:
try {
// Read image EXIF data
LLJTran llj = new LLJTran(imageFile);
llj.read(LLJTran.READ_INFO, true);
AbstractImageInfo<?> imageInfo = llj.getImageInfo();
if (!(imageInfo instanceof Exif))
throw new Exception("Image has no EXIF data");
// Determine the orientation
Exif exif = (Exif) imageInfo;
int orientation = 1;
Entry orientationTag = exif.getTagValue(Exif.ORIENTATION, true);
if (orientationTag != null)
orientation = (Integer) orientationTag.getValue(0);
// Determine required transform operation
int operation = 0;
if (orientation > 0
&& orientation < Exif.opToCorrectOrientation.length)
operation = Exif.opToCorrectOrientation[orientation];
if (operation == 0)
throw new Exception("Image orientation is already correct");
OutputStream output = null;
try {
// Transform image
llj.read(LLJTran.READ_ALL, true);
llj.transform(operation, LLJTran.OPT_DEFAULTS
| LLJTran.OPT_XFORM_ORIENTATION);
// Overwrite original file
output = new BufferedOutputStream(new FileOutputStream(imageFile));
llj.save(output, LLJTran.OPT_WRITE_ALL);
} finally {
IOUtils.closeQuietly(output);
llj.freeMemory();
}
} catch (Exception e) {
// Unable to rotate image based on EXIF data
...
}
Con respecto al problema de que los datos EXIF no necesariamente se manejan correctamente, ya que los datos EXIF son irrelevantes en muchas situaciones, aquí hay un código de ejemplo que demuestra solo la función de rotación JPEG sin pérdidas de LLJTran (gracias al usuario113215):
final File SrcJPEG = new File("my-input.jpg");
final File DestJPEG = new File("my-output.jpg");
final FileInputStream In = new FileInputStream(SrcJPEG);
try {
final LLJTran LLJT = new LLJTran(In);
LLJT.read(LLJTran.READ_ALL, true);
LLJT.transform(LLJTran.ROT_90);
final FileOutputStream Out = new FileOutputStream(DestJPEG);
try {
LLJT.save(Out, LLJTran.OPT_WRITE_ALL);
} finally {
Out.close();
}
} finally {
In.close();
}
Si haces la entrada y salida File
Los objetos se refieren al mismo archivo, puede ejecutar esto una y otra vez y observar que la imagen no se degrada, sin importar cuántas iteraciones se realice.
No es necesario una biblioteca externa para este tipo de cosas, todo está integrado en SE. El ser la función más fácil rotate () del objeto Graphics2D.
Por ejemplo:
Image rotatedImage = new BufferedImage(imageToRotate.getHeight(null), imageToRotate.getWidth(null), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = (Graphics2D) rotatedImage.getGraphics();
g2d.rotate(Math.toRadians(90.0));
g2d.drawImage(imageToRotate, 0, -rotatedImage.getWidth(null), null);
g2d.dispose();
ninguna pérdida!
O, si se quiere ser muy cuidadoso, sólo tiene que utilizar BufferedImage.getRGB (x, y), y traducirlo pixel por pixel a la nueva imagen.