Trying to store to an image.
bt is byte array
InputStream is = new ByteArrayInputStream(bt);
Image img = ImageIO.read(is);
ImageIO.write(img,"jpg",new File("C:\\home_loan.jpg") );
, please help me,
error -
: cannot find symbol
symbol : method write(java.awt.Image,java.lang.String,java.io.File)
location: class javax.imageio.ImageIO
ImageIO.write(img,"jpg",new File("C:\home_loan.jpg") );
^
First you need to know whether the mapping is one int to one byte or one int to multiple bytes (and how many). Then, if the latter, you need to know whether big-endian or little-endian.
For images you also need to have a clue as to what the image format is (and JPG actually has several variants).
Use a BufferedImage. That is an Image backed by memory, and has two setRGB methods.
Tailor your data by that; otherwise you need to convert the data structure, working on one single BufferedImage.
You can use following methods-
/**
* #param path full path of image
* #return image file for supplied path
*/
private BufferedImage getImage(String path) {
BufferedImage image = null;
File file = new File(path);
try {
image = ImageIO.read(file);
} catch(Exception e) {
e.printStackTrace();
}
return image;
}
/**
* #param userSpaceImage
* #return byte array of supplied image
*/
private byte[] getByteData(BufferedImage userSpaceImage) {
WritableRaster raster = userSpaceImage.getRaster();
DataBufferByte buffer = (DataBufferByte) raster.getDataBuffer();
return buffer.getData();
}
/**
* #param image image-file to save
* #param file to save image to
* #param extension of image file
* #return full path of saved image
*/
private String saveImage(BufferedImage image, File file, String extension) {
try {
ImageIO.write(image, extension, file);
} catch(Exception e) {
e.printStackTrace();
}
return file.getAbsolutePath();
}
Related
We want to know how we can share multiple files (image and txt file) with the Gluon ShareService. Especially how to share an image which was previously taken and stored (in gallery) with the PictureService.
But we need to create a file first with the path and image name. Unfortunately, the PictureService saves the image with the image title consisting of date and time at the moment the picture was taken.
We tried to get the image name with the loadImageFromGallery method but this returns void and opens the recent-screen.
Here what we've tried to share an image:
public void sharePicture() {
Services.get(PicturesService.class).ifPresent(picturesService -> {
Image image = picturesService.loadImageFromGallery().get();
File file= new File("Pictures", image.toString());
Services.get(ShareService.class).ifPresent(service -> {
service.share("image/jpg", file);
});
});
}
How can we store the image where we want with a title we want?
How can we share a file and an image together?
You are on the right track, combining different services from Charm Down, in order to select an image from the gallery and share it.
There is a major problem in this approach, though: You can't convert easily a JavaFX Image into a File.
So far the PicturesService returns only a JavaFX Image, and not a File, so we need a way to save that image into a file that we can read and share.
And the process is not easy since on mobile we don't have SwingUtilities.
The initial approach of using a PixelReader to read the image and get a byte array doesn't really work, as it will give you a big raw file that can't be read or share.
I've used this solution that makes use of a PNG encoder to get the byte array of a png from a JavaFX image:
PngEncoderFX encoder = new PngEncoderFX(image, true);
byte[] bytes = encoder.pngEncode();
Then I'll save that byte array into a file in the public storage folder (so it can be shared), that I can retrieve using the `StorageService:
private File getImageFile(Image image) {
if (image == null) {
return null;
}
// 1. Encode image to png
PngEncoderFX encoder = new PngEncoderFX(image, true);
byte[] bytes = encoder.pngEncode();
// 2.Write byte array to a file in public storage
File root = Services.get(StorageService.class)
.flatMap(storage -> storage.getPublicStorage("Pictures"))
.orElse(null);
if (root != null) {
File file = new File(root, "Image-" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("uuuuMMdd-HHmmss")) + ".png");
try (FileOutputStream fos = new FileOutputStream(file)) {
fos.write(bytes);
return file;
} catch (IOException ex) {
System.out.println("Error: " + ex);
}
}
return null;
}
Now, you can call the PicturesService, retrieve the image, save it to the file and finally share it:
Services.get(PicturesService.class).ifPresent(pictures -> {
// 1. Retrieve picture from gallery
pictures.loadImageFromGallery().ifPresent(image -> {
// 2. Convert image to file
File imageFile = getImageFile(image);
// 3. Share file
if (imageFile != null) {
Services.get(ShareService.class).ifPresent(share -> {
share.share("image/png", imageFile);
});
}
});
});
Note that you may run into memory issues if you try to encode big images.
Anyway, all the process could be simplified if the PicturesService will return a file in the first place. If you want to file an issue, you can do it here.
EDIT
A possible solution to avoid memory issues, and to reduce the size of the shared file, and based on this solution, is scaling down the original image, if it exceeds certain size, like it is already done in the iOS implementation of the PicturesService:
private Image scaleImage(Image source) {
// Possible limit based on memory limitations
double maxResolution = 1280;
double width = source.getWidth();
double height = source.getHeight();
double targetWidth = width;
double targetHeight = height;
if (width > maxResolution || height > maxResolution) {
double ratio = width/height;
if (ratio > 1) {
targetWidth = maxResolution;
targetHeight = targetWidth/ ratio;
}
else {
targetHeight = maxResolution;
targetWidth = targetHeight * ratio;
}
}
ImageView imageView = new ImageView(source);
imageView.setPreserveRatio(true);
imageView.setFitWidth(targetWidth);
imageView.setFitHeight(targetHeight);
return imageView.snapshot(null, null);
}
This method can be used now in getImageFile():
// 1 Scale image to avoid memory issues
Image scaledImage = scaleImage(image);
// 2. Encode image to png
PngEncoderFX encoder = new PngEncoderFX(scaledImage, true);
byte[] bytes = encoder.pngEncode();
// 3. Write byte array to a file in public storage
...
It seems to me there are two ways to store an attachment in a NotesDocument.
Either as a RichTextField or as a "MIME Part".
If they are stored as RichText you can do stuff like:
document.getAttachment(fileName)
That does not seem to work for an attachment stored as a MIME Part. See screenshot
I have thousands of documents like this in the backend. This is NOT a UI issue where I need to use the file Download control of XPages.
Each document as only 1 attachment. An Image. A JPG file. I have 3 databases for different sizes. Original, Large, and Small. Originally I created everything from documents that had the attachment stored as RichText. But my code saved them as MIME Part. that's just what it did. Not really my intent.
What happened is I lost some of my "Small" pictures so I need to rebuild them from the Original pictures that are now stored as MIME Part. So my ultimate goal is to get it from the NotesDocument into a Java Buffered Image.
I think I have the code to do what I want but I just "simply" can't figure out how to get the attachment off the document and then into a Java Buffered Image.
Below is some rough code I'm working with. My goal is to pass in the document with the original picture. I already have the fileName because I stored that out in metaData. But I don't know how to get that from the document itself. And I'm passing in "Small" to create the Small image.
I think I just don't know how to work with attachments stored in this manner.
Any ideas/advice would be appreciated! Thanks!!!
public Document processImage(Document inputDoc, String fileName, String size) throws IOException {
// fileName is the name of the attachment on the document
// The goal is to return a NEW BLANK document with the image on it
// The Calling code can then deal with keys and meta data.
// size is "Original", "Large" or "Small"
System.out.println("Processing Image, Size = " + size);
//System.out.println("Filename = " + fileName);
boolean result = false;
Session session = Factory.getSession();
Database db = session.getCurrentDatabase();
session.setConvertMime(true);
BufferedImage img;
BufferedImage convertedImage = null; // the output image
EmbeddedObject image = null;
InputStream imageStream = null;
int currentSize = 0;
int newWidth = 0;
String currentName = "";
try {
// Get the Embedded Object
image = inputDoc.getAttachment(fileName);
System.out.println("Input Form : " + inputDoc.getItemValueString("form"));
if (null == image) {
System.out.println("ALERT - IMAGE IS NULL");
}
currentSize = image.getFileSize();
currentName = image.getName();
// Get a Stream of the Imahe
imageStream = image.getInputStream();
img = ImageIO.read(imageStream); // this is the buffered image we'll work with
imageStream.close();
Document newDoc = db.createDocument();
// Remember this is a BLANK document. The calling code needs to set the form
if ("original".equalsIgnoreCase(size)) {
this.attachImage(newDoc, img, fileName, "JPG");
return newDoc;
}
if ("Large".equalsIgnoreCase(size)) {
// Now we need to convert the LARGE image
// We're assuming FIXED HEIGHT of 600px
newWidth = this.getNewWidth(img.getHeight(), img.getWidth(), 600);
convertedImage = this.getScaledInstance(img, newWidth, 600, false);
this.attachImage(newDoc, img, fileName, "JPG");
return newDoc;
}
if ("Small".equalsIgnoreCase(size)) {
System.out.println("converting Small");
newWidth = this.getNewWidth(img.getHeight(), img.getWidth(), 240);
convertedImage = this.getScaledInstance(img, newWidth, 240, false);
this.attachImage(newDoc, img, fileName, "JPG");
System.out.println("End Converting Small");
return newDoc;
}
return newDoc;
} catch (Exception e) {
// HANDLE EXCEPTION HERE
// SAMLPLE WRITE TO LOG.NSF
System.out.println("****************");
System.out.println("EXCEPTION IN processImage()");
System.out.println("****************");
System.out.println("picName: " + fileName);
e.printStackTrace();
return null;
} finally {
if (null != imageStream) {
imageStream.close();
}
if (null != image) {
LibraryUtils.incinerate(image);
}
}
}
I believe it will be some variation of the following code snippet. You might have to change which mimeentity has the content so it might be in the parent or another child depending.
Stream stream = session.createStream();
doc.getMIMEEntity().getFirstChildEntity().getContentAsBytes(stream);
ByteArrayInputStream bais = new ByteArrayInputStream(stream.read());
return ImageIO.read(bais);
EDIT:
session.setConvertMime(false);
Stream stream = session.createStream();
Item itm = doc.getFirstItem("ParentEntity");
MIMEEntity me = itm.getMIMEEntity();
MIMEEntity childEntity = me.getFirstChildEntity();
childEntity.getContentAsBytes(stream);
ByteArrayOutputStream bo = new ByteArrayOutputStream();
stream.getContents(bo);
byte[] mybytearray = bo.toByteArray();
ByteArrayInputStream bais = new ByteArrayInputStream(mybytearray);
return ImageIO.read(bais);
David have a look at DominoDocument,http://public.dhe.ibm.com/software/dw/lotus/Domino-Designer/JavaDocs/XPagesExtAPI/8.5.2/com/ibm/xsp/model/domino/wrapped/DominoDocument.html
There you can wrap every Notes document
In the DominoDocument, there such as DominoDocument.AttachmentValueHolder where you can access the attachments.
I have explained it at Engage. It very powerful
http://www.slideshare.net/flinden68/engage-use-notes-objects-in-memory-and-other-useful-java-tips-for-x-pages-development
I currently am creating a program (with Java) that imports images and then creates a .gif with these images.
Most of my images have a transparent background with the alpha set at 0.
My current problem is after I have a series of 8 images converted to one .gif they bleed over each other. In other words the .gif does not repaint over the image before painting the next frame. So for example, if there is an apple fall from the tree, it will look like a red streak until the .gif loops.
I consider myself to be getting pretty savvy with Java but the script I found while searching the archives of the internet is way out of my league. Consider none of my 8 Java books cover IIOMETANODE. And resources on the internet are limited. So I'm not sure what the capabilities of iio are.
Here is the script:
import javax.imageio.*;
import javax.imageio.metadata.*;
import javax.imageio.stream.*;
import java.awt.image.*;
import java.io.*;
import java.util.Iterator;
public class GifCreator {
private ImageWriter gifWriter;
private ImageWriteParam imageWriteParam;
private IIOMetadata imageMetaData;
public GifCreator(){}
/**
* Creates a new GifSequenceWriter
*
* #param output the ImageOutputStream to be written to
* #param imgType one of the imageTypes specified in BufferedImage
* #param frameTime the time between frames in miliseconds
* #param loop wether the gif should loop repeatedly
* #throws IIOException if no gif ImageWriters are found
*
*/
public GifCreator(ImageOutputStream output, int imgType, int frameTime, boolean loop)
{
try {
gifWriter = getWriter();
imageWriteParam = gifWriter.getDefaultWriteParam();
ImageTypeSpecifier imageTypeSpecifier = ImageTypeSpecifier.createFromBufferedImageType(imgType);
imageMetaData = gifWriter.getDefaultImageMetadata(imageTypeSpecifier, imageWriteParam);
String metaFormatName = imageMetaData.getNativeMetadataFormatName();
IIOMetadataNode root = (IIOMetadataNode) imageMetaData.getAsTree(metaFormatName);
IIOMetadataNode graphicsControlExtensionNode = getNode(root, "GraphicControlExtension");
graphicsControlExtensionNode.setAttribute("disposalMethod", "none");
graphicsControlExtensionNode.setAttribute("userInputFlag", "FALSE");
graphicsControlExtensionNode.setAttribute("transparentColorFlag", "FALSE");
graphicsControlExtensionNode.setAttribute("delayTime", Integer.toString(frameTime / 10));
graphicsControlExtensionNode.setAttribute("transparentColorIndex", "0");
IIOMetadataNode appEntensionsNode = getNode(root, "ApplicationExtensions");
IIOMetadataNode child = new IIOMetadataNode("ApplicationExtension");
child.setAttribute("applicationID", "NETSCAPE");
child.setAttribute("authenticationCode", "2.0");
int aLoop = loop ? 0 : 1;
child.setUserObject(new byte[]{ 0x1, (byte) (aLoop & 0xFF), (byte) ((aLoop >> 8) & 0xFF)});
appEntensionsNode.appendChild(child);
imageMetaData.setFromTree(metaFormatName, root);
gifWriter.setOutput(output);
gifWriter.prepareWriteSequence(null);
} catch (Exception e) {
e.printStackTrace();
}
}
private void writeToSequence(RenderedImage img) throws IOException
{
gifWriter.writeToSequence(new IIOImage(img, null, imageMetaData), imageWriteParam);
}
/**
* Close this GifSequenceWriter object. This does not close the underlying
* stream, just finishes off the GIF.
*/
public void close() throws IOException
{
gifWriter.endWriteSequence();
}
/**
* Returns the first available GIF ImageWriter using
* ImageIO.getImageWritersBySuffix("gif").
*
* #return a GIF ImageWriter object
* #throws IIOException if no GIF image writers are returned
*/
private static ImageWriter getWriter() throws IIOException
{
Iterator<ImageWriter> iter = ImageIO.getImageWritersBySuffix("gif");
if (!iter.hasNext()) {
throw new IIOException("No GIF Image Writers Exist");
} else {
return iter.next();
}
}
/**
* Returns an existing child node, or creates and returns a new child node (if
* the requested node does not exist).
*
* #param rootNode the <tt>IIOMetadataNode</tt> to search for the child node.
* #param nodeName the name of the child node.
*
* #return the child node, if found or a new node created with the given name.
*/
private static IIOMetadataNode getNode(IIOMetadataNode rootNode, String nodeName)
{
int nNodes = rootNode.getLength();
for (int i = 0; i < nNodes; i++) {
if (rootNode.item(i).getNodeName().compareToIgnoreCase(nodeName) == 0)
return((IIOMetadataNode) rootNode.item(i));
}
IIOMetadataNode node = new IIOMetadataNode(nodeName);
rootNode.appendChild(node);
return(node);
}
public GifCreator(BufferedImage[] imgs, String path)
{
if (imgs.length <= 1)
return;
// Grabs the first BufferedImage from the array.
BufferedImage first = imgs[0];
try {
// Creates a new BufferedOutputStream with the incoming path.
ImageOutputStream output = new FileImageOutputStream(new File(path));
// Creates a gif sequence with the type of the first image, .1 second
// between frames, which loops continuously
GifCreator writer = new GifCreator(output, first.getType(), 100, true);
// write out the first image to our sequence...
writer.writeToSequence((RenderedImage) first);
for (int i = 1; i < imgs.length; i++) {
BufferedImage next = imgs[i];
writer.writeToSequence(next);
}
writer.close();
output.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Once again I'm trying to change the .gif from bleeding images together. I attempted to create a buffer BufferedImage in between but that was a failure.
Basically, you need to change the disposalMethod...
graphicsControlExtensionNode.setAttribute("disposalMethod", "restoreToBackgroundColor");
graphicsControlExtensionNode.setAttribute("userInputFlag", "FALSE");
graphicsControlExtensionNode.setAttribute(
"transparentColorFlag",
"TRUE");
Assuming that each image you are adding is a complete image and to an optimised "addition" to the image
Take a look at GIF Animation and Disposal Methods for some more details and if you're really adventurous, the GIF specification and Image :: Java Animated GIFs (with transparant pixel disposal modes) which lists the possible disposal methods, so you can have a play around and see what works...
I am attempting to display a .tif in Java using a minimal number of additional libraries:
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.WindowConstants;
import javax.media.jai.widget.*;
import it.geosolutions.imageio.utilities.*;
import it.geosolutions.imageioimpl.plugins.tiff.*;
import com.sun.media.imageioimpl.common.*;
public static void main(String[] args) {
try {
File f = new File("image.tif");
BufferedImage tif = ImageIO.read(f);
ImageIcon ic = new ImageIcon(tif);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JLabel label = new JLabel(ic);
frame.add(label);
frame.setVisible(true);
} catch (IOException e) {
e.printStackTrace();
}
}
The libraries I'm using are:
jai-core-1.1.3.jar
jai-imageio-1.1.jar
imageio-ext-tiff.1.1.3.jar
imageio-ext-utilities.1.1.3.jar
From here: http://java.net/projects/imageio-ext (Downloads link on right side)
However, the displayed image is:
which is decidedly not the original image. Nor are any errors being thrown that I know of. Furthermore, the original image is fine, and doesn't change.
However, the original code is small. I don't actually use the imageio-ext imports, but the program will fail without them. I also haven't used imageio-ext before either.
Please help! I need to be able to use .tif images in Java without installing software.
If you already use all JAI/ImageIO libraries, you might want to try the following (which works fine for me):
import com.sun.media.jai.codec.FileSeekableStream;
import com.sun.media.jai.codec.ImageCodec;
import com.sun.media.jai.codec.ImageDecoder;
// This function is minimal, you should add exceptions and error handling
public RenderedImage read(String filename)
FileSeekableStream fss = new FileSeekableStream(filename);
ImageDecoder decoder = ImageCodec.createImageDecoder("tiff", fss, null);
RenderedImage image = decoder.decodeAsRenderedImage()
fss.close();
return image;
}
If you need a BufferedImage instead of a RenderedImage, the only solution I found is to use this function:
public static BufferedImage Rendered2Buffered(RenderedImage image) {
BufferedImage bi = new BufferedImage(image.getWidth(), image.getHeight(), image.getSampleModel().getDataType());
bi.setData(image.getData());
return bi;
}
Be careful though, the image.getSampleModel().getDataType() usually returns a BufferedImage.TYPE_CUSTOM, which makes it impossible for the BufferedImage to be created! In my case I had to "guess" the type according to the sample size returned by image.getSampleModel().getSampleSize(0) (because I know the image format I'm working with).
If you know a better way to transform a RenderedImage to a BufferedImage, please enlighten me :)
You're correct in thinking that you need the JAI libraries to decode and use TIFF files, but even though you've imported them, you aren't actually using them!
Here is a short tutorial showing how you to create a TIFFDecodeParam object (from the JAI library), and then use that to decode (and display) a TIFF image.
You might also find the JAI API Library useful too.
I ended up going with the most-recent version of Apache-Commons Imaging (formerly Sanselan). Imaging offers out of the box support for TIFF files (I had as little bit of trouble at first, but that was solved by switching from the older Sanselan to the newer Commons Imaging).
There was a little bit of functionality I had to reverse-engineer myself (loading a single sub-TIFF at a specified width while maintaining aspect ratio):
/**
* Load a scaled sub-TIFF image. Loads nth sub-image and scales to given width; preserves aspect ratio.
*
* #param fileName String filename
* #param index Index of sub-TIFF; will throw ArrayIndexOutOfBoundsException if sub-image doesn't exist
* #param w Desired width of image; height will scale
* #return Image (BufferedImage)
* #throws IOException
* #throws ImageReadException
*/
public static Image loadScaledSubTIFF(String fileName, int index, int w) throws IOException, ImageReadException {
File imageFile = new File(fileName);
ByteSourceFile bsf = new ByteSourceFile(imageFile);
FormatCompliance formatCompliance = FormatCompliance.getDefault();
TiffReader tiffReader = new TiffReader(true);
TiffContents contents = tiffReader.readDirectories(bsf, true, formatCompliance);
TiffDirectory td = contents.directories.get(index);
Image bi = td.getTiffImage(tiffReader.getByteOrder(), null);
Object width = td.getFieldValue(new TagInfo("", 256, TiffFieldTypeConstants.FIELD_TYPE_SHORT) {/**/});
Object height = td.getFieldValue(new TagInfo("", 257, TiffFieldTypeConstants.FIELD_TYPE_SHORT) {/**/});
int newWidth = w;
int newHeight = (int) ((newWidth * ((Number)height).doubleValue()) / (((Number)width).doubleValue()));
bi = bi.getScaledInstance(w, newHeight, java.awt.Image.SCALE_FAST);
height = null;
width = null;
td = null;
contents = null;
tiffReader = null;
formatCompliance = null;
bsf = null;
return bi;
}
I have a need to convert images from CMYK to RGB - not necessarily back again, but hey, if it can be done...
With the release of ColdFusion 8, we got the CFImage tag, but it doesn't support this conversion; and nor does Image.cfc, or Alagad's Image Component.
However, it should be possible in Java; which we can leverage through CF. For example, here's how you might create a Java thread to sleep a process:
<cfset jthread = createObject("java", "java.lang.Thread")/>
<cfset jthread.sleep(5000)/>
I would guess a similar method could be used to leverage java to do this image conversion, but not being a Java developer, I don't have a clue where to start. Can anyone lend a hand here?
A very simple formula for converting from CMYK to RGB ignoring all color profiles is:
R = ( (255-C)*(255-K) ) / 255;
G = ( (255-M)*(255-K) ) / 255;
B = ( (255-Y)*(255-K) ) / 255;
This code requires CMYK values to be in rage of 0-255. If you have 0 to 100 or 0.0 to 1.0 you'll have to convert the values.
Hope this will get you started.
As for the java and ColdFusion interfacing, I'm sorry, but I have no idea how to do that.
I use the Java ImageIO libraries (https://jai-imageio.dev.java.net). They aren't perfect, but can be simple and get the job done. As far as converting from CMYK to RGB, here is the best I have been able to come up with.
Download and install the ImageIO JARs and native libraries for your platform. The native libraries are essential. Without them the ImageIO JAR files will not be able to detect the CMYK images. Originally, I was under the impression that the native libraries would improve performance but was not required for any functionality. I was wrong.
The only other thing that I noticed is that the converted RGB images are sometimes much lighter than the CMYK images. If anyone knows how to solve that problem, I would be appreciative.
Below is some code to convert a CMYK image into an RGB image of any supported format.
Thank you,
Randy Stegbauer
package cmyk;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import org.apache.commons.lang.StringUtils;
public class Main
{
/**
* Creates new RGB images from all the CMYK images passed
* in on the command line.
* The new filename generated is, for example "GIF_original_filename.gif".
*
*/
public static void main(String[] args)
{
for (int ii = 0; ii < args.length; ii++)
{
String filename = args[ii];
boolean cmyk = isCMYK(filename);
System.out.println(cmyk + ": " + filename);
if (cmyk)
{
try
{
String rgbFile = cmyk2rgb(filename);
System.out.println(isCMYK(rgbFile) + ": " + rgbFile);
}
catch (IOException e)
{
System.out.println(e.getMessage());
}
}
}
}
/**
* If 'filename' is a CMYK file, then convert the image into RGB,
* store it into a JPEG file, and return the new filename.
*
* #param filename
*/
private static String cmyk2rgb(String filename) throws IOException
{
// Change this format into any ImageIO supported format.
String format = "gif";
File imageFile = new File(filename);
String rgbFilename = filename;
BufferedImage image = ImageIO.read(imageFile);
if (image != null)
{
int colorSpaceType = image.getColorModel().getColorSpace().getType();
if (colorSpaceType == ColorSpace.TYPE_CMYK)
{
BufferedImage rgbImage =
new BufferedImage(
image.getWidth(), image.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
ColorConvertOp op = new ColorConvertOp(null);
op.filter(image, rgbImage);
rgbFilename = changeExtension(imageFile.getName(), format);
rgbFilename = new File(imageFile.getParent(), format + "_" + rgbFilename).getPath();
ImageIO.write(rgbImage, format, new File(rgbFilename));
}
}
return rgbFilename;
}
/**
* Change the extension of 'filename' to 'newExtension'.
*
* #param filename
* #param newExtension
* #return filename with new extension
*/
private static String changeExtension(String filename, String newExtension)
{
String result = filename;
if (filename != null && newExtension != null && newExtension.length() != 0);
{
int dot = filename.lastIndexOf('.');
if (dot != -1)
{
result = filename.substring(0, dot) + '.' + newExtension;
}
}
return result;
}
private static boolean isCMYK(String filename)
{
boolean result = false;
BufferedImage img = null;
try
{
img = ImageIO.read(new File(filename));
}
catch (IOException e)
{
System.out.println(e.getMessage() + ": " + filename);
}
if (img != null)
{
int colorSpaceType = img.getColorModel().getColorSpace().getType();
result = colorSpaceType == ColorSpace.TYPE_CMYK;
}
return result;
}
}
The tag cfx_image may be of use to you. I haven't used it in a while but I remember it had a ton of features.
Alternatively, you might be able to script a windows app such as Irfanview (via commandline using cfexecute) to process images.
Hope that helps
I know that this question is old, but I still encounter problems with CMYK images & ColdFusion. However, I just read a CMYK JPEG image using ColdFusion 10 and resaved it. The saved image was able to to be read using ColdFusion 9 (which is only capable of reading RGB JPEGs.) I'm not sure if this conversion is intentional or not and I don't currently have any way of identifying whether the source image's color profile is CMYK or not as the saved color profile still appears to be the same.
<cfset imgData = ImageRead(expandPath("./CMYK_image.jpg"))>
<cfset ImageWrite(imgData, expandPath("./Saved_image.jpg"))>