Ejemplo n.º 1
0
  /*
   * Get the contents of an input dataset element by tag,
   * handling CTP elements specially.
   * @param tag the element tag
   * @return the value of the specified element in the current dataset,
   * @throws Exception if the element is missing.
   */
  public String contents(int tag) throws Exception {
    SpecificCharacterSet cs = inDS.getSpecificCharacterSet();

    // Handle FileMetaInfo references
    if ((inFMI != null) && ((tag & 0x7FFFFFFF) < 0x80000)) {
      DcmElement el = inFMI.get(tag);
      if (el == null) throw new Exception(Tags.toString(tag) + " missing");
      return el.getString(cs);
    }

    // Not FMI, handle DataSet references
    boolean ctp = false;
    if (((tag & 0x00010000) != 0) && ((tag & 0x0000ff00) != 0)) {
      int blk = (tag & 0xffff0000) | ((tag & 0x0000ff00) >> 8);
      try {
        ctp = inDS.getString(blk).equals("CTP");
      } catch (Exception notCTP) {
        ctp = false;
      }
    }
    DcmElement el = inDS.get(tag);
    if (el == null) throw new Exception(Tags.toString(tag) + " missing");

    if (ctp) return new String(inDS.getByteBuffer(tag).array());

    String[] s = el.getStrings(cs);
    if (s.length == 1) return s[0];
    if (s.length == 0) return "";
    StringBuffer sb = new StringBuffer(s[0]);
    for (int i = 1; i < s.length; i++) {
      sb.append("\\" + s[i]);
    }
    return sb.toString();
  }
Ejemplo n.º 2
0
  /**
   * 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());
    }
  }