001/* ***** BEGIN LICENSE BLOCK ***** 002 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 003 * 004 * The contents of this file are subject to the Mozilla Public License Version 005 * 1.1 (the "License"); you may not use this file except in compliance with 006 * the License. You may obtain a copy of the License at 007 * http://www.mozilla.org/MPL/ 008 * 009 * Software distributed under the License is distributed on an "AS IS" basis, 010 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 011 * for the specific language governing rights and limitations under the 012 * License. 013 * 014 * The Original Code is part of dcm4che, an implementation of DICOM(TM) in 015 * Java(TM), hosted at https://github.com/gunterze/dcm4che. 016 * 017 * The Initial Developer of the Original Code is 018 * Agfa Healthcare. 019 * Portions created by the Initial Developer are Copyright (C) 2011 020 * the Initial Developer. All Rights Reserved. 021 * 022 * Contributor(s): 023 * See @authors listed below 024 * 025 * Alternatively, the contents of this file may be used under the terms of 026 * either the GNU General Public License Version 2 or later (the "GPL"), or 027 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 028 * in which case the provisions of the GPL or the LGPL are applicable instead 029 * of those above. If you wish to allow use of your version of this file only 030 * under the terms of either the GPL or the LGPL, and not to allow others to 031 * use your version of this file under the terms of the MPL, indicate your 032 * decision by deleting the provisions above and replace them with the notice 033 * and other provisions required by the GPL or the LGPL. If you do not delete 034 * the provisions above, a recipient may use your version of this file under 035 * the terms of any one of the MPL, the GPL or the LGPL. 036 * 037 * ***** END LICENSE BLOCK ***** */ 038package org.dcm4che3.tool.dcmgen; 039 040import java.io.File; 041import java.io.FileInputStream; 042import java.io.IOException; 043import java.util.ArrayList; 044import java.util.List; 045import java.util.ResourceBundle; 046 047import org.apache.commons.cli.CommandLine; 048import org.apache.commons.cli.OptionBuilder; 049import org.apache.commons.cli.Options; 050import org.apache.commons.cli.ParseException; 051import org.dcm4che3.data.Attributes; 052import org.dcm4che3.data.Tag; 053import org.dcm4che3.data.VR; 054import org.dcm4che3.io.DicomInputStream; 055import org.dcm4che3.io.DicomOutputStream; 056import org.dcm4che3.io.SAXReader; 057import org.dcm4che3.io.DicomInputStream.IncludeBulkData; 058import org.dcm4che3.tool.common.CLIUtils; 059import org.dcm4che3.util.SafeClose; 060import org.dcm4che3.util.UIDUtils; 061import org.slf4j.Logger; 062import org.slf4j.LoggerFactory; 063 064/** 065 * @author Hesham Elbadawi <bsdreko@gmail.com> 066 * 067 */ 068 069public class DcmGen{ 070 071 private static final Logger LOG = LoggerFactory.getLogger(DcmGen.class); 072 073 private static Options options; 074 075 private static ResourceBundle rb = ResourceBundle 076 .getBundle("org.dcm4che3.tool.dcmgen.messages"); 077 078 private int instanceCount = 1; 079 080 private int seriesCount = 1; 081 082 private File outputDir; 083 084 private File seedFile; 085 086 public DcmGen() {} 087 088 @SuppressWarnings("static-access") 089 private static CommandLine parseComandLine(String[] args) 090 throws ParseException { 091 options = new Options(); 092 options.addOption(OptionBuilder 093 .hasArgs() 094 .withLongOpt("override") 095 .withArgName("[seq/]attr=value") 096 .withValueSeparator('=') 097 .withDescription(rb.getString("override")) 098 .create()); 099 CLIUtils.addCommonOptions(options); 100 return CLIUtils.parseComandLine(args,options, rb, DcmGen.class); 101 } 102 103 104 public static void main(String[] args) { 105 CommandLine cl = null; 106 try { 107 DcmGen main = new DcmGen(); 108 cl = parseComandLine(args); 109 Attributes overrideAttrs = new Attributes(); 110 111 112 113 if(cl.getArgList().size()<2) { 114 throw new ParseException("Missing required arguments"); 115 } 116 else { 117 if(cl.hasOption("override")) { 118 CLIUtils.addAttributes(overrideAttrs, cl.getOptionValues("override")); 119 } 120 if(cl.getArgs()[0].contains(":")) 121 setCounts(cl, main,true); 122 else 123 setCounts(cl, main, false); 124 if(cl.getArgList().size()==3) { 125 main.seedFile = new File(cl.getArgs()[1]); 126 main.outputDir = new File(cl.getArgs()[2]); 127 } 128 else if(cl.getArgList().size()==2) { 129 main.seedFile = new File(cl.getArgs()[1]); 130 main.outputDir = new File("./"); 131 } 132 133 else { 134 throw new ParseException("Too many arguments specified"); 135 } 136 if(main.seriesCount > main.instanceCount) { 137 throw new ParseException("Series count can not exceeed instance count"); 138 } 139 main.generateDICOM(overrideAttrs); 140 } 141 142 } catch (ParseException e) { 143 LOG.error("DcmGen\t" + e.getMessage()); 144 System.err.println(rb.getString("try")); 145 System.exit(2); 146 } 147 } 148 149 public List<String> generateDICOM(Attributes overrideAttrs) { 150 ArrayList<String> generatedFiles = new ArrayList<String>(); 151 String studyIUID = UIDUtils.createUID(); 152 Attributes seedAttrs = null; 153 Attributes fmiOld = null; 154 Attributes fmi = null; 155 if (this.seedFile.getName().endsWith(".xml")) { 156 try { 157 seedAttrs = SAXReader.parse(new FileInputStream(this.seedFile)); 158 } catch (Exception e) { 159 e.printStackTrace(); 160 } 161 } 162 else { 163 DicomInputStream din = null; 164 165 try { 166 din = new DicomInputStream(this.seedFile); 167 din.setIncludeBulkData(IncludeBulkData.URI); 168 seedAttrs = din.readDataset(-1, -1); 169 fmiOld = din.readFileMetaInformation(); 170 if (fmiOld == null || !fmiOld.containsValue(Tag.TransferSyntaxUID) 171 || !fmiOld.containsValue(Tag.MediaStorageSOPClassUID) 172 || !fmiOld.containsValue(Tag.MediaStorageSOPInstanceUID)) 173 fmiOld = seedAttrs.createFileMetaInformation(din.getTransferSyntax()); 174 } 175 catch(Exception e) { 176 e.printStackTrace(); 177 } 178 finally { 179 SafeClose.close(din); 180 } 181 } 182 DicomOutputStream dout = null; 183 Attributes modified = new Attributes(); 184 if(!overrideAttrs.isEmpty()) 185 seedAttrs.update(overrideAttrs, modified); 186 187 if(!modified.isEmpty()) { 188 if(modified.contains(Tag.StudyInstanceUID)) { 189 studyIUID = modified.getString(Tag.StudyInstanceUID); 190 } 191 } 192 int splitCnt = this.instanceCount / this.seriesCount; 193 194 int i=0; 195 196 if(this.instanceCount % this.seriesCount !=0) { 197 this.seriesCount++; 198 } 199 while ( i<this.instanceCount) { 200 String seriesuid = UIDUtils.createUID(); 201 seedAttrs.setString(Tag.SeriesInstanceUID, VR.UI, seriesuid); 202 for(int j=0;j<splitCnt;j++) { 203 if(i==this.instanceCount) 204 break; 205 String iuid = UIDUtils.createUID(); 206 seedAttrs.setString(Tag.SOPInstanceUID, VR.UI, iuid); 207 try { 208 File parent = new File(this.outputDir+"/"+studyIUID+"/"+seriesuid); 209 if(!parent.exists()) 210 parent.mkdirs(); 211 File outFile = new File(parent,iuid+".dcm"); 212 dout = new DicomOutputStream(outFile); 213 fmi = seedAttrs.createFileMetaInformation(fmiOld.getString(Tag.TransferSyntaxUID)); 214 dout.writeDataset(fmi, seedAttrs); 215 generatedFiles.add(outFile.getAbsolutePath()); 216 } catch (IOException e) { 217 e.printStackTrace(); 218 } 219 finally{ 220 SafeClose.close(dout); 221 } 222 i++; 223 } 224 225 } 226 return generatedFiles; 227 } 228 229 private static void setCounts(CommandLine cl, DcmGen main, boolean both) 230 throws ParseException { 231 try{ 232 main.instanceCount = Integer.parseInt(cl.getArgs()[0].split(":")[0]); 233 if(both) 234 main.seriesCount = Integer.parseInt(cl.getArgs()[0].split(":")[1]); 235 } 236 catch(ArrayIndexOutOfBoundsException e) { 237 throw new ParseException("number of instances/number of series incorrectly specified"); 238 } 239 } 240 241 public void setInstanceCount(int instanceCount) { 242 this.instanceCount = instanceCount; 243 } 244 245 public void setSeriesCount(int seriesCount) { 246 this.seriesCount = seriesCount; 247 } 248 249 public void setOutputDir(File outputDir) { 250 this.outputDir = outputDir; 251 } 252 253 public void setSeedFile(File seedFile) { 254 this.seedFile = seedFile; 255 } 256 257}