我有一堆图像,其中一些图像必须旋转。
样品:
我想将此图像逆时针旋转90°。
我用Google搜索了解如何旋转图像并找到许多链接和SO线程。但是如何确定图像是否需要旋转? Picasa具有自动旋转功能。我想要有类似的功能。
任何指针都对我很有帮助。
我找到了link,但它与Android有关。
metadata-extractor提供的Roger Rowland的指针解决了这个问题。我将其发布在此处以供将来参考:
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import com.drew.imaging.ImageMetadataReader;
import com.drew.metadata.Metadata;
import com.drew.metadata.exif.ExifIFD0Directory;
import com.drew.metadata.jpeg.JpegDirectory;
public class Main {
private static String inFilePath = "C:\\Users\\TapasB\\Desktop\\MHIS031522.jpg";
private static String outFilePath = "C:\\Users\\TapasB\\Desktop\\MHIS031522-rotated.jpg";
public static void main(String[] args) throws Exception {
File imageFile = new File(inFilePath);
BufferedImage originalImage = ImageIO.read(imageFile);
Metadata metadata = ImageMetadataReader.readMetadata(imageFile);
ExifIFD0Directory exifIFD0Directory = metadata.getDirectory(ExifIFD0Directory.class);
JpegDirectory jpegDirectory = (JpegDirectory) metadata.getDirectory(JpegDirectory.class);
int orientation = 1;
try {
orientation = exifIFD0Directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);
} catch (Exception ex) {
ex.printStackTrace();
}
int width = jpegDirectory.getImageWidth();
int height = jpegDirectory.getImageHeight();
AffineTransform affineTransform = new AffineTransform();
switch (orientation) {
case 1:
break;
case 2: // Flip X
affineTransform.scale(-1.0, 1.0);
affineTransform.translate(-width, 0);
break;
case 3: // PI rotation
affineTransform.translate(width, height);
affineTransform.rotate(Math.PI);
break;
case 4: // Flip Y
affineTransform.scale(1.0, -1.0);
affineTransform.translate(0, -height);
break;
case 5: // - PI/2 and Flip X
affineTransform.rotate(-Math.PI / 2);
affineTransform.scale(-1.0, 1.0);
break;
case 6: // -PI/2 and -width
affineTransform.translate(height, 0);
affineTransform.rotate(Math.PI / 2);
break;
case 7: // PI/2 and Flip
affineTransform.scale(-1.0, 1.0);
affineTransform.translate(-height, 0);
affineTransform.translate(0, width);
affineTransform.rotate(3 * Math.PI / 2);
break;
case 8: // PI / 2
affineTransform.translate(0, width);
affineTransform.rotate(3 * Math.PI / 2);
break;
default:
break;
}
AffineTransformOp affineTransformOp = new AffineTransformOp(affineTransform, AffineTransformOp.TYPE_BILINEAR);
BufferedImage destinationImage = new BufferedImage(originalImage.getHeight(), originalImage.getWidth(), originalImage.getType());
destinationImage = affineTransformOp.filter(originalImage, destinationImage);
ImageIO.write(destinationImage, "jpg", new File(outFilePath));
}
}
我有一些问题让一些开关案例起作用。即使没有旋转,AffineTransform也会在图像中创建一个带有黑色空间的新图像,并会切掉一些尺寸。小猪退出接受的答案,我使用元数据提取器类来确定方向应该是什么。然后我使用Imgscalr库进行缩放和旋转。
可以在下面看到适合我的完整解决方案。谢谢Tapas Bose的原始解决方案。我希望这对任何人都有帮助!
BufferedImage originalImage = Utils.prepareBufferedImage(fileUpload.getFile_data(), fileUpload.getFile_type());
BufferedImage scaledImg = Scalr.resize(originalImage, 200);
// ---- Begin orientation handling ----
Metadata metadata = ImageMetadataReader.readMetadata(fileUpload.getFile_data());
ExifIFD0Directory exifIFD0Directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
int orientation = Integer.parseInt(id);
try {
orientation = exifIFD0Directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);
} catch (Exception ex) {
logger.debug("No EXIF information found for image: " + fileUpload.getFile_name());
}
switch (orientation) {
case 1:
break;
case 2: // Flip X
scaledImg = Scalr.rotate(scaledImg, Rotation.FLIP_HORZ);
break;
case 3: // PI rotation
scaledImg = Scalr.rotate(scaledImg, Rotation.CW_180);
break;
case 4: // Flip Y
scaledImg = Scalr.rotate(scaledImg, Rotation.FLIP_VERT);
break;
case 5: // - PI/2 and Flip X
scaledImg = Scalr.rotate(scaledImg, Rotation.CW_90);
scaledImg = Scalr.rotate(scaledImg, Rotation.FLIP_HORZ);
break;
case 6: // -PI/2 and -width
scaledImg = Scalr.rotate(scaledImg, Rotation.CW_90);
break;
case 7: // PI/2 and Flip
scaledImg = Scalr.rotate(scaledImg, Rotation.CW_90);
scaledImg = Scalr.rotate(scaledImg, Rotation.FLIP_VERT);
break;
case 8: // PI / 2
scaledImg = Scalr.rotate(scaledImg, Rotation.CW_270);
break;
default:
break;
}
// ---- End orientation handling ----
if(fileUpload.getFile_type().toLowerCase().contains("jpeg")){
ImageIO.write(scaledImg, "jpeg", fileUpload.getFile_data());
user.setProfile_picture_ext("jpg");
}
else{
Sanselan.writeImage(scaledImg, fileUpload.getFile_data(), ImageFormat.IMAGE_FORMAT_PNG, null);
user.setProfile_picture_ext("png");
}
有时您不使用相机拍摄的图像,也没有EXIF数据可供使用。在我的情况下,我有一个项目,扫描并导入我们的数字存储库成千上万的老式明信片,其中大多数是正面的景观,其中只有一小部分是肖像(背面保持景观,即使在这些上)。为了最大限度地减少扫描,纠偏和裁剪所花费的时间,它们每次扫描三次和横向(始终)完成。
我来到这个问题寻找自动检测和旋转这些纵向卡扫描的答案。
关于基于相机元数据执行此操作的讨论很多。有一些例子说明了如何使用机器学习自动调整照片,而照片没有被保持在地面/地平线上。我没有找到任何对我的情况有帮助的东西(这并不是说没有,但是如果因为其他情况很难找到它们的话)......
编辑3/22/2019:这是一个https://d4nst.github.io/2017/01/12/image-orientation/
...,所以我确实想出了一个我将要尝试的答案:
对于每个卡片前端(使用ImageMagick和简单脚本进行批处理):
我用一次扫描测试了这个,在我的n = 1的情况下,API有一个更长的标签列表和更好(和更长)的正确方向的建议标题。
潜在问题: