private void windowLUTInt(
     IntBuffer srcBuffer,
     int w,
     int h,
     float txscale,
     float txoffset,
     LookupTable lut,
     WritableRaster resultRaster) {
   int[][] lutRGBAs = lut.getRGBA256intArrays();
   int lutLength = lutRGBAs.length;
   int lutLengthMinus1 = lutLength - 1;
   int index = 0;
   for (int y = 0; y < h; y++) {
     for (int x = 0; x < w; x++) {
       int destLutIndex = (int) (txscale * srcBuffer.get(index++) + txoffset);
       // clamp
       if (destLutIndex < 0) {
         destLutIndex = 0;
       } else if (destLutIndex >= lutLength) {
         destLutIndex = lutLengthMinus1;
       }
       resultRaster.setPixel(x, y, lutRGBAs[destLutIndex]);
     }
   }
 }
  @Override
  public void printLUTIntoCell(
      ImageListViewCellPaintEvent e,
      int lutWidth,
      int lutHeight,
      int intervals,
      Point2D lutPosition,
      Point2D textPosition,
      Color textColor,
      List<String> scaleList) {
    ImageListViewCell cell = e.getSource();
    LookupTable lut = cell.getLookupTable();
    Graphics2D g2d = (Graphics2D) e.getGc().getGraphics2D().create();

    Graphics2D userGraphics = (Graphics2D) g2d.create();

    // draw lut values
    g2d.setColor(textColor);
    int posx = (int) textPosition.getX();
    int posy = (int) textPosition.getY() - 5;
    int lineHeight = lutHeight / intervals;

    for (String scale : scaleList) {
      g2d.drawString(scale, posx - scale.length() * 10, posy);
      posy += lineHeight;
    }
    // draw lut legend
    BufferedImage lutImage =
        scaleImage(
            rotateImage(LutController.getLutMap().get(lut.getName()).getBimg()),
            lutWidth,
            lutHeight);

    // create bordered image
    BufferedImage borderedImage =
        new BufferedImage(lutImage.getWidth() + 2, lutImage.getHeight() + 2, lutImage.getType());
    Graphics2D graphic = borderedImage.createGraphics();
    graphic.setColor(Color.GRAY);
    graphic.fillRect(0, 0, borderedImage.getWidth(), borderedImage.getHeight());
    graphic.drawImage(lutImage, 1, 1, null);

    userGraphics.drawImage(borderedImage, null, (int) lutPosition.getX(), (int) lutPosition.getY());
  }
  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;
      }
    }
  }