Java:BufferedImage上的getHeight()返回图像宽度,getWidth()返回图像高度

时间:2016-11-29 12:57:19

标签: java image metadata

我正在压缩一个用Java进行Jpeg压缩的图像,然后在存储之前调整它们的大小。我将存储空间保持为480并根据宽高比计算height,以保持原始height:width比率相同。

这是我正在使用的代码

String inputImagePath = "1.JPG";
String outputImagePath = "Test Compression\\" + "1.JPG";

File imageFile = new File(inputImagePath);
File compressedImageFile = new File(outputImagePath);

int height = 640;

System.out.print("Conversion Start!\n");

if (imageFile != null)
{

    InputStream is = new FileInputStream(imageFile);
    OutputStream os = new FileOutputStream(compressedImageFile);

    float quality = 0.2 f;

    BufferedImage image = ImageIO.read(is);

    double aspectRatio = (double) image.getWidth() / image.getHeight();

    width = (int)(height * aspectRatio);
    System.out.println("Original height = " + image.getHeight() + " Original  width = " + image.getWidth());
    System.out.println(" aspect ratio = " + aspectRatio);
    System.out.println("height = " + height + " width = " + width + " aspect ratio = " + aspectRatio);

    BufferedImage resizedImage = new BufferedImage(width, height, image.getType());
    Graphics2D g = resizedImage.createGraphics();
    g.drawImage(image, 0, 0, width, height, null);
    g.dispose();

    Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("jpg");

    if (!writers.hasNext())
        throw new IllegalStateException("No writers found");

    ImageWriter writer = (ImageWriter) writers.next();
    ImageOutputStream ios = ImageIO.createImageOutputStream(os);
    writer.setOutput(ios);

    ImageWriteParam param = writer.getDefaultWriteParam();
    param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
    param.setCompressionQuality(quality);

    writer.write(null, new IIOImage(resizedImage, null, null), param);
}

System.out.print("Conversion compete!");

这是图像元数据

Here width = 1920, height = 2560

以下是印刷内容:

Original height = 1920 Original  width = 2560
aspect ratio = 1.3333333333333333

height = 480 width = 640
aspect ratio = 1.3333333333333333

我将代码应用于实际拥有width > height的其他图片,而且我没有轮换问题。这个旋转问题只发生在height > width的图像上据我所知,我的代码没有任何问题,我必须遗漏与getHeight()和getWidth()函数相关的内容。请帮帮我

2 个答案:

答案 0 :(得分:3)

jpeg图像中可能存在旋转元数据,Java默认情况下无法识别。

看起来像jpeg属性中的Orientation : rotate 90

您需要第三方库来处理它,请参阅How to rotate JPEG images based on the orientation metadata?

答案 1 :(得分:1)

为了将来的参考资料,我完成了Sergey Grinev给出的参考资料并稍微修改了代码并获得了理想的结果。这是代码

Metadata metadata = ImageMetadataReader.readMetadata(imageFile);
Directory directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
			
int orientation = 1;
try{
orientation = directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);
} catch (MetadataException me) {
System.out.println("Could not get orientation");
}

int orgWidth = image.getWidth();
int orgHeight = image.getHeight();
			
double orgAspectRatio = (double)orgWidth/orgHeight;
			
			
AffineTransform affineTransform = new AffineTransform();
AffineTransformOp affineTransformOp;
BufferedImage orientedImage = new BufferedImage(image.getHeight(), image.getWidth(), image.getType());
		
boolean rotation = false;
	        
switch (orientation) {
  case 1:
       	orientedImage = image;
        break;
  case 2: // Flip X
        affineTransform.scale(-1.0, 1.0);
        affineTransform.translate(-orgWidth, 0);
    	affineTransformOp = new AffineTransformOp(affineTransform, AffineTransformOp.TYPE_BILINEAR);  
	    orientedImage = affineTransformOp.filter(image, orientedImage);
	    break;
   case 3: // PI rotation
          affineTransform.translate(orgWidth, orgHeight);
          affineTransform.rotate(Math.PI);
          affineTransformOp = new AffineTransformOp(affineTransform,AffineTransformOp.TYPE_BILINEAR);
         orientedImage = affineTransformOp.filter(image, orientedImage);
         break;
   case 4: // Flip Y
          affineTransform.scale(1.0, -1.0);
          affineTransform.translate(0, -orgHeight);
		affineTransformOp = new AffineTransformOp(affineTransform, AffineTransformOp.TYPE_BILINEAR);
          orientedImage = affineTransformOp.filter(image, orientedImage);
          break;
   case 5: // - PI/2 and Flip X
        	rotation = true;
            affineTransform.rotate(-Math.PI / 2);
            affineTransform.scale(-1.0, 1.0);
			affineTransformOp = new AffineTransformOp(affineTransform, AffineTransformOp.TYPE_BILINEAR);
            orientedImage = affineTransformOp.filter(image, orientedImage);
            break;
   case 6: // -PI/2 and -width
        	rotation = true;
            affineTransform.translate(orgHeight, 0);
            affineTransform.rotate(Math.PI/2);
			affineTransformOp = new AffineTransformOp(affineTransform, AffineTransformOp.TYPE_BILINEAR);
            orientedImage = affineTransformOp.filter(image, orientedImage);
            break;
   case 7: // PI/2 and Flip
        	rotation = true;
            affineTransform.scale(-1.0, 1.0);
            affineTransform.translate(-orgHeight, 0);
            affineTransform.translate(0, orgWidth);
            affineTransform.rotate(3 * Math.PI / 2);
			affineTransformOp = new AffineTransformOp(affineTransform, AffineTransformOp.TYPE_BILINEAR);
            orientedImage = affineTransformOp.filter(image, orientedImage);
            break;
   case 8: // PI / 2
        	rotation = true;
            affineTransform.translate(0, orgWidth);
            affineTransform.rotate(3 * Math.PI / 2);
			affineTransformOp = new AffineTransformOp(affineTransform, AffineTransformOp.TYPE_BILINEAR);
            orientedImage = affineTransformOp.filter(image, orientedImage);
            break;
   default:
        	orientedImage = image;
            break;
        }       
	        
double aspectRatio;
	        
if(rotation){
    	aspectRatio = (double)orientedImage.getWidth()/orientedImage.getHeight();
      	width = outWidth;
       	height = (int)(width/aspectRatio);
        }
        else{
        	aspectRatio = (double)orientedImage.getWidth()/orientedImage.getHeight();
         	width = (int)(height*aspectRatio);
        }