Beispiel #1
0
  public static void verifyMD5(File file, String originalMd5) throws Exception {
    log.info("M-READ file:" + file);
    MessageDigest md = MessageDigest.getInstance("MD5");

    BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));

    DigestInputStream dis = new DigestInputStream(in, md);
    try {
      DcmParser parser = DcmParserFactory.getInstance().newDcmParser(dis);
      parser.parseDcmFile(FileFormat.DICOM_FILE, Tags.PixelData);
      if ((parser.getReadTag() & 0xFFFFFFFFL) >= Tags.PixelData) {
        if (parser.getReadLength() == -1) {
          while (parser.parseHeader() == Tags.Item) {
            readOut(parser.getInputStream(), parser.getReadLength());
          }
        }
        readOut(parser.getInputStream(), parser.getReadLength());
        parser.parseDataset(parser.getDcmDecodeParam(), -1);
      }
    } finally {
      try {
        dis.close();
      } catch (IOException ignore) {
      }
    }
    byte[] md5 = md.digest();
    if (!Arrays.equals(md5, MD5.toBytes(originalMd5))) {
      log.error(
          "MD5 for "
              + file.getAbsolutePath()
              + " is different that expected.  Has the file been changed or corrupted?");
      throw new IllegalStateException("MD5 mismatch");
    }
  }
Beispiel #2
0
 public static boolean equalsPixelData(File f1, File f2) throws IOException {
   InputStream in1 = new BufferedInputStream(new FileInputStream(f1));
   try {
     InputStream in2 = new BufferedInputStream(new FileInputStream(f2));
     try {
       Dataset attrs = DcmObjectFactory.getInstance().newDataset();
       DcmParserFactory pf = DcmParserFactory.getInstance();
       DcmParser p1 = pf.newDcmParser(in1);
       DcmParser p2 = pf.newDcmParser(in2);
       p1.setDcmHandler(attrs.getDcmHandler());
       p1.parseDcmFile(FileFormat.DICOM_FILE, Tags.PixelData);
       p2.parseDcmFile(FileFormat.DICOM_FILE, Tags.PixelData);
       int samples = attrs.getInt(Tags.SamplesPerPixel, 1);
       int frames = attrs.getInt(Tags.NumberOfFrames, 1);
       int rows = attrs.getInt(Tags.Rows, 1);
       int columns = attrs.getInt(Tags.Columns, 1);
       int bitsAlloc = attrs.getInt(Tags.BitsAllocated, 8);
       int bitsStored = attrs.getInt(Tags.BitsStored, bitsAlloc);
       int frameLength = rows * columns * samples * bitsAlloc / 8;
       int pixelDataLength = frameLength * frames;
       if (pixelDataLength > p1.getReadLength() || pixelDataLength > p2.getReadLength()) {
         return false;
       }
       byte[] b1 = new byte[BUFFER_SIZE];
       byte[] b2 = new byte[BUFFER_SIZE];
       int[] mask = {0xff, 0xff};
       int len, len2;
       if (bitsAlloc == 16 && bitsStored < 16) {
         mask[p1.getDcmDecodeParam().byteOrder == ByteOrder.LITTLE_ENDIAN ? 1 : 0] =
             0xff >>> (16 - bitsStored);
       }
       int pos = 0;
       while (pos < pixelDataLength) {
         len = in1.read(b1, 0, Math.min(pixelDataLength - pos, BUFFER_SIZE));
         if (len < 0) // EOF
         return false;
         int off = 0;
         while (off < len) {
           off += len2 = in2.read(b2, off, len - off);
           if (len2 < 0) // EOF
           return false;
         }
         for (int i = 0; i < len; i++, pos++)
           if (((b1[i] - b2[i]) & mask[pos & 1]) != 0) return false;
       }
       return true;
     } finally {
       in2.close();
     }
   } finally {
     in1.close();
   }
 }
  /**
   * Convert an image to RGB.
   *
   * @param inFile the file to convert.
   * @param outFile the output file, which may be same as inFile.
   * @return the static status result
   */
  public static AnonymizerStatus convert(File inFile, File outFile) {

    long fileLength = inFile.length();
    logger.debug("Entering DICOMPaletteImageConverter.convert");
    logger.debug("File length       = " + fileLength);

    BufferedInputStream in = null;
    BufferedOutputStream out = null;
    File tempFile = null;
    byte[] buffer = new byte[4096];
    try {
      // Check that this is a known format.
      in = new BufferedInputStream(new FileInputStream(inFile));
      DcmParser parser = pFact.newDcmParser(in);
      FileFormat fileFormat = parser.detectFileFormat();
      if (fileFormat == null) {
        throw new IOException("Unrecognized file format: " + inFile);
      }

      // Get the dataset (excluding pixels) and leave the input stream open
      Dataset dataset = oFact.newDataset();
      parser.setDcmHandler(dataset.getDcmHandler());
      parser.parseDcmFile(fileFormat, Tags.PixelData);

      // Make sure this is an image
      if (parser.getReadTag() != Tags.PixelData) {
        close(in);
        return AnonymizerStatus.SKIP(inFile, "Not an image");
      }

      // Get the required parameters and make sure they are okay
      int numberOfFrames = getInt(dataset, Tags.NumberOfFrames, 1);
      int rows = getInt(dataset, Tags.Rows, 0);
      int columns = getInt(dataset, Tags.Columns, 0);
      String photometricInterpretation = getString(dataset, Tags.PhotometricInterpretation, "");
      if ((rows == 0) || (columns == 0)) {
        close(in);
        return AnonymizerStatus.SKIP(inFile, "Unable to get the rows and columns");
      }
      if (!photometricInterpretation.equals("PALETTE COLOR")) {
        close(in);
        return AnonymizerStatus.SKIP(
            inFile, "Unsupported PhotometricInterpretation: " + photometricInterpretation);
      }
      if (parser.getReadTag() != Tags.PixelData) {
        close(in);
        return AnonymizerStatus.SKIP(inFile, "No pixels");
      }

      // Get the encoding and set the parameters
      DcmDecodeParam fileParam = parser.getDcmDecodeParam();
      String fileEncodingUID = UIDs.ImplicitVRLittleEndian;
      FileMetaInfo fmi = dataset.getFileMetaInfo();
      if (fmi != null) fileEncodingUID = fmi.getTransferSyntaxUID();
      boolean isBigEndian = fileEncodingUID.equals(UIDs.ExplicitVRBigEndian);
      String encodingUID = UIDs.ExplicitVRLittleEndian;
      DcmEncodeParam encoding = (DcmEncodeParam) DcmDecodeParam.valueOf(encodingUID);
      boolean swap = (fileParam.byteOrder != encoding.byteOrder);

      if (encoding.encapsulated) {
        logger.debug("Encapsulated pixel data found");
        close(in);
        return AnonymizerStatus.SKIP(inFile, "Encapsulated pixel data not supported");
      }

      // Get the LUTs
      LUT red =
          new LUT(
              dataset.getInts(Tags.RedPaletteColorLUTDescriptor),
              dataset.getInts(Tags.RedPaletteColorLUTData));
      LUT green =
          new LUT(
              dataset.getInts(Tags.GreenPaletteColorLUTDescriptor),
              dataset.getInts(Tags.GreenPaletteColorLUTData));
      LUT blue =
          new LUT(
              dataset.getInts(Tags.BluePaletteColorLUTDescriptor),
              dataset.getInts(Tags.BluePaletteColorLUTData));

      // Set the PlanarConfiguration to 0
      dataset.putUS(Tags.PlanarConfiguration, 0);

      // Set the PhotometricInterpretation to RGB
      dataset.putCS(Tags.PhotometricInterpretation, "RGB");

      // Set the pixel parameters
      dataset.putUS(Tags.SamplesPerPixel, 3);
      dataset.putUS(Tags.BitsAllocated, 8);
      dataset.putUS(Tags.BitsStored, 8);
      dataset.putUS(Tags.HighBit, 7);

      // Remove the lookup tables and their descriptors
      dataset.remove(Tags.RedPaletteColorLUTDescriptor);
      dataset.remove(Tags.GreenPaletteColorLUTDescriptor);
      dataset.remove(Tags.BluePaletteColorLUTDescriptor);
      dataset.remove(Tags.RedPaletteColorLUTData);
      dataset.remove(Tags.GreenPaletteColorLUTData);
      dataset.remove(Tags.BluePaletteColorLUTData);

      // Save the dataset to a temporary file, and rename at the end.
      File tempDir = outFile.getParentFile();
      tempFile = File.createTempFile("DCMtemp-", ".anon", tempDir);
      out = new BufferedOutputStream(new FileOutputStream(tempFile));

      // Create and write the metainfo for the encoding we are using
      fmi = oFact.newFileMetaInfo(dataset, encodingUID);
      dataset.setFileMetaInfo(fmi);
      fmi.write(out);

      // Write the dataset as far as was parsed
      dataset.writeDataset(out, encoding);

      // Process the pixels
      int nPixels = numberOfFrames * rows * columns;
      int nPixelBytes = nPixels * 3 /*samplesPerPixel*/;
      int pad = nPixelBytes & 1;
      dataset.writeHeader(out, encoding, parser.getReadTag(), VRs.OB, nPixelBytes + pad);

      int pd;
      int b1, b2;
      int bytesPerFrame = rows * columns * 2;
      byte[] frameBytes = new byte[bytesPerFrame];
      for (int frame = 0; frame < numberOfFrames; frame++) {
        if (in.read(frameBytes, 0, frameBytes.length) != bytesPerFrame)
          throw new Exception("End of File");
        for (int p = 0; p < bytesPerFrame; ) {
          b1 = frameBytes[p++];
          b2 = frameBytes[p++];
          if (!swap) {
            pd = ((b2 & 0xff) << 8) | (b1 & 0xff);
          } else {
            pd = ((b1 & 0xff) << 8) | (b2 & 0xff);
          }
          out.write(red.get(pd));
          out.write(green.get(pd));
          out.write(blue.get(pd));
        }
      }
      if (pad != 0) out.write(0);
      logger.debug("Finished writing the pixels");

      // Skip everything after the pixels
      out.flush();
      out.close();
      in.close();
      outFile.delete();
      tempFile.renameTo(outFile);
      return AnonymizerStatus.OK(outFile, "");
    } catch (Exception e) {
      logger.debug("Exception while processing image.", e);

      // Close the input stream if it actually got opened.
      close(in);

      // Close the output stream if it actually got opened,
      // and delete the tempFile in case it is still there.
      try {
        if (out != null) {
          out.close();
          tempFile.delete();
        }
      } catch (Exception ex) {
        logger.warn("Unable to close the output stream.");
      }

      // Quarantine the object
      return AnonymizerStatus.QUARANTINE(inFile, e.getMessage());
    }
  }