Logo Search packages:      
Sourcecode: pixelmed version File versions  Download package

long com::pixelmed::dicom::AttributeList::read ( DicomInputStream  i,
long  byteOffset,
long  lengthToRead,
boolean  stopAfterMetaInformationHeader,
SpecificCharacterSet  specificCharacterSet,
AttributeTag  stopAtTag 
) throws IOException, DicomException [inline, private]

Parameters:
i 
byteOffset 
lengthToRead 
stopAfterMetaInformationHeader 
specificCharacterSet 
stopAtTag the tag (in the top level data set) at which to stop
Exceptions:
IOException 
DicomException 

Definition at line 315 of file AttributeList.java.

References com::pixelmed::dicom::AttributeTag::equals(), com::pixelmed::dicom::EncapsulatedInputStream::getBytesRead(), com::pixelmed::dicom::Attribute::getByteValues(), com::pixelmed::dicom::Attribute::getSingleIntegerValueOrDefault(), com::pixelmed::dicom::Attribute::getSingleStringValueOrDefault(), com::pixelmed::dicom::Attribute::getStringValues(), com::pixelmed::dicom::DicomDictionaryBase::getValueRepresentationFromTag(), com::pixelmed::dicom::EncapsulatedInputStream::nextFrame(), put(), read(), com::pixelmed::dicom::EncapsulatedInputStream::read(), readAttributeTag(), readNewSequenceAttribute(), com::pixelmed::dicom::EncapsulatedInputStream::readSequenceDelimiter(), com::pixelmed::dicom::EncapsulatedInputStream::readUnsigned16(), and com::pixelmed::dicom::Attribute::setValues().

                                                                                                                       {
//System.err.println("AttributeList.read(): start");
//System.err.println("read: Stop tag is "+stopAtTag);
            if (i.areReadingDataSet()) {
                  // Test to see whether or not a codec needs to be pushed on the stream ... after the first time, the TransferSyntax will always be ExplicitVRLittleEndian 
//System.err.println("Testing for deflate and bzip2 TS");
                  if (i.getTransferSyntaxToReadDataSet().isDeflated()) {
                        // insert deflate into input stream and make a new DicomInputStream
//System.err.println("Creating new DicomInputStream from deflate");
                        i = new DicomInputStream(new InflaterInputStream(i,new Inflater(true)),TransferSyntax.ExplicitVRLittleEndian,false);
                        byteOffset=0;
                  }
                  else if (i.getTransferSyntaxToReadDataSet().isBzip2ed()) {
                        // insert bzip2 into input stream and make a new DicomInputStream
//System.err.println("Creating new DicomInputStream from bzip2");
                        try {
                              Class classToUse = Thread.currentThread().getContextClassLoader().loadClass("org.apache.excalibur.bzip2.CBZip2InputStream");
                              Class [] argTypes  = {InputStream.class};
                              Object[] argValues = {i};
                              InputStream bzipInputStream = (InputStream)(classToUse.getConstructor(argTypes).newInstance(argValues));
                              i = new DicomInputStream(bzipInputStream,TransferSyntax.ExplicitVRLittleEndian,false);
                              byteOffset=0;
                        }
                        catch (java.lang.reflect.InvocationTargetException e) {
                              throw new DicomException("Not a correctly encoded bzip2 bitstream - "+e);
                        }
                        catch (Exception e) {   // may be ClassNotFoundException,NoSuchMethodException,InstantiationException
                              throw new DicomException("Could not instantiate bzip2 codec - "+e);
                        }
                  }
            }
            
            createDictionaryifNecessary();
            
            boolean undefinedLength = lengthToRead == 0xffffffffl;
            long endByteOffset=(undefinedLength) ? 0xffffffffl : byteOffset+lengthToRead-1;

//System.err.println("read: start byteOffset="+byteOffset+" endByteOffset="+endByteOffset+" lengthToRead="+lengthToRead);
            byte vrBuffer[] = new byte[2];
            boolean explicit = i.getTransferSyntaxInUse().isExplicitVR();
            
            // keep track of pixel data size in case need VL for encapsulated data ...
            int rows = 0;
            int columns = 0;
            int frames = 1;
            int samplesPerPixel = 1;
            int bytesPerSample = 0;

            AttributeTag tag = null;
            try {
                  // CBZip2InputStream.available() always returns zero, and since we terminate
                  // on exceptions anyway, just forget about it
                  while (/*i.available() > 0 && */(undefinedLength || byteOffset < endByteOffset)) {
//System.err.println("read: i.available()="+i.available());
//System.err.println("read: loop byteOffset="+byteOffset+" endByteOffset="+endByteOffset);
                        tag = readAttributeTag(i);
                        byteOffset+=4;
//System.err.println("read: tag="+tag);

                        if (stopAtTag != null && tag.equals(stopAtTag)) {
//System.err.println("read: stopped at "+tag);
                              return byteOffset;      // stop now, since we have reached the tag at which we were told to stop
                        }
                        
                        if (tag.equals(TagFromName.ItemDelimitationItem)) {
//System.err.println("read: ItemDelimitationItem");
                              // Read and discard value length
                              i.readUnsigned32();
                              byteOffset+=4;
                              return byteOffset;      // stop now, since we must have been called to read an item's dataset
                        }
                        
                        if (tag.equals(TagFromName.Item)) {
                              // this is bad ... there shouldn't be Items here since they should
                              // only be found during readNewSequenceAttribute()
                              // however, try to work around Philips bug ...
                              long vl = i.readUnsigned32();       // always implicit VR form for items and delimiters
                              byteOffset+=4;
System.err.println("Ignoring bad Item at "+byteOffset+" "+tag+" VL=<0x"+Long.toHexString(vl)+">");
                              // let's just ignore it for now
                              continue;
                        }

                        byte vr[];
                        if (explicit) {
                              vr=vrBuffer;
                              i.readInsistently(vr,0,2);
                              byteOffset+=2;
                        }
                        else {
                              vr = dictionary.getValueRepresentationFromTag(tag);
                              if (vr == null)  {
                                    vr=vrBuffer;
                                    vr[0]='U';
                                    vr[1]='N';
                              }
                        }
      
                        long vl;
                        if (explicit) {
                              if (ValueRepresentation.isShortValueLengthVR(vr)) {
                                    vl=i.readUnsigned16();
                                    byteOffset+=2;
                              }
                              else {
                                    i.readUnsigned16();     // reserved bytes
                                    vl=i.readUnsigned32();
                                    byteOffset+=6;
                              }
                        }
                        else {
                              vl=i.readUnsigned32();
                              byteOffset+=4;
                        }

                        if (explicit) {
                              // do not do this until AFTER the value length has been read, since explicit UN uses the long form of length
                              if (ValueRepresentation.isUnknownVR(vr)) {
                                    byte vrd[] = dictionary.getValueRepresentationFromTag(tag);
                                    if (vrd != null && vrd.length >= 2) {
//System.err.println("AttributeList.read(): For tag "+tag+" consider overriding explicit VR "+ValueRepresentation.getAsString(vr)+" with "+ValueRepresentation.getAsString(vrd));
                                          if (!ValueRepresentation.isSequenceVR(vrd)) {
//System.err.println("AttributeList.read(): For tag "+tag+" overriding explicit VR "+ValueRepresentation.getAsString(vr)+" with "+ValueRepresentation.getAsString(vrd));
                                                vr[0] = vrd[0];
                                                vr[1] = vrd[1];
                                          }
                                    }
                              }
                        }
//System.err.println(byteOffset+" "+tag+" VR=<"+ValueRepresentation.getAsString(vr)+"> VL=<0x"+Long.toHexString(vl)+">");

                        Attribute a = null;

                        if (ValueRepresentation.isSequenceVR(vr) || (ValueRepresentation.isUnknownVR(vr) && vl == 0xffffffffl)) {
                              a=new SequenceAttribute(tag);
                              byteOffset=readNewSequenceAttribute(a,i,byteOffset,vl,specificCharacterSet);
                        }
                        else if (vl != 0xffffffffl) {
                              //if (vl > maximumSaneFixedValueLength) throw new DicomException("unlikely fixed VL ("+vl+" dec, 0x"+Long.toHexString(vl)+") - probably incorrect dataset");
                              try {
                                    a = AttributeFactory.newAttribute(tag,vr,vl,i,specificCharacterSet,explicit,bytesPerSample,byteOffset);     // creates and reads the attribute
                              }
                              catch (Exception e) {
                                    e.printStackTrace(System.err);
                                    a = null;
                              }
                              byteOffset+=vl;
                        }
                        else if (vl == 0xffffffffl && tag.equals(TagFromName.PixelData)/* && i.getTransferSyntaxInUse().isEncapsulated()*/) {   // assume encapsulated in case TS is not recognized
                              int wordsPerFrame = rows*columns*samplesPerPixel;
//System.err.println("Undefined length encapsulated Pixel Data: words per frame "+wordsPerFrame);
                              String tsuid = i.getTransferSyntaxInUse().getUID();
//System.err.println("Undefined length encapsulated Pixel Data: TransferSyntax UID "+tsuid);
                              boolean doneReadingEncapsulatedData = false;
                              EncapsulatedInputStream ei = new EncapsulatedInputStream(i);
                              //try {
                              {
                                    if (tsuid.equals(TransferSyntax.PixelMedEncapsulatedRawLittleEndian)) {
                                          if (bytesPerSample == 1) {
                                                byte[] values = new byte[wordsPerFrame*frames];
                                                for (int f=0; f<frames; ++f) {
                                                      ei.read(values,f*wordsPerFrame,wordsPerFrame);
                                                      //ei.nextFrame();
                                                }
                                                a = new OtherByteAttribute(tag);
                                                a.setValues(values);
                                                doneReadingEncapsulatedData=true;
                                          }
                                          else if (bytesPerSample == 2) {
                                                short[] values = new short[wordsPerFrame*frames];
                                                for (int f=0; f<frames; ++f) {
                                                      ei.readUnsigned16(values,f*wordsPerFrame,wordsPerFrame);
                                                      //ei.nextFrame();
                                                }
                                                a = new OtherWordAttribute(tag);
                                                a.setValues(values);
                                                doneReadingEncapsulatedData=true;
                                          }
                                          else {
                                                throw new DicomException("Encapsulated data of more than 2 bytes per sample not supported (got "+bytesPerSample+")");
                                          }
                                    }
                                    else {
                                          if (!haveScannedForCodecs) {
//System.err.println("AttributeList.read(): Scanning for ImageIO plugin codecs");
                                                ImageIO.scanForPlugins();
                                                haveScannedForCodecs=true;
                                          }
                                          pixelDataWasDecompressed = true;
                                          pixelDataWasLossy=false;
                                          lossyMethod=null;
                                          compressionRatio=0;
                                          String readerWanted = null;
//System.err.println("AttributeList.read(): TransferSyntax = "+tsuid);
                                          if (tsuid.equals(TransferSyntax.JPEGBaseline) || tsuid.equals(TransferSyntax.JPEGExtended)) {
                                                readerWanted="JPEG";
                                                pixelDataWasLossy=true;
                                                lossyMethod="ISO_10918_1";
//System.err.println("Undefined length encapsulated Pixel Data in JPEG Lossy");
                                          }
                                          else if (tsuid.equals(TransferSyntax.JPEG2000)) {
                                                readerWanted="JPEG2000";
                                                pixelDataWasLossy=true;
                                                lossyMethod="ISO_15444_1";
//System.err.println("Undefined length encapsulated Pixel Data in JPEG 2000");
                                          }
                                          else if (tsuid.equals(TransferSyntax.JPEG2000Lossless)) {
                                                readerWanted="JPEG2000";
//System.err.println("Undefined length encapsulated Pixel Data in JPEG 2000");
                                          }
                                          else if (tsuid.equals(TransferSyntax.JPEGLossless) || tsuid.equals(TransferSyntax.JPEGLosslessSV1)) {
                                                readerWanted="jpeg-lossless";
//System.err.println("Undefined length encapsulated Pixel Data in JPEG Lossless");
                                          }
                                          else if (tsuid.equals(TransferSyntax.JPEGLS)) {
                                                readerWanted="jpeg-ls";
//System.err.println("Undefined length encapsulated Pixel Data in JPEG-LS");
                                          }
                                          else if (tsuid.equals(TransferSyntax.JPEGNLS)) {
                                                readerWanted="jpeg-ls";
                                                pixelDataWasLossy=true;
                                                lossyMethod="ISO_14495_1";
//System.err.println("Undefined length encapsulated Pixel Data in JPEG-LS");
                                          }
                                          else {
                                                readerWanted="JPEG";
System.err.println("Unrecognized Transfer Syntax "+tsuid+" for encapsulated PixelData - guessing "+readerWanted);
                                          }
                                          if (readerWanted != null) {
                                                ImageReader reader = null;
                                                ImageReaderSpi spi = null;
                                                try {
                                                      reader =  (ImageReader)(ImageIO.getImageReadersByFormatName(readerWanted).next());
                                                      spi = reader.getOriginatingProvider();
                                                      String readerDescription = spi.getDescription(Locale.US);
                                                      String readerVendorName = spi.getVendorName();
                                                      String readerVersion = spi.getVersion();
                                                      if (tsuid.equals(TransferSyntax.JPEGExtended) && readerDescription.equals("Standard JPEG Image Reader") && readerVendorName.equals("Sun Microsystems, Inc.")) {
                                                            throw new DicomException("Reader "+readerDescription+" "+readerVendorName+" "+readerVersion+" does not support extended lossy JPEG Transfer Syntax "+tsuid);
                                                      }
System.err.println("Using reader from "+readerDescription+" "+readerVendorName+" "+readerVersion);
                                                      OurIIOReadProgressListener progressListener = new OurIIOReadProgressListener();
                                                      reader.addIIOReadProgressListener(progressListener);
//System.err.println("Back from reader.addIIOReadProgressListener()");
                                                }
                                                catch (Exception e) {
                                                      dumpListOfAllAvailableReaders(System.err);
                                                      throw new DicomException("No reader for "+readerWanted+" available for Transfer Syntax "+tsuid+"\nCaused by: "+e);
                                                }
                                                if (reader != null) {
                                                      byte[]  bytePixelData = null; // lazy instantiation of one or the other
                                                      short[] shortPixelData = null;
//System.err.println("Using columns = "+columns);
//System.err.println("Using rows = "+rows);
//System.err.println("Using frames = "+frames);
//System.err.println("Using samplesPerPixel = "+samplesPerPixel);
//System.err.println("Using bytesPerSample = "+bytesPerSample);
                                                      int pixelsPerFrame = columns*rows*samplesPerPixel;
                                                      int pixelsPerMultiFrameImage = pixelsPerFrame*frames;
                                                      for (int f=0; f<frames; ++f) {
//System.err.println("Starting frame "+f);
                                                            BufferedImage image = null;
                                                            ImageInputStream iiois = ImageIO.createImageInputStream(ei);
                                                            reader.setInput(iiois,true/*seekForwardOnly*/,true/*ignoreMetadata*/);
                                                            image = reader.read(0);
//System.err.println("Back from frame "+f+" reader.read(), BufferedImage="+image);
                                                            if (image == null) {
                                                                  throw new DicomException("Reader "+spi.getDescription(Locale.US)+" "+spi.getVendorName()+" "+spi.getVersion()
                                                                        +" returned null image for Transfer Syntax "+tsuid);
                                                            }
                                                            else {
                                                                  Raster raster = image.getData();
                                                                  int numDataElements = raster.getNumDataElements();
//System.err.println("getNumDataElements="+numDataElements);
                                                                  if (numDataElements == samplesPerPixel) {
                                                                        int transferType = raster.getTransferType();
//System.err.println("getTransferType="+transferType);
                                                                        if (transferType == DataBuffer.TYPE_BYTE) {
//System.err.println("Getting "+(samplesPerPixel > 1 ? "interleaved " : "")+samplesPerPixel+" channel byte data");
                                                                              byte[] vPixelData = (byte[])(raster.getDataElements(0,0,columns,rows,null));
//System.err.println("Decompressed byte array length "+vPixelData.length+" expected "+pixelsPerFrame);
                                                                              if (bytePixelData == null) {
                                                                                    if (frames == 1) {
                                                                                          bytePixelData = vPixelData;
                                                                                    }
                                                                                    else {
                                                                                          bytePixelData = new byte[pixelsPerMultiFrameImage];
                                                                                    }
                                                                              }
                                                                              if (vPixelData != null) {
                                                                                    System.arraycopy(vPixelData,0,bytePixelData,pixelsPerFrame*f,pixelsPerFrame);
                                                                              }
                                                                        }
                                                                        else if (transferType == DataBuffer.TYPE_SHORT
                                                                              || transferType == DataBuffer.TYPE_USHORT) {
//System.err.println("Getting "+(samplesPerPixel > 1 ? "interleaved " : "")+samplesPerPixel+" channel byte data");
                                                                              short[] vPixelData = (short[])(raster.getDataElements(0,0,columns,rows,null));
//System.err.println("Decompressed short array length "+vPixelData.length+" expected "+pixelsPerFrame);
                                                                              if (shortPixelData == null) {
                                                                                    if (frames == 1) {
                                                                                          shortPixelData = vPixelData;
                                                                                    }
                                                                                    else {
                                                                                          shortPixelData = new short[pixelsPerMultiFrameImage];
                                                                                    }
                                                                              }
                                                                              if (vPixelData != null) {
                                                                                    System.arraycopy(vPixelData,0,shortPixelData,pixelsPerFrame*f,pixelsPerFrame);
                                                                              }
                                                                        }
                                                                  }
                                                            }
                                                            ei.nextFrame();
                                                      }
                                                      ei.readSequenceDelimiter();         // since we terminated loop on number of frames, rather than keeping going until ran out, we need to absorb the delimiter
                                                      if (bytePixelData != null) {
                                                            a = new OtherByteAttribute(tag);
                                                            a.setValues(bytePixelData);
                                                            pixelDataWasDecompressed = true;
                                                      }
                                                      else if (shortPixelData != null) {
                                                            a = new OtherWordAttribute(tag);
                                                            a.setValues(shortPixelData);
                                                            pixelDataWasDecompressed = true;
                                                      }
                                                      doneReadingEncapsulatedData=true;
                                                }
                                          }
                                          else {
//System.err.println("Unrecognized Transfer Syntax "+tsuid+" for encapsulated PixelData");
                                                throw new DicomException("Unrecognized Transfer Syntax "+tsuid+" for encapsulated PixelData");
                                          }
                                    }
                              }
                              //catch (Exception e) {
                              //    e.printStackTrace(System.err);
                              //}
                              if (!doneReadingEncapsulatedData) {
//System.err.println("Skipping encapsulated pixel data");
                                    while (ei.skip(1024) > 0);    // it is appropriate to use skip() rather than use skipInsistently() here 
                              }
                              {
                                    long encapsulatedBytesRead = ei.getBytesRead();
                                    byteOffset+= encapsulatedBytesRead;       // otherwise won't be able to detect end of fixed length sequences and items that contain encapsulated pixel data (e.g., IconImageSequence)
                                    if (pixelDataWasDecompressed) {
                                          // compute CR with precision of three decimal places
                                          compressionRatio = (long)columns*rows*samplesPerPixel*bytesPerSample*frames*1000/encapsulatedBytesRead;
                                          compressionRatio = compressionRatio / 1000;
//System.err.println("AttributeList.read(): compressionRatio = "+compressionRatio);
                                    }
                              }
//System.err.println("Done with encapsulated pixel data");
                        }

                        if (a != null) {
//System.err.println(a.toString());
                              if (get(tag) != null) {
System.err.println("Illegal duplicate tag in dataset - "+tag+" - replacing previous occurence");
                              }
                              put(tag,a);

                              if (tag.equals(TagFromName.FileMetaInformationGroupLength)) {
                                    if (i.areReadingMetaHeader()) {
//System.err.println("Found meta-header");
//System.err.println("Length attribute class="+a.getClass());
                                          long metaLength=a.getSingleIntegerValueOrDefault(0);
                                          byteOffset=read(i,byteOffset,metaLength,false,null,stopAtTag);          // detects and sets transfer syntax for reading dataset
                                          i.setReadingDataSet();
                                          if (stopAfterMetaInformationHeader) {
//System.err.println("Stopping after meta-header");
                                                break;
                                          }
                                          else {
//System.err.println("Calling read");
                                                byteOffset=read(i,byteOffset,0xffffffffl,false,null,stopAtTag);   // read to end (will detect and set own SpecificCharacterSet)
//System.err.println("Back from read after metaheader: now undefinedLength="+undefinedLength+" byteOffset="+byteOffset+" endByteOffset="+endByteOffset);
                                                break;      // ... no plausible reason to continue past this point
                                          }
                                    }
                                    else {
                                          // ignore it, e.g. nested within a sequence item (GE bug).
//System.err.println("Ignoring unexpected FileMetaInformationGroupLength outside meta information header");
                                    }
                              }
                              else if (tag.equals(TagFromName.TransferSyntaxUID)) {
                                    if (i.areReadingMetaHeader()) {
                                          i.setTransferSyntaxToReadDataSet(new TransferSyntax(a.getSingleStringValueOrDefault(TransferSyntax.ExplicitVRLittleEndian)));
                                    }
                                    else {
                                          // ignore it, e.g. nested within a sequence item (GE bug).
//System.err.println("Ignoring unexpected TransferSyntaxUID outside meta information header");
                                    }
                              }
                              else if (tag.equals(TagFromName.SpecificCharacterSet)) {
                                    specificCharacterSet = new SpecificCharacterSet(a.getStringValues(),a.getByteValues());
                              }
                              else if (tag.equals(TagFromName.Columns)) {
                                    columns = a.getSingleIntegerValueOrDefault(0);
//System.err.println("Setting columns = "+columns);
                              }
                              else if (tag.equals(TagFromName.Rows)) {
                                    rows = a.getSingleIntegerValueOrDefault(0);
//System.err.println("Setting rows = "+rows);
                              }
                              else if (tag.equals(TagFromName.NumberOfFrames)) {
                                    frames = a.getSingleIntegerValueOrDefault(1);
//System.err.println("Setting frames = "+frames);
                              }
                              else if (tag.equals(TagFromName.SamplesPerPixel)) {
                                    samplesPerPixel = a.getSingleIntegerValueOrDefault(1);
//System.err.println("Setting samplesPerPixel = "+samplesPerPixel);
                              }
                              else if (tag.equals(TagFromName.BitsAllocated)) {
                                    bytesPerSample = (a.getSingleIntegerValueOrDefault(16)-1)/8+1;
//System.err.println("Setting bytesPerSample = "+bytesPerSample);
                              }
                        }
                  }
            }
            catch (EOFException e) {
//System.err.println("Closing on "+e);
                  if (!undefinedLength) throw new EOFException();
            }
            catch (IOException e) {
//System.err.println("Closing on "+e);
                  if (!undefinedLength) throw new IOException();        // InflaterInputStream seems to throw IOException rather than EOFException
            }
//System.err.println("AttributeList.read(): end");
            return byteOffset;
      }


Generated by  Doxygen 1.6.0   Back to index