使用 Java 进行图像处理 - 编码输出高分辨率图像

版权声明:转载时请务必保留以下作者信息和链接
作者:陈维([email protected])作者的网站:http://www.chenwei.mobi

通常我们使用Java 编码输出图像默认的图像分辨率是72dpi(关于图像分辨率可以看我转载的一篇文章《图片分辨率介绍》),PC显示器的设备分辨率一般在60~120dpi之间,而熟悉印刷行业的朋友都知道,印刷一张图像需要的图像分辨率一般是300dpi,就是说这样的图像在显示器上显示可能很细腻但是印刷输出的效果却非常粗糙。那么我们针对印刷或者其他需要高分辨率的应用场合,就需要输出更高分辨率的图像,可是纵观Java SE 中标准的ImageIO 库并没有提供设置DPI值的方法,那么怎么使用Java生成适合印刷或者更高分辨率的图像呢?

幸好,JAI_ImageIO 为我们解决了这个难题,或者只能说部分解决。目前JAI_ImageIO_1.1 对于设置DPI 信息的支持仅限于TIFF格式,我并没有在JAI_ImageIO_1.1 中找到针对其他图像格式(例如常见的JPEG)设置DPI 的方法。

JAI_ImageIO_1.1 中对于的TIFF 格式提供了2种途径(DOM 和 API)可以在图像编码时将DPI 信息设置进Meatadata。下面是一段创建图像并且以300dpi 编码输出的样例程序,它分别就这两种方法都做了实现,可以提供大家学习参考。编译运行需要引用JAI_ImageIO_1.1,可以从https://jai-imageio.dev.java.net/下载。

import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet;
import com.sun.media.imageio.plugins.tiff.TIFFDirectory;
import com.sun.media.imageio.plugins.tiff.TIFFField;
import com.sun.media.imageio.plugins.tiff.TIFFTag;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.File;
import java.util.Iterator;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.ImageWriter;
import javax.imageio.metadata.IIOInvalidTreeException;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.stream.FileImageOutputStream;

/***/ /**
*设置自定义dpi值到TIFF格式图像的样例程序。
*需要JAI_ImageIO_1.1提供支持。
*/

public class SetDPI4TIFF ... {

privatestaticStringMETADATA_NAME="com_sun_media_imageio_plugins_tiff_image_1.0";
privatestaticintDPI_X=300;
privatestaticintDPI_Y=300;

publicstaticvoidmain(String[]args)throwsThrowable...{
//Createsampleimage.
RenderedImageimage=newBufferedImage(256,256,BufferedImage.TYPE_3BYTE_BGR);

//GetTIFFwriter.
Iteratorwriters=ImageIO.getImageWritersByFormatName("TIFF");
if(writers==null||!writers.hasNext())...{
thrownewIllegalStateException("NoTIFFwriters!");
}

ImageWriterwriter
=(ImageWriter)writers.next();

//Getthedefaultimagemetadata.
ImageTypeSpecifierimageType=ImageTypeSpecifier.createFromRenderedImage(image);
IIOMetadataimageMetadata
=writer.getDefaultImageMetadata(imageType,null);

//SetDPI.
StringfileName;
Stringmethodology;
if(args.length==0||args[0].equalsIgnoreCase("DOM"))...{
fileName
="dpi_dom.tif";
setDPIViaDOM(imageMetadata);
methodology
="DOM";
}
else...{
fileName
="dpi_api.tif";
imageMetadata
=setDPIViaAPI(imageMetadata);
methodology
="API";
}


System.out.println(
" Writing"+fileName+"using"+methodology+"methodology ");

//Writeimage.
writer.setOutput(newFileImageOutputStream(newFile(fileName)));
writer.write(
newIIOImage(image,null,imageMetadata));
}


/***//**
*SetDPIusingDOMnodes.
*/

privatestaticvoidsetDPIViaDOM(IIOMetadataimageMetadata)throwsIIOInvalidTreeException...{
//GettheDOMtree.
IIOMetadataNoderoot=(IIOMetadataNode)imageMetadata.getAsTree(METADATA_NAME);

//GettheIFD.
IIOMetadataNodeifd=(IIOMetadataNode)root.getElementsByTagName("TIFFIFD").item(0);

//Get{X,Y}Resolutiontags.
BaselineTIFFTagSetbase=BaselineTIFFTagSet.getInstance();
TIFFTagtagXRes
=base.getTag(BaselineTIFFTagSet.TAG_X_RESOLUTION);
TIFFTagtagYRes
=base.getTag(BaselineTIFFTagSet.TAG_Y_RESOLUTION);

//Create{X,Y}Resolutionnodes.
IIOMetadataNodenodeXRes=createRationalNode(tagXRes.getName(),tagXRes.getNumber(),DPI_X,1);
IIOMetadataNodenodeYRes
=createRationalNode(tagYRes.getName(),tagYRes.getNumber(),DPI_Y,1);

//Append{X,Y}ResolutionnodestoIFDnode.
ifd.appendChild(nodeXRes);
ifd.appendChild(nodeYRes);

//Setmetadatafromtree.
imageMetadata.setFromTree(METADATA_NAME,root);
}


/***//**
*CreatesanodeofTIFFdatatypeRATIONAL.
*/

privatestaticIIOMetadataNodecreateRationalNode(StringtagName,inttagNumber,intnumerator,intdenominator)...{
//Createthefieldnodewithtagnameandnumber.
IIOMetadataNodefield=newIIOMetadataNode("TIFFField");
field.setAttribute(
"name",tagName);
field.setAttribute(
"number",""+tagNumber);

//CreatetheRATIONALnode.
IIOMetadataNoderational=newIIOMetadataNode("TIFFRational");
rational.setAttribute(
"value",numerator+"/"+denominator);

//CreatetheRATIONALnodeandappendRATIONALnode.
IIOMetadataNoderationals=newIIOMetadataNode("TIFFRationals");
rationals.appendChild(rational);

//AppendRATIONALSnodetofieldnode.
field.appendChild(rationals);

returnfield;
}


/***//**
*SetDPIusingAPI.
*/

privatestaticIIOMetadatasetDPIViaAPI(IIOMetadataimageMetadata)throwsIIOInvalidTreeException...{
//DerivetheTIFFDirectoryfromthemetadata.
TIFFDirectorydir=TIFFDirectory.createFromMetadata(imageMetadata);

//Get{X,Y}Resolutiontags.
BaselineTIFFTagSetbase=BaselineTIFFTagSet.getInstance();
TIFFTagtagXRes
=base.getTag(BaselineTIFFTagSet.TAG_X_RESOLUTION);
TIFFTagtagYRes
=base.getTag(BaselineTIFFTagSet.TAG_Y_RESOLUTION);

//Create{X,Y}Resolutionfields.
TIFFFieldfieldXRes=newTIFFField(tagXRes,TIFFTag.TIFF_RATIONAL,1,newlong[][]...{...{DPI_X,1}});
TIFFFieldfieldYRes
=newTIFFField(tagYRes,TIFFTag.TIFF_RATIONAL,1,newlong[][]...{...{DPI_Y,1}});

//Append{X,Y}Resolutionfieldstodirectory.
dir.addTIFFField(fieldXRes);
dir.addTIFFField(fieldYRes);

//Converttometadataobjectandreturn.
returndir.getAsMetadata();
}

}

你可能感兴趣的:(java,.net,sun)