I'm trying to convert a DICOM image in jpeg2000 using imageio as in the below code, the same procedure is explained in oracle documentation, but doesn't work! I don't understand what I'm doing wrong. The Java Advanced Image I/O library is installed into the JRE.
Using: ImageIO.getReaderFormatNames() and ImageIO.getWriterFormatNames() it can be verified that DICOM and JPEG2000 are supported!
There are no errors thrown, but it takes too long to write the file, and the output file is corrupted.
Thank you in advance...
public void convert2JPEG(File sourceFileName) throws IOException{
Iterator<ImageReader> iter = ImageIO.getImageReadersByFormatName("DICOM");
ImageReader reader = iter.next();
if(reader == null) {
log.error("Could not locate any Readers for the DICOM format image.");
return;
}
File sourceFile = new File (sourceFileName);
ImageInputStream iis = ImageIO.createImageInputStream(sourceFile);
BufferedImage bi;
try{
bi = ImageIO.read(iis);
File outputFile = new File("outputFileName");
String format = "jpeg 2000";
ImageIO.write(bi, format, outputFile);
} catch(Exception e){
log.info("ERROR: " + e);
}finally {
iis.close();
}
}
JAI Image IO does not support DICOM to my knowledge, but does support JPEG2000. Do note that there is no Windows 64-bit version of JAI (that may be an issue for you too). I am surprised it is not giving any kind of error.
However, I agree with Anders that the best course for converting DICOM would be to use a toolkit. I'd suggest DCM4CHE2 (http://www.dcm4che.org/confluence/display/d2/dcm4che2+DICOM+Toolkit). They have a number of command line tools for doing exactly what you are suggesting, and Dicom[Input/Output]Stream classes for reading and writing DICOM.
Related
I got a strange issue with a GIF image in Java. The image is provided by an XML API as Base64 encoded string. To decode the Base64, I use the commons-codec library in version 1.13.
When I just decode the Base64 string and write the bytes out to a file, the image shows properly in browsers and MS Paint (nothing else to test here).
final String base64Gif = "[Base64 as provided by API]";
final byte[] sigImg = Base64.decodeBase64(base64Gif);
File sigGif = new File("C:/Temp/pod_1Z12345E5991872040.org.gif");
try (FileOutputStream fos = new FileOutputStream()) {
fos.write(sigImg);
fos.flush();
}
The resulting file opened in MS Paint:
But when I now start consuming this file using Java (for example creating a PDF document from HTML using the openhtmltopdf library), it is corrupted and does not show properly.
final String htmlLetterStr = "[HTML as provided by API]";
final Document doc = Jsoup.parse(htmlLetterStr);
try (FileOutputStream fos = new FileOutputStream(new File("C:/Temp/letter_1Z12345E5991872040.pdf"))) {
PdfRendererBuilder builder = new PdfRendererBuilder();
builder.useFastMode();
builder.withW3cDocument(new W3CDom().fromJsoup(doc), "file:///C:/Temp/");
builder.toStream(fos);
builder.useDefaultPageSize(210, 297, BaseRendererBuilder.PageSizeUnits.MM);
builder.run();
fos.flush();
}
When I now open the resulting PDF, the image created above looks like this. It seems that only the first pixel lines are printed, some layer is missing, or something like that.
The same happens, if I read the image again with ImageIO and try to convert it into PNG. The resulting PNG looks exactly the same as the image printed in the PDF document.
How can I get the image to display properly in the PDF document?
Edit:
Link to original GIF Base64 as provided by API: https://pastebin.com/sYJv6j0h
As #haraldK pointed out in the comments, the GIF file provided via the XML API does not conform to the GIF standard and thus cannot be parsed by Java's ImageIO API.
Since there does not seem to exist a pure Java tool to repair the file, the workaround I came up with now is to use ImageMagick via Java's Process API. Calling the convert command with the -coalesce option will parse the broken GIF and create a new one that does conform to the GIF standard.
// Decode broken GIF image and write to disk
final String base64Gif = "[Base64 as provided by API]";
final byte[] sigImg = Base64.decodeBase64(base64Gif);
Path gifPath = Paths.get("C:/Temp/pod_1Z12345E5991872040.tmp.gif");
if (!Files.exists(gifPath)) {
Files.createFile(gifPath);
}
Files.write(gifPath, sigImg, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING);
// Use the Java Process API to call ImageMagick (on Linux you would use the 'convert' binary)
ProcessBuilder procBuild = new ProcessBuilder();
procBuild.command("C:\\Program Files\\ImageMagick-7.0.9-Q16\\magick.exe", "C:\\Temp\\pod_1Z12345E5991872040.tmp.gif", "-coalesce", "C:\\Temp\\pod_1Z12345E5991872040.gif");
Process proc = procBuild.start();
// Wait for ImageMagick to complete its work
proc.waitFor();
The newly created file can be read by Java's ImageIO API and be used as expected.
I need to display the 3rd page of scanned tiff files. i used the code
TIFFReader reader = new TIFFReader(new File(pathOfFile));
RenderedImage image = reader.getPage(2);
its sometimes work. and show error : Decoding of old style JPEG-in-TIFF data is not supported.
I used aspriseTIFF.jar
then how i solve this problem.
please reply.
thanks in advance
The problem you have run into is that "old style" JPEG compression in the TIFF format (compression == 6), is not supported in the library you use.
This is quite common I guess, as "old-style" JPEG compression is deprecated in TIFF, because it was never fully specified. And because of this under-specification, various vendors implemented it in different, incompatible ways. Support was dropped in favor for TIFF compression 7, JPEG.
Unfortunately, old TIFF files using this compression still exists, so you need to find another library. The good news is that you can use ImageIO and a proper plug-in.
Using a TIFF ImageReader plug-in, like the one from my TwelveMonkeys ImageIO open source project, you should be able to do this:
// Create input stream
try (ImageInputStream input = ImageIO.createImageInputStream(file)) {
// Get the reader
ImageReader reader = ImageIO.getImageReaders(input).next();
try {
reader.setInput(input);
// Read page 2 of the TIFF file
BufferedImage image = reader.read(2, null);
}
finally {
reader.dispose();
}
}
(sorry about the try/finally boiler-plate, but it is important to avoid resource/memory leaks).
DicomDroid.jar used to open a .dcm formated image in my Android application. I got the follwing exception when try to open it.
java.io.IOException: DICOM JPEG compression not yet supported
Adding my code below
try {
// Read the imagefile into a byte array (data[])
File imagefile = new File(path);
byte[] data = new byte[(int) imagefile.length()];
FileInputStream fis = new FileInputStream(imagefile);
fis.read(data);
fis.close();
// Create a DicomReader with the given data array (data[])
DicomReader DR = new DicomReader(data);
} catch (Exception ex) {
Log.e("ERROR", ex.toString());
}
What can be done to avoid this error?
Thanks in advance.
The cause is pretty obvious. That DICOM library doesn't support that particular kind of DICOM file.
There's not much you can do about it ... unless you are prepared to enhance the library yourself.
But I think you have probably made a mistake in setting up your instrument to generate DICOM files with JPEG compression. JPEG is lossy, and best practice is to capture and store images with the best resolution feasible. If you need to downgrade resolution to reduce bandwidth, it would be better to
save a high resolution DICOM,
convert the DICOM to a low resolution JPG, and
send the JPEG.
Another option is to get the Dicom file in an uncompressed format (ej: Explicit VR Little Endian). This is the simplest dicom file format and every dicom library has support for such format.
So, when you get your Dicom file from your PACS, force this transfer syntax. This way, your dicom library will be able to deal with the image file.
is there any libraries to convert SVG to JPG ? else than BATIK ?
i used BATIK but i found some problems like this exception :
java.lang.NullPointerException
at org.apache.batik.css.engine.CSSEngine.getCascadedStyleMap(CSSEngine.java:684)
at org.apache.batik.css.engine.CSSEngine.getComputedStyle(CSSEngine.java:755)
at org.apache.batik.bridge.CSSUtilities.getComputedStyle(CSSUtilities.java:96)
at org.apache.batik.bridge.CSSUtilities.convertDisplay(CSSUtilities.java:509)
at org.apache.batik.bridge.GVTBuilder.buildGraphicsNode(GVTBuilder.java:176)
at org.apache.batik.bridge.GVTBuilder.buildComposite(GVTBuilder.java:148)
at org.apache.batik.bridge.GVTBuilder.build(GVTBuilder.java:76)
at org.apache.batik.transcoder.SVGAbstractTranscoder.transcode(SVGAbstractTranscoder.java:165)
at org.apache.batik.transcoder.image.ImageTranscoder.transcode(ImageTranscoder.java:86)
at org.apache.batik.transcoder.XMLAbstractTranscoder.transcode(XMLAbstractTranscoder.java:132)
this is my code :
JPEGTranscoder transcoder = new JPEGTranscoder();
transcoder.addTranscodingHint(JPEGTranscoder.KEY_XML_PARSER_CLASSNAME,
"org.apache.crimson.parser.XMLReaderImpl");
transcoder.addTranscodingHint(JPEGTranscoder.KEY_QUALITY,
new Float(1.0));
TranscoderInput input = new TranscoderInput(new FileInputStream("C:/Taha/SmartPlannerNew/rectangles.svg"));
OutputStream ostream = new FileOutputStream("C:/Taha/SmartPlannerNew/out.jpg");
TranscoderOutput output = new TranscoderOutput(ostream);
try {
transcoder.transcode(input, output);
} catch (TranscoderException e) {
System.out.println("error***************************************************************************************************************************");
e.printStackTrace();
}
System.out.println("done.");
ostream.close();
System.exit(0);
can any one help me please ?
Batik is exactly what you are looking for, is totally stable, and there really is not much else.
You can read the handy official tutorial on using the transcoder portion of batik:
http://xmlgraphics.apache.org/batik/using/transcoder.html
If you are still having trouble, try posting the code that you are using that causes the error, and a complete stack trace. Somebody here will be able to help you.
my mistake was that i was using different versions of jar files i deleted all my jars and downloaded a new set of jars from the same
I am using JAI and create a file with:
PlanarImage img = JAI.create("fileload", myFilename);
I check before that line if the file exists. But how could I check if the file is a .bmp or a .tiff or an image file?
Does anyone know?
The Image Magick project has facilities to identify image and there's a Java wrapper for Image Magick called JMagick which I think you may want to consider instead of reinventing the wheel:
http://www.jmagick.org
I'm using Image Magick all the time, including its "identify" feature from the command line and it never failed once to identify a picture.
Back in the days where I absolutely needed that feature and JMagick didn't exist yet I used to Runtime.exec() ImageMagick's identify command from Java and it worked perfectly.
Nowadays that JMagick exist this is probably not necessary anymore (but I haven't tried JMagick yet).
Note that it gives much more than just the format, for example:
$ identify tmp3.jpg
tmp3.jpg JPEG 1680x1050 1680x1050+0+0 DirectClass 8-bit 293.582kb
$ identify tmp.png
tmp.png PNG 1012x900 1012x900+0+0 DirectClass 8-bit 475.119kb
Try using the width of the image:
boolean isImage(String image_path){
Image image = new ImageIcon(image_path).getImage();
if(image.getWidth(null) == -1){
return false;
}
else{
return true;
}
}
if the width is -1 then is not image.
To tell if something is a png, I've used this below snippet in Android java.
public CompressFormat getCompressFormat(Context context, Uri fileUri) throws IOException {
// create input stream
int numRead;
byte[] signature = new byte[8];
byte[] pngIdBytes = { -119, 80, 78, 71, 13, 10, 26, 10 };
InputStream is = null;
try {
ContentResolver resolver = context.getContentResolver();
is = resolver.openInputStream(fileUri);
// if first 8 bytes are PNG then return PNG reader
numRead = is.read(signature);
if (numRead == -1)
throw new IOException("Trying to reda from 0 byte stream");
} finally {
if (is != null)
is.close();
}
if (numRead == 8 && Arrays.equals(signature, pngIdBytes)) {
return CompressFormat.PNG;
}
return null;
}
At the beginning of files, there is an identifying character sequence.
For example JPEG files starts with FF D8 FF.
You can check for this sequence in your program but I am not sure whether this works for every file.
For information about identifying characters you can have a look at http://filext.com
You could use DROID, a tool for file format identification that also offers a Java API, to be used roughly like this:
AnalysisController controller = new AnalysisController();
controller.readSigFile(signatureFileLocation);
controller.addFile(fileToIdentify.getAbsolutePath());
controller.runFileFormatAnalysis();
Iterator<IdentificationFile> it = controller.getFileCollection().getIterator();
Documentation on the API usage is rather sparse, but you can have a look at this working example (the interesting part is in the identifyOneBinary method).
The only (semi-)reliable way to determine the contents of a file is to open it and read the first few characters. Then you can use a set of tests such as implemented in the Unix file command to make an educated guess as to the contents of the file.
Expanding on Birkan's answer, there is a list of 'magic numbers' available here:
http://www.astro.keele.ac.uk/oldusers/rno/Computing/File_magic.html
I just checked a BMP and TIFF file (both just created in Windows XP / Paint), and they appear to be correct:
First two bytes "42 4d" -> BMP
First four bytes "4d 4d 00 2a" -> TIFF
I used VIM to edit the files and then did Tools | Convert to Hex, but you can also use 'od -c' or something similar to check them.
As a complete aside, I was slightly amused when I found out the magic numbers used for compiled Java Classes: 'ca fe ba be' - 'cafe babe' :)
Try using the standard JavaBeans Activation Framework (JAF)
With the JavaBeans Activation Framework standard extension, developers who use Java technology can take advantage of standard services to determine the type of an arbitrary piece of data, encapsulate access to it, discover the operations available on it, and to instantiate the appropriate bean to perform said operation(s). For example, if a browser obtained a JPEG image, this framework would enable the browser to identify that stream of data as an JPEG image, and from that type, the browser could locate and instantiate an object that could manipulate, or view that image.
if(currentImageType ==null){
ByteArrayInputStream is = new ByteArrayInputStream(image);
String mimeType = URLConnection.guessContentTypeFromStream(is);
if(mimeType == null){
AutoDetectParser parser = new AutoDetectParser();
Detector detector = parser.getDetector();
Metadata md = new Metadata();
mimeType = detector.detect(is,md).toString();
if (mimeType.contains("pdf")){
mimeType ="pdf";
}
else if(mimeType.contains("tif")||mimeType.contains("tiff")){
mimeType = "tif";
}
}
if(mimeType.contains("png")){
mimeType ="png";
}
else if( mimeType.contains("jpg")||mimeType.contains("jpeg")){
mimeType = "jpg";
}
else if (mimeType.contains("pdf")){
mimeType ="pdf";
}
else if(mimeType.contains("tif")||mimeType.contains("tiff")){
mimeType = "tif";
}
currentImageType = ImageType.fromValue(mimeType);
}