/* * * Copyright (C) 2001-2021, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by * * OFFIS e.V. * R&D Division Health * Escherweg 2 * D-26121 Oldenburg, Germany * * * Module: dcmjpeg * * Author: Marco Eichelberg * * Purpose: Compress DICOM file * */ #include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmdata/dctk.h" #include "dcmtk/dcmdata/cmdlnarg.h" #include "dcmtk/ofstd/ofconapp.h" #include "dcmtk/dcmdata/dcuid.h" /* for dcmtk version name */ #include "dcmtk/dcmjpeg/djdecode.h" /* for dcmjpeg decoders */ #include "dcmtk/dcmjpeg/djencode.h" /* for dcmjpeg encoders */ #include "dcmtk/dcmjpeg/djrplol.h" /* for DJ_RPLossless */ #include "dcmtk/dcmjpeg/djrploss.h" /* for DJ_RPLossy */ #include "dcmtk/dcmjpeg/dipijpeg.h" /* for dcmimage JPEG plugin */ #include "dcmtk/dcmimage/diregist.h" /* include to support color images */ #ifdef WITH_ZLIB #include /* for zlibVersion() */ #endif #define OFFIS_CONSOLE_APPLICATION "dcmcjpeg" static OFLogger dcmcjpegLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION); static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $"; // ******************************************** #define SHORTCOL 4 #define LONGCOL 21 int main(int argc, char *argv[]) { const char *opt_ifname = NULL; const char *opt_ofname = NULL; E_FileReadMode opt_readMode = ERM_autoDetect; E_TransferSyntax opt_ixfer = EXS_Unknown; E_GrpLenEncoding opt_oglenc = EGL_recalcGL; E_EncodingType opt_oenctype = EET_ExplicitLength; E_PaddingEncoding opt_opadenc = EPD_noChange; OFCmdUnsignedInt opt_filepad = 0; OFCmdUnsignedInt opt_itempad = 0; OFBool opt_acceptWrongPaletteTags = OFFalse; OFBool opt_acrNemaCompatibility = OFFalse; // JPEG options E_TransferSyntax opt_oxfer = EXS_JPEGProcess14SV1; OFCmdUnsignedInt opt_selection_value = 6; OFCmdUnsignedInt opt_point_transform = 0; OFCmdUnsignedInt opt_quality = 90; OFBool opt_huffmanOptimize = OFTrue; OFCmdUnsignedInt opt_smoothing = 0; int opt_compressedBits = 0; // 0=auto, 8/12/16=force E_CompressionColorSpaceConversion opt_compCSconversion = ECC_lossyYCbCr; E_DecompressionColorSpaceConversion opt_decompCSconversion = EDC_photometricInterpretation; OFBool opt_predictor6WorkaroundEnable = OFFalse; OFBool opt_cornellWorkaroundEnable = OFFalse; OFBool opt_forceSingleFragmentPerFrame = OFFalse; E_SubSampling opt_sampleFactors = ESS_422; OFBool opt_useYBR422 = OFTrue; OFCmdUnsignedInt opt_fragmentSize = 0; // 0=unlimited OFBool opt_createOffsetTable = OFTrue; int opt_windowType = 0; /* default: no windowing; 1=Wi, 2=Wl, 3=Wm, 4=Wh, 5=Ww, 6=Wn, 7=Wr */ OFCmdUnsignedInt opt_windowParameter = 0; OFCmdFloat opt_windowCenter=0.0, opt_windowWidth=0.0; E_UIDCreation opt_uidcreation = EUC_default; OFBool opt_secondarycapture = OFFalse; OFCmdUnsignedInt opt_roiLeft = 0, opt_roiTop = 0, opt_roiWidth = 0, opt_roiHeight = 0; OFBool opt_usePixelValues = OFTrue; OFBool opt_useModalityRescale = OFFalse; OFBool opt_trueLossless = OFTrue; OFBool opt_lossless = OFTrue; OFBool lossless = OFTrue; /* see opt_oxfer */ OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION, "Encode DICOM file to JPEG transfer syntax", rcsid); OFCommandLine cmd; cmd.setOptionColumns(LONGCOL, SHORTCOL); cmd.setParamColumn(LONGCOL + SHORTCOL + 4); cmd.addParam("dcmfile-in", "DICOM input filename to be converted"); cmd.addParam("dcmfile-out", "DICOM output filename"); cmd.addGroup("general options:", LONGCOL, SHORTCOL + 2); cmd.addOption("--help", "-h", "print this help text and exit", OFCommandLine::AF_Exclusive); cmd.addOption("--version", "print version information and exit", OFCommandLine::AF_Exclusive); OFLog::addOptions(cmd); cmd.addGroup("input options:"); cmd.addSubGroup("input file format:"); cmd.addOption("--read-file", "+f", "read file format or data set (default)"); cmd.addOption("--read-file-only", "+fo", "read file format only"); cmd.addOption("--read-dataset", "-f", "read data set without file meta information"); cmd.addSubGroup("input transfer syntax:"); cmd.addOption("--read-xfer-auto", "-t=", "use TS recognition (default)"); cmd.addOption("--read-xfer-detect", "-td", "ignore TS specified in the file meta header"); cmd.addOption("--read-xfer-little", "-te", "read with explicit VR little endian TS"); cmd.addOption("--read-xfer-big", "-tb", "read with explicit VR big endian TS"); cmd.addOption("--read-xfer-implicit", "-ti", "read with implicit VR little endian TS"); cmd.addSubGroup("compatibility (ignored by +tl):"); cmd.addOption("--accept-acr-nema", "+Ma", "accept ACR-NEMA images without photometric\ninterpretation"); cmd.addOption("--accept-palettes", "+Mp", "accept incorrect palette attribute tags\n(0028,111x) and (0028,121x)"); cmd.addGroup("JPEG encoding options:"); cmd.addSubGroup("JPEG process:"); cmd.addOption("--encode-lossless-sv1", "+e1", "encode lossless sv1 (default)"); cmd.addOption("--encode-lossless", "+el", "encode lossless"); cmd.addOption("--encode-baseline", "+eb", "encode baseline"); cmd.addOption("--encode-extended", "+ee", "encode extended sequential"); cmd.addOption("--encode-spectral", "+es", "encode spectral selection"); cmd.addOption("--encode-progressive", "+ep", "encode progressive"); cmd.addSubGroup("lossless JPEG codec selection:"); cmd.addOption("--true-lossless", "+tl", "true lossless codec (default)"); cmd.addOption("--pseudo-lossless", "+pl", "old pseudo-lossless codec"); cmd.addSubGroup("lossless JPEG representation:"); cmd.addOption("--selection-value", "+sv", 1, "[sv]: integer (1..7, default: 6)", "use selection value sv\nonly with --encode-lossless"); cmd.addOption("--point-transform", "+pt", 1, "[pt]: integer (0..15, default: 0)", "use point transform pt"); cmd.addSubGroup("lossy JPEG representation:"); cmd.addOption("--quality", "+q", 1, "[q]: integer (0..100, default: 90)", "use quality factor q"); cmd.addOption("--smooth", "+sm", 1, "[s]: integer (0..100, default: 0)", "use smoothing factor s"); cmd.addSubGroup("other JPEG options:"); cmd.addOption("--huffman-optimize", "+ho", "optimize huffman tables (default)"); cmd.addOption("--huffman-standard", "-ho", "use standard huffman tables if 8 bits/sample"); cmd.addSubGroup("compressed bits per sample (always +ba with +tl):"); cmd.addOption("--bits-auto", "+ba", "choose bits/sample automatically (default)"); cmd.addOption("--bits-force-8", "+be", "force 8 bits/sample"); cmd.addOption("--bits-force-12", "+bt", "force 12 bits/sample (not with baseline)"); cmd.addOption("--bits-force-16", "+bs", "force 16 bits/sample (lossless only)"); cmd.addSubGroup("compression color space conversion (overridden by +tl):"); cmd.addOption("--color-ybr", "+cy", "use YCbCr for color images if lossy (default)"); cmd.addOption("--color-rgb", "+cr", "use RGB for color images if lossy"); cmd.addOption("--monochrome", "+cm", "convert color images to monochrome"); cmd.addSubGroup("decompr. color space conversion (if input is compressed; always +cn with +tl):"); cmd.addOption("--conv-photometric", "+cp", "convert if YCbCr photometric interpr. (default)"); cmd.addOption("--conv-lossy", "+cl", "convert YCbCr to RGB if lossy JPEG"); cmd.addOption("--conv-guess", "+cg", "convert to RGB if YCbCr is guessed by library"); cmd.addOption("--conv-guess-lossy", "+cgl", "convert to RGB if lossy JPEG and YCbCr is\nguessed by the underlying JPEG library"); cmd.addOption("--conv-always", "+ca", "always convert YCbCr to RGB"); cmd.addOption("--conv-never", "+cn", "never convert color space"); cmd.addSubGroup("decompr. workaround options for incorrect encodings (if input is compressed):"); cmd.addOption("--workaround-pred6", "+w6", "enable workaround for JPEG lossless images\nwith overflow in predictor 6"); cmd.addOption("--workaround-incpl", "+wi", "enable workaround for incomplete JPEG data"); cmd.addOption("--workaround-cornell", "+wc", "enable workaround for 16-bit JPEG lossless\nCornell images with Huffman table overflow"); cmd.addSubGroup("YCbCr component subsampling (lossy JPEG only):"); cmd.addOption("--sample-422", "+s2", "4:2:2 subsampling with YBR_FULL_422 (default)"); cmd.addSubGroup("non-standard YCbCr component subsampling (lossy JPEG only):"); cmd.addOption("--nonstd-444", "+s4", "4:4:4 sampling with YBR_FULL"); cmd.addOption("--nonstd-422-full", "+n2", "4:2:2 subsampling with YBR_FULL"); cmd.addOption("--nonstd-411-full", "+n1", "4:1:1 subsampling with YBR_FULL"); cmd.addOption("--nonstd-411", "+np", "4:1:1 subsampling with YBR_FULL_422"); cmd.addGroup("encapsulated pixel data encoding options:"); cmd.addSubGroup("pixel data fragmentation:"); cmd.addOption("--fragment-per-frame", "+ff", "encode each frame as one fragment (default)"); cmd.addOption("--fragment-size", "+fs", 1, "[s]ize: integer", "limit fragment size to s kbytes"); cmd.addSubGroup("basic offset table encoding:"); cmd.addOption("--offset-table-create", "+ot", "create offset table (default)"); cmd.addOption("--offset-table-empty", "-ot", "leave offset table empty"); cmd.addSubGroup("VOI windowing for monochrome images (not with +tl):"); cmd.addOption("--no-windowing", "-W", "no VOI windowing (default)"); cmd.addOption("--use-window", "+Wi", 1, "[n]umber: integer", "use the n-th VOI window from image file"); cmd.addOption("--use-voi-lut", "+Wl", 1, "[n]umber: integer", "use the n-th VOI look up table from image file"); cmd.addOption("--min-max-window", "+Wm", "compute VOI window using min-max algorithm"); cmd.addOption("--min-max-window-n", "+Wn", "compute VOI window using min-max algorithm,\nignoring extreme values"); cmd.addOption("--roi-min-max-window", "+Wr", 4, "[l]eft [t]op [w]idth [h]eight: integer", "compute ROI window using min-max algorithm,\nregion of interest is specified by l,t,w,h"); cmd.addOption("--histogram-window", "+Wh", 1, "[n]umber: integer", "compute VOI window using Histogram algorithm,\nignoring n percent"); cmd.addOption("--set-window", "+Ww", 2, "[c]enter [w]idth: float", "compute VOI window using center c and width w"); cmd.addSubGroup("pixel scaling for monochrome images (-W; ignored by +tl):"); cmd.addOption("--scaling-pixel", "+sp", "scale using min/max pixel value (default)"); cmd.addOption("--scaling-range", "+sr", "scale using min/max range"); cmd.addSubGroup("rescale slope/intercept encoding for monochrome (-W; ignored by +tl):"); cmd.addOption("--rescale-identity", "+ri", "encode identity modality rescale (default)\nNever used for CT images"); cmd.addOption("--rescale-map", "+rm", "use modality rescale to scale pixel range\nNever used for XA/RF/XA Biplane images"); cmd.addSubGroup("SOP Class UID:"); cmd.addOption("--class-default", "+cd", "keep SOP Class UID (default)"); cmd.addOption("--class-sc", "+cs", "convert to Secondary Capture Image\n(implies --uid-always)"); cmd.addSubGroup("SOP Instance UID:"); cmd.addOption("--uid-default", "+ud", "assign new UID if lossy compression (default)"); cmd.addOption("--uid-always", "+ua", "always assign new UID"); cmd.addOption("--uid-never", "+un", "never assign new UID"); cmd.addGroup("output options:"); cmd.addSubGroup("post-1993 value representations:"); cmd.addOption("--enable-new-vr", "+u", "enable support for new VRs (UN/UT) (default)"); cmd.addOption("--disable-new-vr", "-u", "disable support for new VRs, convert to OB"); cmd.addSubGroup("group length encoding:"); cmd.addOption("--group-length-recalc", "+g=", "recalculate group lengths if present (default)"); cmd.addOption("--group-length-create", "+g", "always write with group length elements"); cmd.addOption("--group-length-remove", "-g", "always write without group length elements"); cmd.addSubGroup("length encoding in sequences and items:"); cmd.addOption("--length-explicit", "+e", "write with explicit lengths (default)"); cmd.addOption("--length-undefined", "-e", "write with undefined lengths"); cmd.addSubGroup("data set trailing padding:"); cmd.addOption("--padding-retain", "-p=", "do not change padding (default)"); cmd.addOption("--padding-off", "-p", "no padding"); cmd.addOption("--padding-create", "+p", 2, "[f]ile-pad [i]tem-pad: integer", "align file on multiple of f bytes\nand items on multiple of i bytes"); /* evaluate command line */ prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION); if (app.parseCommandLine(cmd, argc, argv)) { /* check exclusive options first */ if (cmd.hasExclusiveOption()) { if (cmd.findOption("--version")) { app.printHeader(OFTrue /*print host identifier*/); COUT << OFendl << "External libraries used:" << OFendl; #ifdef WITH_ZLIB COUT << "- ZLIB, Version " << zlibVersion() << OFendl; #endif COUT << "- " << DiJPEGPlugin::getLibraryVersionString() << OFendl; return 0; } } /* command line parameters */ cmd.getParam(1, opt_ifname); cmd.getParam(2, opt_ofname); /* options */ OFLog::configureFromCommandLine(cmd, app); cmd.beginOptionBlock(); if (cmd.findOption("--read-file")) opt_readMode = ERM_autoDetect; if (cmd.findOption("--read-file-only")) opt_readMode = ERM_fileOnly; if (cmd.findOption("--read-dataset")) opt_readMode = ERM_dataset; cmd.endOptionBlock(); cmd.beginOptionBlock(); if (cmd.findOption("--read-xfer-auto")) opt_ixfer = EXS_Unknown; if (cmd.findOption("--read-xfer-detect")) dcmAutoDetectDatasetXfer.set(OFTrue); if (cmd.findOption("--read-xfer-little")) { app.checkDependence("--read-xfer-little", "--read-dataset", opt_readMode == ERM_dataset); opt_ixfer = EXS_LittleEndianExplicit; } if (cmd.findOption("--read-xfer-big")) { app.checkDependence("--read-xfer-big", "--read-dataset", opt_readMode == ERM_dataset); opt_ixfer = EXS_BigEndianExplicit; } if (cmd.findOption("--read-xfer-implicit")) { app.checkDependence("--read-xfer-implicit", "--read-dataset", opt_readMode == ERM_dataset); opt_ixfer = EXS_LittleEndianImplicit; } cmd.endOptionBlock(); if (cmd.findOption("--accept-acr-nema")) opt_acrNemaCompatibility = OFTrue; if (cmd.findOption("--accept-palettes")) opt_acceptWrongPaletteTags = OFTrue; // JPEG options cmd.beginOptionBlock(); if (cmd.findOption("--encode-lossless-sv1")) { opt_oxfer = EXS_JPEGProcess14SV1; opt_lossless = OFTrue; } if (cmd.findOption("--encode-lossless")) { opt_oxfer = EXS_JPEGProcess14; opt_lossless = OFTrue; } if (cmd.findOption("--encode-baseline")) { opt_oxfer = EXS_JPEGProcess1; opt_lossless = OFFalse; } if (cmd.findOption("--encode-extended")) { opt_oxfer = EXS_JPEGProcess2_4; opt_lossless = OFFalse; } if (cmd.findOption("--encode-spectral")) { opt_oxfer = EXS_JPEGProcess6_8; opt_lossless = OFFalse; } if (cmd.findOption("--encode-progressive")) { opt_oxfer = EXS_JPEGProcess10_12; opt_lossless = OFFalse; } cmd.endOptionBlock(); // check for JPEG lossless output transfer syntaxes lossless = (opt_oxfer == EXS_JPEGProcess14SV1) || (opt_oxfer == EXS_JPEGProcess14); cmd.beginOptionBlock(); if (cmd.findOption("--true-lossless")) { // true lossless explicitely requested but selected TS denotes lossy process app.checkDependence("--true-lossless", "--encode-lossless-sv1 or --encode-lossless", lossless); opt_trueLossless = OFTrue; } if (cmd.findOption("--pseudo-lossless")) { // pseudo lossless explicitely requested but selected TS denotes lossy process app.checkDependence("--pseudo-lossless", "--encode-lossless-sv1 or --encode-lossless", lossless); opt_trueLossless = OFFalse; } cmd.endOptionBlock(); // disable true lossless mode since we are not encoding with JPEG lossless if (!lossless) opt_trueLossless = OFFalse; if (cmd.findOption("--selection-value")) { app.checkDependence("--selection-value", "--encode-lossless", opt_oxfer == EXS_JPEGProcess14); app.checkValue(cmd.getValueAndCheckMinMax(opt_selection_value, OFstatic_cast(OFCmdUnsignedInt, 1), OFstatic_cast(OFCmdUnsignedInt, 7))); } if (cmd.findOption("--point-transform")) { app.checkDependence("--point-transform", "lossless JPEG", lossless); app.checkValue(cmd.getValueAndCheckMinMax(opt_point_transform, OFstatic_cast(OFCmdUnsignedInt, 0), OFstatic_cast(OFCmdUnsignedInt, 15))); } if (cmd.findOption("--quality")) { app.checkDependence("--quality", "lossy JPEG", !lossless); app.checkValue(cmd.getValueAndCheckMinMax(opt_quality, OFstatic_cast(OFCmdUnsignedInt, 0), OFstatic_cast(OFCmdUnsignedInt, 100))); } cmd.beginOptionBlock(); if (cmd.findOption("--huffman-optimize")) opt_huffmanOptimize = OFTrue; if (cmd.findOption("--huffman-standard")) opt_huffmanOptimize = OFFalse; cmd.endOptionBlock(); if (cmd.findOption("--smooth")) { app.checkConflict("--smooth", "--true-lossless", opt_trueLossless); app.checkValue(cmd.getValueAndCheckMinMax(opt_smoothing, OFstatic_cast(OFCmdUnsignedInt, 0), OFstatic_cast(OFCmdUnsignedInt, 100))); } cmd.beginOptionBlock(); if (cmd.findOption("--bits-auto")) { opt_compressedBits = 0; } if (cmd.findOption("--bits-force-8")) { app.checkConflict("--bits-force-8", "--true-lossless", opt_trueLossless); opt_compressedBits = 8; } if (cmd.findOption("--bits-force-12")) { app.checkConflict("--bits-force-12", "--true-lossless", opt_trueLossless); app.checkConflict("--bits-force-12", "--encode-baseline", opt_oxfer == EXS_JPEGProcess1); opt_compressedBits = 12; } if (cmd.findOption("--bits-force-16")) { app.checkConflict("--bits-force-16", "--true-lossless", opt_trueLossless); app.checkConflict("--bits-force-16", "--encode-baseline", opt_oxfer == EXS_JPEGProcess1); app.checkConflict("--bits-force-16", "--encode-extended", opt_oxfer == EXS_JPEGProcess2_4); app.checkConflict("--bits-force-16", "--encode-spectral", opt_oxfer == EXS_JPEGProcess6_8); app.checkConflict("--bits-force-16", "--encode-progressive", opt_oxfer == EXS_JPEGProcess10_12); opt_compressedBits = 16; } cmd.endOptionBlock(); cmd.beginOptionBlock(); if (cmd.findOption("--color-ybr")) { opt_compCSconversion = ECC_lossyYCbCr; } if (cmd.findOption("--color-rgb")) { app.checkConflict("--color-rgb", "--true-lossless", opt_trueLossless); opt_compCSconversion = ECC_lossyRGB; } if (cmd.findOption("--monochrome")) { app.checkConflict("--monochrome", "--true-lossless", opt_trueLossless); opt_compCSconversion = ECC_monochrome; } cmd.endOptionBlock(); cmd.beginOptionBlock(); if (cmd.findOption("--conv-photometric")) { opt_decompCSconversion = EDC_photometricInterpretation; } if (cmd.findOption("--conv-lossy")) { app.checkConflict("--conv-lossy", "--true-lossless", opt_trueLossless); opt_decompCSconversion = EDC_lossyOnly; } if (cmd.findOption("--conv-guess")) { app.checkConflict("--conv-guess", "--true-lossless", opt_trueLossless); opt_decompCSconversion = EDC_guess; } if (cmd.findOption("--conv-guess-lossy")) { app.checkConflict("--conv-guess-lossy", "--true-lossless", opt_trueLossless); opt_decompCSconversion = EDC_guessLossyOnly; } if (cmd.findOption("--conv-always")) { app.checkConflict("--conv-always", "--true-lossless", opt_trueLossless); opt_decompCSconversion = EDC_always; } if (cmd.findOption("--conv-never")) opt_decompCSconversion = EDC_never; cmd.endOptionBlock(); if (opt_trueLossless) opt_decompCSconversion = EDC_never; if (cmd.findOption("--workaround-pred6")) opt_predictor6WorkaroundEnable = OFTrue; if (cmd.findOption("--workaround-incpl")) opt_forceSingleFragmentPerFrame = OFTrue; if (cmd.findOption("--workaround-cornell")) opt_cornellWorkaroundEnable = OFTrue; cmd.beginOptionBlock(); if (cmd.findOption("--nonstd-444")) { app.checkConflict("--nonstd-444", "--true-lossless", opt_trueLossless); app.checkConflict("--nonstd-444", "--pseudo-lossless", opt_lossless); opt_sampleFactors = ESS_444; opt_useYBR422 = OFFalse; } if (cmd.findOption("--sample-422")) { app.checkConflict("--sample-422", "--true-lossless", opt_trueLossless); app.checkConflict("--sample-422", "--pseudo-lossless", opt_lossless); opt_sampleFactors = ESS_422; opt_useYBR422 = OFTrue; } if (cmd.findOption("--nonstd-422-full")) { app.checkConflict("--nonstd-422-full", "--true-lossless", opt_trueLossless); app.checkConflict("--nonstd-422-full", "--pseudo-lossless", opt_lossless); opt_sampleFactors = ESS_422; opt_useYBR422 = OFFalse; } if (cmd.findOption("--nonstd-411-full")) { app.checkConflict("--nonstd-411-full", "--true-lossless", opt_trueLossless); app.checkConflict("--nonstd-411-full", "--pseudo-lossless", opt_lossless); opt_sampleFactors = ESS_411; opt_useYBR422 = OFFalse; } if (cmd.findOption("--nonstd-411")) { app.checkConflict("--nonstd-411", "--true-lossless", opt_trueLossless); app.checkConflict("--nonstd-411", "--pseudo-lossless", opt_lossless); opt_sampleFactors = ESS_411; opt_useYBR422 = OFTrue; } cmd.endOptionBlock(); cmd.beginOptionBlock(); if (cmd.findOption("--fragment-per-frame")) opt_fragmentSize = 0; if (cmd.findOption("--fragment-size")) { app.checkValue(cmd.getValueAndCheckMin(opt_fragmentSize, OFstatic_cast(OFCmdUnsignedInt, 1))); } cmd.endOptionBlock(); cmd.beginOptionBlock(); if (cmd.findOption("--offset-table-create")) opt_createOffsetTable = OFTrue; if (cmd.findOption("--offset-table-empty")) opt_createOffsetTable = OFFalse; cmd.endOptionBlock(); cmd.beginOptionBlock(); if (cmd.findOption("--no-windowing")) opt_windowType = 0; if (cmd.findOption("--use-window")) { app.checkConflict("--use-window", "--true-lossless", opt_trueLossless); opt_windowType = 1; app.checkValue(cmd.getValueAndCheckMin(opt_windowParameter, 1)); } if (cmd.findOption("--use-voi-lut")) { app.checkConflict("--use-voi-lut", "--true-lossless", opt_trueLossless); opt_windowType = 2; app.checkValue(cmd.getValueAndCheckMin(opt_windowParameter, 1)); } if (cmd.findOption("--min-max-window")) { app.checkConflict("--min-max-window", "--true-lossless", opt_trueLossless); opt_windowType = 3; } if (cmd.findOption("--min-max-window-n")) { app.checkConflict("--min-max-window-n", "--true-lossless", opt_trueLossless); opt_windowType = 6; } if (cmd.findOption("--roi-min-max-window")) { app.checkConflict("--roi-min-max-window", "--true-lossless", opt_trueLossless); opt_windowType = 7; app.checkValue(cmd.getValue(opt_roiLeft)); app.checkValue(cmd.getValue(opt_roiTop)); app.checkValue(cmd.getValueAndCheckMin(opt_roiWidth, 1)); app.checkValue(cmd.getValueAndCheckMin(opt_roiHeight, 1)); } if (cmd.findOption("--histogram-window")) { app.checkConflict("--histogram-window", "--true-lossless", opt_trueLossless); opt_windowType = 4; app.checkValue(cmd.getValueAndCheckMinMax(opt_windowParameter, 0, 100)); } if (cmd.findOption("--set-window")) { app.checkConflict("--set-window", "--true-lossless", opt_trueLossless); opt_windowType = 5; app.checkValue(cmd.getValue(opt_windowCenter)); app.checkValue(cmd.getValueAndCheckMin(opt_windowWidth, 1.0)); } cmd.endOptionBlock(); cmd.beginOptionBlock(); if (cmd.findOption("--scaling-pixel")) opt_usePixelValues = OFTrue; if (cmd.findOption("--scaling-range")) opt_usePixelValues = OFFalse; cmd.endOptionBlock(); cmd.beginOptionBlock(); if (cmd.findOption("--rescale-identity")) opt_useModalityRescale = OFFalse; if (cmd.findOption("--rescale-map")) opt_useModalityRescale = OFTrue; cmd.endOptionBlock(); cmd.beginOptionBlock(); if (cmd.findOption("--class-default")) opt_secondarycapture = OFFalse; if (cmd.findOption("--class-sc")) opt_secondarycapture = OFTrue; cmd.endOptionBlock(); cmd.beginOptionBlock(); if (cmd.findOption("--uid-default")) opt_uidcreation = EUC_default; if (cmd.findOption("--uid-always")) opt_uidcreation = EUC_always; if (cmd.findOption("--uid-never")) opt_uidcreation = EUC_never; cmd.endOptionBlock(); cmd.beginOptionBlock(); if (cmd.findOption("--enable-new-vr")) dcmEnableGenerationOfNewVRs(); if (cmd.findOption("--disable-new-vr")) dcmDisableGenerationOfNewVRs(); cmd.endOptionBlock(); cmd.beginOptionBlock(); if (cmd.findOption("--group-length-recalc")) opt_oglenc = EGL_recalcGL; if (cmd.findOption("--group-length-create")) opt_oglenc = EGL_withGL; if (cmd.findOption("--group-length-remove")) opt_oglenc = EGL_withoutGL; cmd.endOptionBlock(); cmd.beginOptionBlock(); if (cmd.findOption("--length-explicit")) opt_oenctype = EET_ExplicitLength; if (cmd.findOption("--length-undefined")) opt_oenctype = EET_UndefinedLength; cmd.endOptionBlock(); cmd.beginOptionBlock(); if (cmd.findOption("--padding-retain")) opt_opadenc = EPD_noChange; if (cmd.findOption("--padding-off")) opt_opadenc = EPD_withoutPadding; if (cmd.findOption("--padding-create")) { app.checkValue(cmd.getValueAndCheckMin(opt_filepad, 0)); app.checkValue(cmd.getValueAndCheckMin(opt_itempad, 0)); opt_opadenc = EPD_withPadding; } cmd.endOptionBlock(); } /* print resource identifier */ OFLOG_DEBUG(dcmcjpegLogger, rcsid << OFendl); // register global decompression codecs DJDecoderRegistration::registerCodecs( opt_decompCSconversion, opt_uidcreation, EPC_default, opt_predictor6WorkaroundEnable, opt_cornellWorkaroundEnable, opt_forceSingleFragmentPerFrame); // register global compression codecs DJEncoderRegistration::registerCodecs( opt_compCSconversion, opt_uidcreation, opt_huffmanOptimize, OFstatic_cast(int, opt_smoothing), opt_compressedBits, OFstatic_cast(Uint32, opt_fragmentSize), opt_createOffsetTable, opt_sampleFactors, opt_useYBR422, opt_secondarycapture, OFstatic_cast(Uint32, opt_windowType), OFstatic_cast(Uint32, opt_windowParameter), opt_windowCenter, opt_windowWidth, OFstatic_cast(Uint32, opt_roiLeft), OFstatic_cast(Uint32, opt_roiTop), OFstatic_cast(Uint32, opt_roiWidth), OFstatic_cast(Uint32, opt_roiHeight), opt_usePixelValues, opt_useModalityRescale, opt_acceptWrongPaletteTags, opt_acrNemaCompatibility, opt_trueLossless); /* make sure data dictionary is loaded */ if (!dcmDataDict.isDictionaryLoaded()) { OFLOG_WARN(dcmcjpegLogger, "no data dictionary loaded, check environment variable: " << DCM_DICT_ENVIRONMENT_VARIABLE); } // open inputfile if ((opt_ifname == NULL) || (strlen(opt_ifname) == 0)) { OFLOG_FATAL(dcmcjpegLogger, "invalid filename: "); return 1; } OFLOG_INFO(dcmcjpegLogger, "reading input file " << opt_ifname); DcmFileFormat fileformat; OFCondition error = fileformat.loadFile(opt_ifname, opt_ixfer, EGL_noChange, DCM_MaxReadLength, opt_readMode); if (error.bad()) { OFLOG_FATAL(dcmcjpegLogger, error.text() << ": reading file: " << opt_ifname); return 1; } DcmDataset *dataset = fileformat.getDataset(); DcmXfer original_xfer(dataset->getOriginalXfer()); if (original_xfer.isEncapsulated()) { OFLOG_INFO(dcmcjpegLogger, "DICOM file is already compressed, converting to uncompressed transfer syntax first"); if (EC_Normal != dataset->chooseRepresentation(EXS_LittleEndianExplicit, NULL)) { OFLOG_FATAL(dcmcjpegLogger, "no conversion from compressed original to uncompressed transfer syntax possible!"); return 1; } } OFString sopClass; if (fileformat.getMetaInfo()->findAndGetOFString(DCM_MediaStorageSOPClassUID, sopClass).good()) { /* check for DICOMDIR files */ if (sopClass == UID_MediaStorageDirectoryStorage) { OFLOG_FATAL(dcmcjpegLogger, "DICOMDIR files (Media Storage Directory Storage SOP Class) cannot be compressed!"); return 1; } } OFLOG_INFO(dcmcjpegLogger, "Convert DICOM file to compressed transfer syntax"); DcmXfer opt_oxferSyn(opt_oxfer); // create representation parameters for lossy and lossless DJ_RPLossless rp_lossless(OFstatic_cast(int, opt_selection_value), OFstatic_cast(int, opt_point_transform)); DJ_RPLossy rp_lossy(OFstatic_cast(int, opt_quality)); const DcmRepresentationParameter *rp = &rp_lossy; if (lossless) rp = &rp_lossless; if (dataset->chooseRepresentation(opt_oxfer, rp).good() && dataset->canWriteXfer(opt_oxfer)) { OFLOG_INFO(dcmcjpegLogger, "Output transfer syntax " << opt_oxferSyn.getXferName() << " can be written"); } else { OFLOG_FATAL(dcmcjpegLogger, "no conversion to transfer syntax " << opt_oxferSyn.getXferName() << " possible!"); return 1; } OFLOG_INFO(dcmcjpegLogger, "creating output file " << opt_ofname); fileformat.loadAllDataIntoMemory(); error = fileformat.saveFile(opt_ofname, opt_oxfer, opt_oenctype, opt_oglenc, opt_opadenc, OFstatic_cast(Uint32, opt_filepad), OFstatic_cast(Uint32, opt_itempad), EWM_updateMeta); if (error.bad()) { OFLOG_FATAL(dcmcjpegLogger, error.text() << ": writing file: " << opt_ofname); return 1; } OFLOG_INFO(dcmcjpegLogger, "conversion successful"); // deregister global codecs DJDecoderRegistration::cleanup(); DJEncoderRegistration::cleanup(); return 0; }