home *** CD-ROM | disk | FTP | other *** search
/ ftp.pasteur.org/FAQ/ / ftp-pasteur-org-FAQ.zip / FAQ / medical-image-faq / part2 < prev    next >
Internet Message Format  |  2003-12-22  |  50KB

  1. Path: senator-bedfellow.mit.edu!bloom-beacon.mit.edu!news.rediris.es!irazu.switch.ch!switch.ch!tiscali!newsfeed1.ip.tiscali.net!newshosting.com!news-xfer1.atl.newshosting.com!diablo.voicenet.com!news2.epix.net!news1.epix.net!dclunie.com
  2. Newsgroups: alt.image.medical,comp.protocols.dicom,sci.data.formats,alt.answers,comp.answers,sci.answers,news.answers
  3. Message-ID: <20031221091625.3015.2@dclunie.com>
  4. Expires: 21 Jan 2004 00:00:00 GMT
  5. Subject: Medical Image Format FAQ, Part 2/8
  6. From: dclunie@dclunie.com (David A. Clunie)
  7. Followup-To: alt.image.medical
  8. Reply-To: dclunie@dclunie.com (David A. Clunie)
  9. Approved: news-answers-request@MIT.EDU
  10. Summary: This posting contains answers to the most Frequently Asked
  11.          Question on alt.image.medical - how do I convert from image
  12.          format X from vendor Y to something I can use ? In addition
  13.          it contains information about various standard formats.
  14. Lines: 1030
  15. Date: Sun, 21 Dec 2003 14:16:30 GMT
  16. NNTP-Posting-Host: 216.37.230.197
  17. X-Complaints-To: abuse@epix.net
  18. X-Trace: news1.epix.net 1072016190 216.37.230.197 (Sun, 21 Dec 2003 09:16:30 EST)
  19. NNTP-Posting-Date: Sun, 21 Dec 2003 09:16:30 EST
  20. Xref: senator-bedfellow.mit.edu alt.image.medical:12455 comp.protocols.dicom:11711 sci.data.formats:3060 alt.answers:70769 comp.answers:55774 sci.answers:15695 news.answers:263500
  21.  
  22. Archive-name: medical-image-faq/part2
  23. Posting-Frequency: monthly
  24. Last-modified: Sun Dec 21 09:16:29 EST 2003
  25. Version: 4.26
  26.  
  27.     2.2 ACR/NEMA DICOM 3.0
  28.  
  29.  
  30.     ACR/NEMA Standards Publications
  31.  
  32.         PS 3.1 <- DICOM 3 - Introduction & Overview PS 3.8 <- DICOM 3 -
  33.         Network Communication Support
  34.  
  35.         PS 3.2 <- DICOM 3 - Conformance PS 3.3 <- DICOM 3 - Information
  36.         Object Definitions PS 3.4 <- DICOM 3 - Service Class Specifications
  37.         PS 3.5 <- DICOM 3 - Data Structures & Encoding PS 3.6 <- DICOM 3 -
  38.         Data Dictionary PS 3.7 <- DICOM 3 - Message Exchange PS 3.9 <- DICOM
  39.         3 - Point-to-Point Communication
  40.  
  41.         PS 3.10 <- DICOM 3 - Media Storage & File Format PS 3.11 <- DICOM 3
  42.         - Media Storage Application Profiles PS 3.12 <- DICOM 3 - Media
  43.         Formats & Physical Media
  44.  
  45.         PS 3.13 <- DICOM 3 - Print Management Point-to-Point Communication
  46.         Support PS 3.14 <- DICOM 3 - Grayscale Standard Display Function PS
  47.         3.15 <- DICOM 3 - Security Profiles PS 3.16 <- DICOM 3 - Content
  48.         Mapping Resource (DCMR)
  49.  
  50.  
  51.     DICOM (Digital Imaging and Communications in Medicine) standards are of
  52.     course the hot topic at every radiological trade show.  Unlike previous
  53.     attempts at developing a standard, this one seems to have the potential
  54.     to actually achieve its objective, which in a nutshell, is to allow
  55.     vendors to produce a piece of equipment or software that has a high
  56.     probability of communicating with devices from other vendors.
  57.  
  58.  
  59.     Where DICOM differs substantially from other attempts, is in defining so
  60.     called Service-Object Pairs.  For instance if a vendor's MR DICOM
  61.     conformance statement says that it supports an MR Storage Class as a
  62.     Service Class Provider, and another vendor's workstation says that it
  63.     supports an MR Storage Class as a Service Class User, and both can
  64.     connect via TCP/IP over Ethernet, then the two devices will almost
  65.     certainly be able to talk to each other once they are setup with each
  66.     others network addresses and so on.
  67.  
  68.  
  69.     The keys to the success of DICOM are the use of standard network
  70.     facilities for interconnection (TCP/IP and ISO-OSI), a mechanism of
  71.     association establishment that allows for negotiation of how messages
  72.     are to be transferred, and an object-oriented specification of
  73.     Information Objects (ie.  data sets) and Service Classes.
  74.  
  75.  
  76.     Of course all this makes for a huge and difficult to read standard, but
  77.     once the basic concepts are grasped, the standard itself just provides a
  78.     detailed reference.  From the users' and equipment purchasers' points of
  79.     view the important thing is to be able to read and match up the
  80.     Conformance Statements from each vendor to see if two pieces of
  81.     equipment will talk.
  82.  
  83.  
  84.     Just being able to communicate and transfer information is of course not
  85.     sufficient - these are only tools to help construct a total system with
  86.     useful functionality.  Because a workstation can pull an image off an
  87.     MRI scanner doesn't mean it knows when to do it, when the image has
  88.     become available, to which patient it belongs, and where it is
  89.     subsequently archived, not to mention notifying the Radiology or
  90.     Hospital Information System (RIS/HIS) when such a task has been
  91.     performed.  In other words DICOM Conformance does not guarantee
  92.     functionality, it only facilitates connectivity.
  93.  
  94.  
  95.     In otherwords, don't get too carried away with espousing the virtues of
  96.     DICOM, demanding it from vendors, and expecting it to be the panacea to
  97.     create a useful multi-vendor environment.
  98.  
  99.  
  100.     To get more information about DICOM:
  101.  
  102.  
  103.        - Purchase the standards from NEMA.
  104.  
  105.        - Ftp the final versions of the drafts in electronic form
  106.           one of the sites described below.
  107.  
  108.        - Follow the Usenet group comp.protocols.dicom.
  109.  
  110.        - Get a copy of "Understanding DICOM 3.0" $12.50 from Kodak.
  111.  
  112.        - Insist that your existing and potential vendors supply you
  113.           with DICOM conformance statements before you upgrade or purchase,
  114.           and don't buy until you know what they mean.  Don't take no for an
  115.           answer!!!!
  116.  
  117.  
  118.     What is all this doing in an FAQ about medical image formats you ask ?
  119.     Well first of all, in many ways DICOM 3.0 will solve future connectivity
  120.     problems, if not provide functional solutions to common problems.  Hence
  121.     actually getting the images from point A to B is going to be easier if
  122.     everyone conforms.  Furthermore, for those of us with old equipment,
  123.     interfacing it to new DICOM conforming equipment is going to be a
  124.     problem.  In otherwords old network solutions and file formats are going
  125.     to have to be transformed if they are going to communicate
  126.     unidirectionally or bidirectionally with DICOM 3.0 nodes.  One is still
  127.     faced with the same old questions of how does one move the data and how
  128.     does one interpret it.
  129.  
  130.  
  131.     The specifics of the DICOM message format are very similar to the
  132.     previous versions of ACR/NEMA on which it is based.  The data dictionary
  133.     is greatly extended, and certain data elements have been "retired" but
  134.     can be ignored gracefully if present.  The message itself can now be
  135.     transmitted as a byte stream over networks, rather than using a
  136.     point-to-point paradigm excusively (though the old point-to-point
  137.     interface is available).  This message can be encoded in various
  138.     different Transfer Syntaxes for transmission.
  139.  
  140.  
  141.     When two devices ("Application Entities" or AE) begin to establish an
  142.     "Association", they negotiate an appropriate transfer syntax.  They may
  143.     choose an Explicit Big-Endian Transfer Syntax in which integers are
  144.     encoded as big-endian and where each data element includes a specific
  145.     field that says "I am an unsigned 16 bit integer" or "I am an ascii
  146.     floating-point number", or alternatively they can fall back on the
  147.     default transfer syntax which every AE must support, the Implicit
  148.     Little-Endian Transfer Syntax which is just the same as an old ACR/NEMA
  149.     message with the byte order defined once and for all.
  150.  
  151.  
  152.     This is all very well if you are using DICOM as it was originally
  153.     envisaged - talking over a network, negotiating an association, and
  154.     determining what Transfer Syntax to use.  What if one wants to store a
  155.     DICOM message in a file though ?  Who is to say which transfer syntax
  156.     one will use to encode it offline ?  One approach, used for example by
  157.     the Central Test Node software produced by Mallinkrodt and used in the
  158.     RSNA Inforad demonstrations, is just to store it in the default
  159.     little-endian implicit syntax and be done with it.  This is obviously
  160.     not good enough if one is going to be mailing tapes, floppies and
  161.     optical disks between sites and vendors though, and hence the DICOM
  162.     group decided to define a "Media Storage & File Format" part of the
  163.     standard, the new Parts 10, 11 and 12 which have recently passed their
  164.     ballot and should be available in final form from NEMA soon.
  165.  
  166.  
  167.     Amongst other things, Part 10 defines a generic DICOM file format that
  168.     contains a brief header, the "DICOM File Meta Information Header" which
  169.     contains a 128 byte preamble (that the user can fill with anything), a 4
  170.     byte DICOM prefix "DICM", then a short DICOM format message that
  171.     contains newly defined elements of group 0002 in a specified Transfer
  172.     Syntax, which uniquely identify the data set as well as specifying the
  173.     Transfer Syntax for the rest of the file.  The rest of the message must
  174.     specify a single SOP instance.  The length of the brief message in the
  175.     Meta Information Header is specified in the first data element as usual,
  176.     the group length.
  177.  
  178.  
  179.     Originally the draft of Part 10 specified the default Implicit Value
  180.     Representation Little Endian Transfer Syntax as the DICOM File Meta
  181.     Information Header Transfer Syntax, which is in keeping with the concept
  182.     that it is the default for all other parts of the standard.  The final
  183.     text fortunately changed this to Explicit Value Representation Little
  184.     Endian Transfer Syntax.
  185.  
  186.  
  187.     So what choices of Transfer Syntax does one have and why all the fuss ?
  188.     Well the biggest distinction is between implicit and explicit value
  189.     representation which allows for multiple possible representations for a
  190.     single element, in theory at least, and perhaps allows one to make more
  191.     of an unknown data element than one otherwise could perhaps.  Some
  192.     purists (and Interfile people) would argue that the element should be
  193.     identified descriptively, and there is nothing to stop someone from
  194.     defining their own private Transfer Syntax that does just that (what a
  195.     heretical thought, wash my mouth out with soap).  With regard to the
  196.     little vs.  big endian debate I can't see what the fuss is about, as it
  197.     can't really be a serious performance issue.
  198.  
  199.  
  200.     Perhaps more importantly in the long run, the Transfer Syntax mechanism
  201.     provides a means for encapsulating compressed data streams, without
  202.     having to deal with the vagaries and mechanics of compression in the
  203.     standard itself.  For example, if DICOM version 3.0, in addition to the
  204.     "normal" Transfer Syntaxes, a series are defined to correspond to each
  205.     of the Joint Photographic Experts Group (JPEG) processes.  Each one of
  206.     these Transfer Syntaxes encodes data elements in the normal way, except
  207.     for the image pixel data, which is defined to be encoded as a valid and
  208.     self-contained JPEG byte stream.  Both reversible and irreversible
  209.     processes of various types are provided for, without having to mess with
  210.     the intricacies of encoding the various tables and parameters that JPEG
  211.     processes require.  Presumably a display application that supports such
  212.     a Transfer Syntax will just chop out the byte stream, pass it to the
  213.     relevant JPEG decode, and get an uncompressed image back.
  214.  
  215.  
  216.     Contrast this approach with that taken by those defining the TIFF
  217.     (Tagged Image File Format) for general imaging and page layout
  218.     applications.  In their version 6.0 standard they attempted to
  219.     disassemble the JPEG stream into its various components and assign each
  220.     to a specific tag.  Unfortunately this proved to be unworkable after the
  221.     standard was disseminated and they have gone back to the drawing board.
  222.  
  223.  
  224.     Now one may not like the JPEG standard, but one cannot argue with the
  225.     fact that the scheme is workable, and a readily available means of
  226.     reversible compression has been incorporated painlessly.  How effective
  227.     a compression scheme this is remains to be determined, and whether or
  228.     not the irreversible modes gain wide acceptance will be dictated by the
  229.     usual medico-legal paranoia that prevails in the United States, but the
  230.     option is there for those who want to take it up.  Though originally
  231.     every conceivable JPEG (ISO 10918-1) compression process was defined in
  232.     the standard, recently all but the most commonly used (8 and 12 bit DCT
  233.     lossy huffman and 16 bit lossless huffman) have been retired.  There is
  234.     of course no reason why private compression schemes cannot be readily
  235.     incorporated using this "encapsulation" mechanism, and to preserve
  236.     bandwidth this will undoubtedly occur.  This will not compromise
  237.     compatibility though, as one can always fall back to a default,
  238.     uncompressed Transfer Syntax.  More recently, JPEG-LS and JPEG 2000 have
  239.     also been added to the standard.  RLE (Run Length Encoded) compression,
  240.     using the TIFF PackBits mechanism, is also present in the standard and
  241.     is used for Ultrasound applications (only, as far as I know).
  242.  
  243.  
  244.     In order to identify all these various syntaxes, information objects,
  245.     and so on, DICOM has adopted the ISO concept of the Unique Identifier
  246.     (UID) which is a text string of numbers and periods with a unique root
  247.     for each organization that is registered with ISO and various
  248.     organizations that in turn register others in a hierarchical fashion.
  249.     For example 1.2.840.10008.1.2 is defined as the Implicit VR Little
  250.     Endian Transfer Syntax.  The 1 identifies ISO, the 2 is the ISO member
  251.     body branch, the 840 is the specific member body country code, in this
  252.     case ANSI, and the 10008 is registered by ANSI to NEMA for DICOM.  UID's
  253.     are also used to uniqely identify non-DICOM specific things, such as
  254.     information objects.  What DICOM calls "UIDs" are referred to in the ISO
  255.     OSI world as Object Identifiers (OIDs).
  256.  
  257.  
  258.     UIDs are constructed from a prefix registered to the supplier or vendor
  259.     or site, and a unique suffix that may be generated from say a date and
  260.     time stamp (which is not to be parsed).  For example an instance of a CT
  261.     information object might have a UID of
  262.     1.2.840.123456.2.999999.940623.170717 where a (presumably US) vendor
  263.     registered 123456, and the modality generated a unique suffix based on
  264.     its device number, patient hospital id, date and time, which have no
  265.     other significance other than to create a unique suffix.  Each vendor of
  266.     a DICOM implementation needs a UID root from which to begin generating
  267.     their own UIDs.  See UID - Getting a Registered Organization Number for
  268.     a DICOM UID Root for details.  It is said that Joint ISO-ITU root form
  269.     of "2.16.country" is currently preferred over the "1.country" form of
  270.     the root, which is something to bear in mind when building your own root
  271.     once you are a registered number.  Picker for example uses
  272.     "2.16.840.1.113662" as their root.  GE uses "1.2.840.113619".  The "840"
  273.     is the country code for US (there is an assumption that there is one
  274.     member body per country responsible for registration) using ISO 3166
  275.     numeric country codes.  I am not sure why there is a "1" after the
  276.     "2.16.840", but one does not seem to need to add a "1" after "1.2.840"
  277.     using the ISO registration scheme.  I am also not sure if the "1" after
  278.     the "840" is a US thing only for joint registrations, or whether other
  279.     countries use the "1" also.  Note that one does NOT zero-pad UID
  280.     components, hence the three-letter ISO 3166 code for Brazil of "076"
  281.     would actually be used as "76", e.g.  "1.2.76.xxxxxx".  This is
  282.     something to take great care with when generating the unique suffix for
  283.     a particular UID (e.g.  don't use serial number "002456" but "2456"
  284.     instead).
  285.  
  286.  
  287.     The other important new concept that DICOM introduced was the concept of
  288.     Information Objects.  In the previous ACR/NEMA standard, though
  289.     modalities were identified by a specific data element, and though there
  290.     were rules about which data elements were mandatory, conditional or
  291.     optional in ceratin settings, the concept was relatively loosely
  292.     defined.  Presumably in order to provide a mechanism to allow
  293.     conformance to be specified and hence ensure interoperability, various
  294.     Information Objects are defined that are composed of sets of Modules,
  295.     each module containing a specific set of data elements that are present
  296.     or absent according to specific rules.
  297.  
  298.  
  299.     For example, a CT Image Information Object contains amongst others, a
  300.     Patient module, a General Equipment module, a CT Image module, and an
  301.     Image Pixel module.  An MR Image Information module would contain all of
  302.     these except the CT Image module which would be replaced by an MR Image
  303.     module.  Clearly one needs descriptive information about a CT image that
  304.     is different from an MR image, yet the commonality of the image pixel
  305.     data and the patient information is recognized by this model.
  306.  
  307.  
  308.     Hence, as described earlier, one can define pairs of Information Objects
  309.     and Services that operate on such objects (Storage, Query/Retrieve,
  310.     etc.) and one gets SOP classes and instances.  All very object oriented
  311.     and initially confusing perhaps, but it provides a mechanism for
  312.     specifying conformance.  From the point of view of an interpreters of a
  313.     DICOM compatible data stream this means that for a certain instance of
  314.     an Information Object, certain information is guaranteed to be in there,
  315.     which is nice.  As a creator of such a data stream, one must ensure that
  316.     one follows all the rules to make sure that all the data elements from
  317.     all the necessary modules are present.
  318.  
  319.  
  320.     Having done so one then just throws all the data elements together,
  321.     sorts them into ascending order by group and element order, and pumps
  322.     them out.  It is a shame that the data stream itself doesn't reflect the
  323.     underlying order in the Information Objects, but I guess they had to
  324.     maintain backward compatibility, hence this little bit of ugliness.
  325.     This gets worse when one considers how to put more than one object in a
  326.     folder inside another object.
  327.  
  328.  
  329.     At this point I am tempted to include more details of various different
  330.     modules, data elements and transfer syntaxes, as well as the TCP/IP
  331.     mechanism for connection.  However all this information is in the
  332.     standard itself, copies of which are readily available electronically
  333.     from ftp sites, and in the interests of brevity I will not succumb to
  334.     temptation at this time.
  335.  
  336.  
  337.     2.2.1 Localizer lines on DICOM images
  338.  
  339.       A specific topic that is frequently asked in comp.protocols.dicom is
  340.       how to use display an image
  341. of a "localizer" (or "scout" or "scanogram" or "topogram" depending on your
  342. vendor) that has the "lines" corresponding to orthogonal images displayed on it.
  343. This applies both in the case where the orthogonal images were "graphically
  344. prescribed" from the localizer as well as when one just wants to see the
  345. location of images that happen to be orthogonal.  In the case of CT images, the
  346. localizer is usually a specific image that is not really a cross-section but a
  347. projection image.  In the case of MR one or more sagittal or coronal images are
  348. usually obtained from which axial images are prescribed, and so on.  The problem
  349. of "posting" the location of the orthogonal images on a localizer involves:
  350.  
  351.  
  352.       -Determining which image or images is/are the localizer for a particular
  353.       set of images: some vendors send this information in the "Referenced Image
  354.       Sequence" attribute, in the case of CT it may simply be an image with an
  355.       "Image Type" value 3 of "LOCALIZER" (this doesn't apply to MR) and the
  356.       same Frame of Reference UID, and in other cases one just has to search the
  357.       entire set of images and find other likely candidates that are orthogonal
  358.       or close to it based on "Image Orientation(Patient)".  -Having identified
  359.       a localizer and a list of images whose locations are to be "posted",
  360.       drawing the appropriate lines: there are two approaches that are
  361.       fundamentally different conceptually.  One can either determine the
  362.       intersection between the planes and extents of the localizer and the
  363.       orthogonal image, or one can project the boundaries of the orthogonal
  364.       image onto the plane of the localizer.
  365.  
  366.  
  367.       The problem with the "intersection" approach is that no such intersection
  368.       may exist.  For example, CT localizers are theoretically of infinite
  369.       thickness, they are projections not slices, and hence the concept of
  370.       intersection does not apply.  Even in the case of orthogonal slices, the
  371.       boundaries of one slice may not intersect the orthogonal slice at all.
  372.       The users requirement is really not to show the intersection, but rather
  373.       to "project" the boundaries of a slice onto the plane of the localizer, as
  374.       if it were viewed from a position along the normal to the plane of the
  375.       localizer.  For the purposes of simplicity, perspective is ignored.
  376.       Strictly speaking, the projected boundaries form a polygon, but if the
  377.       slices are truly orthogonal the polygon will appear as a straight line
  378.       (which is what most users expect to see).
  379.  
  380.  
  381.       The approach I use is to perform a parallel projection of the plane and
  382.       extent of the source slice onto the plane of the target
  383.  localizer image.  One can think of various ways of calculating angles between
  384.  planes, dropping normals, etc., but there is a simple approach ...
  385.  
  386.  
  387.        If one considers the localizer plane as a "viewport" onto the DICOM 3D
  388.        coordinate space, then that viewport is described by
  389.  its origin, its row unit vector, column unit vector and a normal unit vector
  390.  (derived from the row and column vectors by taking the cross product).  Now if
  391.  one moves the origin to 0,0,0 and rotates this viewing plane such that the row
  392.  vector is in the +X direction, the column vector the +Y direction, and the
  393.  normal in the +Z direction, then one has a situation where the X coordinate now
  394.  represents a column offset in mm from the localizer's top left hand corner, and
  395.  the Y coordinate now represents a row offset in mm from the localizer's top
  396.  left hand corner, and the Z coordinate can be ignored.  One can then convert
  397.  the X and Y mm offsets into pixel offsets using the pixel spacing of the
  398.  localizer image.
  399.  
  400.  
  401.        This trick is neat, because the actual rotations can be specified
  402.        entirely using the direction cosines that are the row,
  403.  column and normal unit vectors, without having to figure out any angles, arc
  404.  cosines and sines, which octant of the 3D space one is dealing with, etc.
  405.  Indeed, simplified it looks like:
  406.  
  407.  
  408. dst_nrm_dircos_x = dst_row_dircos_y * dst_col_dircos_z - dst_row_dircos_z *
  409. dst_col_dircos_y; dst_nrm_dircos_y = dst_row_dircos_z * dst_col_dircos_x -
  410. dst_row_dircos_x * dst_col_dircos_z; dst_nrm_dircos_z = dst_row_dircos_x *
  411. dst_col_dircos_y - dst_row_dircos_y * dst_col_dircos_x;
  412.  
  413. src_pos_x -= dst_pos_x; src_pos_y -= dst_pos_y; src_pos_z -= dst_pos_z;
  414.  
  415. dst_pos_x = dst_row_dircos_x * src_pos_x
  416.       + dst_row_dircos_y * src_pos_y + dst_row_dircos_z * src_pos_z;
  417.  
  418. dst_pos_y = dst_col_dircos_x * src_pos_x
  419.       + dst_col_dircos_y * src_pos_y + dst_col_dircos_z * src_pos_z;
  420.  
  421. dst_pos_z = dst_nrm_dircos_x * src_pos_x
  422.       + dst_nrm_dircos_y * src_pos_y + dst_nrm_dircos_z * src_pos_z;
  423.  
  424.  
  425.        The traditional homogeneous transformation matrix form of this is:
  426.  
  427.  
  428. [ dst_row_dircos_x dst_row_dircos_y dst_row_dircos_z -dst_pos_x ] [
  429. dst_col_dircos_x dst_col_dircos_y dst_col_dircos_z -dst_pos_y ] [
  430. dst_nrm_dircos_x dst_nrm_dircos_y dst_nrm_dircos_z -dst_pos_z ] [ 0 0 0 1 ]
  431.  
  432.  
  433.        So this tells you how to transform arbitrary 3D points into localizer
  434.        pixel offset space (which then obviously need to be
  435.  clipped to the localizer boundaries for drawing), but which points to draw ?
  436.  
  437.  
  438.        My approach is to project the square that is the bounding box of the
  439.        source image (i.e.  lines joining the TLHC,
  440.  TRHC,BRHC and BLHC of the slice).  That way, if the slice is orthogonal to the
  441.  localizer the square will project as a single line (i.e.  all four lines will
  442.  pile up on top of each other), and if it is not, some sort of rectangle or
  443.  trapezoid will be drawn.  I rather like the effect and it provides a general
  444.  solution, though looks messy with a lot of slices with funky angulations.
  445.  Other possibilities are just draw the longest projected side, draw a diagonal,
  446.  etc.
  447.  
  448.       Do not get too carried away with the precision of the resulting image.
  449.       There is some controversy as to whether or not the coordinates in Image
  450.       Position (Patient) represent the center of the slice or the edge of it,
  451.       and if the edge which edge (leading or trailing with respect to scan
  452.       "direction", top or bottom with respect to some axis, etc.).  Obviously
  453.       the center is the most sensible choice but you cannot guarantee this
  454.       (though a recent CP to the standard specifies that it is in fact the
  455.       center of the slice - see CP 212).  Just be aware that the displayed lines
  456.       (and recorded location) may be +/- the slice thickness (or perhaps
  457.       spacing) with respect to the orthogonal localizer image.
  458.  
  459.  
  460.       Do not forget to check that the Frame of Reference UID is the same for
  461.       both the localizer and the orthogonal images to be posted.  If they are
  462.       different one cannot assume the coordinates and vectors are using the same
  463.       coordinate space.
  464.  
  465.  
  466.       Finally, some vendors (especially on older scanners) provide the user with
  467.       an ability to post the localizer on the acquisition device and to save
  468.       that image, either as a secondary capture object with the lines burned
  469.       into the pixel data, or using some form of overlay.  There is considerable
  470.       variation in the choice of overlay mechanism to use, and not very
  471.       consistent support for overlays in other vendors workstations.  This leads
  472.       to frustrated users who can't see the lines on third party workstations
  473.       even though they are supposed to be there.  Hopefully in future vendors
  474.       will consistently make use of the new Grayscale Softcopy Presentation
  475.       State Storage objects to store such graphics, and to fill in "Referenced
  476.       Image Sequence" to allow workstations to post the localizers themselves
  477.       without hunting for plausible candidates.  The IHE Technical Framework for
  478.       Year 3 specifies that Referenced Image Sequence shall be used and burned
  479.       in lines shall not, which hopefully provides direction for new devices.
  480.  
  481.  
  482.       There are various implementations of this and other algorithms that may be
  483.       of interest at the following sites:
  484.  
  485.  
  486.       - http://www.dclunie.com/dicom3tools.html in my dicom3tools: look for
  487.       "appsrc/dctools/dcpost.cc" -
  488.       http://www.dclunie.com/dicom3tools/workinprogress/dcpost.cc dcpost.cc
  489.       (won't compile by itself, but shows the algorithm) -
  490.       ftp://ftp.charm.net/pub/usr/home2/dcsipo/slices.ZIP from Dee Csipo -
  491.       http://www.tiani.com/JDicom/out/scouts4j.zip from Gunter Zeilinger (Java)
  492.       - http://www.tiani.com/JDicom/out/scouts4cxx.zip from Gunter Zeilinger
  493.       (C++)
  494.  
  495.  
  496.  
  497.  
  498.  
  499.  
  500.  
  501.  
  502.      2.2.2 Orientation of DICOM images
  503.  
  504.       Another question that is frequently asked in comp.protocols.dicom is
  505.       how to determine which side of an image is which (e.g.  left, right)
  506.       and so on.  The short answer is that for projection radiographs this
  507.       is specified explicitly using the Patient Orientation attribute, and
  508.       for cross-sectional images it needs to be derived from the Image
  509.       Orientation (Patient) direction cosines.  In the standard these are
  510.       explained as follows:
  511.  
  512.  
  513.       -"C.7.6.1.1.1 Patient Orientation.
  514. The Patient Orientation (0020,0020) relative to the image plane shall be
  515. specified by two values that designate the anatomical direction of the positive
  516. row axis (left to right) and the positive column axis (top to bottom).  The
  517. first entry is the direction of the rows, given by the direction of the last
  518. pixel in the first row from the first pixel in that row.  The second entry is
  519. the direction of the columns, given by the direction of the last pixel in the
  520. first column from the first pixel in that column.
  521.  
  522. Anatomical direction shall be designated by the capital letters: A (anterior), P
  523. (posterior), R (right), L (left), H (head), F (foot).  Each value of the
  524. orientation attribute shall contain at least one of these characters.  If
  525. refinements in the orientation descriptions are to be specified, then they shall
  526. be designated by one or two additional letters in each value.  Within each
  527. value, the letters shall be ordered with the principal orientation designated in
  528. the first character."
  529.       -"C.7.6.2.1.1 Image Position And Image Orientation.
  530. The Image Position (0020,0032) specifies the x, y, and z coordinates of the
  531. upper left hand corner of the image; it is the center of the first voxel
  532. transmitted.  Image Orientation (0020,0037) specifies the direction cosines of
  533. the first row and the first column with respect to the patient.  These
  534. Attributes shall be provide as a pair.  Row value for the x, y, and z axes
  535. respectively followed by the Column value for
  536.  
  537. the x, y, and z axes respectively.
  538.  
  539. The direction of the axes is defined fully by the patient's orientation.  The
  540. x-axis is increasing to the left hand side of the patient.  The y-axis is
  541. increasing to the posterior side of the patient.  The z-axis is increasing
  542. toward the head of the patient.
  543.  
  544. The patient based coordinate system is a right handed system, i.e.  the
  545.  vector cross product of a unit vector along the positive x-axis and a
  546. unit vector along the positive y-axis is equal to a unit vector along the
  547. positive z-axis."
  548.  
  549.  
  550.       Some simple code to take one of the direction cosines (vectors) from the
  551.       Image Orientation (Patient) attribute and generate strings equivalent to
  552.       one of the values of Patient Orientation looks like this (noting that if
  553.       the vector is not aligned exactly with one of the major axes, the
  554.       resulting string will have multiple letters in as described under
  555.       "refinements" in C.7.6.1.1.1):
  556.  
  557.  
  558. char * DerivedImagePlane::getOrientation(Vector3D vector) {
  559.     char *orientation=new char[4]; char *optr = orientation; *optr='\0';
  560.  
  561.     char orientationX = vector.getX() < 0 ?  'R' : 'L'; char orientationY =
  562.     vector.getY() < 0 ?  'A' : 'P'; char orientationZ = vector.getZ() < 0 ?
  563.     'F' : 'H';
  564.  
  565.     double absX = fabs(vector.getX()); double absY = fabs(vector.getY());
  566.     double absZ = fabs(vector.getZ());
  567.  
  568.     int i; for (i=0; i<3; ++i) {
  569.         if (absX>.0001 && absX>absY && absX>absZ) {
  570.             *optr++=orientationX; absX=0;
  571.         } else if (absY>.0001 && absY>absX && absY>absZ) {
  572.             *optr++=orientationY; absY=0;
  573.         } else if (absZ>.0001 && absZ>absX && absZ>absY) {
  574.             *optr++=orientationZ; absZ=0;
  575.         } else break; *optr='\0';
  576.     } return orientation;
  577. }
  578.  
  579.  
  580.  
  581.  
  582.  
  583.      2.2.3 Determining the Transfer Syntax of DICOM input Streams
  584.  
  585.       Another question that is frequently asked in comp.protocols.dicom is
  586.       how to read a DICOM dataset from, for example, a file, whether or not
  587.       there is a PS 3.10 style meta information header.
  588.  
  589.  
  590.       Firstly, if a DICOMDIR is being, it is always written with explicit VR
  591.       little endian transfer syntax, and a meta information header is always
  592.       present.  Note also that DICOMDIRs are never sent over the network;
  593.       they are purely an interchange media object.
  594.  
  595.  
  596.       The meta information header is preceeded by a 128 byte preamble and
  597.       then the bytes 'DICM' as a magic number.
  598.  
  599.  
  600.       The meta-information that precedes the dataset of a PS 3.10 file is
  601.       always written in explicit VR little endian transfer syntax, and
  602.       contains within it tags which describe the succeeding dataset,
  603.       including what transfer syntax it is encoded in, something that needs
  604.       to be extracted and interpreted before proceeding to read past the end
  605.       of the meta information header and into the dataset.  Note that the
  606.       group length of the meta information header elements is mandatory and
  607.       can be used to determine the end of the meta information header (i.e.,
  608.       when to change transfer syntaxes).  Note that a draft of PS 3.10
  609.       before the final text suggested implicit VR for the meta-information
  610.       header, and some older applications may use that internally - these
  611.       non-DICOM files should never see the light of day however, and you can
  612.       probably forget about this.
  613.  
  614.  
  615.       The dataset following the meta information header will have the
  616.       specified transfer syntax, which obviously may be different from the
  617.       explicit VR little endian transfer syntax of the meta information
  618.       header itself.  In the case of the most transfer syntaxes the encoding
  619.       of the data elements will subtly change at this point.  In the case of
  620.       compressed pixel data transfer syntaxes everything will be the same as
  621.       the explicit VR little endian transfer syntax until one reaches
  622.       undefined length (7fe0,0010) elements.  In the case of the deflated
  623.       compression transfer syntax, the defalted (zipped without the zip
  624.       header) bit stream will begin immediately after the last meta
  625.       information header attribute.
  626.  
  627.  
  628.       When one is unfortunate enough to encounter a file that has no
  629.       preamble and meta information header, then one has to guess the
  630.       transfer syntax, for example by assuming the object starts with low
  631.       group numbered tags and using the values of the first 16 bits to guess
  632.       big or little endian, and looking for upper case letters where an
  633.       explicit VR might be, and determining explicit or implicit VR from
  634.       that.
  635.  
  636.  
  637.       Note however, that there is no random intermingling of implicit and
  638.       explicit value representations.  The transfer syntax dictates that
  639.       either one or the other is used throughout, after the meta information
  640.       header has been read.
  641.  
  642.  
  643.       Having said that, if you are reading something encoded in implicit VR,
  644.       then you can a) ignore the value by simply skipping it (using the VL
  645.       field), or b) interpret the value if you need to use it for something.
  646.       In the latter case you need to know in advance what the VR "should
  647.       be", i.e.  you need a dictionary.  However, that dictionary only needs
  648.       to be as long as the attributes you need to interpret ...  all the
  649.       others can be skipped passively.
  650.  
  651.  
  652.       Note that it is NEVER necessary to test on the fly on a per-element
  653.       basis whether or not the value representation is implicit or explicit.
  654.       This is always decided before you start.  Either you know the entire
  655.       dataset is explicit or implicit because you read the meta-information,
  656.       found the transfer syntax uid specified there and decided to switch to
  657.       that transfer syntax after the meta-information (the length of which
  658.       is always specified and tells you when to switch), or there was no
  659.       meta-information and you used some heuristic (or command line switch)
  660.       to decide what the transfer syntax is.
  661.  
  662. Here is one approach to handling the meta information header and guessing the
  663. transfer syntax if none is present, written in C++, much as it is done in
  664. dicom3tools:
  665.  
  666. void DicomInputStream::initializeTransferSyntax(const char *uid,bool meta) {
  667.     TransferSyntaxToReadMetaHeader = 0; TransferSyntaxToReadDataSet = 0; //
  668.     First make use of command line parameters that override guesswork ...
  669.     if (uid) {
  670.         TransferSyntax *ts = new TransferSyntax(uid); if (meta) {
  671.             TransferSyntaxToReadMetaHeader = ts; // specified UID is
  672.             transfer syntax to read metaheader
  673.         } else {
  674.             TransferSyntaxToReadDataSet = ts; // specified UID is
  675.             transfer syntax to read dataset (there is no metaheader)
  676.         }
  677.     } // else transfer syntax has to be determined by either guesswork or
  678.     metaheader ...  char b[8]; if (meta) {
  679.         // test for metaheader prefix after 128 byte preamble
  680.         seekg(128,ios::beg); if (good() && read(b,4) &&
  681.         strncmp(b,"DICM",4) == 0) {
  682.             if (!TransferSyntaxToReadMetaHeader)
  683.             TransferSyntaxToReadMetaHeader = // guess only if not
  684.             specified on command line
  685.                 read(b,6) && isupper(b[4]) && isupper(b[5]) ?
  686.                 new
  687.                 TransferSyntax(ExplicitVRLittleEndianTransferSyntaxUID)
  688.                 // standard : new
  689.                 TransferSyntax(ImplicitVRLittleEndianTransferSyntaxUID);
  690.                 // old draft (e.g.  used internally on GE IOS
  691.                 platform)
  692.  
  693.             // leaves positioned at start of metaheader
  694.             seekg(128+4,ios::beg);
  695.         } else {
  696.             clear(); seekg(0,ios::beg); // reset stream since
  697.             metaheader was sought but not found
  698.             TransferSyntaxToReadDataSet=TransferSyntaxToReadMetaHeader;
  699.             TransferSyntaxToReadMetaHeader=0;
  700.         }
  701.     } if (!TransferSyntaxToReadDataSet && !TransferSyntaxToReadMetaHeader) {
  702.     // was not specified on the command line and there is no metaheader
  703.         bool bigendian = false; bool explicitvr = false; clear();
  704.         seekg(0,ios::beg); if (good() && read(b,8)) {
  705.             // examine probable group number ...  assume <= 0x00ff
  706.             if (b[0] < b[1]) bigendian=true; else if (b[0] == 0 &&
  707.             b[1] == 0) {
  708.                 // blech ...  group number is zero // no point
  709.                 in looking at element number // as it will
  710.                 probably be zero too (group length) // try the
  711.                 32 bit value length of implicit vr if (b[4] <
  712.                 b[7]) bigendian=true;
  713.             } // else littleendian if (isupper(b[4]) &&
  714.             isupper(b[5])) explicitvr=true;
  715.         } // else unrecognized ...  assume default if (bigendian)
  716.             if (explicitvr)
  717.                 TransferSyntaxToReadDataSet = new
  718.                 TransferSyntax(ExplicitVRBigEndianTransferSyntaxUID);
  719.             else
  720.                 TransferSyntaxToReadDataSet = new
  721.                 TransferSyntax(ImplicitVR,BigEndian);
  722.         else
  723.             if (explicitvr)
  724.                 TransferSyntaxToReadDataSet = new
  725.                 TransferSyntax(ExplicitVRLittleEndianTransferSyntaxUID);
  726.             else
  727.                 TransferSyntaxToReadDataSet = new
  728.                 TransferSyntax(ImplicitVRLittleEndianTransferSyntaxUID);
  729.         // leaves positioned at start of dataset clear();
  730.         seekg(0,ios::beg);
  731.     } TransferSyntaxInUse = TransferSyntaxToReadMetaHeader ?
  732.     TransferSyntaxToReadMetaHeader : TransferSyntaxToReadDataSet;
  733.     Assert(TransferSyntaxInUse);
  734.     setEndian(TransferSyntaxInUse->getEndian());
  735. }
  736.  
  737. Here is the same sort of thing in Java, paraphrasing the PixelMed Java DICOM
  738. toolkit:
  739.  
  740. private void initializeTransferSyntax(String uid,boolean tryMeta) throws
  741. IOException {
  742.     TransferSyntaxToReadMetaHeader = null; TransferSyntaxToReadDataSet =
  743.     null; byte b[] = new byte[8]; // First make use of argument that
  744.     overrides guesswork at transfer syntax ...  if (uid != null) {
  745.         TransferSyntax ts = new TransferSyntax(uid); if (tryMeta) {
  746.             TransferSyntaxToReadMetaHeader = ts; // specified UID is
  747.             transfer syntax to read metaheader
  748.         } else {
  749.             TransferSyntaxToReadDataSet = ts; // specified UID is
  750.             transfer syntax to read dataset (there is no metaheader)
  751.         }
  752.     } // else transfer syntax has to be determined by either guesswork or
  753.     metaheader ...  if (tryMeta) {
  754.         // test for metaheader prefix after 128 byte preamble if
  755.         (markSupported()) mark(140); if (skip(128) == 128 && read(b,0,4)
  756.         == 4 && new String(b,0,4).equals("DICM")) {
  757.             if (TransferSyntaxToReadMetaHeader == null) { // guess
  758.             only if not specified as an argument
  759.                 if (markSupported()) {
  760.                     mark(8); if (read(b,0,6) == 6) { // the
  761.                     first 6 bytes of the first attribute tag
  762.                     in the metaheader
  763.                         TransferSyntaxToReadMetaHeader =
  764.                             Character.isUpperCase((char)(b[4]))
  765.                             &&
  766.                             Character.isUpperCase((char)(b[5]))
  767.                             ?  new
  768.                             TransferSyntax(TransferSyntax.ExplicitVRLittleEndian)
  769.                             // standard : new
  770.                             TransferSyntax(TransferSyntax.ImplicitVRLittleEndian);
  771.                             // old draft (e.g.  used
  772.                             internally on GE IOS
  773.                             platform)
  774.                     } else {
  775.                         TransferSyntaxToReadMetaHeader =
  776.                         new
  777.                         TransferSyntax(TransferSyntax.ExplicitVRLittleEndian);
  778.                     } reset();
  779.                 } else {
  780.                     // can't guess since can't rewind ...
  781.                     insist on standard transfer syntax
  782.                     TransferSyntaxToReadMetaHeader = new
  783.                     TransferSyntax(TransferSyntax.ExplicitVRLittleEndian);
  784.                 }
  785.             } byteOffsetOfStartOfData=132;
  786.         } else {
  787.             // no preamble, so rewind and try using the specified
  788.             transfer syntax (if any) for the dataset instead if
  789.             (markSupported()) {
  790.                 reset(); TransferSyntaxToReadDataSet =
  791.                 TransferSyntaxToReadMetaHeader; // may be null
  792.                 anyway if no uid argument specified
  793.                 byteOffsetOfStartOfData=0;
  794.             } else {
  795.                 throw new IOException("Not a DICOM PS 3.10 file
  796.                 - no DICM after preamble in metaheader, and
  797.                 can't rewind input");
  798.             }
  799.         }
  800.     } // at this point either we have succeeded or failed at finding a
  801.     metaheader, or we didn't look // so we either have a detected or
  802.     specified transfer syntax for the metaheader, or the dataset, or nothing
  803.     at all if (TransferSyntaxToReadDataSet == null &&
  804.     TransferSyntaxToReadMetaHeader == null) { // was not specified as an
  805.     argument and there is no metaheader
  806.         boolean bigendian = false; boolean explicitvr = false; if
  807.         (markSupported()) {
  808.             mark(10); if (read(b,0,8) == 8) {
  809.                 // examine probable group number ...  assume <=
  810.                 0x00ff if (b[0] < b[1]) bigendian=true; else if
  811.                 (b[0] == 0 && b[1] == 0) {
  812.                     // blech ...  group number is zero // no
  813.                     point in looking at element number // as
  814.                     it will probably be zero too (group
  815.                     length) // try the 32 bit value length
  816.                     of implicit vr if (b[4] < b[7])
  817.                     bigendian=true;
  818.                 } // else little endian if
  819.                 (Character.isUpperCase((char)(b[4])) &&
  820.                 Character.isUpperCase((char)(b[5])))
  821.                 explicitvr=true;
  822.             } // go back to start of dataset reset();
  823.         } // else can't guess or unrecognized ...  assume default
  824.         ImplicitVRLittleEndian (most common without metaheader due to
  825.         Mallinckrodt CTN default) if (bigendian)
  826.             if (explicitvr)
  827.                 TransferSyntaxToReadDataSet = new
  828.                 TransferSyntax(TransferSyntax.ExplicitVRBigEndian);
  829.             else
  830.                 throw new IOException("Not a DICOM file
  831.                 (masquerades as explicit VR big endian)");
  832.         else
  833.             if (explicitvr)
  834.                 TransferSyntaxToReadDataSet = new
  835.                 TransferSyntax(TransferSyntax.ExplicitVRLittleEndian);
  836.             else
  837.                 TransferSyntaxToReadDataSet = new
  838.                 TransferSyntax(TransferSyntax.ImplicitVRLittleEndian);
  839.     }
  840.  
  841.     TransferSyntaxInUse = TransferSyntaxToReadMetaHeader != null ?
  842.     TransferSyntaxToReadMetaHeader : TransferSyntaxToReadDataSet; if
  843.     (TransferSyntaxInUse == null) throw new IOException("Not a DICOM file
  844.     (or can't detect Transfer Syntax)");
  845.     setEndian(TransferSyntaxInUse.isBigEndian()); // leaves us positioned at
  846.     start of group and element tags (for either metaheader or dataset)
  847. }
  848.  
  849.  
  850.  
  851.  
  852.  
  853.  
  854.     2.3 Papyrus
  855.  
  856.  
  857.     Papyrus is an image file format based on ACR/NEMA version 2.0.  It was
  858.     developed by the Digital Imaging Unit of the University Hospital of
  859.     Geneva for the European project on telemedicine (TELEMED project of the
  860.     RACE program), under the leadership of Dr.  Osman Ratib
  861.     (osman@cih.hcuge.ch).  The University Hospital of Geneva uses Papyrus
  862.     for their hospital-wide PACS.
  863.  
  864.  
  865.     The medical file format component of Papyrus version 2 extended the
  866.     ACR/NEMA format, particularly in order to reference multiple images by
  867.     placing folder information referencing ACR-NEMA data sets in a shadow
  868.     (private) group.  Contributing to the development of DICOM 3, the team
  869.     are updating their format to be compatible with the offline file format
  870.     provisions of the draft Part 10 of DICOM 3 in Papyrus version 3.
  871.  
  872.  
  873.     The specifications, toolkit and image manipulation software that is
  874.     Papyrus aware, Osiris, is available for the Mac, Windows, and
  875.     Unix/X11/Motif by ftp from ftp://expasy.hcuge.ch/pub/Osiris.
  876.  
  877.  
  878.     See also Papyrus and Osiris.
  879.  
  880.  
  881.     Further information is available in printed form.  Contact
  882.     yves@cih.hcuge.ch (Yves Ligier).
  883.  
  884.     2.4 Interfile V3.3
  885.  
  886.  
  887.     Interfile is a "file format for the exchange of nuclear medicine image
  888.     data" created I gather to satisfy the needs of the European COST B2
  889.     Project for the transfer of images of quality control phantoms, and
  890.     incorporates the AAPM (American Association of Physicists in Medicine)
  891.     Report No.  10, and has been subsequently used for clinical work.
  892.  
  893.  
  894.     It specifies a file format composed of ascii "key-value" pairs and a
  895.     data dictionary of keys.  The binary image data may be contained in the
  896.     same file as the "administrative information", or in a separate file
  897.     pointed to by a "name of data file" key.  Image data may be binary
  898.     integers, IEEE floating point values, or ascii and the byte order is
  899.     specified by a key "imagedata byte order".  The order of keys is defined
  900.     by the Interfile syntax which is more sophisticated than a simple list
  901.     of keys, allowing for groups, conditionals and loops to dictate the
  902.     order of key-value pairs.
  903.  
  904.  
  905.     Conformance to the Interfile standard is informally described in terms
  906.     of which types of image data types, pixel types, multiple windows,
  907.     special Interfile features including curves, and restriction to various
  908.     maximum recommended limits.
  909.  
  910.  
  911.     Interfile is specifically NOT a communications protocol and strictly
  912.     deals with offline files.  There are efforts to extend Interfile to
  913.     include modalities other than nuclear medicine, as well as to keep
  914.     ACR/NEMA and Interfile data dictionaries in some kind of harmony.
  915.  
  916.  
  917.     A sample list of Interfile 3.3 key-value pairs is shown here to give you
  918.     some idea of the flavor of the format.  The example is culled from part
  919.     of a Static study in the Interfile standard document and is not
  920.     complete:
  921.  
  922.  
  923.         !INTERFILE := !imaging modality :=nucmed !version of keys :=3.3
  924.         data description :=static patient name :=joe doe !patient ID
  925.         :=12345 patient dob :=1968:08:21 patient sex :=M !study ID
  926.         :=test exam type :=test data compression :=none !image number
  927.         :=1 !matrix size [1] :=64 !matrix size [2] :=64 !number format
  928.         :=signed integer !number of bytes per pixel :=2 !image duration
  929.         (sec) :=100 image start time :=10:20: 0 total counts :=8512 !END
  930.         OF INTERFILE :=
  931.  
  932.  
  933.     One can see how easy such a format would be to extend, as well as how it
  934.     is readable and almost useable without reference to any standard
  935.     document or data dictionary.
  936.  
  937.  
  938.     Undoubtedly ACR/NEMA DICOM 3.0 to Interfile translators will soon
  939.     proliferate in view of the fact that many Nuclear Medicine vendors
  940.     supply Interfile translators at present.
  941.  
  942.  
  943.     To get hold of the Interfile 3.3 standard, see the Interfile sources,
  944.     Interfile information contacts and Interfile mailing list described
  945.     later in this document.
  946.  
  947.  
  948.     2.5 Qsh
  949.  
  950.  
  951.     Qsh is a family of programs for manipulating images, and it defines an
  952.     intermediate file format.  The following information was derived with
  953.     the help of one of the authors maguire@it.kth.se(Chip Maguire):
  954.  
  955.  
  956.     Uses an ASCII key-value-pair (KVP sic.) system, based on the AAPM Report
  957.     #10 proposal.  This format influenced both Interfile and ACR-NEMA
  958.     (DICOM).  The file format is referred to as "IMAGE" in some of their
  959.     articles (see references).  The header and the image data are stored as
  960.     two separate files with extensions *.qhd and *.qim respectively.
  961.  
  962.  
  963.     Qsh is available by anonymous ftp from the Qsh ftp site.  This is a
  964.     seriously large tar file, including as it does some sample images, and
  965.     lots of source code, as well as some post-script documents.  Subtrees
  966.     are available as separate tar files.
  967.  
  968.  
  969.     QSH's Motif-based menu system (qmenu) will work with OpenWindows 3.0 if
  970.     SUN patch number 100444-54 for SUNOS 4.1.3 rev.  A is applied.  The
  971.     patch is available from ftp://sunsolve1.sun.com (192.9.9.24).
  972.  
  973.  
  974.     The image access subroutines take the same parameters as the older
  975.     /usr/image package from UNC, however, the actual subroutines support the
  976.     qsh KVP and image data files.
  977.  
  978.  
  979.     The frame buffer access subroutines take the same parameters as the
  980.     Univ.  of Utah software (of the mid.  1970s).  The design is based on
  981.     the use of a virtual frame buffer which is then implemented via a
  982.     library for a specific frame buffer.  There exists a version of the the
  983.     display routines for X11.
  984.  
  985.  
  986.     Conversions are not supported any longer, instead there is a commercial
  987.     product called InterFormat.  InterFormat includes a qsh to Interfile
  988.     conversion, along with DICOM to qsh, and many others.  Information is
  989.     available from reddy@nucmed.med.nyu.edu (David Reddy) (see InterFormat
  990.     in the Sources section).
  991.  
  992.  
  993.     [Editorial note: this seems a bit of a shame to me - the old
  994.     distribution included lots of handy bits of information, particularly on
  995.     driving tape drives.  I am advised however that the conversion stuff was
  996.     pulled out because people wanted it supported, the authors were worried
  997.     they were disclosing things perhaps they ought not to be, and NYU had
  998.     switched to using InterFormat themselves anyway.  DAC.]
  999.  
  1000.  
  1001.     The authors of the qsh package are:
  1002.  
  1003.  
  1004.            - maguire@it.kth.se (Gerald Q.  (Chip) Maguire) -
  1005.            noz@nucmed.NYU.EDU (Marilyn E Noz)
  1006.  
  1007.  
  1008.     The following references are helpful in understanding the philosophy
  1009.     behind the file format, and are included in postscript form in the qsh
  1010.     ftp distribution:
  1011.  
  1012.  
  1013.     @Article[noz88b,
  1014.         Key=<noz88b>, Author=<M.  E.  Noz and G.  Q.  Maguire Jr.>,
  1015.         Title=<QSH: A Minimal but Highly Portable Image Display
  1016.                and Processing Toolkit>,
  1017.         Journal=<Computer Methods and Programs in Biomedicine>,
  1018.         volume=<27>, month=<November>, Year=<1988>, Pages=<229-240>
  1019.     ] @Article[maguire89e,
  1020.         Key=<maguire>, Author=<G.Q.  Maguire Jr., and M.E.  Noz>,
  1021.         Title=<Image Formats: Five Years after the AAPM Standard Format
  1022.         for Digital Image Interchange>, Journal=<Medical Physics>,
  1023.         volume=<16>, month=<September/October>, year=<1989>,
  1024.         pages=<818-823>, comment=<Also as CUCS-369-88>
  1025.     ]
  1026.  
  1027.     2.6 DEFF
  1028.  
  1029.  
  1030.     DEFF (Data Exchange File Format) is a portable image file format
  1031.     designed for the exchange, printing and archiving of ultrasound images.
  1032.     It is written by John Bono of ATL from whom the specification may be
  1033.     obtained.  The latest version is 2.5, March 25, 1994.  It is based on
  1034.     the TIFF 5.0 specification, though a more recent version, TIFF 6.0 is
  1035.     available.
  1036.  
  1037.  
  1038.     Theorectically, any TIFF reader should be able to read the standard tags
  1039.     from a DEFF image, so long as only 8 bit images are in use, as in the
  1040.     Camera Ready class of DEFF images for instance.  Additional support is
  1041.     provided for multi-frame images, and 9 to 16 bit images by extending the
  1042.     TIFF format.  Because Aldus only allocates a small number of unique
  1043.     registered tags to each vendor, ATL have defined their own extensive set
  1044.     of additional tags, which are referenced by using one of the registered
  1045.     tags ExtendedTagsOffset.  Hence these additional tags will not be
  1046.     visible to a conventional TIFF reader.
  1047.  
  1048.  
  1049. The next part is part3 - proprietary CT formats.
  1050.  
  1051.  
  1052.