Java tutorial
/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is part of dcm4che, an implementation of DICOM(TM) in * Java(TM), hosted at https://github.com/gunterze/dcm4che. * * The Initial Developer of the Original Code is * Agfa Healthcare. * Portions created by the Initial Developer are Copyright (C) 2013 * the Initial Developer. All Rights Reserved. * * Contributor(s): * See @authors listed below * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ package org.dcm4che.tool.dcm2jpg; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.io.File; import java.io.IOException; import java.text.MessageFormat; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.ResourceBundle; import javax.imageio.IIOImage; import javax.imageio.ImageIO; import javax.imageio.ImageReadParam; import javax.imageio.ImageReader; import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; import javax.imageio.stream.ImageInputStream; import javax.imageio.stream.ImageOutputStream; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.OptionBuilder; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.apache.commons.cli.PatternOptionBuilder; import org.dcm4che.data.Attributes; import org.dcm4che.image.PaletteColorModel; import org.dcm4che.imageio.plugins.dcm.DicomImageReadParam; import org.dcm4che.io.DicomInputStream; import org.dcm4che.tool.common.CLIUtils; import org.dcm4che.util.SafeClose; /** * @author Gunter Zeilinger <gunterze@gmail.com> */ public class Dcm2Jpg { private static ResourceBundle rb = ResourceBundle.getBundle("org.dcm4che.tool.dcm2jpg.messages"); private String suffix; private int frame = 1; private int windowIndex; private int voiLUTIndex; private boolean preferWindow = true; private float windowCenter; private float windowWidth; private boolean autoWindowing = true; private Attributes prState; private final ImageReader imageReader = ImageIO.getImageReadersByFormatName("DICOM").next(); private ImageWriter imageWriter; private ImageWriteParam imageWriteParam; private int overlayActivationMask = 0xffff; private int overlayGrayscaleValue = 0xffff; public void initImageWriter(String formatName, String suffix, String clazz, String compressionType, Number quality) { Iterator<ImageWriter> imageWriters = ImageIO.getImageWritersByFormatName(formatName); if (!imageWriters.hasNext()) throw new IllegalArgumentException( MessageFormat.format(rb.getString("formatNotSupported"), formatName)); this.suffix = suffix != null ? suffix : formatName.toLowerCase(); imageWriter = imageWriters.next(); if (clazz != null) while (!clazz.equals(imageWriter.getClass().getName())) if (imageWriters.hasNext()) imageWriter = imageWriters.next(); else throw new IllegalArgumentException( MessageFormat.format(rb.getString("noSuchImageWriter"), clazz, formatName)); imageWriteParam = imageWriter.getDefaultWriteParam(); if (compressionType != null || quality != null) { imageWriteParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); if (compressionType != null) imageWriteParam.setCompressionType(compressionType); if (quality != null) imageWriteParam.setCompressionQuality(quality.floatValue()); } } public final void setFrame(int frame) { this.frame = frame; } public final void setWindowCenter(float windowCenter) { this.windowCenter = windowCenter; } public final void setWindowWidth(float windowWidth) { this.windowWidth = windowWidth; } public final void setWindowIndex(int windowIndex) { this.windowIndex = windowIndex; } public final void setVOILUTIndex(int voiLUTIndex) { this.voiLUTIndex = voiLUTIndex; } public final void setPreferWindow(boolean preferWindow) { this.preferWindow = preferWindow; } public final void setAutoWindowing(boolean autoWindowing) { this.autoWindowing = autoWindowing; } public final void setPresentationState(Attributes prState) { this.prState = prState; } public void setOverlayActivationMask(int overlayActivationMask) { this.overlayActivationMask = overlayActivationMask; } public void setOverlayGrayscaleValue(int overlayGrayscaleValue) { this.overlayGrayscaleValue = overlayGrayscaleValue; } @SuppressWarnings("static-access") private static CommandLine parseComandLine(String[] args) throws ParseException { Options opts = new Options(); CLIUtils.addCommonOptions(opts); opts.addOption( OptionBuilder.hasArg().withArgName("format").withDescription(rb.getString("format")).create("F")); opts.addOption( OptionBuilder.hasArg().withArgName("class").withDescription(rb.getString("encoder")).create("E")); opts.addOption(OptionBuilder.hasArg().withArgName("type").withDescription(rb.getString("compression")) .create("C")); opts.addOption(OptionBuilder.hasArg().withArgName("quality").withType(PatternOptionBuilder.NUMBER_VALUE) .withDescription(rb.getString("quality")).create("q")); opts.addOption(OptionBuilder.hasArg().withArgName("suffix").withDescription(rb.getString("suffix")) .withLongOpt("suffix").create()); opts.addOption(OptionBuilder.hasArg().withArgName("number").withType(PatternOptionBuilder.NUMBER_VALUE) .withDescription(rb.getString("frame")).withLongOpt("frame").create()); opts.addOption(OptionBuilder.hasArg().withArgName("center").withType(PatternOptionBuilder.NUMBER_VALUE) .withDescription(rb.getString("windowCenter")).withLongOpt("windowCenter").create("c")); opts.addOption(OptionBuilder.hasArg().withArgName("width").withType(PatternOptionBuilder.NUMBER_VALUE) .withDescription(rb.getString("windowWidth")).withLongOpt("windowWidth").create("w")); opts.addOption(OptionBuilder.hasArg().withArgName("number").withType(PatternOptionBuilder.NUMBER_VALUE) .withDescription(rb.getString("window")).withLongOpt("window").create()); opts.addOption(OptionBuilder.hasArg().withArgName("number").withType(PatternOptionBuilder.NUMBER_VALUE) .withDescription(rb.getString("voilut")).withLongOpt("voilut").create()); opts.addOption(OptionBuilder.hasArg().withArgName("file").withType(PatternOptionBuilder.EXISTING_FILE_VALUE) .withDescription(rb.getString("ps")).withLongOpt("ps").create()); opts.addOption(OptionBuilder.hasArg().withArgName("mask").withDescription(rb.getString("overlays")) .withLongOpt("overlays").create()); opts.addOption(OptionBuilder.hasArg().withArgName("value").withDescription(rb.getString("ovlygray")) .withLongOpt("ovlygray").create()); opts.addOption(null, "uselut", false, rb.getString("uselut")); opts.addOption(null, "noauto", false, rb.getString("noauto")); opts.addOption(null, "lsE", false, rb.getString("lsencoders")); opts.addOption(null, "lsF", false, rb.getString("lsformats")); CommandLine cl = CLIUtils.parseComandLine(args, opts, rb, Dcm2Jpg.class); if (cl.hasOption("lsF")) { listSupportedFormats(); System.exit(0); } if (cl.hasOption("lsE")) { listSupportedImageWriters(cl.getOptionValue("F", "JPEG")); System.exit(0); } return cl; } public static void main(String[] args) { try { CommandLine cl = parseComandLine(args); Dcm2Jpg main = new Dcm2Jpg(); main.initImageWriter(cl.getOptionValue("F", "JPEG"), cl.getOptionValue("suffix"), cl.getOptionValue("E"), cl.getOptionValue("C"), (Number) cl.getParsedOptionValue("q")); if (cl.hasOption("frame")) main.setFrame(((Number) cl.getParsedOptionValue("frame")).intValue()); if (cl.hasOption("c")) main.setWindowCenter(((Number) cl.getParsedOptionValue("c")).floatValue()); if (cl.hasOption("w")) main.setWindowWidth(((Number) cl.getParsedOptionValue("w")).floatValue()); if (cl.hasOption("window")) main.setWindowIndex(((Number) cl.getParsedOptionValue("window")).intValue() - 1); if (cl.hasOption("voilut")) main.setVOILUTIndex(((Number) cl.getParsedOptionValue("voilut")).intValue() - 1); if (cl.hasOption("overlays")) main.setOverlayActivationMask(parseHex(cl.getOptionValue("overlays"))); if (cl.hasOption("ovlygray")) main.setOverlayGrayscaleValue(parseHex(cl.getOptionValue("ovlygray"))); main.setPreferWindow(!cl.hasOption("uselut")); main.setAutoWindowing(!cl.hasOption("noauto")); main.setPresentationState(loadDicomObject((File) cl.getParsedOptionValue("ps"))); @SuppressWarnings("unchecked") final List<String> argList = cl.getArgList(); int argc = argList.size(); if (argc < 2) throw new ParseException(rb.getString("missing")); File dest = new File(argList.get(argc - 1)); if ((argc > 2 || new File(argList.get(0)).isDirectory()) && !dest.isDirectory()) throw new ParseException(MessageFormat.format(rb.getString("nodestdir"), dest)); for (String src : argList.subList(0, argc - 1)) main.mconvert(new File(src), dest); } catch (ParseException e) { System.err.println("dcm2jpg: " + e.getMessage()); System.err.println(rb.getString("try")); System.exit(2); } catch (Exception e) { System.err.println("dcm2jpg: " + e.getMessage()); e.printStackTrace(); System.exit(2); } } private static int parseHex(String s) throws ParseException { try { return Integer.parseInt(s, 16); } catch (NumberFormatException e) { throw new ParseException(e.getMessage()); } } private void mconvert(File src, File dest) { if (src.isDirectory()) { dest.mkdir(); for (File file : src.listFiles()) mconvert(file, new File(dest, file.isFile() ? suffix(file) : file.getName())); return; } if (dest.isDirectory()) dest = new File(dest, suffix(src)); try { convert(src, dest); System.out.println(MessageFormat.format(rb.getString("converted"), src, dest)); } catch (Exception e) { System.out.println(MessageFormat.format(rb.getString("failed"), src, e.getMessage())); e.printStackTrace(System.out); } } public void convert(File src, File dest) throws IOException { ImageInputStream iis = ImageIO.createImageInputStream(src); try { BufferedImage bi = readImage(iis); bi = convert(bi); dest.delete(); ImageOutputStream ios = ImageIO.createImageOutputStream(dest); try { writeImage(ios, bi); } finally { try { ios.close(); } catch (IOException ignore) { } } } finally { try { iis.close(); } catch (IOException ignore) { } } } private BufferedImage convert(BufferedImage bi) { ColorModel cm = bi.getColorModel(); if (cm instanceof PaletteColorModel) return ((PaletteColorModel) cm).convertToIntDiscrete(bi.getData()); return bi; } private BufferedImage readImage(ImageInputStream iis) throws IOException { imageReader.setInput(iis); return imageReader.read(frame - 1, readParam()); } private ImageReadParam readParam() { DicomImageReadParam param = (DicomImageReadParam) imageReader.getDefaultReadParam(); param.setWindowCenter(windowCenter); param.setWindowWidth(windowWidth); param.setAutoWindowing(autoWindowing); param.setWindowIndex(windowIndex); param.setVOILUTIndex(voiLUTIndex); param.setPreferWindow(preferWindow); param.setPresentationState(prState); param.setOverlayActivationMask(overlayActivationMask); param.setOverlayGrayscaleValue(overlayGrayscaleValue); return param; } private void writeImage(ImageOutputStream ios, BufferedImage bi) throws IOException { imageWriter.setOutput(ios); imageWriter.write(null, new IIOImage(bi, null, null), imageWriteParam); } private String suffix(File src) { return src.getName() + '.' + suffix; } private static Attributes loadDicomObject(File f) throws IOException { if (f == null) return null; DicomInputStream dis = new DicomInputStream(f); try { return dis.readDataset(-1, -1); } finally { SafeClose.close(dis); } } public static void listSupportedImageWriters(String format) { System.out.println(MessageFormat.format(rb.getString("writers"), format)); Iterator<ImageWriter> it = ImageIO.getImageWritersByFormatName(format); while (it.hasNext()) { ImageWriter writer = it.next(); ImageWriteParam param = writer.getDefaultWriteParam(); System.out.println(MessageFormat.format(rb.getString("writer"), writer.getClass().getName(), param.canWriteCompressed(), param.canWriteProgressive(), param.canWriteTiles(), param.canOffsetTiles(), param.canWriteCompressed() ? Arrays.toString(param.getCompressionTypes()) : null)); } } public static void listSupportedFormats() { System.out.println( MessageFormat.format(rb.getString("formats"), Arrays.toString(ImageIO.getWriterFormatNames()))); } }