private synchronized void computeHistogram(Rectangle visibleRect, PlanarImage image) { int channels = image.getSampleModel().getNumBands(); Histogram hist = new Histogram(256, 256, 512, channels); bins = hist.getBins(); // Raster raster = image.getData(visibleRect); Rectangle bounds = visibleRect; // image.getBounds(); int pixel[] = null; int maxPixels = 256; int incX = bounds.width >= 2 * maxPixels ? bounds.width / maxPixels : 1; int incY = bounds.height >= 2 * maxPixels ? bounds.height / maxPixels : 1; double log2 = Math.log(2); int minTileX = image.XToTileX(bounds.x); int maxTileX = image.XToTileX(bounds.x + bounds.width - 1); int minTileY = image.YToTileY(bounds.y); int maxTileY = image.YToTileY(bounds.y + bounds.height - 1); for (int tx = minTileX; tx <= maxTileX; tx++) for (int ty = minTileY; ty <= maxTileY; ty++) { Raster raster = image.getTile(tx, ty); int minX = Math.max(bounds.x, raster.getMinX()); int maxX = Math.min(bounds.x + bounds.width, raster.getMinX() + raster.getWidth()); int minY = Math.max(bounds.y, raster.getMinY()); int maxY = Math.min(bounds.y + bounds.height, raster.getMinY() + raster.getHeight()); for (int x = minX; x < maxX; x += incX) for (int y = minY; y < maxY; y += incY) { pixel = raster.getPixel(x, y, pixel); for (int c = 0; c < channels; c++) { int v = (int) (511 * logTable[pixel[c]] / (16 * log2)); if (v > 255) bins[c][v - 256]++; else bins[c][0]++; } } } bins = hist.getBins(); }
private BufferedImage cropScaleGrayscale(Rectangle visibleRect, RenderedImage image) { int minX = image.getMinX(); int minY = image.getMinY(); int width = image.getWidth(); int height = image.getHeight(); Rectangle bounds = new Rectangle(minX, minY, width, height); visibleRect = bounds.intersection(visibleRect); if (bounds.contains(visibleRect)) { ParameterBlock pb = new ParameterBlock(); pb.addSource(image); pb.add((float) visibleRect.x); pb.add((float) visibleRect.y); pb.add((float) visibleRect.width); pb.add((float) visibleRect.height); image = JAI.create("Crop", pb, JAIContext.noCacheHint); } Dimension previewSize = getSize(); if ((visibleRect.width > previewSize.width) || (visibleRect.height > previewSize.height)) { float scale = Math.min( previewSize.width / (float) visibleRect.width, previewSize.height / (float) visibleRect.height); image = ConvolveDescriptor.create(image, Functions.getGaussKernel(.25 / scale), null); ParameterBlock pb = new ParameterBlock(); pb.addSource(image); pb.add(scale); pb.add(scale); image = JAI.create("Scale", pb, JAIContext.noCacheHint); } image = Functions.toColorSpace(image, JAIContext.systemColorSpace, null); if (image.getSampleModel().getDataType() == DataBuffer.TYPE_USHORT) { image = Functions.fromUShortToByte(image, null); } return Functions.toFastBufferedImage(image); }
protected synchronized void paintComponent(Graphics gr) { Graphics2D g2d = (Graphics2D) gr; if (bins == null) engine.update(null, false); Dimension bounds = getSize(); final float minx = 0; final float miny = 0; final float width = bounds.width; final float height = bounds.height - 18; g2d.setColor(Color.lightGray); g2d.fill(new Rectangle2D.Float(minx, miny, width, height + 18)); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); if (bins != null) { final int max = binmax(); class scaler { int yscale(double y) { return (int) (height - (height - 4) * (y / (double) max) + 0.5 + miny); } } scaler s = new scaler(); for (int c = 0; c < bins.length; c++) { Color color = Color.BLACK; if (bins.length > 1) switch (c) { case 0: color = Color.RED; break; case 1: color = Color.GREEN; break; case 2: color = Color.BLUE; break; } g2d.setColor(color); int numBins = bins[c].length; int zeroY = s.yscale(0); float xstep = (width + 1) / numBins; GeneralPath gp = new GeneralPath(); gp.moveTo(minx, zeroY); float lastx = minx; float lasty = zeroY; for (int i = 0; i < numBins; i++) { int y = s.yscale(bins[c][i]); float x = xstep * i + minx; if (lasty != zeroY || y != zeroY) { gp.lineTo(x, y); lastx = x; lasty = y; } } if (lasty != zeroY) gp.lineTo(lastx, zeroY); g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f)); g2d.fill(gp); g2d.setComposite(AlphaComposite.SrcOver); g2d.draw(gp); } } float step = width / 16.0f; for (int i = 0; i < 16; i++) { if (i == currentFocusZone) g2d.setColor(Color.yellow); else { float color = (float) ((Math.pow(2, i * 8.0 / (16 - 1)) - 1) / 255.); float[] srgbColor = Functions.fromLinearToCS( JAIContext.systemColorSpace, new float[] {color, color, color}); g2d.setColor( new Color( (int) (255 * srgbColor[0]), (int) (255 * srgbColor[1]), (int) (255 * srgbColor[2]))); } g2d.fill(new Rectangle2D.Float(minx + step * i, height + miny, step + 0.5f, 18)); } }
static { for (int i = 0; i < 0x10000; i++) logTable[i] = (float) Math.log1p(i); }