READING, MODIFYING, AND SAVING IMAGES

By Julian Robichaux,
SNAPPS






This month's developer article talks about how to manipulate image files
(like JPG or PNG files) with your code. While there are a number of third-party
DLLs and applications you might tap into for this purpose, you'll probably find
that you can do most, if not all, of the things you want to do using Java right
out of the box.


Reading Images
The built-in Java
library for reading and writing images is the ImageIO library. This was
available as an extra library in early versions of Java (you could download it
from Sun and add it to your classpath), and it has been a part of the standard
Java distribution since Java 1.4. That's Lotus Notes 7.0 and higher to you and
me.


As Java versions have been updated with newer
versions of the Notes client, we have also gained some additional functionality
with the built-in ImageIO framework with newer versions of the client.
Specifically, here are the image types we can read in Notes 7 and higher:



  • Notes 7: JPG and PNG
  • Notes 8: JPG, PNG, BMP, and GIF
  • Notes 8.5: JPG, PNG, BMP, and GIF

An interesting thing to keep in mind is that while Notes 8 can read GIF files, support for writing GIF files (as we'll see later) is not
available by default until Notes 8.5. Also, the ImageIO framework has an API for
plugins, so there are additional plugins available that you can use to read
and/or write other image formats.


I've also found that certain types of PNG files are not able to be read
properly by the base Java ImageIO class. See this page for one instance and a little explanation. As with
the use of additional file types, you might find that you have to use other
libraries or plugins (like javapng from Google)
to get full PNG support.


Reading a file for manipulation as a BufferedImage is as easy as writing a few lines of code
like this:


   FileInputStream fis = new FileInputStream(fileName);
   BufferedImage bi = ImageIO.read(fis);

From there, you can modify the BufferedImage to
make any alterations to the image before resaving it.


Modifying Images
Modifying an image
involves making modifications to the in-memory BufferedImage that we now have access to. There are two
primary ways in which we will modify an image: redrawing the image and filtering
the image.


Redrawing an image (cropping it, rotating it,
adjusting its size) can be done by using the Graphics2D object to create a new
"canvas" to redraw the BufferedImage onto it, thereby creating a new
BufferedImage at the desired size, rotation, or position. For example, here's
how to resize an image:


   BufferedImage bi2 = new BufferedImage(width, height, bi.getType());
   Graphics2D g2 = bi2.createGraphics();
   g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
   g2.drawImage(bi, 0, 0, width, height, null);
   g2.dispose();
   return bi2;

You can call g2.rotate() before the call to g2.drawImage() if you want to rotate the image, and you
can actually crop the image by calling BufferedImage.getSubimage() to create a new cropped BufferedImage.


You can actually use AffineTransforms (which we'll discuss in the next
paragraph) to do the image scaling or rotation as well. However, you have much
better control over the quality of the resulting image if you use Graphics2D
methods directly for this functionality. For a good workaround for the problem
of poor image quality when you create image thumbnails, see Chris Campbell's
article "The Perils of Image.getScaledInstance()".


Pretty much any other kind of image manipulation
you want to do — like adjusting colors and contrast, blurring, sharpening, etc.
— requires the use of a Java 2D BufferedImageOp filter. Some of the ones you'll
find useful are:



  • AffineTransformOp for
    scaling, flipping, or rotating (although as mentioned above, you might get
    better results for scaling and rotating by using Graphics2D directly)
  • ColorConvertOp for
    adjusting image colors or converting to greyscale
  • RescaleOp for
    adjusting contrast and brightness
  • ConvolveOp for
    blurring, sharpening, or edge-detection

Here's an example of creating a greyscale version
of an image:


   ColorConvertOp op = new ColorConvertOp(
      ColorSpace.getInstance(ColorSpace.CS_GRAY), null);
   return op.filter(bi, null);

None of these operations will directly modify the BufferedImage that they operate on; rather, they do their
work and return a new instance of a BufferedImage
that you must now retain in memory.


Saving
Images

The ImageIO class again comes into
play when we save the BufferedImage that we've
modified. We just have to make a call to ImageIO.write() to save the in-memory image to a file. For
example:


   String fileName = "c:\\myNewFile.png";
   ImageIO.write(bi, "png", new File(fileName));

As with the file types that can be read, the file
types that we can generate are different for different versions of Lotus
Notes:



  • Notes 7: JPG and PNG
  • Notes 8: JPG, PNG, and BMP
  • Notes 8.5: JPG, PNG, BMP, and GIF

Even if you don't make any changes to the image
file at all, you can use the ImageIO class to
convert from one file type to another. One limitation that I've run into is that
the JPG output quality is often pretty poor. I don't know why that is, but a
workaround I've found is to use code like this for generating JPG output:


   Iterator iter = ImageIO.getImageWritersByFormatName("jpeg");
   ImageWriter writer = (ImageWriter)iter.next();
   ImageWriteParam iwp = writer.getDefaultWriteParam();
   iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
   iwp.setCompressionQuality(quality);  // 1f = 100%, 0.9f = 90%, etc.
	
   File file = new File(fileName);
   FileImageOutputStream out = new FileImageOutputStream(file);
   writer.setOutput(out);
   IIOImage image = new IIOImage(bi, null, null);
   writer.write(null, image, iwp);
	
   out.close();
   writer.dispose();

As I mentioned in the "Reading Images" section, there are plugins and
additional libraries available that can be used to generate other image types
too.


What About LotusScript?
If you're a
LotusScript programmer, you can still take advantage of all this built-in
functionality directly through your LotusScript code. Just use LS2J. In fact, an
example of using many of the techniques I've talked about above as well as an
LS2J wrapper to make calls to an image manipulation Java library is available on
my
Web site.


Limitations
The primary (and
obvious) limitation is the small number of file types that you are limited to.
However, that's just an "out of the box" limitation that you can use plugins and
other libraries to work around. Ask Google for help.


If you're doing a large amount of image processing (or working on very large
images), make sure you don't hold too many BufferedImages in memory.


Also, because you will almost certainly be dealing with the local file system
(reading files, writing files, or both), make sure that any server-based agents
that use these techniques have the security set to "Allow restricted operations"
and the agent signer is allowed to run unrestricted operations on the
server.


BONUS:
Embedding images into rich text fields

As a related topic, see my
December 2008 Clippings article "Four Things You Thought You Couldn't Do With Rich Text" to get
some information on how you can embed an image file directly into a rich text
field — as a real image, not just an attachment.

原文地址:https://www.cnblogs.com/hannover/p/2466761.html