diff options
author | Rafael Laboissière <rafael@debian.org> | 2022-07-08 09:28:26 -0300 |
---|---|---|
committer | Rafael Laboissière <rafael@debian.org> | 2022-07-08 09:28:26 -0300 |
commit | 4c9af98998a4e914ce7562c3abe7402c0765c89f (patch) | |
tree | 778d69b7025ec867d04db830b98990eb20b20971 | |
parent | 5bf4f2ed5986cc4819d61b716eea4417fe073185 (diff) | |
parent | 04a4e459f804652334fcbbe923b9e433090a628d (diff) |
Merge tag 'upstream/0.5.0' into debian/latest
Upstream version 0.5.0
-rw-r--r-- | DESCRIPTION | 6 | ||||
-rw-r--r-- | INDEX | 2 | ||||
-rw-r--r-- | NEWS | 9 | ||||
-rw-r--r-- | doc/dicom.pdf | bin | 309339 -> 316802 bytes | |||
-rw-r--r-- | doc/dicom.texi | 5 | ||||
-rw-r--r-- | doc/functions.texi | 240 | ||||
-rw-r--r-- | inst/dicomfind.m | 111 | ||||
-rw-r--r-- | inst/dicomupdate.m | 141 | ||||
-rw-r--r-- | inst/imdata/CT-MONO2-16-ankle.dcm | bin | 0 -> 525436 bytes | |||
-rw-r--r-- | inst/imdata/README.md | 2 | ||||
-rw-r--r-- | inst/imdata/US-PAL-8-10x-echo.dcm | bin | 0 -> 483610 bytes | |||
-rw-r--r-- | inst/imdata/rtstruct.dcm | bin | 0 -> 134254 bytes | |||
-rw-r--r-- | inst/imdata/simple-test.dcm | bin | 0 -> 1554 bytes | |||
-rw-r--r-- | inst/imdata/simpleImageWithIcon.dcm | bin | 0 -> 33862 bytes | |||
-rw-r--r-- | src/config.h.in | 3 | ||||
-rwxr-xr-x | src/configure | 826 | ||||
-rw-r--r-- | src/configure.ac | 23 | ||||
-rw-r--r-- | src/dicomanon.cpp | 3 | ||||
-rw-r--r-- | src/dicomdict.cpp | 21 | ||||
-rw-r--r-- | src/dicomdisp.cpp | 6 | ||||
-rw-r--r-- | src/dicominfo.cpp | 67 | ||||
-rw-r--r-- | src/dicomlookup.cpp | 25 | ||||
-rw-r--r-- | src/dicomread.cpp | 43 | ||||
-rw-r--r-- | src/dicomuid.cpp | 11 | ||||
-rw-r--r-- | src/dicomwrite.cpp | 24 | ||||
-rw-r--r-- | src/isdicom.cpp | 18 |
26 files changed, 1142 insertions, 444 deletions
diff --git a/DESCRIPTION b/DESCRIPTION index 998ebbc..b51c9b1 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,8 +1,8 @@ Name: dicom -Version: 0.4.1 -Date: 2022-02-22 +Version: 0.5.0 +Date: 2022-06-30 Author: Andy Buckle -Maintainer: Andy Buckle, John Donoghue +Maintainer: John Donoghue Title: dicom: file io for medical images and other data Description: Digital communications in medicine (DICOM) file io. Depends on Grassroots DICOM (GDCM). This package is not available @@ -3,9 +3,11 @@ Dicom Functions dicomanon dicomdict dicomdisp + dicomfind dicominfo dicomlookup dicomread dicomuid + dicomupdate dicomwrite isdicom @@ -1,3 +1,12 @@ + Summary of important user-visible changes for dicom 0.5.0 (2022/06/30): +------------------------------------------------------------------------- + + ** added dicomfind and dicomupdate function + + ** minor doc updates + + ** added sample data files for example usage + Summary of important user-visible changes for dicom 0.4.1 (2022/02/22): ------------------------------------------------------------------------- diff --git a/doc/dicom.pdf b/doc/dicom.pdf Binary files differindex 44ec881..7fe8ba3 100644 --- a/doc/dicom.pdf +++ b/doc/dicom.pdf diff --git a/doc/dicom.texi b/doc/dicom.texi index 56660fa..7933575 100644 --- a/doc/dicom.texi +++ b/doc/dicom.texi @@ -136,7 +136,7 @@ read and write dicom data. @example %% read the meta information from a dicom file -> info = dicominfo ('test.dcm'); +> info = dicominfo (file_in_loadpath('imdata/simple-test.dcm'); info = scalar structure containing the fields: Filename = a.dcm @@ -176,8 +176,7 @@ info = %% read the image data -> image = dicomread('test.dcm') -image = dicomread ('a.dcm') +> image = dicomread(file_in_loadpath('imdata/simple-test.dcm')) image = 0 0 0 0 0 0 0 0 0 0 diff --git a/doc/functions.texi b/doc/functions.texi index 3eccd21..5800cf3 100644 --- a/doc/functions.texi +++ b/doc/functions.texi @@ -11,6 +11,7 @@ Anonymize a DICOM format file by removing or replacing specific fields. +@subsubheading Inputs @var{file_in} is filename to read from.@* @var{file_out} is the filename to write to.@* @var{name}, @var{value} optional name/value properties.@* @@ -22,6 +23,8 @@ The value is a cell array of names to not remove during the anonymize procedure. @item update A structure of name/values to update rather than remove. @end table +@subsubheading Outputs +None @xseealso{dicomread, dicomwrite, dicominfo} @end deftypefn @@ -40,6 +43,27 @@ The first usage returns the filename of the dictionary that is currently being u Using @code{factory} resets the dictionary to the default. Using @code{set} allows setting the dictionary for future operations. In this case, the dictionary file @var{dictionary_name} can be anywhere in the path. +@subsubheading Inputs +@var{code} - string value of 'get', 'set' or 'factory'. + +@var{dictionary_name'} - name of dictionary file to use + +@subsubheading Outputs +@var{dictionary_name'} - name of dictionary file currently set for dictionaty + +@subsubheading Examples +Get current dicom dict path: + +@example +> f = dicomdict('get') +f = octavedicom.dic +@end example + +Set a new dictionary: + +@example +> dicomdict('set', 'anewdictfile.txt') +@end example @xseealso{dicomread, dicomwrite} @end deftypefn @@ -52,13 +76,43 @@ In this case, the dictionary file @var{dictionary_name} can be anywhere in the p @deftypefnx {Loadable Function} {} dicomdisp (@var{filename}, [@var{propertyname}, @var{propertvalue} ...]) Read and display the metadata from a DICOM file. +@subsubheading Inputs @var{filename} - dicomfilename to display.@* @var{propertyname}, @var{propertvalue} - property pairs for options to the display function. Currently the only known property is 'dictionary' to specify a non default dict to use. +@subsubheading Outputs +None + @xseealso{dicomread, dicominfo} @end deftypefn +@c Dicom Functions dicomfind +@c ----------------------------------------- +@subsection dicomfind +@cindex dicomfind + @deftypefn {} {@var{attrinfo}} = dicomfind(@var{filename}, @var{attribute}) + @deftypefnx {} {@var{attrinfo}} = dicomfind(@var{info}, @var{attribute}) + Find the location and value of an attribute in a dicom file or info structure. + + @subsubheading Inputs + @var{filename} - filename to open. + + @var{info} - dicominfo struct. + + @var{attribute} - attribute name to find. + + @subsubheading Outputs + @var{attrinfo} - a table with fields Location and Value fior each matched attribute. + + @subsubheading Examples + @example + filename = file_in_loadpath("imdata/rtstruct.dcm"); + + info = dicomfind(filename, "ROINumber"); + + @end example + @end deftypefn @c Dicom Functions dicominfo @c ----------------------------------------- @subsection dicominfo @@ -77,10 +131,62 @@ a DICOM dump. If the @code{dictionary} argument is used, the given @var{dictionary-name} is used for this operation, otherwise, the dictionary set by @code{dicomdict} is used. +@subsubheading Inputs +@var{filename} - name of file to read. + +@var{'dictionary'} - string constant of 'dictionary'. + +@var{dictionary-name} - filename of dictionary to use. + @var{options}: @code{truncate=n} where n is the number of characters to limit the dump output display to @code{n} for each value. +@subsubheading Outputs +@var{info} - struct of fields read frome the dicom file. + +@subsubheading Examples +Read the metadata of a dicomfile: + +@example +> info = dicominfo(file_in_loadpath('imdata/simple-test.dcm') +info = +scalar structure containing the fields: +Filename = a.dcm +FileModDate = 04-Feb-2017 02:08:31 +FileMetaInformationVersion = +0 1 +MediaStorageSOPClassUID = 1.2.840.10008.5.1.4.1.1.7 +MediaStorageSOPInstanceUID = 1.2.826.0.1.3680043.2.1143.4379544382488839209812957878553810312 +TransferSyntaxUID = 1.2.840.10008.1.2 +ImplementationClassUID = 1.2.826.0.1.3680043.2.1143.107.104.103.115.2.6.3 +ImplementationVersionName = GDCM 2.6.3 +SourceApplicationEntityTitle = GDCM +ImageType = DERIVED \\SECONDARY +SOPClassUID = 1.2.840.10008.5.1.4.1.1.7 +SOPInstanceUID = 1.2.826.0.1.3680043.2.1143.4379544382488839209812957878553810312 +StudyDate = 20170203 +StudyTime = 210831.360586 +Modality = OT +ConversionType = WSD +NominalScannedPixelSpacing = +1 +1 +StudyInstanceUID = 1.2.826.0.1.3680043.2.1143.1282184104726305239898701219563360204 +SeriesInstanceUID = 1.2.826.0.1.3680043.2.1143.9385265081744858155080799316976198629 +SamplesPerPixel = 1 +PhotometricInterpretation = MONOCHROME1 +Rows = 10 +Columns = 5 +BitsAllocated = 8 +BitsStored = 8 +HighBit = 7 +PixelRepresentation = 0 +RescaleIntercept = 0 +RescaleSlope = 1 +RescaleType = US +PixelData = not assigned +@end example @xseealso{dicomread, dicomdict} @end deftypefn @@ -102,6 +208,31 @@ of the attribute. dictionary for a specified @var{keyword} string and returns the @var{group} and @var{element} for keyword. +@subsubheading Inputs +@var{keyword} - string keyword name to look up a group, element value.@* +@var{group} - group value to look up (string or integer).@* +@var{element} - element value to look up (string or integer).@* + +@subsubheading Outputs +@var{keyword} - string keyword name to looked up from a group, element value.@* +@var{group}, @var{element} - group and element value looked up from keyword.@* + +@subsubheading Outputs +Look up tag name for 0x10 0x10: + +@example +> name = dicomlookup(0x10,0x10) +name = PatientName + +@end example + +Look up tag group and element value: + +@example +> [grp, elm] = dicomlookup('TransferSyntaxUID') +grp = 2 +elm = 16 +@end example @xseealso{dicomdict} @end deftypefn @@ -113,10 +244,33 @@ for keyword. @deftypefnx {Loadable Function} @var{image} = dicomread (@var{structure}) Load the image from a DICOM file. -@var{filename} is a string (giving the filename). -@var{structure} is a structure with a field @code{Filename} (such as returned by @code{dicominfo}). -@var{image} may be two or three dimensional, depending on the content of the file. -An integer or float matrix will be returned, the number of bits will depend on the file. +@subsubheading Inputs +@var{filename} - a string giving the filename.* + +@var{structure} - a structure with a field @code{Filename} (such as returned by @code{dicominfo}). + +@var{image} - may be two or three dimensional, depending on the content of the file. + +@subsubheading Outputs +@var{image} - An integer or float matrix will be returned, the number of bits will depend on the file. + +@subsubheading Examples +Load the image data of a dcm file: + +@example +> image = dicomread(file_in_load_path('imdata/simple-test.dcm')) +image = +0 0 0 0 0 +0 0 0 0 0 +0 0 0 0 0 +0 0 0 0 0 +0 0 0 0 0 +0 0 0 0 0 +0 0 0 0 0 +0 0 0 0 0 +0 0 0 0 0 +0 0 0 0 0 +@end example @xseealso{dicominfo} @end deftypefn @@ -129,10 +283,56 @@ An integer or float matrix will be returned, the number of bits will depend on t Generate a DICOM unique id . +@subsubheading Inputs +None +@subsubheading Outputs @var{uuid} is a unique id string. +@subsubheading Examples +Get a new uid: + +@example +> uid = dicomuid () +uid = 1.2.826.0.1.3680043.2.1143.3114589836670200378351641061429967573 +@end example + @end deftypefn +@c Dicom Functions dicomupdate +@c ----------------------------------------- +@subsection dicomupdate +@cindex dicomupdate + @deftypefn {} {@var{info} =} dicomupdate(@var{fileinfo}, @var{attribute}, @var{value}) + @deftypefnx {} {@var{info} =} dicomupdate(@var{info}, @var{attrinfo}) + Update a dicom struct with new values + + @subsubheading Inputs + @var{info} - dicominfo struct. + + @var{attribute} - attribute name to find and change value of. + + @var{value} - attribute value to set. + + @var{attrinfo} - a table with fields Location and Value for each matched attribute to change. + + @subsubheading Outputs + @var{info} - dicominfo struct. + + @subsubheading Examples + @example + filename = file_in_loadpath("imdata/rtstruct.dcm"); + info = dicominfo(filename); + + % update specific values + finfo = dicomfind(info, "ROINumber"); + finfo.Value@{1@} = 10; + info = dicomupdate(info, finfo); + + % update all matching + info = dicomupdate(info, "ROINumber", 100); + + @end example + @end deftypefn @c Dicom Functions dicomwrite @c ----------------------------------------- @subsection dicomwrite @@ -142,9 +342,27 @@ Generate a DICOM unique id . Write a DICOM format file to @var{filename}. -@var{im} is image data or empty matrix, [], if only metadata save is required -@var{filename} is filename to write dicom to. if [], then function runs in verbose trial mode. -@var{info} struct, like that produced by dicominfo +@subsubheading Inputs +@var{im} - image data or empty matrix, [], if only metadata save is required + +@var{filename} - filename to write dicom to. if [], then function runs in verbose trial mode. + +@var{info} - struct, like that produced by dicominfo + +@subsubheading Examples +Create a dicom file using default info, and the supplied data: +@example +> wdata = uint8 (10*rand (10,10)); +> dicomwrite (wdata, 'test.dcm'); +@end example + +Create a dicom file using data and meta info: + +@example +> wdata = dicomread(file_in_loadpath('imdata/CT-MONO2-16-ankle.dcm'); +> info = dicominfo(file_in_loadpath('imdata/CT-MONO2-16-ankle.dcm'); +> dicomwrite(wdata, info); +@end example @xseealso{dicomread, dicominfo} @end deftypefn @@ -153,8 +371,14 @@ Write a DICOM format file to @var{filename}. @c ----------------------------------------- @subsection isdicom @cindex isdicom -@deftypefn {Loadable Function} {} isdicom (@var{filename}) +@deftypefn {Loadable Function} {@var{yesno} =} isdicom (@var{filename}) Return true if @var{filename} is a valid DICOM file. +@subsubheading Inputs +@var{filename} - name of file to read. + +@subsubheading Outputs +@var{yesno} - logical value of true if filename is a dicom file. + @xseealso{dicomdict, dicominfo, dicomread, dicomwrite} @end deftypefn diff --git a/inst/dicomfind.m b/inst/dicomfind.m new file mode 100644 index 0000000..c8fcccf --- /dev/null +++ b/inst/dicomfind.m @@ -0,0 +1,111 @@ +## Copyright (C) 2022 John Donoghue <john.donoghue@ieee.org> +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program is distributed in the hope that it will be useful, but WITHOUT +## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn {} {@var{attrinfo}} = dicomfind(@var{filename}, @var{attribute}) +## @deftypefnx {} {@var{attrinfo}} = dicomfind(@var{info}, @var{attribute}) +## Find the location and value of an attribute in a dicom file or info structure. +## +## @subsubheading Inputs +## @var{filename} - filename to open. +## +## @var{info} - dicominfo struct. +## +## @var{attribute} - attribute name to find. +## +## @subsubheading Outputs +## @var{attrinfo} - a table with fields Location and Value fior each matched attribute. +## +## @subsubheading Examples +## @example +## filename = file_in_loadpath("imdata/rtstruct.dcm"); +## +## info = dicomfind(filename, "ROINumber"); +## +## @end example +## @end deftypefn + +function data = dicomfind(filename, attributename) + if ischar(filename) + info = dicominfo(filename); + elseif isstruct(filename) + info = filename; + else + error ("Expected first argument as a filename or dicominfo structure"); + endif + + if !ischar(attributename) + error ("Expected attribute as a string"); + endif + + data = recurse_dicom_struct(info, "", attributename); +endfunction + +function data = recurse_dicom_struct(info, base, name) + data = struct('Location', [], 'Value', []); + + names = fieldnames(info); + for idx = 1:length(names) + fieldname = names{idx}; + fieldval = info.(fieldname); + fieldtype = class(fieldval); + if length(base) == 0 + nbase = fieldname; + else + nbase = [base "." fieldname]; + endif + + if strcmp(fieldtype, "struct") + ndata = recurse_dicom_struct(fieldval, nbase, name); + if !isempty(ndata) && !isempty(ndata.Location) + #ndata + if isempty(data.Location) + data.Location = [ ndata.Location ]; + data.Value = [ ndata.Value ]; + else + data.Location = [ data.Location; ndata.Location ]; + data.Value = [ data.Value; ndata.Value ]; + endif + endif + else + if strcmp(fieldname, name) + if isempty(data.Location) + data.Location = [{nbase}]; + data.Value = [{fieldval}]; + else + data.Location = [ data.Location; {nbase} ]; + data.Value = [ data.Value; {fieldval} ]; + endif + endif + endif + endfor + +endfunction + +%!test +%! filename = file_in_loadpath("imdata/rtstruct.dcm"); +%! info = dicomfind(filename, "ROINumber"); +%! assert(length(info.Location),4) +%! assert(length(info.Value),4) +%! assert(info.Location{1}, 'StructureSetROISequence.Item_1.ROINumber') + +%!test +%! filename = file_in_loadpath("imdata/rtstruct.dcm"); +%! dinfo = dicominfo(filename); +%! info = dicomfind(dinfo, "ROINumber"); +%! assert(length(info.Location),4) +%! assert(length(info.Value),4) +%! assert(info.Location{1}, 'StructureSetROISequence.Item_1.ROINumber') + diff --git a/inst/dicomupdate.m b/inst/dicomupdate.m new file mode 100644 index 0000000..edec7e1 --- /dev/null +++ b/inst/dicomupdate.m @@ -0,0 +1,141 @@ +## Copyright (C) 2022 John Donoghue <john.donoghue@ieee.org> +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program is distributed in the hope that it will be useful, but WITHOUT +## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn {} {@var{info} =} dicomupdate(@var{fileinfo}, @var{attribute}, @var{value}) +## @deftypefnx {} {@var{info} =} dicomupdate(@var{info}, @var{attrinfo}) +## Update a dicom struct with new values +## +## @subsubheading Inputs +## @var{info} - dicominfo struct. +## +## @var{attribute} - attribute name to find and change value of. +## +## @var{value} - attribute value to set. +## +## @var{attrinfo} - a table with fields Location and Value for each matched attribute to change. +## +## @subsubheading Outputs +## @var{info} - dicominfo struct. +## +## @subsubheading Examples +## @example +## filename = file_in_loadpath("imdata/rtstruct.dcm"); +## info = dicominfo(filename); +## +## % update specific values +## finfo = dicomfind(info, "ROINumber"); +## finfo.Value@{1@} = 10; +## info = dicomupdate(info, finfo); +## +## % update all matching +## info = dicomupdate(info, "ROINumber", 100); +## +## @end example +## @end deftypefn + +function info = dicomupdate(info, attrname, value=0) + + # if attrname is a char, need find positions + if ischar(attrname) + if nargin != 3 + error ("Expected value"); + endif + attribinfo = dicomfind(info, attrname); + else + attribinfo = attrname; + if nargin != 2 + error ("Unexpected value"); + endif + if !isfield(attribinfo, "Location") || !isfield(attribinfo, "Value") + error ("Expected struct to contain Location and Value fields"); + endif + endif + for idx=1:size(attribinfo.Location, 1) + if size(attribinfo.Location, 1) == 1 + loc = attribinfo.Location; + if nargin > 2 + val = value; + else + val = attribinfo.Value + endif + else + loc = attribinfo.Location{idx}; + if nargin > 2 + val = value; + else + val = attribinfo.Value{idx}; + endif + endif + # set value in location + info = recurse_set_dicom_struct(info, "", loc, val); + endfor + +endfunction + +function info = recurse_set_dicom_struct(info, base, name, value) + + names = fieldnames(info); + + # TODO: rather than recurse till find, we could traverse down the struct + for idx = 1:length(names) + fieldname = names{idx}; + fieldval = info.(fieldname); + fieldtype = class(fieldval); + if length(base) == 0 + nbase = fieldname; + else + nbase = [base "." fieldname]; + endif + + if strcmp(fieldtype, "struct") + info.(fieldname) = recurse_set_dicom_struct(fieldval, nbase, name, value); + else + if strcmp(nbase, name) + info.(fieldname) = value; + endif + endif + endfor + +endfunction + +%!test +%! filename = file_in_loadpath("imdata/rtstruct.dcm"); +%! info = dicominfo(filename); +%! finfo = dicomfind(info, "ROINumber"); +%! assert(length(finfo.Location),4); +%! assert(length(finfo.Value),4); +%! assert(finfo.Location{1}, 'StructureSetROISequence.Item_1.ROINumber'); +%! assert(finfo.Value{1}, 2); +%! finfo.Value{1} = 10; +%! info = dicomupdate(info, finfo); +%! finfo = dicomfind(info, "ROINumber"); +%! assert(finfo.Value{1}, 10); + +%!test +%! filename = file_in_loadpath("imdata/rtstruct.dcm"); +%! info = dicominfo(filename); +%! finfo = dicomfind(info, "ROINumber"); +%! assert(length(finfo.Location),4); +%! assert(length(finfo.Value),4); +%! assert(finfo.Location{1}, 'StructureSetROISequence.Item_1.ROINumber'); +%! assert(finfo.Value{1}, 2); +%! info = dicomupdate(info, "ROINumber", 100); +%! finfo = dicomfind(info, "ROINumber"); +%! assert(finfo.Value{1}, 100); +%! assert(finfo.Value{2}, 100); +%! assert(finfo.Value{3}, 100); +%! assert(finfo.Value{4}, 100); + diff --git a/inst/imdata/CT-MONO2-16-ankle.dcm b/inst/imdata/CT-MONO2-16-ankle.dcm Binary files differnew file mode 100644 index 0000000..ecfe6ce --- /dev/null +++ b/inst/imdata/CT-MONO2-16-ankle.dcm diff --git a/inst/imdata/README.md b/inst/imdata/README.md new file mode 100644 index 0000000..3d207cc --- /dev/null +++ b/inst/imdata/README.md @@ -0,0 +1,2 @@ +test data taken from the gdcmData repo of GDCM. +http://sourceforge.net/projects/gdcm/files/gdcmData/gdcmData/ diff --git a/inst/imdata/US-PAL-8-10x-echo.dcm b/inst/imdata/US-PAL-8-10x-echo.dcm Binary files differnew file mode 100644 index 0000000..771447f --- /dev/null +++ b/inst/imdata/US-PAL-8-10x-echo.dcm diff --git a/inst/imdata/rtstruct.dcm b/inst/imdata/rtstruct.dcm Binary files differnew file mode 100644 index 0000000..b144842 --- /dev/null +++ b/inst/imdata/rtstruct.dcm diff --git a/inst/imdata/simple-test.dcm b/inst/imdata/simple-test.dcm Binary files differnew file mode 100644 index 0000000..cadebeb --- /dev/null +++ b/inst/imdata/simple-test.dcm diff --git a/inst/imdata/simpleImageWithIcon.dcm b/inst/imdata/simpleImageWithIcon.dcm Binary files differnew file mode 100644 index 0000000..e9d2d66 --- /dev/null +++ b/inst/imdata/simpleImageWithIcon.dcm diff --git a/src/config.h.in b/src/config.h.in index 57d0f41..a9b103c 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -2,6 +2,9 @@ #include "undef-ah-octave.h" +/* Define to 1 if you have the <gdcmVersion.h> header file. */ +#undef HAVE_GDCMVERSION_H + /* Define to 1 if you have the <inttypes.h> header file. */ #undef HAVE_INTTYPES_H diff --git a/src/configure b/src/configure index ef866df..62a28e0 100755 --- a/src/configure +++ b/src/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for Octave-Forge dicom package 0.4.1. +# Generated by GNU Autoconf 2.69 for Octave-Forge dicom package 0.5.0. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -577,8 +577,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='Octave-Forge dicom package' PACKAGE_TARNAME='octave-forge-dicom-package' -PACKAGE_VERSION='0.4.1' -PACKAGE_STRING='Octave-Forge dicom package 0.4.1' +PACKAGE_VERSION='0.5.0' +PACKAGE_STRING='Octave-Forge dicom package 0.5.0' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -620,11 +620,11 @@ ac_includes_default="\ ac_subst_vars='LTLIBOBJS LIBOBJS -EGREP -CXXCPP GDCM_LIBS GDCM_CXXFLAGS CMAKE_BINARY +EGREP +CXXCPP OBJEXT EXEEXT ac_ct_CXX @@ -702,10 +702,10 @@ LDFLAGS LIBS CPPFLAGS CCC +CXXCPP CMAKE_BINARY GDCM_CXXFLAGS -GDCM_LIBS -CXXCPP' +GDCM_LIBS' # Initialize some variables set by options. @@ -1256,7 +1256,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures Octave-Forge dicom package 0.4.1 to adapt to many kinds of systems. +\`configure' configures Octave-Forge dicom package 0.5.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1324,7 +1324,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of Octave-Forge dicom package 0.4.1:";; + short | recursive ) echo "Configuration of Octave-Forge dicom package 0.5.0:";; esac cat <<\_ACEOF @@ -1336,12 +1336,12 @@ Some influential environment variables: LIBS libraries to pass to the linker, e.g. -l<library> CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if you have headers in a nonstandard directory <include dir> + CXXCPP C++ preprocessor CMAKE_BINARY path to the cmake binary GDCM_CXXFLAGS CXX compiler flags for GDCM. This overrides the cmake output GDCM_LIBS linker flags for GDCM. This overrides the cmake output - CXXCPP C++ preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. @@ -1409,7 +1409,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -Octave-Forge dicom package configure 0.4.1 +Octave-Forge dicom package configure 0.5.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1461,52 +1461,6 @@ fi } # ac_fn_cxx_try_compile -# ac_fn_cxx_try_link LINENO -# ------------------------- -# Try to link conftest.$ac_ext, and return whether this succeeded. -ac_fn_cxx_try_link () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - rm -f conftest.$ac_objext conftest$ac_exeext - if { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && { - test -z "$ac_cxx_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && { - test "$cross_compiling" = yes || - test -x conftest$ac_exeext - }; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information - # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would - # interfere with the next link command; also delete a directory that is - # left behind by Apple's compiler. We do this before executing the actions. - rm -rf conftest.dSYM conftest_ipa8_conftest.oo - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - as_fn_set_status $ac_retval - -} # ac_fn_cxx_try_link - # ac_fn_cxx_try_cpp LINENO # ------------------------ # Try to preprocess conftest.$ac_ext, and return whether this succeeded. @@ -1703,11 +1657,57 @@ $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_cxx_check_header_compile + +# ac_fn_cxx_try_link LINENO +# ------------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_link cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by Octave-Forge dicom package $as_me 0.4.1, which was +It was created by Octave-Forge dicom package $as_me 0.5.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -3004,6 +3004,351 @@ ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 +$as_echo_n "checking how to run the C++ preprocessor... " >&6; } +if test -z "$CXXCPP"; then + if ${ac_cv_prog_CXXCPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CXXCPP needs to be expanded + for CXXCPP in "$CXX -E" "/lib/cpp" + do + ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CXXCPP=$CXXCPP + +fi + CXXCPP=$ac_cv_prog_CXXCPP +else + ac_cv_prog_CXXCPP=$CXXCPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 +$as_echo "$CXXCPP" >&6; } +ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + +# check can access std c files + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h> + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <string.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdlib.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ctype.h> +#include <stdlib.h> +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_cxx_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_cxx_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in string.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "string.h" "ac_cv_header_string_h" "$ac_includes_default" +if test "x$ac_cv_header_string_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STRING_H 1 +_ACEOF + +fi + +done ## octave API tests @@ -3021,7 +3366,6 @@ LIBS="-loctinterp $LIBS" # need to use interpreter->get_load_path in dev version of octave, # prior to that methods of load_path were static - { $as_echo "$as_me:${as_lineno-$LINENO}: checking interpreter get_load_path" >&5 $as_echo_n "checking interpreter get_load_path... " >&6; } if ${octave_cv_interpreter_get_load_path+:} false; then : @@ -3341,10 +3685,34 @@ else $as_echo "yes" >&6; } fi +if test "$GDCM_CXXFLAGS$GDCM_LIBS" != "" ; then + # if have cmake detection, see if can find include files + + save_CPPFLAGS=$CPPFLAGS + CPPFLAGS="$CPPFLAGS $GDCM_CXXFLAGS" + + for ac_header in gdcmVersion.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "gdcmVersion.h" "ac_cv_header_gdcmVersion_h" "$ac_includes_default" +if test "x$ac_cv_header_gdcmVersion_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_GDCMVERSION_H 1 +_ACEOF + +else + GDCM_CXXFLAGS=""; GDCM_LIBS="" +fi + +done + + + CPPFLAGS=$save_CPPFLAGS +fi + # newer cmake seems to have issues so if found nothing, and dont have anything set, then try hard way if test "$GDCM_CXXFLAGS$GDCM_LIBS" == "" ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: No GDCM detected using cmake - trying fallback detection" >&5 -$as_echo "$as_me: WARNING: No GDCM detected using cmake - trying fallback detection" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: Trying fallback GDCM detection" >&5 +$as_echo "$as_me: Trying fallback GDCM detection" >&6;} #AC_LANG(C++) save_LDFLAGS=$LDFLAGS @@ -3417,7 +3785,7 @@ fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - LDFLAGS=$saved_LDFLAGS + LDFLAGS=$save_LDFLAGS CPPFLAGS=$save_CPPFLAGS fi @@ -3442,336 +3810,6 @@ CPPFLAGS="$CPPFLAGS $GDCM_CXXFLAGS" ## All the GDCM headers we use (we should probably have something less ugly) GDCM_HEADERS=$($SED -n 's,^#include.*"\(gdcm[^"]*\)\".*$,\1,p' *.cpp *.h | $SORT | $UNIQ) -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 -$as_echo_n "checking how to run the C++ preprocessor... " >&6; } -if test -z "$CXXCPP"; then - if ${ac_cv_prog_CXXCPP+:} false; then : - $as_echo_n "(cached) " >&6 -else - # Double quotes because CXXCPP needs to be expanded - for CXXCPP in "$CXX -E" "/lib/cpp" - do - ac_preproc_ok=false -for ac_cxx_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since - # <limits.h> exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifdef __STDC__ -# include <limits.h> -#else -# include <assert.h> -#endif - Syntax error -_ACEOF -if ac_fn_cxx_try_cpp "$LINENO"; then : - -else - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.i conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <ac_nonexistent.h> -_ACEOF -if ac_fn_cxx_try_cpp "$LINENO"; then : - # Broken: success on invalid input. -continue -else - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.i conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext -if $ac_preproc_ok; then : - break -fi - - done - ac_cv_prog_CXXCPP=$CXXCPP - -fi - CXXCPP=$ac_cv_prog_CXXCPP -else - ac_cv_prog_CXXCPP=$CXXCPP -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 -$as_echo "$CXXCPP" >&6; } -ac_preproc_ok=false -for ac_cxx_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since - # <limits.h> exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifdef __STDC__ -# include <limits.h> -#else -# include <assert.h> -#endif - Syntax error -_ACEOF -if ac_fn_cxx_try_cpp "$LINENO"; then : - -else - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.i conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <ac_nonexistent.h> -_ACEOF -if ac_fn_cxx_try_cpp "$LINENO"; then : - # Broken: success on invalid input. -continue -else - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.i conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.i conftest.err conftest.$ac_ext -if $ac_preproc_ok; then : - -else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check -See \`config.log' for more details" "$LINENO" 5; } -fi - -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 -$as_echo_n "checking for egrep... " >&6; } -if ${ac_cv_path_EGREP+:} false; then : - $as_echo_n "(cached) " >&6 -else - if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 - then ac_cv_path_EGREP="$GREP -E" - else - if test -z "$EGREP"; then - ac_path_EGREP_found=false - # Loop through the user's path and test for each of PROGNAME-LIST - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in egrep; do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" - as_fn_executable_p "$ac_path_EGREP" || continue -# Check for GNU ac_path_EGREP and select it if it is found. - # Check for GNU $ac_path_EGREP -case `"$ac_path_EGREP" --version 2>&1` in -*GNU*) - ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; -*) - ac_count=0 - $as_echo_n 0123456789 >"conftest.in" - while : - do - cat "conftest.in" "conftest.in" >"conftest.tmp" - mv "conftest.tmp" "conftest.in" - cp "conftest.in" "conftest.nl" - $as_echo 'EGREP' >> "conftest.nl" - "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break - diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - as_fn_arith $ac_count + 1 && ac_count=$as_val - if test $ac_count -gt ${ac_path_EGREP_max-0}; then - # Best one so far, save it but keep looking for a better one - ac_cv_path_EGREP="$ac_path_EGREP" - ac_path_EGREP_max=$ac_count - fi - # 10*(2^10) chars as input seems more than enough - test $ac_count -gt 10 && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out;; -esac - - $ac_path_EGREP_found && break 3 - done - done - done -IFS=$as_save_IFS - if test -z "$ac_cv_path_EGREP"; then - as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 - fi -else - ac_cv_path_EGREP=$EGREP -fi - - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 -$as_echo "$ac_cv_path_EGREP" >&6; } - EGREP="$ac_cv_path_EGREP" - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 -$as_echo_n "checking for ANSI C header files... " >&6; } -if ${ac_cv_header_stdc+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <float.h> - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - ac_cv_header_stdc=yes -else - ac_cv_header_stdc=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -if test $ac_cv_header_stdc = yes; then - # SunOS 4.x string.h does not declare mem*, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <string.h> - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "memchr" >/dev/null 2>&1; then : - -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <stdlib.h> - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "free" >/dev/null 2>&1; then : - -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. - if test "$cross_compiling" = yes; then : - : -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <ctype.h> -#include <stdlib.h> -#if ((' ' & 0x0FF) == 0x020) -# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') -# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) -#else -# define ISLOWER(c) \ - (('a' <= (c) && (c) <= 'i') \ - || ('j' <= (c) && (c) <= 'r') \ - || ('s' <= (c) && (c) <= 'z')) -# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) -#endif - -#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) -int -main () -{ - int i; - for (i = 0; i < 256; i++) - if (XOR (islower (i), ISLOWER (i)) - || toupper (i) != TOUPPER (i)) - return 2; - return 0; -} -_ACEOF -if ac_fn_cxx_try_run "$LINENO"; then : - -else - ac_cv_header_stdc=no -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi - -fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 -$as_echo "$ac_cv_header_stdc" >&6; } -if test $ac_cv_header_stdc = yes; then - -$as_echo "#define STDC_HEADERS 1" >>confdefs.h - -fi - -# On IRIX 5.3, sys/types and inttypes.h are conflicting. -for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ - inttypes.h stdint.h unistd.h -do : - as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` -ac_fn_cxx_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default -" -if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - -fi - -done - - for ac_header in $GDCM_HEADERS do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` @@ -4299,7 +4337,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by Octave-Forge dicom package $as_me 0.4.1, which was +This file was extended by Octave-Forge dicom package $as_me 0.5.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -4361,7 +4399,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -Octave-Forge dicom package config.status 0.4.1 +Octave-Forge dicom package config.status 0.5.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/src/configure.ac b/src/configure.ac index 371a1ac..05dc53b 100644 --- a/src/configure.ac +++ b/src/configure.ac @@ -18,7 +18,7 @@ ### <http://www.gnu.org/licenses/>. AC_PREREQ([2.67]) -AC_INIT([Octave-Forge dicom package], [0.4.1]) +AC_INIT([Octave-Forge dicom package], [0.5.0]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_MACRO_DIRS([m4]) AH_TOP([#include "undef-ah-octave.h"]) @@ -40,8 +40,12 @@ AC_CHECK_PROG(OCTAVE_CONFIG,octave-config,octave-config) test -z "$OCTAVE_CONFIG" && OCTAVE_CONFIG=$MKOCTFILE AC_PROG_CXX +AC_PROG_CXXCPP AC_LANG(C++) +# check can access std c files +AC_CHECK_HEADERS([string.h]) + ## octave API tests save_CXX="$CXX" save_CXXFLAGS="$CXXFLAGS" @@ -131,9 +135,22 @@ dnl dependent directories. dnl CMAKE_FIND_PACKAGE([GDCM], [CXX], , , , [target_arch]) +if test "$GDCM_CXXFLAGS$GDCM_LIBS" != "" ; then + # if have cmake detection, see if can find include files + + save_CPPFLAGS=$CPPFLAGS + CPPFLAGS="$CPPFLAGS $GDCM_CXXFLAGS" + + AC_CHECK_HEADERS([gdcmVersion.h], , + [GDCM_CXXFLAGS=""; GDCM_LIBS=""], + ) + + CPPFLAGS=$save_CPPFLAGS +fi + # newer cmake seems to have issues so if found nothing, and dont have anything set, then try hard way if test "$GDCM_CXXFLAGS$GDCM_LIBS" == "" ; then - AC_MSG_WARN([No GDCM detected using cmake - trying fallback detection]) + AC_MSG_NOTICE([Trying fallback GDCM detection]) #AC_LANG(C++) save_LDFLAGS=$LDFLAGS @@ -177,7 +194,7 @@ if test "$GDCM_CXXFLAGS$GDCM_LIBS" == "" ; then [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no])]) - LDFLAGS=$saved_LDFLAGS + LDFLAGS=$save_LDFLAGS CPPFLAGS=$save_CPPFLAGS fi diff --git a/src/dicomanon.cpp b/src/dicomanon.cpp index a948d96..1d5c918 100644 --- a/src/dicomanon.cpp +++ b/src/dicomanon.cpp @@ -56,6 +56,7 @@ DEFUN_DLD (dicomanon, args, nargout, \n\ Anonymize a DICOM format file by removing or replacing specific fields.\n\ \n\ +@subsubheading Inputs\n\ @var{file_in} is filename to read from.@*\n\ @var{file_out} is the filename to write to.@*\n\ @var{name}, @var{value} optional name/value properties.@*\n\ @@ -67,6 +68,8 @@ The value is a cell array of names to not remove during the anonymize procedure. @item update\n\ A structure of name/values to update rather than remove.\n\ @end table\n\ +@subsubheading Outputs\n\ +None\n\ \n\ @seealso{dicomread, dicomwrite, dicominfo}\n\ @end deftypefn \n\ diff --git a/src/dicomdict.cpp b/src/dicomdict.cpp index 17dd0ad..f2bd28e 100644 --- a/src/dicomdict.cpp +++ b/src/dicomdict.cpp @@ -78,6 +78,27 @@ The first usage returns the filename of the dictionary that is currently being u Using @code{factory} resets the dictionary to the default.\n\ Using @code{set} allows setting the dictionary for future operations.\n\ In this case, the dictionary file @var{dictionary_name} can be anywhere in the path.\n\ +@subsubheading Inputs\n\ +@var{code} - string value of 'get', 'set' or 'factory'.\n\ +\n\ +@var{dictionary_name'} - name of dictionary file to use\n \ +\n\ +@subsubheading Outputs\n\ +@var{dictionary_name'} - name of dictionary file currently set for dictionaty\n \ +\n\ +@subsubheading Examples\n\ +Get current dicom dict path:\n\ +\n\ +@example\n\ +> f = dicomdict('get')\n\ +f = octavedicom.dic\n\ +@end example\n\ +\n\ +Set a new dictionary:\n\ +\n\ +@example\n\ +> dicomdict('set', 'anewdictfile.txt')\n\ +@end example\n\ \n\ @seealso{dicomread, dicomwrite}\n\ @end deftypefn \n") diff --git a/src/dicomdisp.cpp b/src/dicomdisp.cpp index fca7260..9279dc8 100644 --- a/src/dicomdisp.cpp +++ b/src/dicomdisp.cpp @@ -1,5 +1,5 @@ /* - * Copyright John Donoghue, 2019: + * Copyright John Donoghue, 2019-2022: * * The GNU Octave dicom package is free software: you can redistribute * it and/or modify it under the terms of the GNU General Public @@ -68,10 +68,14 @@ DEFUN_DLD (dicomdisp, args, nargout, @deftypefnx {Loadable Function} {} dicomdisp (@var{filename}, [@var{propertyname}, @var{propertvalue} ...]) \n\ Read and display the metadata from a DICOM file.\n\ \n\ + @subsubheading Inputs\n\ @var{filename} - dicomfilename to display.@*\n \ @var{propertyname}, @var{propertvalue} - property pairs for options to the display function.\n \ \n \ Currently the only known property is 'dictionary' to specify a non default dict to use.\n \ + @subsubheading Outputs\n\ + None\n\ + \n\ @seealso{dicomread, dicominfo} \n\ @end deftypefn\n\ ") diff --git a/src/dicominfo.cpp b/src/dicominfo.cpp index 4940c66..4b190c6 100644 --- a/src/dicominfo.cpp +++ b/src/dicominfo.cpp @@ -1,5 +1,5 @@ /* - * The GNU Octave dicom package is Copyright Andy Buckle 2010-2020 + * The GNU Octave dicom package is Copyright Andy Buckle 2010-2022 * Contact: blondandy using the sf.net system, * <https://sourceforge.net/sendmessage.php?touser=1760416> * @@ -103,10 +103,62 @@ a DICOM dump. \n\ If the @code{dictionary} argument is used, the given @var{dictionary-name} is used for this operation, \n\ otherwise, the dictionary set by @code{dicomdict} is used.\n\ \n\ +@subsubheading Inputs\n\ +@var{filename} - name of file to read.\n\ +\n\ +@var{'dictionary'} - string constant of 'dictionary'.\n\ +\n\ +@var{dictionary-name} - filename of dictionary to use.\n\ +\n\ @var{options}:\n\ @code{truncate=n}\n\ where n is the number of characters to limit the dump output display to @code{n}\ for each value. \n\ +@subsubheading Outputs\n\ +@var{info} - struct of fields read frome the dicom file.\n\ +\n\ +@subsubheading Examples\n\ +Read the metadata of a dicomfile:\n\ +\n\ +@example\n \ +> info = dicominfo(file_in_loadpath('imdata/simple-test.dcm')\n \ +info = \n \ + scalar structure containing the fields:\n \ + Filename = a.dcm\n \ + FileModDate = 04-Feb-2017 02:08:31\n \ + FileMetaInformationVersion =\n \ + 0 1\n \ + MediaStorageSOPClassUID = 1.2.840.10008.5.1.4.1.1.7\n \ + MediaStorageSOPInstanceUID = 1.2.826.0.1.3680043.2.1143.4379544382488839209812957878553810312\n \ + TransferSyntaxUID = 1.2.840.10008.1.2\n \ + ImplementationClassUID = 1.2.826.0.1.3680043.2.1143.107.104.103.115.2.6.3\n \ + ImplementationVersionName = GDCM 2.6.3\n \ + SourceApplicationEntityTitle = GDCM\n \ + ImageType = DERIVED \\SECONDARY \n \ + SOPClassUID = 1.2.840.10008.5.1.4.1.1.7\n \ + SOPInstanceUID = 1.2.826.0.1.3680043.2.1143.4379544382488839209812957878553810312\n \ + StudyDate = 20170203\n \ + StudyTime = 210831.360586 \n \ + Modality = OT\n \ + ConversionType = WSD \n \ + NominalScannedPixelSpacing =\n \ + 1\n \ + 1\n \ + StudyInstanceUID = 1.2.826.0.1.3680043.2.1143.1282184104726305239898701219563360204\n \ + SeriesInstanceUID = 1.2.826.0.1.3680043.2.1143.9385265081744858155080799316976198629\n \ + SamplesPerPixel = 1\n \ + PhotometricInterpretation = MONOCHROME1 \n \ + Rows = 10\n \ + Columns = 5\n \ + BitsAllocated = 8\n \ + BitsStored = 8\n \ + HighBit = 7\n \ + PixelRepresentation = 0\n \ + RescaleIntercept = 0\n \ + RescaleSlope = 1\n \ + RescaleType = US\n \ + PixelData = not assigned\n \ +@end example\n \ \n\ @seealso{dicomread, dicomdict} \n\ @end deftypefn\n\ @@ -685,9 +737,7 @@ char* name2Keyword (char *d, int *d_len_p, const char* s) /* %!shared testfile -%! testfile = urlwrite ( ... -%! 'http://sourceforge.net/p/octave/code/11601/tree/trunk/octave-forge/extra/dicom/dcm_examples/RD.15MV.DCM?format=raw', ... -%! tempname() ); +%! testfile = file_in_loadpath("imdata/simpleImageWithIcon.dcm"); %!fail("dicominfo") @@ -695,14 +745,9 @@ char* name2Keyword (char *d, int *d_len_p, const char* s) %!test %! s=dicominfo(testfile); -%! assert(s.PatientName,"PHANTOM^IsodoseComparison^^^"); +%! assert(s.PatientName,"GDCM^Patient"); %!test %! s=dicominfo(testfile); -%! assert(s.ROIContourSequence.Item_1.ContourSequence.Item_1.ContourGeometricType,"POINT "); - -%!test -%! if exist (testfile, 'file') -%! delete (testfile); -%! endif +%! assert(s.IconImageSequence.Item_1.PhotometricInterpretation,"MONOCHROME2 "); */ diff --git a/src/dicomlookup.cpp b/src/dicomlookup.cpp index 8c2a816..065fc63 100644 --- a/src/dicomlookup.cpp +++ b/src/dicomlookup.cpp @@ -53,6 +53,31 @@ of the attribute.\n\ dictionary for a specified @var{keyword} string and returns the @var{group} and @var{element}\n \ for keyword.\n\ \n\ +@subsubheading Inputs\n\ +@var{keyword} - string keyword name to look up a group, element value.@*\n\ +@var{group} - group value to look up (string or integer).@*\n\ +@var{element} - element value to look up (string or integer).@*\n\ +\n\ +@subsubheading Outputs\n\ +@var{keyword} - string keyword name to looked up from a group, element value.@*\n\ +@var{group}, @var{element} - group and element value looked up from keyword.@*\n\ +\n\ +@subsubheading Outputs\n\ +Look up tag name for 0x10 0x10:\n\ +\n\ +@example\n\ +> name = dicomlookup(0x10,0x10)\n\ +name = PatientName\n\ +\n\ +@end example\n\ +\n\ +Look up tag group and element value:\n\ +\n\ +@example\n\ +> [grp, elm] = dicomlookup('TransferSyntaxUID')\n\ +grp = 2\n\ +elm = 16\n\ +@end example\n\ @seealso{dicomdict}\n\ @end deftypefn \n\ ") diff --git a/src/dicomread.cpp b/src/dicomread.cpp index dec6d4c..31498d2 100644 --- a/src/dicomread.cpp +++ b/src/dicomread.cpp @@ -45,10 +45,33 @@ DEFUN_DLD (dicomread, args, nargout, @deftypefnx {Loadable Function} @var{image} = dicomread (@var{structure}) \n\ \n\ Load the image from a DICOM file. \n\ -@var{filename} is a string (giving the filename).\n\ -@var{structure} is a structure with a field @code{Filename} (such as returned by @code{dicominfo}).\n\ -@var{image} may be two or three dimensional, depending on the content of the file. \n\ -An integer or float matrix will be returned, the number of bits will depend on the file. \n\ +@subsubheading Inputs\n\ +@var{filename} - a string giving the filename.*\n\ +\n\ +@var{structure} - a structure with a field @code{Filename} (such as returned by @code{dicominfo}).\n\ +\n\ +@var{image} - may be two or three dimensional, depending on the content of the file. \n\ +\n\ +@subsubheading Outputs\n\ +@var{image} - An integer or float matrix will be returned, the number of bits will depend on the file. \n\ +\n\ +@subsubheading Examples\n\ +Load the image data of a dcm file:\n\ +\n\ +@example\n\ +> image = dicomread(file_in_load_path('imdata/simple-test.dcm'))\n\ +image =\n\ + 0 0 0 0 0\n\ + 0 0 0 0 0\n\ + 0 0 0 0 0\n\ + 0 0 0 0 0\n\ + 0 0 0 0 0\n\ + 0 0 0 0 0\n\ + 0 0 0 0 0\n\ + 0 0 0 0 0\n\ + 0 0 0 0 0\n\ + 0 0 0 0 0\n\ +@end example\n\ \n\ @seealso{dicominfo} \n\ @end deftypefn \n\ @@ -190,9 +213,7 @@ An integer or float matrix will be returned, the number of bits will depend on t /* %!shared testfile -%! testfile = urlwrite ( ... -%! 'http://sourceforge.net/p/octave/code/11601/tree/trunk/octave-forge/extra/dicom/dcm_examples/RD.15MV.DCM?format=raw', ... -%! tempname() ); +%! testfile = file_in_loadpath("imdata/CT-MONO2-16-ankle.dcm"); %!fail ("dicomread"); %!fail ("dicomread (1)"); @@ -200,15 +221,11 @@ An integer or float matrix will be returned, the number of bits will depend on t %!test %! rd=dicomread(testfile); -%! assert(rd(100,101,30),uint16(2021)); +%! assert(rd(100,101),int16(128)); %!test %! data={}; %! data.Filename = testfile; %! rd=dicomread(data); -%! assert(rd(100,101,30),uint16(2021)); - -%! if exist (testfile, 'file') -%! delete (testfile); -%! endif +%! assert(rd(100,101),int16(128)); */ diff --git a/src/dicomuid.cpp b/src/dicomuid.cpp index 3831788..664d5ae 100644 --- a/src/dicomuid.cpp +++ b/src/dicomuid.cpp @@ -39,8 +39,19 @@ DEFUN_DLD (dicomuid, args, nargout, \n\ Generate a DICOM unique id . \n\ \n \ +@subsubheading Inputs\n\ +None\n\ +@subsubheading Outputs\n\ @var{uuid} is a unique id string.\n\ \n\ +@subsubheading Examples\n\ +Get a new uid:\n\ +\n\ +@example\n\ +> uid = dicomuid ()\n\ +uid = 1.2.826.0.1.3680043.2.1143.3114589836670200378351641061429967573\n\ +@end example\n\ +\n\ @end deftypefn \n\ ") { diff --git a/src/dicomwrite.cpp b/src/dicomwrite.cpp index 3ed3c74..0317346 100644 --- a/src/dicomwrite.cpp +++ b/src/dicomwrite.cpp @@ -62,9 +62,27 @@ DEFUN_DLD (dicomwrite, args, nargout, \n\ Write a DICOM format file to @var{filename}.\n\ \n\ -@var{im} is image data or empty matrix, [], if only metadata save is required\n\ -@var{filename} is filename to write dicom to. if [], then function runs in verbose trial mode.\n\ -@var{info} struct, like that produced by dicominfo\n\ +@subsubheading Inputs\n\ +@var{im} - image data or empty matrix, [], if only metadata save is required\n\ +\n\ +@var{filename} - filename to write dicom to. if [], then function runs in verbose trial mode.\n\ +\n\ +@var{info} - struct, like that produced by dicominfo\n\ +\n\ +@subsubheading Examples\n\ +Create a dicom file using default info, and the supplied data:\n\ +@example\n\ +> wdata = uint8 (10*rand (10,10));\n\ +> dicomwrite (wdata, 'test.dcm');\n\ +@end example\n\ +\n\ +Create a dicom file using data and meta info:\n\ +\n\ +@example\n\ +> wdata = dicomread(file_in_loadpath('imdata/CT-MONO2-16-ankle.dcm');\n\ +> info = dicominfo(file_in_loadpath('imdata/CT-MONO2-16-ankle.dcm');\n\ +> dicomwrite(wdata, info);\n\ +@end example\n\ \n\ @seealso{dicomread, dicominfo}\n\ @end deftypefn \n\ diff --git a/src/isdicom.cpp b/src/isdicom.cpp index da4bdba..4aa551f 100644 --- a/src/isdicom.cpp +++ b/src/isdicom.cpp @@ -37,19 +37,27 @@ isdicom (const std::string& filename) if (!filename.length ()) return false; + // we seem to crash for some reason is use a const filename + char namebuff[filename.length () + 1]; + strcpy(namebuff, filename.c_str()); + gdcm::Reader reader; - reader.SetFileName (filename.c_str ()); + reader.SetFileName (namebuff); - // gdcm::Reader.Read() will return false if the file does not exists but - // also prints to stderr so we check it first. - return OCTAVE__FILE_STAT (filename).exists () && reader.Read (); + return OCTAVE__FILE_STAT (namebuff).exists () && reader.Read (); } DEFUN_DLD (isdicom, args, , "-*- texinfo -*- \n\ -@deftypefn {Loadable Function} {} isdicom (@var{filename}) \n\ +@deftypefn {Loadable Function} {@var{yesno} =} isdicom (@var{filename}) \n\ Return true if @var{filename} is a valid DICOM file.\n\ \n\ +@subsubheading Inputs\n\ +@var{filename} - name of file to read.\n\ +\n\ +@subsubheading Outputs\n\ +@var{yesno} - logical value of true if filename is a dicom file.\n\ +\n\ @seealso{dicomdict, dicominfo, dicomread, dicomwrite} \n\ @end deftypefn") { |