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; } } }