Example #1
0
  private BufferedImage windowMonochrome(
      ImageListViewCell displayedCell,
      BufferedImage srcImg,
      float windowLocation,
      float windowWidth) {
    BufferedImage destImg =
        new BufferedImage(srcImg.getWidth(), srcImg.getHeight(), BufferedImage.TYPE_INT_RGB);

    boolean isSigned = false;
    int minValue = 0;
    {
      // hack: try to determine signedness and minValue from DICOM metadata if available --
      // the BufferedImage's metadata don't contain that information reliably.
      // Only works for some special cases
      ImageListViewModelElement elt = displayedCell.getDisplayedModelElement();
      if (elt instanceof DicomImageListViewModelElement) {
        DicomImageListViewModelElement delt = (DicomImageListViewModelElement) elt;
        DicomObject imgMetadata = delt.getDicomImageMetaData();
        int bitsAllocated = imgMetadata.getInt(Tag.BitsAllocated);
        isSigned = (1 == imgMetadata.getInt(Tag.PixelRepresentation));
        if (isSigned && (bitsAllocated > 0)) {
          minValue = -(1 << (bitsAllocated - 1));
        }
      }
    }

    final int windowedImageGrayscalesCount = 256; // for BufferedImage.TYPE_INT_RGB
    float scale = windowedImageGrayscalesCount / windowWidth;
    float offset = (windowWidth / 2 - windowLocation) * scale;
    if (!(srcImg.getColorModel().getColorSpace().getType() == ColorSpace.TYPE_GRAY)) {
      throw new IllegalArgumentException("source image must be grayscales");
    }
    Raster srcRaster = srcImg.getRaster();
    if (srcRaster.getNumBands() != 1) {
      throw new IllegalArgumentException(
          "grayscale source image must have one color band, but has "
              + srcRaster.getNumBands()
              + "??");
    }
    WritableRaster resultRaster = destImg.getRaster();
    for (int x = 0; x < srcImg.getWidth(); x++) {
      for (int y = 0; y < srcImg.getHeight(); y++) {
        int srcGrayValue = srcRaster.getSample(x, y, 0);
        if (isSigned) {
          srcGrayValue = (int) (short) srcGrayValue; // will only work for 16-bit signed...
        }
        float destGrayValue = scale * srcGrayValue + offset;
        // clamp
        if (destGrayValue < 0) {
          destGrayValue = 0;
        } else if (destGrayValue >= windowedImageGrayscalesCount) {
          destGrayValue = windowedImageGrayscalesCount - 1;
        }
        resultRaster.setSample(x, y, 0, destGrayValue);
        resultRaster.setSample(x, y, 1, destGrayValue);
        resultRaster.setSample(x, y, 2, destGrayValue);
      }
    }
    return destImg;
  }
Example #2
0
  protected BufferedImage getWindowedImage(ImageListViewCell displayedCell) {
    BufferedImage windowedImage = tryWindowRawImage(displayedCell);
    if (windowedImage != null) {
      return windowedImage;
    } else {
      // TODO: caching of windowed images, probably using
      //       displayedCell.getDisplayedModelElement().getImageKey() and the windowing parameters
      // as the cache key
      BufferedImage srcImg = displayedCell.getDisplayedModelElement().getImage().getBufferedImage();
      // TODO: use the model element's RawImage instead of the BufferedImage when possible
      /// *
      if (srcImg.getColorModel().getColorSpace().getType() == ColorSpace.TYPE_GRAY) {
        try {
          windowedImage =
              windowMonochrome(
                  displayedCell,
                  srcImg,
                  displayedCell.getWindowLocation(),
                  displayedCell.getWindowWidth());
        } catch (IllegalArgumentException e) {
          // TODO: store message somehow so ILVInitStateController can render it
          //      either into ILVModelElt#errorInfo (in which case errorInfo would be a warning for
          // initialized elements),
          //      or, probably better, into a new attribute in the cell
          logger.warn("couldn't window grayscale image: " + e.getLocalizedMessage() /*, e*/);
          return srcImg;
        }
      } else if (srcImg.getColorModel().getColorSpace().isCS_sRGB()) {
        try {
          windowedImage =
              windowRGB(srcImg, displayedCell.getWindowLocation(), displayedCell.getWindowWidth());
        } catch (IllegalArgumentException e) {
          // TODO: store message somehow so ILVInitStateController can render it (see
          // windowMonochrome above)
          logger.warn("couldn't window RGB image: " + e.getLocalizedMessage() /*, e*/);
          return srcImg;
        }
      } else {
        throw new IllegalStateException(
            "don't know how to window image with color space "
                + srcImg.getColorModel().getColorSpace());
        // TODO: do something cleverer here? Like, create windowedImage
        //    with a color space that's "compatible" to srcImg (using
        //    some createCompatibleImage() method in BufferedImage or elsewhere),
        //    window all bands of that, and let the JRE figure out how to draw the result?
      }
      // */
      // windowedImage = windowWithRasterOp(srcImg, windowLocation, windowWidth);
      // windowedImage = srcImg;

      return windowedImage;
    }
  }
Example #3
0
  private BufferedImage tryWindowRawImage(ImageListViewCell displayedCell) {
    ImageListViewModelElement elt = displayedCell.getDisplayedModelElement();
    ViskitImage img = elt.getImage();
    if (!(img.hasRawImage() && img.isRawImagePreferable())) {
      return null;
    }

    // logger.debug("trying to create windowed BufferedImage for: " + elt.getImageKey());

    float[] pixelTransform =
        new float[] {1, 0}; // compute the complete raw input => output pixel transformation in here

    // rescale/slope tags
    if (elt instanceof DicomImageListViewModelElement) {
      try {
        DicomImageListViewModelElement delt = (DicomImageListViewModelElement) elt;
        if (delt.getDicomImageMetaData().contains(Tag.RescaleSlope)
            && delt.getDicomImageMetaData().contains(Tag.RescaleIntercept)) {
          float rscSlope = delt.getDicomImageMetaData().getFloat(Tag.RescaleSlope);
          float rscIntercept = delt.getDicomImageMetaData().getFloat(Tag.RescaleIntercept);
          LinAlg.matrMult1D(new float[] {rscSlope, rscIntercept}, pixelTransform, pixelTransform);
        }
      } catch (Exception e) {
        // ignore -- no error
      }
    }

    // normalization to [0,1]
    FloatRange pxValuesRange = img.getMaximumPixelValuesRange();
    float minGrayvalue = pxValuesRange.getMin();
    float nGrayvalues = pxValuesRange.getDelta();
    LinAlg.matrMult1D(
        new float[] {1.0F / nGrayvalues, -minGrayvalue / nGrayvalues},
        pixelTransform,
        pixelTransform);

    // window level/width
    float wl = (displayedCell.getWindowLocation() - minGrayvalue) / nGrayvalues;
    float ww = displayedCell.getWindowWidth() / nGrayvalues;
    float scale = 1F / ww;
    float offset = (ww / 2 - wl) * scale;
    LinAlg.matrMult1D(new float[] {scale, offset}, pixelTransform, pixelTransform);

    LookupTable lut = displayedCell.getLookupTable();
    /*if (displayedCell.isOutputGrayscaleRGBs()) {
        //TODO: perform 12-bit grayscale output in J2D as well
    } else */ if (lut != null) {
      // transformation to output LUT index
      int lutLength = lut.getRGBAValues().limit() / 4;
      LinAlg.matrMult1D(new float[] {lutLength, 0}, pixelTransform, pixelTransform);
    } else {
      // transformation to output grayscale range ( [0,256) )
      LinAlg.matrMult1D(new float[] {256, 0}, pixelTransform, pixelTransform);
    }

    RawImage rimg = img.getRawImage();
    if (rimg.getPixelFormat() != RawImage.PIXEL_FORMAT_LUMINANCE) {
      return null; // can't window raw RGB images for now
    } else {
      switch (rimg.getPixelType()) {
          // will only window RawImages whose pixelData buffer is a ShortBuffer for now
        case RawImage.PIXEL_TYPE_UNSIGNED_BYTE:
        case RawImage.PIXEL_TYPE_SIGNED_12BIT:
        case RawImage.PIXEL_TYPE_SIGNED_16BIT:
        case RawImage.PIXEL_TYPE_UNSIGNED_12BIT:
          {
            // TODO: maybe reuse BufferedImages of the same size to relieve the GC
            float txscale = pixelTransform[0];
            float txoffset = pixelTransform[1];
            ShortBuffer srcBuffer = (ShortBuffer) rimg.getPixelData();
            int w = rimg.getWidth();
            int h = rimg.getHeight();
            BufferedImage result = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
            WritableRaster resultRaster = result.getRaster();
            if (lut != null) {
              windowLUTShort(srcBuffer, w, h, txscale, txoffset, lut, resultRaster);
            } else {
              windowGrayShort(srcBuffer, w, h, txscale, txoffset, resultRaster);
            }
            return result;
          }
          // ...and IntBuffer
        case RawImage.PIXEL_TYPE_UNSIGNED_16BIT:
          {
            // TODO: maybe reuse BufferedImages of the same size to relieve the GC
            float txscale = pixelTransform[0];
            float txoffset = pixelTransform[1];
            IntBuffer srcBuffer = (IntBuffer) rimg.getPixelData();
            int w = rimg.getWidth();
            int h = rimg.getHeight();
            BufferedImage result = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
            WritableRaster resultRaster = result.getRaster();
            if (lut != null) {
              windowLUTInt(srcBuffer, w, h, txscale, txoffset, lut, resultRaster);
            } else {
              windowGrayInt(srcBuffer, w, h, txscale, txoffset, resultRaster);
            }
            return result;
          }
        default:
          return null;
      }
    }
  }
Example #4
0
 private Point2D getScaledImageSize(ImageListViewCell cell) {
   ViskitImage img = cell.getDisplayedModelElement().getImage();
   return getDicomToUiTransform(cell)
       .transform(new Point2D.Double(img.getWidth(), img.getHeight()), null);
 }