Patch #661 » i2d_multiframe.patch.patch
dcmdata/apps/img2dcm.cc | ||
---|---|---|
#define OFFIS_CONSOLE_APPLICATION "img2dcm"
|
||
static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $";
|
||
#if defined (HAVE_WINDOWS_H) || defined(HAVE_FNMATCH_H)
|
||
#define PATTERN_MATCHING_AVAILABLE
|
||
#endif
|
||
#define SHORTCOL 4
|
||
#define LONGCOL 21
|
||
... | ... | |
cmd.addOption("--disable-ext", "-de", "disable support for extended sequential JPEG");
|
||
cmd.addOption("--insist-on-jfif", "-jf", "insist on JFIF header");
|
||
cmd.addOption("--keep-appn", "-ka", "keep APPn sections (except JFIF)");
|
||
cmd.addSubGroup("input files:");
|
||
cmd.addOption("--scan-directory", "+sd", "scan directory for input files (imgfile-in)");
|
||
#ifdef PATTERN_MATCHING_AVAILABLE
|
||
cmd.addOption("--scan-pattern", "+sp", 1, "[p]attern: string (only with --scan-directories)",
|
||
"pattern for filename matching (wildcards)");
|
||
#endif
|
||
cmd.addOption("--no-recurse", "-r", "do not recurse within directories (default)");
|
||
cmd.addOption("--recurse", "+r", "recurse within specified directories");
|
||
cmd.addGroup("processing options:", LONGCOL, SHORTCOL + 2);
|
||
cmd.addSubGroup("attribute checking:");
|
||
... | ... | |
cmd.addGroup("output options:");
|
||
cmd.addSubGroup("target SOP class:");
|
||
cmd.addOption("--sec-capture", "-sc", "write Secondary Capture SOP class (default)");
|
||
cmd.addOption("--new-sc", "-nsc", "write new Secondary Capture SOP classes");
|
||
cmd.addOption("--new-sc", "-nsc", "write new Multiframe Secondary Capture SOP classes (default for multiframe)");
|
||
cmd.addOption("--vl-photo", "-vlp", "write Visible Light Photographic SOP class");
|
||
cmd.addSubGroup("output file format:");
|
||
... | ... | |
{
|
||
// Parse command line and exclusive options
|
||
prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION);
|
||
OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION, "Convert standard image formats into DICOM format", rcsid);
|
||
OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION, "Convert standard image formats into DICOM format. Supports multiframe creation.", rcsid);
|
||
if (app.parseCommandLine(cmd, argc, argv))
|
||
{
|
||
/* check exclusive options first */
|
||
... | ... | |
// The transfer syntax proposed to be written by output plugin
|
||
E_TransferSyntax writeXfer;
|
||
//input file options
|
||
OFBool scanDir = OFFalse;
|
||
OFBool recurse = OFFalse;
|
||
OFString scanPattern = "";
|
||
//input file(s)
|
||
OFList<OFString> inputFiles;
|
||
// Parse rest of command line options
|
||
OFLog::configureFromCommandLine(cmd, app);
|
||
... | ... | |
}
|
||
OFLOG_INFO(img2dcmLogger, OFFIS_CONSOLE_APPLICATION ": Instantiated input plugin: " << inputPlug->inputFormat());
|
||
if (cmd.findOption("--scan-directory")) scanDir = OFTrue;
|
||
#ifdef PATTERN_MATCHING_AVAILABLE
|
||
if (cmd.findOption("--scan-pattern"))
|
||
{
|
||
app.checkDependence("--scan-pattern", "--scan-directory", scanDir);
|
||
app.checkValue(cmd.getValue(scanPattern));
|
||
}
|
||
#endif
|
||
cmd.beginOptionBlock();
|
||
if (cmd.findOption("--no-recurse")) recurse = OFFalse;
|
||
if (cmd.findOption("--recurse"))
|
||
{
|
||
app.checkDependence("--recurse", "--scan-directories", scanDir);
|
||
recurse = OFTrue;
|
||
}
|
||
cmd.endOptionBlock();
|
||
|
||
//scan for input files
|
||
if (scanDir)
|
||
{
|
||
//validate directory for beeing directory or file
|
||
if (!OFStandard::dirExists(pixDataFile))
|
||
{
|
||
OFLOG_ERROR(img2dcmLogger, "Directory input scanning option needs a folder as input");
|
||
return EC_IllegalCall;
|
||
}
|
||
OFStandard::searchDirectoryRecursively( pixDataFile, inputFiles, scanPattern, "", recurse );
|
||
}
|
||
else
|
||
inputFiles.push_front(pixDataFile);
|
||
|
||
// Find out which plugin to use
|
||
cmd.beginOptionBlock();
|
||
if (cmd.findOption("--sec-capture"))
|
||
... | ... | |
outPlug = new I2DOutputPlugNewSC();
|
||
cmd.endOptionBlock();
|
||
if (!outPlug) // default is the old Secondary Capture object
|
||
outPlug = new I2DOutputPlugSC();
|
||
{
|
||
if (scanDir) //default for multiframe input is new Multiframe Secondary Caputrue
|
||
outPlug = new I2DOutputPlugNewSC();
|
||
else
|
||
outPlug = new I2DOutputPlugSC();
|
||
}
|
||
if (outPlug == NULL) return EC_MemoryExhausted;
|
||
OFLOG_INFO(img2dcmLogger, OFFIS_CONSOLE_APPLICATION ": Instantiated output plugin: " << outPlug->ident());
|
||
... | ... | |
if ( cmd.findOption("--keep-appn") )
|
||
jpgSource->setKeepAPPn(OFTrue);
|
||
}
|
||
inputPlug->setImageFile(pixDataFile);
|
||
/* make sure data dictionary is loaded */
|
||
if (!dcmDataDict.isDictionaryLoaded())
|
||
... | ... | |
DcmDataset *resultObject = NULL;
|
||
OFLOG_INFO(img2dcmLogger, OFFIS_CONSOLE_APPLICATION ": Starting image conversion");
|
||
cond = i2d.convert(inputPlug, outPlug, resultObject, writeXfer);
|
||
cond = i2d.convert(inputPlug, outPlug, &inputFiles, resultObject, writeXfer);
|
||
// Save
|
||
if (cond.good())
|
dcmdata/include/dcmtk/dcmdata/libi2d/i2d.h | ||
---|---|---|
* a dataset with the resulting DICOM object.
|
||
* @param inputPlug - [in] The input plugin to read pixel data
|
||
* @param outPlug - [in] The output plugin for specific SOP class output
|
||
* @param imageFiles - [in] The image input file(s) as source for the input plugin
|
||
* @param resultDset - [out] The DICOM object resulting from the conversion
|
||
* @param proposedTS - [out] The proposed transfer syntax (needed e. g.
|
||
* by JPEG input plugin)
|
||
... | ... | |
*/
|
||
OFCondition convert(I2DImgSource *inputPlug,
|
||
I2DOutputPlug *outPlug,
|
||
OFList<OFString>* imageFiles,
|
||
DcmDataset*& resultDset,
|
||
E_TransferSyntax& proposedTS);
|
||
... | ... | |
OFBool insertMissingType2 = OFTrue,
|
||
OFBool inventMissingType1 = OFTrue);
|
||
/** Destructor, frees plugin memory
|
||
* @return none
|
||
*/
|
||
... | ... | |
/** Reads pixel data and corresponding attributes like rows etc. from image
|
||
* file and inserts them into dataset.
|
||
* @param imageSource - [in] The input plugin that actually reads the pixel data
|
||
* @param imageFiles - [in] The image input file(s) as source for the input plugin
|
||
* @param dset - [out] The dataset to export the pixel data attributes to
|
||
* @param outputTS - [out] The proposed transfex syntax of the dataset
|
||
* @return EC_Normal, if successful, error otherwise
|
||
*/
|
||
OFCondition readAndInsertPixelData( I2DImgSource* imageSource,
|
||
OFList<OFString>* imageFiles,
|
||
DcmDataset* dset,
|
||
E_TransferSyntax& outputTS);
|
||
... | ... | |
private:
|
||
/** Correctly inserts encapsulated pixel data.
|
||
* @param dset [in] - The dataset to which we should add this.
|
||
* @param pixData [in] - The data to add.
|
||
* @param length [in] - The length of pixData.
|
||
* @param outputTS [in] - The output transfer syntax to be used
|
||
* @return EC_Normal, if successfull, error otherwise.
|
||
*/
|
||
OFCondition insertEncapsulatedPixelData(DcmDataset* dset,
|
||
char *pixData,
|
||
Uint32 length,
|
||
const E_TransferSyntax& outputTS) const;
|
||
/* Attributes for writing DICOM dataset */
|
||
/// These attributes are applied to the dataset after conversion
|
dcmdata/include/dcmtk/dcmdata/libi2d/i2dbmps.h | ||
---|---|---|
* information is removed from the BMP stream.
|
||
* This function allocates memory for the pixel data returned to the user.
|
||
* The caller of this function is responsible for deleting the memory buffer.
|
||
* @param rows - [out] Rows of image
|
||
* @param cols - [out] Columns of image
|
||
* @param samplesPerPixel - [out] Number of components per pixel
|
||
* @param photoMetrInt - [out] The DICOM color model used for the compressed data
|
||
* @param bitsAlloc - [out] Bits Allocated for one sample
|
||
* @param bitsStored - [out] Bits Stored, Number of bits actually stored within
|
||
* Bits Allocated
|
||
* @param highBit - [out] High Bit, Highest stored in bit within Bits Allocated
|
||
* @param pixelRepr - [out] Pixel Representation (0=unsigned, 1=signed)
|
||
* @param planConf - [out] Planar Configuration
|
||
* @param pixAspectH - [out] Horizontal value of pixel aspect ratio
|
||
* @param pixAspectV - [out] Vertical value of pixel aspect ratio
|
||
* @param imgInfo - [out] Collection of Dicom Image Informations
|
||
* @param pixData - [out] Pointer to the pixel data in BMP Interchange Format
|
||
* @param length - [out] Length of pixel data
|
||
* @param ts - [out] The transfer syntax imposed by the imported pixel pixel data
|
||
* @return EC_Normal, if successful, error otherwise
|
||
*/
|
||
OFCondition readPixelData( Uint16& rows,
|
||
Uint16& cols,
|
||
Uint16& samplesPerPixel,
|
||
OFString& photoMetrInt,
|
||
Uint16& bitsAlloc,
|
||
Uint16& bitsStored,
|
||
Uint16& highBit,
|
||
Uint16& pixelRepr,
|
||
Uint16& planConf,
|
||
Uint16& pixAspectH,
|
||
Uint16& pixAspectV,
|
||
OFCondition readPixelData( I2DImgDataInfo& imgInfo,
|
||
char*& pixData,
|
||
Uint32& length,
|
||
E_TransferSyntax& ts);
|
||
Uint32& length);
|
||
/** After reading of pixel data, this function can be used for getting
|
||
* information about lossy compression parameters.
|
dcmdata/include/dcmtk/dcmdata/libi2d/i2dimgs.h | ||
---|---|---|
#include "dcmtk/dcmdata/dcxfer.h"
|
||
#include "dcmtk/dcmdata/libi2d/i2define.h"
|
||
struct I2DImgDataInfo
|
||
{
|
||
/** Helper structure for storing and comparing extracted pixel data image informations
|
||
*/
|
||
//Rows of image
|
||
Uint16 rows;
|
||
//Columns of image
|
||
Uint16 cols;
|
||
//Number of components per pixel
|
||
Uint16 samplesPerPixel;
|
||
//The DICOM color model used for the compressed data
|
||
OFString photoMetrInt;
|
||
//Bits Allocated for one sample
|
||
Uint16 bitsAlloc;
|
||
//Bits Stored, number of bits stored within Bits Allocated
|
||
Uint16 bitsStored;
|
||
//High Bit, hightest bit position set within Bits Allocated
|
||
Uint16 highBit;
|
||
//Pixel Representation (0=unsigned, 1=signed)
|
||
Uint16 pixelRepr;
|
||
//Planar Configuration
|
||
Uint16 planConf;
|
||
//Horizontal value of pixel aspect ratio
|
||
Uint16 pixAspectH;
|
||
//Vertical value of pixel aspect ratio
|
||
Uint16 pixAspectV;
|
||
//The transfer syntax imposed by the imported pixel pixel data.
|
||
//This is necessary for the JPEG importer that needs to report
|
||
//which TS must be used for the imported JPEG data (ie. baseline, progressive, ...).
|
||
E_TransferSyntax transSyn;
|
||
/** Compares if all members of both instances are equal
|
||
* @param other - [in] comparism instance
|
||
* @return True if all member are identical, false otherwise
|
||
*/
|
||
OFBool operator==(const I2DImgDataInfo& other)
|
||
{
|
||
return
|
||
(rows == other.rows) &&
|
||
(cols == other.cols) &&
|
||
(samplesPerPixel == other.samplesPerPixel) &&
|
||
(photoMetrInt == other.photoMetrInt) &&
|
||
(bitsAlloc == other.bitsAlloc) &&
|
||
(bitsStored == other.bitsStored) &&
|
||
(highBit == other.highBit) &&
|
||
(pixelRepr == other.pixelRepr) &&
|
||
(planConf == other.planConf) &&
|
||
(pixAspectH == other.pixAspectH) &&
|
||
(pixAspectV == other.pixAspectV) &&
|
||
(transSyn == other.transSyn);
|
||
};
|
||
OFBool operator!=(const I2DImgDataInfo& other)
|
||
{
|
||
return !(*this == other);
|
||
};
|
||
};
|
||
/** Base Class for plugins extracting pixel data from standard image files
|
||
*/
|
||
class DCMTK_I2D_EXPORT I2DImgSource
|
||
... | ... | |
* information about this pixel data.
|
||
* This function allocates memory for the pixel data returned to the user.
|
||
* The caller of this function is responsible for deleting the memory buffer
|
||
* @param rows - [out] Rows of image
|
||
* @param cols - [out] Columns of image
|
||
* @param samplesPerPixel - [out] Number of components per pixel
|
||
* @param photoMetrInt - [out] The DICOM color model used for the compressed data
|
||
* @param bitsAlloc - [out] Bits Allocated for one sample
|
||
* @param bitsStored - [out] Bits Stored, number of bits stored within Bits Allocated
|
||
* @param highBit - [out] High Bit, highest bit position set within Bits Allocated
|
||
* @param pixelRepr - [out] Pixel Representation (0=unsigned, 1=signed)
|
||
* @param planConf - [out] Planar Configuration
|
||
* @param pixAspectH - [out] Horizontal value of pixel aspect ratio
|
||
* @param pixAspectV - [out] Vertical value of pixel aspect ratio
|
||
* @param imgInfo - [out] Collection of Dicom Image Informations
|
||
* @param pixData - [out] Pointer to the pixel data
|
||
* @param length - [out] Length of pixel data
|
||
* @param ts - [out] The transfer syntax imposed by the imported pixel pixel data
|
||
* @return EC_Normal, if successful, error otherwise
|
||
*/
|
||
virtual OFCondition readPixelData( Uint16& rows,
|
||
Uint16& cols,
|
||
Uint16& samplesPerPixel,
|
||
OFString& photoMetrInt,
|
||
Uint16& bitsAlloc,
|
||
Uint16& bitsStored,
|
||
Uint16& highBit,
|
||
Uint16& pixelRepr,
|
||
Uint16& planConf,
|
||
Uint16& pixAspectH,
|
||
Uint16& pixAspectV,
|
||
virtual OFCondition readPixelData( I2DImgDataInfo& imgInfo,
|
||
char*& pixData,
|
||
Uint32& length,
|
||
E_TransferSyntax& ts) =0;
|
||
Uint32& length) =0;
|
||
/** After reading of pixel data, this function can be used for getting
|
||
* information about lossy compression parameters.
|
dcmdata/include/dcmtk/dcmdata/libi2d/i2djpgs.h | ||
---|---|---|
* The pixel data returned is a JPEG stream in JPEG interchange format.
|
||
* This function allocates memory for the pixel data returned to the user.
|
||
* The caller of this function is responsible for deleting the memory buffer.
|
||
* @param rows - [out] Rows of image
|
||
* @param cols - [out] Columns of image
|
||
* @param samplesPerPixel - [out] Number of components per pixel
|
||
* @param photoMetrInt - [out] The DICOM color model used for the compressed data
|
||
* @param bitsAlloc - [out] Bits Allocated for one sample
|
||
* @param bitsStored - [out] Bits Stored, Number of bits actually stored within
|
||
* Bits Allocated
|
||
* @param highBit - [out] High Bit, Highest stored in bit within Bits Allocated
|
||
* @param pixelRepr - [out] Pixel Representation (0=unsigned, 1=signed)
|
||
* @param planConf - [out] Planar Configuration
|
||
* @param pixAspectH - [out] Horizontal value of pixel aspect ratio
|
||
* @param pixAspectV - [out] Vertical value of pixel aspect ratio
|
||
* @param imgInfo - [out] Collection of Dicom Image Informations
|
||
* @param pixData - [out] Pointer to the pixel data in JPEG Interchange Format
|
||
* (but without APPx markers).
|
||
* @param length - [out] Length of pixel data
|
||
* @param ts - [out] The transfer syntax imposed by the imported pixel pixel
|
||
* data. This is necessary for the JPEG importer that needs
|
||
* to report which TS must be used for the imported JPEG data
|
||
* (ie. baseline, progressive, ...).
|
||
* @return EC_Normal, if successful, error otherwise
|
||
*/
|
||
OFCondition readPixelData( Uint16& rows,
|
||
Uint16& cols,
|
||
Uint16& samplesPerPixel,
|
||
OFString& photoMetrInt,
|
||
Uint16& bitsAlloc,
|
||
Uint16& bitsStored,
|
||
Uint16& highBit,
|
||
Uint16& pixelRepr,
|
||
Uint16& planConf,
|
||
Uint16& pixAspectH,
|
||
Uint16& pixAspectV,
|
||
OFCondition readPixelData( I2DImgDataInfo& imgInfo,
|
||
char*& pixData,
|
||
Uint32& length,
|
||
E_TransferSyntax& ts);
|
||
Uint32& length);
|
||
/** After reading of pixel data, this function can be used for getting
|
||
* information about lossy compression parameters.
|
dcmdata/libi2d/i2d.cc | ||
---|---|---|
OFCondition Image2Dcm::convert(I2DImgSource *inputPlug,
|
||
I2DOutputPlug *outPlug,
|
||
OFList<OFString>* imageFiles,
|
||
DcmDataset*& resultDset,
|
||
E_TransferSyntax& proposedTS)
|
||
... | ... | |
generateUIDs(resultDset);
|
||
// Read and insert pixel data
|
||
cond = readAndInsertPixelData(inputPlug, resultDset, proposedTS);
|
||
cond = readAndInsertPixelData(inputPlug, imageFiles, resultDset, proposedTS);
|
||
if (cond.bad())
|
||
{
|
||
delete resultDset; resultDset = NULL;
|
||
... | ... | |
}
|
||
OFCondition Image2Dcm::insertEncapsulatedPixelData(DcmDataset* dset,
|
||
char *pixData,
|
||
Uint32 length,
|
||
const E_TransferSyntax& outputTS) const
|
||
OFCondition Image2Dcm::readAndInsertPixelData(I2DImgSource* imageSource,
|
||
OFList<OFString>* imageFiles,
|
||
DcmDataset* dset,
|
||
E_TransferSyntax& outputTS)
|
||
{
|
||
OFCondition cond;
|
||
I2DImgDataInfo imgInfo, frameInfo;
|
||
imgInfo.transSyn = EXS_Unknown;
|
||
DCMDATA_LIBI2D_DEBUG("Image2Dcm: Storing imported pixel data to DICOM file");
|
||
// create initial pixel sequence
|
||
DcmPixelSequence* pixelSequence = new DcmPixelSequence(DcmTag(DCM_PixelData, EVR_OB));
|
||
if (pixelSequence == NULL)
|
||
return EC_MemoryExhausted;
|
||
char* pixData = NULL;
|
||
Uint32 length;
|
||
// insert empty offset table into sequence
|
||
DcmPixelItem *offsetTable = new DcmPixelItem(DcmTag(DCM_Item, EVR_OB));
|
||
if (offsetTable == NULL)
|
||
{
|
||
delete pixelSequence; pixelSequence = NULL;
|
||
return EC_MemoryExhausted;
|
||
}
|
||
cond = pixelSequence->insert(offsetTable);
|
||
if (cond.bad())
|
||
{
|
||
delete offsetTable; offsetTable = NULL;
|
||
delete pixelSequence; pixelSequence = NULL;
|
||
return cond;
|
||
}
|
||
//check for having at least one image frame
|
||
if (imageFiles->empty())
|
||
return makeOFCondition(OFM_dcmdata, 18, OF_error, "No input file(s) available");
|
||
// store compressed frame into pixel sequence
|
||
DcmOffsetList dummyList;
|
||
cond = pixelSequence->storeCompressedFrame(dummyList, OFreinterpret_cast(Uint8*,pixData), length, 0);
|
||
// storeCompressedFrame(..) does a deep copy, so the pixData memory can be freed now
|
||
delete[] pixData;
|
||
|
||
//decode first image
|
||
OFIterator<OFString> imageIter = imageFiles->begin();
|
||
OFIterator<OFString> imageEnd = imageFiles->end();
|
||
imageSource->setImageFile(*imageIter);
|
||
OFCondition cond = imageSource->readPixelData(imgInfo, pixData, length);
|
||
if (cond.bad())
|
||
{
|
||
delete pixelSequence; pixelSequence = NULL;
|
||
return cond;
|
||
}
|
||
// insert pixel data attribute incorporating pixel sequence into dataset
|
||
DcmPixelData *pixelData = new DcmPixelData(DCM_PixelData);
|
||
if (pixelData == NULL)
|
||
{
|
||
delete pixelSequence; pixelSequence = NULL;
|
||
return EC_MemoryExhausted;
|
||
}
|
||
/* tell pixel data element that this is the original presentation of the pixel data
|
||
* pixel data and how it compressed
|
||
*/
|
||
pixelData->putOriginalRepresentation(outputTS, NULL, pixelSequence);
|
||
cond = dset->insert(pixelData);
|
||
if (cond.bad())
|
||
//store transfer syntax
|
||
outputTS = imgInfo.transSyn;
|
||
//differ between encapsulated and raw image data and process all data and frames
|
||
// - also check for identical images
|
||
DcmXfer transport(imgInfo.transSyn);
|
||
if (transport.isEncapsulated())
|
||
{
|
||
delete pixelData; pixelData = NULL; // also deletes contained pixel sequence
|
||
return cond;
|
||
}
|
||
//insert first pixel frame
|
||
DCMDATA_LIBI2D_DEBUG("Image2Dcm: Storing imported pixel data to DICOM file");
|
||
return EC_Normal;
|
||
}
|
||
// create initial pixel sequence
|
||
DcmPixelSequence* pixelSequence = new DcmPixelSequence(DcmTag(DCM_PixelData, EVR_OB));
|
||
if (pixelSequence == NULL)
|
||
return EC_MemoryExhausted;
|
||
// insert empty offset table into sequence
|
||
DcmPixelItem *offsetTable = new DcmPixelItem(DcmTag(DCM_Item, EVR_OB));
|
||
if (offsetTable == NULL)
|
||
{
|
||
delete pixelSequence; pixelSequence = NULL;
|
||
return EC_MemoryExhausted;
|
||
}
|
||
cond = pixelSequence->insert(offsetTable);
|
||
if (cond.bad())
|
||
{
|
||
delete offsetTable; offsetTable = NULL;
|
||
delete pixelSequence; pixelSequence = NULL;
|
||
return cond;
|
||
}
|
||
OFCondition Image2Dcm::readAndInsertPixelData(I2DImgSource* imgSource,
|
||
DcmDataset* dset,
|
||
E_TransferSyntax& outputTS)
|
||
{
|
||
Uint16 samplesPerPixel, rows, cols, bitsAlloc, bitsStored, highBit, pixelRepr, planConf;
|
||
Uint16 pixAspectH =1; Uint16 pixAspectV = 1;
|
||
OFString photoMetrInt;
|
||
outputTS = EXS_Unknown;
|
||
char* pixData = NULL;
|
||
Uint32 length;
|
||
// store compressed frame into pixel seqeuence
|
||
DcmOffsetList dummyList;
|
||
cond = pixelSequence->storeCompressedFrame(dummyList, OFreinterpret_cast(Uint8*,pixData), length, 0);
|
||
// storeCompressedFrame(..) does a deep copy, so the pixdata memory can be freed now
|
||
delete[] pixData;
|
||
if (cond.bad())
|
||
{
|
||
delete pixelSequence; pixelSequence = NULL;
|
||
return cond;
|
||
}
|
||
OFCondition cond = imgSource->readPixelData(rows, cols,
|
||
samplesPerPixel, photoMetrInt, bitsAlloc, bitsStored, highBit, pixelRepr,
|
||
planConf, pixAspectH, pixAspectV, pixData, length, outputTS);
|
||
//process all remaining frames
|
||
while( ++imageIter != imageEnd )
|
||
{
|
||
//decode next frame
|
||
imageSource->setImageFile(*imageIter);
|
||
OFCondition cond = imageSource->readPixelData(frameInfo, pixData, length);
|
||
if (cond.bad())
|
||
return cond;
|
||
if (cond.bad())
|
||
return cond;
|
||
//compare for identical frame info: size, type, etc
|
||
if (frameInfo != imgInfo)
|
||
return makeOFCondition(OFM_dcmdata, 18, OF_error, "Input files differ in size and or type");
|
||
DcmXfer transport(outputTS);
|
||
if (transport.isEncapsulated())
|
||
insertEncapsulatedPixelData(dset, pixData, length, outputTS);
|
||
//finaly add the new frame
|
||
cond = pixelSequence->storeCompressedFrame(dummyList, OFreinterpret_cast(Uint8*,pixData), length, 0);
|
||
// storeCompressedFrame(..) does a deep copy, so the pixdata memory can be freed now
|
||
delete[] pixData;
|
||
if (cond.bad())
|
||
{
|
||
delete pixelSequence; pixelSequence = NULL;
|
||
return cond;
|
||
}
|
||
}
|
||
// insert pixel data attribute incorporating pixel sequence into dataset
|
||
DcmPixelData *pixelData = new DcmPixelData(DCM_PixelData);
|
||
if (pixelData == NULL)
|
||
{
|
||
delete pixelSequence; pixelSequence = NULL;
|
||
return EC_MemoryExhausted;
|
||
}
|
||
/* tell pixel data element that this is the original presentation of the pixel data
|
||
* pixel data and how it compressed
|
||
*/
|
||
pixelData->putOriginalRepresentation(imgInfo.transSyn, NULL, pixelSequence);
|
||
cond = dset->insert(pixelData);
|
||
if (cond.bad())
|
||
{
|
||
delete pixelData; pixelData = NULL; // also deletes contained pixel sequence
|
||
return cond;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
/* Not encapsulated */
|
||
dset->putAndInsertUint8Array(DCM_PixelData, OFreinterpret_cast(Uint8*, pixData), length);
|
||
delete[] pixData;
|
||
//single frame? just insert the data and finish
|
||
if (imageFiles->size() == 1)
|
||
{
|
||
cond = dset->putAndInsertUint8Array(DCM_PixelData, OFreinterpret_cast(Uint8*, pixData), length);
|
||
delete[] pixData;
|
||
if (cond.bad())
|
||
return cond;
|
||
}
|
||
else
|
||
{
|
||
//multiframe
|
||
//try to allocate enough space for all image frames
|
||
// - first check, if we hit the 2GB limit
|
||
// - we need to allocate n times the first image size
|
||
Uint64 byteSize = Uint64(length) * Uint64(imageFiles->size());
|
||
if (byteSize > Uint64(2*1024)*Uint64(1024*1024))
|
||
{
|
||
delete[] pixData;
|
||
return makeOFCondition(OFM_dcmdata, 18, OF_error, "Multiframe image data size will exceed 2GB limit.");
|
||
}
|
||
//allocate enough space
|
||
char* frameData = new char[Uint32(byteSize)];
|
||
char* framePos = frameData;
|
||
//fill first frame
|
||
memcpy(framePos, pixData, length);
|
||
delete[] pixData;
|
||
//move to next frame position
|
||
framePos += length;
|
||
//process all remaining frames
|
||
while( ++imageIter != imageEnd )
|
||
{
|
||
//decode next frame
|
||
imageSource->setImageFile(*imageIter);
|
||
OFCondition cond = imageSource->readPixelData(frameInfo, pixData, length);
|
||
if (cond.bad())
|
||
return cond;
|
||
//compare for identical frame info: size, type, etc
|
||
if (frameInfo != imgInfo)
|
||
return makeOFCondition(OFM_dcmdata, 18, OF_error, "Input files differ in size and or type");
|
||
//copy current frame data
|
||
memcpy(framePos, pixData, length);
|
||
delete[] pixData;
|
||
//move to next frame position
|
||
framePos += length;
|
||
}
|
||
//now store the framedata inside dataset
|
||
//- avoid a deep copy /TODO
|
||
cond = dset->putAndInsertUint8Array(DCM_PixelData, OFreinterpret_cast(Uint8*, frameData), (framePos-frameData));
|
||
delete[] frameData; //TODO - remove the need for this
|
||
if (cond.bad())
|
||
return cond;
|
||
}
|
||
}
|
||
DCMDATA_LIBI2D_DEBUG("Image2Dcm: Inserting Image Pixel module information");
|
||
cond = dset->putAndInsertUint16(DCM_SamplesPerPixel, samplesPerPixel);
|
||
cond = dset->putAndInsertUint16(DCM_SamplesPerPixel, frameInfo.samplesPerPixel);
|
||
if (cond.bad())
|
||
return cond;
|
||
cond = dset->putAndInsertOFStringArray(DCM_PhotometricInterpretation, photoMetrInt);
|
||
cond = dset->putAndInsertOFStringArray(DCM_PhotometricInterpretation, frameInfo.photoMetrInt);
|
||
if (cond.bad())
|
||
return cond;
|
||
// Should only be written if Samples per Pixel > 1
|
||
if (samplesPerPixel > 1)
|
||
if (frameInfo.samplesPerPixel > 1)
|
||
{
|
||
cond = dset->putAndInsertUint16(DCM_PlanarConfiguration, planConf);
|
||
cond = dset->putAndInsertUint16(DCM_PlanarConfiguration, frameInfo.planConf);
|
||
if (cond.bad())
|
||
return cond;
|
||
}
|
||
cond = dset->putAndInsertUint16(DCM_Rows, rows);
|
||
cond = dset->putAndInsertUint16(DCM_Rows, frameInfo.rows);
|
||
if (cond.bad())
|
||
return cond;
|
||
cond = dset->putAndInsertUint16(DCM_Columns, cols);
|
||
cond = dset->putAndInsertUint16(DCM_Columns, frameInfo.cols);
|
||
if (cond.bad())
|
||
return cond;
|
||
cond = dset->putAndInsertUint16(DCM_BitsAllocated, bitsAlloc);
|
||
cond = dset->putAndInsertUint16(DCM_BitsAllocated, frameInfo.bitsAlloc);
|
||
if (cond.bad())
|
||
return cond;
|
||
cond = dset->putAndInsertUint16(DCM_BitsStored, bitsStored);
|
||
cond = dset->putAndInsertUint16(DCM_BitsStored, frameInfo.bitsStored);
|
||
if (cond.bad())
|
||
return cond;
|
||
cond = dset->putAndInsertUint16(DCM_HighBit, highBit);
|
||
cond = dset->putAndInsertUint16(DCM_HighBit, frameInfo.highBit);
|
||
if (cond.bad())
|
||
return cond;
|
||
if ( pixAspectH != pixAspectV )
|
||
//add frame count if multiframe image
|
||
if (imageFiles->size() > 1)
|
||
{
|
||
char buf[200];
|
||
int err = sprintf(buf, "%u", imageFiles->size());
|
||
if (err == -1) return EC_IllegalCall;
|
||
cond = dset->putAndInsertOFStringArray(DCM_NumberOfFrames, buf);
|
||
if (cond.bad())
|
||
return cond;
|
||
cond = dset->putAndInsertString(DCM_FrameIncrementPointer, "");
|
||
if (cond.bad())
|
||
return cond;
|
||
}
|
||
if ( frameInfo.pixAspectH != frameInfo.pixAspectV )
|
||
{
|
||
char buf[200];
|
||
int err = sprintf(buf, "%u\\%u", pixAspectV, pixAspectH);
|
||
int err = sprintf(buf, "%u\\%u", frameInfo.pixAspectV, frameInfo.pixAspectH);
|
||
if (err == -1) return EC_IllegalCall;
|
||
cond = dset->putAndInsertOFStringArray(DCM_PixelAspectRatio, buf);
|
||
if (cond.bad())
|
||
return cond;
|
||
}
|
||
return dset->putAndInsertUint16(DCM_PixelRepresentation, pixelRepr);
|
||
return dset->putAndInsertUint16(DCM_PixelRepresentation, frameInfo.pixelRepr);
|
||
}
|
||
dcmdata/libi2d/i2dbmps.cc | ||
---|---|---|
}
|
||
OFCondition I2DBmpSource::readPixelData(Uint16& rows,
|
||
Uint16& cols,
|
||
Uint16& samplesPerPixel,
|
||
OFString& photoMetrInt,
|
||
Uint16& bitsAlloc,
|
||
Uint16& bitsStored,
|
||
Uint16& highBit,
|
||
Uint16& pixelRepr,
|
||
Uint16& planConf,
|
||
Uint16& pixAspectH,
|
||
Uint16& pixAspectV,
|
||
char*& pixData,
|
||
Uint32& length,
|
||
E_TransferSyntax &ts)
|
||
OFCondition I2DBmpSource::readPixelData(I2DImgDataInfo& imgInfo,
|
||
char*& pixData,
|
||
Uint32& length)
|
||
{
|
||
DCMDATA_LIBI2D_DEBUG("I2DBmpSource: Importing BMP pixel data");
|
||
OFCondition cond = openFile(m_imageFile);
|
||
... | ... | |
/* Now we got all the info that we need, return it to caller */
|
||
rows = height;
|
||
cols = width;
|
||
samplesPerPixel = 3; /* 24 bpp */
|
||
imgInfo.rows = height;
|
||
imgInfo.cols = width;
|
||
imgInfo.samplesPerPixel = 3; /* 24 bpp */
|
||
bitsAlloc = 8;
|
||
bitsStored = 8;
|
||
highBit = 7;
|
||
photoMetrInt = "RGB";
|
||
planConf = 0; /* For each pixel we save rgb in that order */
|
||
imgInfo.bitsAlloc = 8;
|
||
imgInfo.bitsStored = 8;
|
||
imgInfo.highBit = 7;
|
||
imgInfo.photoMetrInt = "RGB";
|
||
imgInfo.planConf = 0; /* For each pixel we save rgb in that order */
|
||
pixData = data;
|
||
length = data_length;
|
||
pixAspectH = pixAspectV = 1;
|
||
pixelRepr = 0;
|
||
ts = EXS_LittleEndianExplicit;
|
||
imgInfo.pixAspectH = imgInfo.pixAspectV = 1;
|
||
imgInfo.pixelRepr = 0;
|
||
imgInfo.transSyn = EXS_LittleEndianExplicit;
|
||
return cond;
|
||
}
|
dcmdata/libi2d/i2djpgs.cc | ||
---|---|---|
}
|
||
OFCondition I2DJpegSource::readPixelData(Uint16& rows,
|
||
Uint16& cols,
|
||
Uint16& samplesPerPixel,
|
||
OFString& photoMetrInt,
|
||
Uint16& bitsAlloc,
|
||
Uint16& bitsStored,
|
||
Uint16& highBit,
|
||
Uint16& pixelRepr,
|
||
Uint16& planConf,
|
||
Uint16& pixAspectH,
|
||
Uint16& pixAspectV,
|
||
OFCondition I2DJpegSource::readPixelData(I2DImgDataInfo& imgInfo,
|
||
char*& pixData,
|
||
Uint32& length,
|
||
E_TransferSyntax &ts)
|
||
Uint32& length)
|
||
{
|
||
DCMDATA_LIBI2D_DEBUG("I2DJpegSource: Importing JPEG pixel data");
|
||
OFCondition cond = openFile(m_imageFile);
|
||
... | ... | |
}
|
||
// Get transfer syntax associated with the given JPEG encoding
|
||
ts = associatedTS(jpegEncoding);
|
||
imgInfo.transSyn = associatedTS(jpegEncoding);
|
||
// Extract width, height, samples per pixel, bits per sample
|
||
Uint16 width, height, spp, bps;
|
||
... | ... | |
return cond;
|
||
}
|
||
}
|
||
pixAspectH = aspectH;
|
||
pixAspectV = aspectV;
|
||
imgInfo.pixAspectH = aspectH;
|
||
imgInfo.pixAspectV = aspectV;
|
||
// Collect information needed for image pixel module
|
||
rows = height;
|
||
cols = width;
|
||
samplesPerPixel = spp;
|
||
bitsAlloc = bps;
|
||
bitsStored = bitsAlloc;
|
||
highBit = OFstatic_cast(Uint16, bitsStored - 1);
|
||
if (samplesPerPixel == 1)
|
||
photoMetrInt = "MONOCHROME2";
|
||
else if (samplesPerPixel == 3)
|
||
photoMetrInt = "YBR_FULL_422";
|
||
imgInfo.rows = height;
|
||
imgInfo.cols = width;
|
||
imgInfo.samplesPerPixel = spp;
|
||
imgInfo.bitsAlloc = bps;
|
||
imgInfo.bitsStored = imgInfo.bitsAlloc;
|
||
imgInfo.highBit = OFstatic_cast(Uint16, imgInfo.bitsStored - 1);
|
||
if (imgInfo.samplesPerPixel == 1)
|
||
imgInfo.photoMetrInt = "MONOCHROME2";
|
||
else if (imgInfo.samplesPerPixel == 3)
|
||
imgInfo.photoMetrInt = "YBR_FULL_422";
|
||
else
|
||
return makeOFCondition(OFM_dcmdata, 18, OF_error, "For JPEG data, Samples per Pixel must be 1 or 3");
|
||
// Planar Configuration and Pixel Representation is always 0 for JPEG data
|
||
planConf = 0;
|
||
pixelRepr = 0;
|
||
imgInfo.planConf = 0;
|
||
imgInfo.pixelRepr = 0;
|
||
Uint32 tLength = 0;
|
||
char* tPixelData = NULL;
|
dcmdata/libi2d/i2dplnsc.cc | ||
---|---|---|
if (!targetDataset)
|
||
return EC_IllegalParameter;
|
||
// We only support 1 image Multi-frames so far
|
||
return targetDataset->putAndInsertOFStringArray(DCM_NumberOfFrames, "1");
|
||
//check for existing number of frames attribute - if not available add a 1-frame attribute
|
||
if (!targetDataset->tagExistsWithValue(DCM_NumberOfFrames))
|
||
return targetDataset->putAndInsertOFStringArray(DCM_NumberOfFrames, "1");
|
||
else
|
||
return EC_Normal;
|
||
// Frame Increment pointer is set later in the more specific SC Multi-frame Image context
|
||
}
|
||
dcmdata/tests/ti2dbmp.cc | ||
---|---|---|
static bool readFile(char *&pixData, Uint32 &outputLength, Uint16 &rows, Uint16 &cols)
|
||
{
|
||
I2DBmpSource source;
|
||
Uint16 samplesPerPixel, bitsAlloc, bitsStored;
|
||
Uint16 highBit, pixelRepr, planConf, pixAspectH, pixAspectV;
|
||
OFString photoMetrInt;
|
||
E_TransferSyntax ts;
|
||
I2DImgDataInfo imgInfo;
|
||
source.setImageFile(temporaryFile);
|
||
OFCondition res = source.readPixelData(rows, cols, samplesPerPixel, photoMetrInt,
|
||
bitsAlloc, bitsStored, highBit, pixelRepr,
|
||
planConf, pixAspectH, pixAspectV, pixData,
|
||
outputLength, ts);
|
||
OFCondition res = source.readPixelData(imgInfo, pixData, outputLength);
|
||
rows = imgInfo.rows;
|
||
cols = imgInfo.cols;
|
||
if (res.bad())
|
||
{
|
||
LOG_DEBUG("Reading file failed: " << res.text());
|