Skip to content

Commit

Permalink
Utility dcm2str to apply Attributes Format Pattern to dicom file and/…
Browse files Browse the repository at this point in the history
…or command line parameters #385
  • Loading branch information
vrindanayak committed Jan 9, 2019
1 parent 9d8f6b6 commit 3e3c56f
Show file tree
Hide file tree
Showing 11 changed files with 382 additions and 0 deletions.
2 changes: 2 additions & 0 deletions README.md
Expand Up @@ -59,6 +59,7 @@ Utilities
---------
- [dcm2dcm][]: Transcode DICOM file according the specified Transfer Syntax
- [dcm2jpg][]: Convert DICOM image to JPEG or other image formats
- [dcm2str][]: Apply Attributes Format Pattern to dicom file or command line parameters.
- [dcm2xml][]: Convert DICOM file in XML presentation
- [dcmdir][]: Dump, create or update DICOMDIR file
- [dcmdump][]: Dump DICOM file in textual form
Expand Down Expand Up @@ -93,6 +94,7 @@ Utilities

[dcm2dcm]: https://github.com/dcm4che/dcm4che/blob/master/dcm4che-tool/dcm4che-tool-dcm2dcm/README.md
[dcm2jpg]: https://github.com/dcm4che/dcm4che/blob/master/dcm4che-tool/dcm4che-tool-dcm2jpg/README.md
[dcm2str]: https://github.com/dcm4che/dcm4che/blob/master/dcm4che-tool/dcm4che-tool-dcm2str/README.md
[dcm2xml]: https://github.com/dcm4che/dcm4che/blob/master/dcm4che-tool/dcm4che-tool-dcm2xml/README.md
[dcmdir]: https://github.com/dcm4che/dcm4che/blob/master/dcm4che-tool/dcm4che-tool-dcmdir/README.md
[dcmdump]: https://github.com/dcm4che/dcm4che/blob/master/dcm4che-tool/dcm4che-tool-dcmdump/README.md
Expand Down
5 changes: 5 additions & 0 deletions dcm4che-assembly/pom.xml
Expand Up @@ -270,6 +270,11 @@
<artifactId>dcm4che-tool-dcm2json</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.dcm4che.tool</groupId>
<artifactId>dcm4che-tool-dcm2str</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.dcm4che.tool</groupId>
<artifactId>dcm4che-tool-dcm2xml</artifactId>
Expand Down
56 changes: 56 additions & 0 deletions dcm4che-assembly/src/bin/dcm2str
@@ -0,0 +1,56 @@
#!/bin/sh
# -------------------------------------------------------------------------
# dcm2str Launcher
# -------------------------------------------------------------------------

MAIN_CLASS=org.dcm4che3.tool.dcm2str.Dcm2Str
MAIN_JAR=dcm4che-tool-dcm2str-${project.version}.jar

DIRNAME="`dirname "$0"`"

# OS specific support (must be 'true' or 'false').
cygwin=false;
case "`uname`" in
CYGWIN*)
cygwin=true
;;
esac

# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
[ -n "$DCM4CHE_HOME" ] &&
DCM4CHE_HOME=`cygpath --unix "$DCM4CHE_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi

# Setup DCM4CHE_HOME
if [ "x$DCM4CHE_HOME" = "x" ]; then
DCM4CHE_HOME=`cd "$DIRNAME"/..; pwd`
fi

# Setup the JVM
if [ "x$JAVA_HOME" != "x" ]; then
JAVA=$JAVA_HOME/bin/java
else
JAVA="java"
fi

# Setup the classpath
CP="$DCM4CHE_HOME/etc/dcm2str/"
CP="$CP:$DCM4CHE_HOME/lib/$MAIN_JAR"
CP="$CP:$DCM4CHE_HOME/lib/dcm4che-core-${project.version}.jar"
CP="$CP:$DCM4CHE_HOME/lib/dcm4che-tool-common-${project.version}.jar"
CP="$CP:$DCM4CHE_HOME/lib/slf4j-api-1.7.25.jar"
CP="$CP:$DCM4CHE_HOME/lib/slf4j-log4j12-1.7.25.jar"
CP="$CP:$DCM4CHE_HOME/lib/log4j-1.2.17.jar"
CP="$CP:$DCM4CHE_HOME/lib/commons-cli-${commons-cli.version}.jar"

# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
JAVA=`cygpath --path --windows "$JAVA"`
CP=`cygpath --path --windows "$CP"`
fi

# Execute the JVM
exec "$JAVA" $JAVA_OPTS -cp "$CP" $MAIN_CLASS "$@"
52 changes: 52 additions & 0 deletions dcm4che-assembly/src/bin/dcm2str.bat
@@ -0,0 +1,52 @@
@echo off
rem -------------------------------------------------------------------------
rem dcm2str Launcher
rem -------------------------------------------------------------------------

if not "%ECHO%" == "" echo %ECHO%
if "%OS%" == "Windows_NT" setlocal

set MAIN_CLASS=org.dcm4che3.tool.dcm2str.Dcm2Str
set MAIN_JAR=dcm4che-tool-dcm2str-${project.version}.jar

set DIRNAME=.\
if "%OS%" == "Windows_NT" set DIRNAME=%~dp0%

rem Read all command line arguments

set ARGS=
:loop
if [%1] == [] goto end
set ARGS=%ARGS% %1
shift
goto loop
:end

if not "%DCM4CHE_HOME%" == "" goto HAVE_DCM4CHE_HOME

set DCM4CHE_HOME=%DIRNAME%..

:HAVE_DCM4CHE_HOME

if not "%JAVA_HOME%" == "" goto HAVE_JAVA_HOME

set JAVA=java

goto SKIP_SET_JAVA_HOME

:HAVE_JAVA_HOME

set JAVA=%JAVA_HOME%\bin\java

:SKIP_SET_JAVA_HOME

set CP=%DCM4CHE_HOME%\etc\dcm2str\
set CP=%CP%;%DCM4CHE_HOME%\lib\%MAIN_JAR%
set CP=%CP%;%DCM4CHE_HOME%\lib\dcm4che-core-${project.version}.jar
set CP=%CP%;%DCM4CHE_HOME%\lib\dcm4che-tool-common-${project.version}.jar
set CP=%CP%;%DCM4CHE_HOME%\lib\slf4j-api-1.7.25.jar
set CP=%CP%;%DCM4CHE_HOME%\lib\slf4j-log4j12-1.7.25.jar
set CP=%CP%;%DCM4CHE_HOME%\lib\log4j-1.2.17.jar
set CP=%CP%;%DCM4CHE_HOME%\lib\commons-cli-${commons-cli.version}.jar

"%JAVA%" %JAVA_OPTS% -cp "%CP%" %MAIN_CLASS% %ARGS%
5 changes: 5 additions & 0 deletions dcm4che-assembly/src/etc/dcm2str/log4j.properties
@@ -0,0 +1,5 @@
log4j.rootLogger=INFO, stdout

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %-5p - %m\n
1 change: 1 addition & 0 deletions dcm4che-assembly/src/main/assembly/bin.xml
Expand Up @@ -139,6 +139,7 @@
<include>org.dcm4che.tool:dcm4che-tool-dcm2dcm</include>
<include>org.dcm4che.tool:dcm4che-tool-dcm2jpg</include>
<include>org.dcm4che.tool:dcm4che-tool-dcm2json</include>
<include>org.dcm4che.tool:dcm4che-tool-dcm2str</include>
<include>org.dcm4che.tool:dcm4che-tool-dcm2xml</include>
<include>org.dcm4che.tool:dcm4che-tool-dcmdir</include>
<include>org.dcm4che.tool:dcm4che-tool-dcmldap</include>
Expand Down
51 changes: 51 additions & 0 deletions dcm4che-tool/dcm4che-tool-dcm2str/README.md
@@ -0,0 +1,51 @@
usage: dcm2str -p PATTERN <file(s)|directory(ies)> -s
<[seq/]attr=value>...

Apply Attributes Format Pattern either to one or more DICOM files and/or
DICOM file(s) in one or more directories. If individual attributes are
specified, the attributes of the DICOM file(s) shall be overwritten by the
specified attributes before the Attributes Format Pattern is applied.
-
Options:
-h,--help display this help and exit
-p <arg> Specify Attributes Format Pattern to be applied.
-s <[seq/]attr=value> Specify attributes added to the object(s). It can
be specified by keyword or tag (in hex), e.g.
StudyInstanceUID=1.2.3 or 0020000D=1.2.3.
Attributes in nested Datasets can be specified by
including the keyword/tag value of the sequence
attribute, e.g. 00400275/00400009 for Scheduled
Procedure Step ID in the Request Attributes
Sequence.
-V,--version output version information and exit

Examples:
=> dcm2str -p {0020000D,hash}/{0020000E,hash}/{00080018,hash}/{rnd}
image.dcm
Apply Attributes Format Pattern to the specified DICOM file.

=> dcm2str -p {0020000D,hash}/{0020000E,hash}/{00080018,hash}/{rnd}
image.dcm -sStudyInstanceUID=1.2.3 -sSeriesInstanceUID=1.2.3.4
-sSOPInstanceUID=1.2.3.4.5
Overwrite attributes of the specified DICOM file with specified DICOM
attributes and then apply Attributes Format Pattern to the specified DICOM
file.

=> dcm2str -p {0020000D,hash}/{0020000E,hash}/{00080018,hash}/{rnd}
image.dcm /path-to-other-DICOM-files-directory -sStudyInstanceUID=1.2.3
-sSeriesInstanceUID=1.2.3.4 -sSOPInstanceUID=1.2.3.4.5
Overwrite attributes of the specified DICOM file and of other DICOM files
in the directory with the specified DICOM attributes and only then apply
Attributes Format Pattern to DICOM file and to other DICOM files in the
directory.

=> dcm2str -p {0020000D,hash}/{0020000E,hash}/{00080018,hash}/{rnd}
image.dcm /path-to-other-DICOM-files-directory
Apply Attributes Format Pattern to the specified DICOM file and also to
the other DICOM files in the specified directory.

=> dcm2str -p {0020000D,hash}/{0020000E,hash}/{00080018,hash}/{rnd}
-sStudyInstanceUID=1.2.3 -sSeriesInstanceUID=1.2.3.4
-sSOPInstanceUID=1.2.3.4.5
Apply Attributes Format Pattern to DICOM attributes passed as command line
parameters.
32 changes: 32 additions & 0 deletions dcm4che-tool/dcm4che-tool-dcm2str/pom.xml
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>dcm4che-tool</artifactId>
<groupId>org.dcm4che.tool</groupId>
<version>5.15.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>dcm4che-tool-dcm2str</artifactId>
<name>dcm4che-tool-dcm2str</name>

<dependencies>
<dependency>
<groupId>org.dcm4che</groupId>
<artifactId>dcm4che-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
<dependency>
<groupId>org.dcm4che.tool</groupId>
<artifactId>dcm4che-tool-common</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>

</project>
@@ -0,0 +1,146 @@
/* ***** 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/dcm4che.
*
* The Initial Developer of the Original Code is
* J4Care.
* Portions created by the Initial Developer are Copyright (C) 2015-2019
* 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.dcm4che3.tool.dcm2str;

import org.apache.commons.cli.*;
import org.dcm4che3.data.Attributes;
import org.dcm4che3.io.DicomInputStream;
import org.dcm4che3.tool.common.CLIUtils;
import org.dcm4che3.util.AttributesFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.text.MessageFormat;
import java.util.EnumSet;
import java.util.List;
import java.util.ResourceBundle;

/**
* @author Vrinda Nayak <vrinda.nayak@j4care.com>
* @since Jan 2019
*/
public class Dcm2Str {
private static final Logger LOG = LoggerFactory.getLogger(Dcm2Str.class);
private static final ResourceBundle rb = ResourceBundle.getBundle("org.dcm4che3.tool.dcm2str.messages");
private static String pattern;
private static String[] uidOptVals;
private static List<String> pathNames;

public static void main(String[] args) {
try {
CommandLine cl = parseComandLine(args);
init(cl);
dcm2str();
} catch (ParseException e) {
System.err.println("dcm2str: " + e.getMessage());
System.err.println(rb.getString("try"));
System.exit(2);
} catch (Exception e) {
System.err.println("dcm2str: " + e.getMessage());
e.printStackTrace();
System.exit(2);
}
}

private static CommandLine parseComandLine(String[] args) throws ParseException {
Options opts = new Options();
CLIUtils.addCommonOptions(opts);
opts.addOption(Option.builder("p")
.hasArg()
.desc(rb.getString("pattern"))
.build());
opts.addOption(Option.builder("s")
.hasArgs()
.argName("[seq/]attr=value")
.valueSeparator('=')
.desc(rb.getString("str"))
.build());
return CLIUtils.parseComandLine(args, opts, rb, Dcm2Str.class);
}

private static void init(CommandLine cl) throws Exception {
if ((pattern = cl.getOptionValue("p")) == null)
throw new MissingOptionException("Missing Attributes Format pattern");

uidOptVals = cl.getOptionValues("s");
pathNames = cl.getArgList();
}

private static void dcm2str() throws IOException {
for (String pathName : pathNames) {
Path path = Paths.get(pathName);
if (Files.isDirectory(path)) {
try {
Files.walkFileTree(path, EnumSet.of(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE,
new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path filePath, BasicFileAttributes attrs1) throws IOException {
convert(filePath);
return FileVisitResult.CONTINUE;
}
});
} catch (IOException e) {
LOG.warn(e.getMessage());
}
} else
convert(path);
}
if (pathNames.isEmpty())
convert(null);
}

private static void convert(Path path) throws IOException {
Attributes attrs = toAttributes(path);
CLIUtils.addAttributes(attrs, uidOptVals);
System.out.println(MessageFormat.format(
rb.getString("converted"),
path != null ? path : "",
new AttributesFormat(pattern).format(attrs)));
}

private static Attributes toAttributes(Path path) throws IOException {
return path != null
? new DicomInputStream(new FileInputStream(path.toFile())).readDataset(-1, -1)
: new Attributes();
}
}

0 comments on commit 3e3c56f

Please sign in to comment.