package org.das2.graph; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.Shape; import java.awt.geom.AffineTransform; import java.awt.image.AffineTransformOp; import java.awt.image.BufferedImage; import java.util.LinkedHashMap; import java.util.Map; import java.util.logging.Level; import javax.swing.Icon; import javax.swing.ImageIcon; import org.das2.DasApplication; import org.das2.DasException; import org.das2.datum.Datum; import org.das2.datum.Units; import org.das2.datum.UnitsUtil; import org.das2.event.CrossHairMouseModule; import org.das2.event.DasMouseInputAdapter; import org.das2.event.MouseModule; import org.das2.util.monitor.ProgressMonitor; import org.das2.qds.DDataSet; import org.das2.qds.JoinDataSet; import org.das2.qds.QDataSet; import org.das2.qds.SemanticOps; import org.das2.qds.examples.Schemes; import org.das2.qds.ops.Ops; /** * Renders RBG images stored in a QDataSet[m,n,3], etc. * @author jbf */ public class RGBImageRenderer extends Renderer { BufferedImage image=null; /** * the bounds of the last rendering */ Rectangle rect= null; @Override public void setControl(String s) { super.setControl(s); this.nearestNeighborInterpolation= getBooleanControl( RGBImageRenderer.PROP_NEARESTNEIGHBORINTERPOLATION, nearestNeighborInterpolation ); } @Override public String getControl() { Map controls= new LinkedHashMap(); controls.put( RGBImageRenderer.PROP_NEARESTNEIGHBORINTERPOLATION, encodeBooleanControl( nearestNeighborInterpolation ) ); return Renderer.formatControl(controls); } @Override public void render(Graphics2D g, DasAxis xAxis, DasAxis yAxis) { QDataSet lds= getDataSet(); QDataSet dep0; QDataSet dep1; if ( lds==null || lds.length() == 0) { postMessage( "null data set", Level.INFO, null, null ); return; } if ( image==null ) { getParent().postException( this, lastException ); } BufferedImage im= image; // make local copy for thread safety if ( im==null ) return; // transitional state dep0= (QDataSet)lds.property(QDataSet.DEPEND_0); dep1= (QDataSet)lds.property(QDataSet.DEPEND_1); if ( dep0==null ) dep0= Ops.dindgen(im.getWidth()); if ( dep1==null ) dep1= Ops.dindgen(im.getHeight()); { int n= dep0.length(); double dx1= ( dep0.value(1)- dep0.value(0) ); double dx2= ( dep0.value(n-1)- dep0.value(n-2) ); boolean xlog= (dx2/dx1)>10.; if ( xAxis.isLog()!=xlog ) { postMessage( "xaxis must be " + ( xlog ? "log" : "linear" ) + ", for this image", Level.INFO, null, null ); return; } } { int n= dep1.length(); double dy1= ( dep1.value(1)- dep1.value(0) ); double dy2= ( dep1.value(n-1)- dep1.value(n-2) ); boolean ylog= (dy2/dy1)>10.; if ( yAxis.isLog()!=ylog ) { postMessage( "yaxis must be " + ( ylog ? "log" : "linear" )+ ", for this image", Level.INFO, null, null ); return; } } Units xunits= SemanticOps.getUnits(dep0); Units yunits= SemanticOps.getUnits(dep1); if ( yunits==Units.dimensionless && yAxis.getUnits()!=Units.dimensionless && UnitsUtil.isRatioMeasurement( yAxis.getUnits() ) ) { yunits= yAxis.getUnits(); dep1= Ops.putProperty( dep1, QDataSet.UNITS, yunits ); } int h= im.getHeight(); int w= im.getWidth(); double dx0= dep0.value(1)-dep0.value(0); double dy0= dep1.value(1)-dep1.value(0); int ix0; int ix1; // inclusive int iy0; int iy1; // inclusive double dx= dep0.value(1)-dep0.value(0); int x0; if ( true ) { //if ( x0==-10000 ) { Datum d= xAxis.invTransform( 0. ); if ( !d.getUnits().isConvertibleTo(xunits) ) { d= xunits.createDatum(d.value()); } if ( dx>0 ) { ix0= (int)( Math.floor( Ops.findex( dep0, xAxis.invTransform( 0. ) ).value() ) ); } else { ix0= (int)( Math.floor( Ops.findex( Ops.multiply(-1,dep0), d.multiply(-1) ).value() ) ); } ix0= Math.max( 0, ix0 ); ix0= Math.min( w-1, ix0 ); x0= (int)xAxis.transform( dep0.value(ix0) - dx0/2, xAxis.getUnits() ); } double dy= dep1.value(1)-dep1.value(0); int y0; if ( true ) { //y0==10000 ) { if ( dy>0 ) { iy0= (int)( Math.floor( Ops.findex( dep1, yAxis.invTransform( yAxis.getHeight()+yAxis.getY() ) ).value() ) ); } else { iy0= (int)( Math.floor( Ops.findex( Ops.multiply(-1,dep1), yAxis.invTransform( yAxis.getHeight()+yAxis.getY() ).multiply(-1) ).value() ) ); } iy0= Math.max( 0, iy0 ); iy0= Math.min( h-1, iy0 ); y0= (int)yAxis.transform( dep1.value(iy0) - dy0/2, yAxis.getUnits() ); } int x1; if ( true ) { //if ( x1==10000 ) { Datum d= xAxis.invTransform( xAxis.getWidth()+xAxis.getX() ); if ( !d.getUnits().isConvertibleTo(xunits) ) { d= xunits.createDatum(d.value()); } if ( dx>0 ) { ix1= (int)( Math.ceil( Ops.findex( dep0, d ).value() ) ); } else { ix1= (int)( Math.ceil( Ops.findex( Ops.multiply(-1,dep0), d.multiply(-1) ).value() ) ); } ix1= Math.max( 0, ix1 ); ix1= Math.min( w-1, ix1 ); x1= (int)xAxis.transform( dep0.value(ix1) + dx0/2, xAxis.getUnits() ); } int y1; if ( true ) { //if ( y1==-10000 ) { if ( dy>0 ) { iy1= (int)( Math.ceil( Ops.findex( dep1, yAxis.invTransform( 0 ) ).value() ) ); } else { iy1= (int)( Math.floor( Ops.findex( Ops.multiply(-1,dep1), yAxis.invTransform( 0. ).multiply(-1) ).value() ) ); } iy1= Math.max( 0, iy1 ); iy1= Math.min( h-1, iy1 ); y1= (int)yAxis.transform( dep1.value(iy1) + dy0/2, yunits); } if ( nearestNeighborInterpolation ) { ((Graphics2D)g).setRenderingHint( RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR ); } ix1= ix1+1; // now exclusive iy1= iy1+1; if ( ix0==ix1 ) { postMessage( "image is off screen", Level.INFO, null, null ); } if ( iy0==iy1 ) { postMessage( "image is off screen", Level.INFO, null, null ); } if ( ix0>0 || ix10 || iy1