Changeset 60:88826a8c5728

Show
Ignore:
Timestamp:
04/13/08 09:21:03 (4 years ago)
Author:
Harri Kaimio <harri@…>
Tags:
tip
Message:

Finalized wrking version of scan area selection dialog

  • Use the area selected in when doing real scans
  • Show a small "magnifying glass" area in preview pane to help precise
    selection
  • etc.

Z

Location:
src
Files:
1 added
11 modified

Legend:

Unmodified
Added
Removed
  • src/main/pcapp/org/freecine/sane/FixedPointNumber.java

    r50 r60  
    2727 
    2828/** 
    29  * 
    30  * @author harri 
     29 Fixed point number used when setting parameters for Sane. 
     30  
     31 Sane uses 32 bit fixed point number (with 16 bit integer, 16 bit fractional  
     32 part for many parameters. This class provides conversions and basic arithmetic  
     33 operations for those. 
     34  
    3135 */ 
    32 public class FixedPointNumber { 
     36public class FixedPointNumber implements Comparable { 
     37     
     38    final static int SANE_FIXED_SCALE_SHIFT = 16; 
     39  
     40    /** 
     41     Value of the number, shifted left SANE_FIXED_SCALE_SHIFT bits 
     42     */ 
    3343    private int val; 
     44     
     45    /** 
     46     Creates a new fixed point number from the SANE internal representation of it 
     47     @param fpval 
     48     */ 
    3449    public FixedPointNumber( int fpval ) { 
    3550        val = fpval; 
    3651    } 
    3752     
     53    /** 
     54     Get the representation that Sane uses for this number 
     55     @return 
     56     */ 
    3857    public int getVal() { 
    3958        return val; 
    4059    } 
    4160     
     61    /** 
     62     Test for equality 
     63     @param o The object to test with 
     64     @return true if this object and o are equal, false otherwise 
     65     */ 
     66    @Override 
     67    public boolean equals( Object o ) { 
     68        if ( o == this ) { 
     69            return true; 
     70        } 
     71        if ( !(o instanceof FixedPointNumber) ) { 
     72            return false; 
     73        } 
     74        FixedPointNumber f = (FixedPointNumber) o; 
     75        return f.val == val; 
     76    } 
     77 
     78    /** 
     79     Calculate hash code for this object 
     80     @return 
     81     */ 
     82    @Override 
     83    public int hashCode() { 
     84        int hash = 7; 
     85        hash = 67 * hash + this.val; 
     86        return hash; 
     87    } 
     88     
     89    /** 
     90     Compare with another FixedPointNumber 
     91     @param o 
     92     @return 
     93     */ 
     94    public int compareTo( Object o ) { 
     95        FixedPointNumber f = (FixedPointNumber) o; 
     96        if ( val > f.val ) { 
     97            return 1; 
     98        } 
     99        if ( val < f.val ) { 
     100            return -1; 
     101        } 
     102        return 0; 
     103    } 
     104     
     105    /** 
     106     Add two fixed point numbers 
     107     @param f The number to add to this. 
     108     @return FixedPointNumber with value this+f 
     109     */      
     110    public FixedPointNumber add( FixedPointNumber f ) { 
     111        return new FixedPointNumber( this.val + f.val ); 
     112    } 
     113     
     114    /** 
     115     Subtract two fixed point numbers 
     116     @param f The number to subtract from this. 
     117     @return FixedPointNumber with value this-f 
     118     */      
     119    public FixedPointNumber subtract( FixedPointNumber f ) { 
     120        return new FixedPointNumber( this.val - f.val ); 
     121    } 
     122     
     123    /** 
     124     Convert this fixed point nubmer to double 
     125     @return double with value that is as close as possible to value of this. 
     126     */ 
     127    public double toDouble() { 
     128        return (double)val / (double)( 1 << SANE_FIXED_SCALE_SHIFT ); 
     129    } 
     130     
     131    /** 
     132     Convert the number to string 
     133     @return 
     134     */ 
     135    @Override 
     136    public String toString() { 
     137        int intPart = val >> SANE_FIXED_SCALE_SHIFT; 
     138        int fracPart = val & ( (1 << SANE_FIXED_SCALE_SHIFT) -1); 
     139        String str = "" + intPart; 
     140        if ( fracPart != 0 ) { 
     141            str += " " + fracPart + "/" + (1 << SANE_FIXED_SCALE_SHIFT ); 
     142        } 
     143        return str; 
     144    } 
     145     
     146    /** 
     147     Create a new fixed point number whose value is close to given double  
     148     precision number 
     149     @param v 
     150     @return 
     151     */ 
     152    public static FixedPointNumber valueOf( double v ) { 
     153        double v2 = v * (double)(1<<SANE_FIXED_SCALE_SHIFT); 
     154        return new FixedPointNumber( (int)v2 );         
     155    } 
    42156} 
  • src/main/pcapp/org/freecine/sane/SaneDevice.java

    r59 r60  
    101101            if ( desc.getType() == OptionType.SANE_TYPE_STRING ) { 
    102102                if ( desc.size >= value.length() ) { 
    103                     int status = sane.sane_control_option(deviceHandle, id, 1, value, null ); 
     103                    IntByReference info = new IntByReference(); 
     104                    int status = sane.sane_control_option(deviceHandle, id, 1, value, info ); 
    104105                    if ( status != 0 ) { 
    105106                        throw new SaneException( "Error setting option " + option + " to " + value ); 
     107                    } 
     108                    // Check if options need to be reloaded 
     109                    if ( ( info.getValue() & 2 ) != 0 ) { 
     110                        initOptions(); 
    106111                    } 
    107112                } else { 
     
    126131            if ( desc.getType() == OptionType.SANE_TYPE_INT ) { 
    127132                if ( desc.size == value.length * 4 ) { 
    128                     int status = sane.sane_control_option(deviceHandle, id, 1, value, null ); 
     133                    IntByReference info = new IntByReference(); 
     134                    int status = sane.sane_control_option(deviceHandle, id, 1, value, info ); 
    129135                    if ( status != 0 ) { 
    130136                        throw new SaneException( "Error setting option " + option ); 
     137                    } 
     138                    // Check if options need to be reloaded 
     139                    if ( ( info.getValue() & 2 ) != 0 ) { 
     140                        initOptions(); 
    131141                    } 
    132142                } else { 
     
    147157    } 
    148158     
    149     public void setOption( String option, FixedPointNumber[] value ) throws SaneException { 
     159    public FixedPointNumber[] setOption( String option, FixedPointNumber[] value ) throws SaneException { 
    150160        if ( optionIds == null ) { 
    151161            initOptions(); 
    152162        } 
     163        FixedPointNumber[] newValue = value; 
    153164        int id = -1; 
    154165        if ( optionIds.containsKey(option ) ) { 
     
    161172                } 
    162173                if ( desc.size == value.length * 4 ) { 
    163                     int status = sane.sane_control_option(deviceHandle, id, 1, v, null ); 
     174                    IntByReference info = new IntByReference(); 
     175                    int status = sane.sane_control_option(deviceHandle, id, 1, v, info ); 
    164176                    if ( status != 0 ) { 
    165177                        throw new SaneException( "Error setting option " + option ); 
     178                    } 
     179                    // Check if options need to be reloaded 
     180                    if ( ( info.getValue() & 2 ) != 0 ) { 
     181                        initOptions(); 
     182                    } 
     183                    if ( ( info.getValue() & 1 ) != 0 ) { 
     184                        System.err.println( "Value modified :" ); 
     185                        newValue = new FixedPointNumber[value.length]; 
     186                        for ( int n = 0 ; n < v.length ; n++  ) { 
     187                            newValue[n] = new FixedPointNumber( v[n] ); 
     188                        } 
    166189                    } 
    167190                } else { 
     
    174197            throw new SaneException( "No option named " + option ); 
    175198        } 
    176          
    177     } 
    178      
    179     public void setOption( String option, FixedPointNumber value ) throws SaneException { 
     199        return newValue; 
     200    } 
     201     
     202    public FixedPointNumber setOption( String option, FixedPointNumber value ) throws SaneException { 
    180203        FixedPointNumber[] a = {value}; 
    181         setOption( option, a ); 
     204        return setOption( option, a )[0]; 
    182205    }     
     206 
    183207     
    184208    public void startScan() throws SaneException { 
  • src/main/pcapp/org/freecine/swingui/PreviewPane.form

    r59 r60  
    99    <EventHandler event="mouseReleased" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="formMouseReleased"/> 
    1010    <EventHandler event="mouseDragged" listener="java.awt.event.MouseMotionListener" parameters="java.awt.event.MouseEvent" handler="formMouseDragged"/> 
     11    <EventHandler event="mouseMoved" listener="java.awt.event.MouseMotionListener" parameters="java.awt.event.MouseEvent" handler="formMouseMoved"/> 
    1112  </Events> 
    1213  <AuxValues> 
  • src/main/pcapp/org/freecine/swingui/PreviewPane.java

    r59 r60  
    5656    BufferedImage scaledImage; 
    5757     
     58    int magnWidth = 100; 
     59     
    5860    public void setPreviewImage( BufferedImage img ) { 
    5961        BufferedImage oldPreview = previewImage; 
     
    121123            } 
    122124            ((Graphics2D) g).drawRenderedImage( scaledImage, null ); 
    123         } 
    124          
    125         if ( selection != null ) { 
     125             
     126            // Draw the magnification window 
     127            int imageX = (int)((double)lastMouseX / scale) - magnWidth / 2; 
     128            int imageY = (int)((double)lastMouseY / scale) - magnWidth / 2; 
     129             
     130            imageX = Math.max( 0, imageX ); 
     131            imageX = Math.min( previewImage.getWidth()-magnWidth, imageX ); 
     132            imageY = Math.max( 0, imageY ); 
     133            imageY = Math.min( previewImage.getHeight() - magnWidth, imageY ); 
     134            BufferedImage magnImage = previewImage.getSubimage( imageX, imageY, magnWidth, magnWidth ); 
     135            ((Graphics2D) g).drawImage( magnImage, null, 0, getHeight() - magnWidth ); 
     136             
     137        } 
     138         
     139        if ( selection != null && scaledImage != null ) { 
    126140            // Calculate device space coordinates for the selection rectangle 
    127             double w = getWidth(); 
    128             double h = getHeight(); 
     141            double w = scaledImage.getWidth(); 
     142            double h = scaledImage.getHeight(); 
    129143            double tlx = w * (( selection.getMinX()-previewArea.getMinX() ) / previewArea.getWidth()); 
    130144            double tly = h * (( selection.getMinY()-previewArea.getMinY() ) / previewArea.getHeight()); 
     
    147161    } 
    148162     
    149     /** 
    150      Calculate scaledIamge from previewImage so that it fits in the control 
     163    double scale = 1.0; 
     164     
     165    /** 
     166     Calculate scaledIamge from previewImage so that it fits in the control. The 
     167     scale of scaledImage is stored in scale member. 
    151168     */ 
    152169    private void scaleImage() { 
     
    158175        double xscale = (double)compWidth / (double) iw; 
    159176        double yscale = (double)compHeight / (double) ih; 
    160         double scale = Math.min( xscale, yscale ); 
     177        scale = Math.min( xscale, yscale ); 
    161178        AffineTransform xform = AffineTransform.getScaleInstance( scale, scale ); 
    162179        AffineTransformOp xformOp = new AffineTransformOp( xform, null ); 
     
    186203            public void mouseDragged(java.awt.event.MouseEvent evt) { 
    187204                formMouseDragged(evt); 
     205            } 
     206            public void mouseMoved(java.awt.event.MouseEvent evt) { 
     207                formMouseMoved(evt); 
    188208            } 
    189209        }); 
     
    217237    private void formMouseDragged(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_formMouseDragged 
    218238        log.entering("PreviewPane", "formMouseDragged"); 
     239 
     240        lastMouseX = evt.getX(); 
     241        lastMouseY = evt.getY(); 
     242         
     243        if ( scaledImage == null ) { 
     244            return; 
     245        } 
    219246        Point2D p1 = screenToDev( dragStartX, dragStartY ); 
    220247        Point2D p2 = screenToDev( evt.getX(), evt.getY() ); 
     
    227254    private void formMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_formMouseReleased 
    228255        log.entering( "PreviewPane", "formMouseReleased" ); 
     256        if ( scaledImage == null ) { 
     257            return; 
     258        } 
    229259        Point2D p1 = screenToDev( dragStartX, dragStartY ); 
    230260        Point2D p2 = screenToDev( evt.getX(), evt.getY() ); 
     
    232262        s.add( p2 ); 
    233263        setSelection( s ); 
     264        log.severe( "new area " + s ); 
    234265        log.exiting("PreviewPane", "formMouseDragged"); 
    235266    }//GEN-LAST:event_formMouseReleased 
    236      
    237     /** 
    238      Convert position from screen coordinates to scanner device coordinates 
     267 
     268    int lastMouseX = 0; 
     269    int lastMouseY = 0; 
     270     
     271    private void formMouseMoved(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_formMouseMoved 
     272        lastMouseX = evt.getX(); 
     273        lastMouseY = evt.getY(); 
     274        repaint(); 
     275    }//GEN-LAST:event_formMouseMoved 
     276     
     277    /** 
     278     Convert position from screen coordinates to scanner device coordinates. 
     279     To call this function, the scaledImage must exist as it defines the mapping  
     280     screen space coordinate system 
    239281     @param x 
    240282     @param y 
    241283     @return 
    242284     */ 
    243     Point2D screenToDev( int x, int y ) { 
    244         double w = getWidth(); 
    245         double h = getHeight(); 
     285    private Point2D screenToDev( int x, int y ) { 
     286        double w = scaledImage.getWidth(); 
     287        double h = scaledImage.getHeight(); 
    246288        double devx = previewArea.getMinX() + previewArea.getWidth() * (x/w); 
    247289        double devy = previewArea.getMinY() + previewArea.getHeight() * (y/h); 
  • src/main/pcapp/org/freecine/swingui/ScanPreviewDlg.form

    r59 r60  
    2626              <EmptySpace max="-2" attributes="0"/> 
    2727              <Component id="previewPane" min="-2" max="-2" attributes="0"/> 
    28               <EmptySpace pref="75" max="32767" attributes="0"/> 
    29               <Component id="startPreviewScanBtn" min="-2" max="-2" attributes="0"/> 
     28              <EmptySpace max="32767" attributes="0"/> 
     29              <Group type="103" groupAlignment="1" attributes="0"> 
     30                  <Component id="startPreviewScanBtn" min="-2" max="-2" attributes="0"/> 
     31                  <Component id="okBtn" alignment="1" min="-2" max="-2" attributes="0"/> 
     32              </Group> 
    3033              <EmptySpace max="-2" attributes="0"/> 
    3134          </Group> 
     
    3740              <EmptySpace max="-2" attributes="0"/> 
    3841              <Group type="103" groupAlignment="0" attributes="0"> 
    39                   <Component id="startPreviewScanBtn" alignment="0" min="-2" max="-2" attributes="0"/> 
     42                  <Group type="102" alignment="0" attributes="0"> 
     43                      <Component id="startPreviewScanBtn" min="-2" max="-2" attributes="0"/> 
     44                      <EmptySpace max="-2" attributes="0"/> 
     45                      <Component id="okBtn" min="-2" max="-2" attributes="0"/> 
     46                  </Group> 
    4047                  <Component id="previewPane" alignment="0" max="32767" attributes="0"/> 
    4148              </Group> 
     
    8087      </Properties> 
    8188    </Component> 
     89    <Component class="javax.swing.JButton" name="okBtn"> 
     90      <Properties> 
     91        <Property name="action" type="javax.swing.Action" editor="org.netbeans.modules.swingapp.ActionEditor"> 
     92          <action class="org.freecine.swingui.ScanPreviewDlg" id="ok" methodName="ok"/> 
     93        </Property> 
     94        <Property name="name" type="java.lang.String" value="okBtn" noResource="true"/> 
     95      </Properties> 
     96    </Component> 
    8297  </SubComponents> 
    8398</Form> 
  • src/main/pcapp/org/freecine/swingui/ScanPreviewDlg.java

    r59 r60  
    2626package org.freecine.swingui; 
    2727 
     28import java.awt.geom.Rectangle2D; 
    2829import java.awt.image.BufferedImage; 
    2930import java.util.concurrent.ExecutionException; 
     
    5657        initComponents(); 
    5758    } 
    58  
    5959    /** 
    6060     The scanner used 
     
    7979        firePropertyChange( "scanner", oldScanner, s ); 
    8080    } 
     81         
     82    /** 
     83     Scan area 
     84     */ 
     85    Rectangle2D scanArea; 
     86     
     87    /** 
     88     Get the currently set scan area. 
     89     @return Rectangle describing currently selected scan area, in device  
     90     coordinate units. The units are the same used by Sane back end for this type 
     91     of scanner (e.g. millimeters, not pixels) 
     92     */ 
     93    public Rectangle2D getScanArea() { 
     94        return scanArea; 
     95    } 
     96     
     97    /** 
     98     Set the scan area displayed in the dialog. 
     99     @param newArea New area, in device coordinate units (see getScanArea() for 
     100     more information. 
     101     */ 
     102    public void setScanArea( Rectangle2D newArea ) { 
     103        Rectangle2D oldVal = scanArea; 
     104        scanArea = newArea; 
     105        ((PreviewPane)previewPane).setSelection( newArea ); 
     106        firePropertyChange( "scanArea", oldVal, newArea ); 
     107    } 
     108     
    81109 
    82110    /** This method is called from within the constructor to 
     
    90118        previewPane = new PreviewPane(); 
    91119        startPreviewScanBtn = new javax.swing.JButton(); 
     120        okBtn = new javax.swing.JButton(); 
    92121 
    93122        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); 
     
    111140        startPreviewScanBtn.setAction(actionMap.get("scanPreviewImage")); // NOI18N 
    112141        startPreviewScanBtn.setName("startPreviewScanBtn"); // NOI18N 
     142 
     143        okBtn.setAction(actionMap.get("ok")); // NOI18N 
     144        okBtn.setName("okBtn"); // NOI18N 
    113145 
    114146        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); 
     
    119151                .addContainerGap() 
    120152                .addComponent(previewPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) 
    121                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 75, Short.MAX_VALUE) 
    122                 .addComponent(startPreviewScanBtn) 
     153                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) 
     154                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) 
     155                    .addComponent(startPreviewScanBtn) 
     156                    .addComponent(okBtn)) 
    123157                .addContainerGap()) 
    124158        ); 
     
    128162                .addContainerGap() 
    129163                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
    130                     .addComponent(startPreviewScanBtn) 
     164                    .addGroup(layout.createSequentialGroup() 
     165                        .addComponent(startPreviewScanBtn) 
     166                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) 
     167                        .addComponent(okBtn)) 
    131168                    .addComponent(previewPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) 
    132169                .addContainerGap()) 
     
    168205                try { 
    169206                    ((PreviewPane) previewPane).setPreviewImage( t.get() ); 
     207                     
     208                    ((PreviewPane) previewPane).setPreviewArea( t.getPreviewArea() ); 
    170209                } catch ( InterruptedException ex ) { 
    171210                    log.log( Level.SEVERE, null, ex ); 
     
    179218    } 
    180219 
     220    /** 
     221     The OK button was pressed 
     222     */ 
     223    @Action 
     224    public void ok() { 
     225        Rectangle2D oldArea = scanArea; 
     226        scanArea = ((PreviewPane)previewPane).getSelection(); 
     227        setVisible( false ); 
     228        firePropertyChange( "scanArea", oldArea, scanArea ); 
     229    } 
     230 
    181231     
    182232    // Variables declaration - do not modify//GEN-BEGIN:variables 
     233    private javax.swing.JButton okBtn; 
    183234    private javax.swing.JPanel previewPane; 
    184235    private javax.swing.JButton startPreviewScanBtn; 
  • src/main/pcapp/org/freecine/swingui/ScanPreviewTask.java

    r59 r60  
    2727 
    2828import java.awt.Point; 
     29import java.awt.Rectangle; 
     30import java.awt.geom.Rectangle2D; 
    2931import java.awt.image.BufferedImage; 
    3032import java.awt.image.ColorModel; 
     
    5759    private int TILE_WIDTH; 
    5860     
     61    /** 
     62     Create a new preview task 
     63     @param app Application this task is associated with 
     64     @param dev ScanDevice to use 
     65     */ 
    5966    public ScanPreviewTask( Application app, SaneDevice dev ) { 
    6067        super( app ); 
     
    6269        log.setLevel(Level.FINE); 
    6370    } 
    64  
     71     
     72    /** 
     73     Area of the preview scan, in device coordinates. 
     74     */ 
     75    Rectangle2D previewArea = null; 
     76     
     77    /** 
     78     Get the area of preview scan 
     79     @return Preview area, in device coordinates. 
     80     */ 
     81    public Rectangle2D getPreviewArea() { 
     82        return previewArea; 
     83    } 
     84 
     85    /** 
     86     Do the actual scanning in background thread. 
     87     @return The scanned preview image. 
     88     @throws java.lang.Exception 
     89     */ 
    6590    @Override 
    6691    protected BufferedImage doInBackground() throws Exception { 
     
    78103        dev.setOption( "mode", "Color" ); 
    79104        dev.setOption( "depth", 16 ); 
    80         dev.setOption( "resolution", 100 ); 
     105        dev.setOption( "resolution", 200 ); 
    81106        dev.setOption( "source", "Transparency Unit" ); 
    82107         
    83108        // Find out the maximum scanning area 
    84         int minX = -1; 
    85         int maxX = -1; 
    86         int minY = -1; 
    87         int maxY = -1; 
     109        FixedPointNumber minX = null; 
     110        FixedPointNumber maxX = null; 
     111        FixedPointNumber minY = null; 
     112        FixedPointNumber maxY = null; 
    88113        SaneOptionDescriptor xdesc = dev.getOptionDesc( "tl-x" );         
    89114        switch ( xdesc.getConstraintType() ) { 
    90115            case SANE_CONSTRAINT_RANGE: 
    91116                SaneRange r = (SaneRange) xdesc.getConstraints(); 
    92                 minX = r.min; 
    93                 maxX = r.max; 
     117                minX = new FixedPointNumber( r.min ); 
     118                maxX = new FixedPointNumber( r.max ); 
    94119                break; 
    95120            case SANE_CONSTRAINT_WORD_LIST: 
    96121                int[] values = (int[]) xdesc.getConstraints(); 
    97                 minX = values[0]; 
    98                 maxX = values[values.length-1]; 
     122                minX = new FixedPointNumber( values[0] ); 
     123                maxX = new FixedPointNumber( values[values.length-1] ); 
    99124                break; 
    100125            default: 
     
    105130            case SANE_CONSTRAINT_RANGE: 
    106131                SaneRange r = (SaneRange) ydesc.getConstraints(); 
    107                 minY = r.min; 
    108                 maxY = r.max; 
     132                minY = new FixedPointNumber( r.min ); 
     133                maxY = new FixedPointNumber( r.max );                 
    109134                break; 
    110135            case SANE_CONSTRAINT_WORD_LIST: 
    111136                int[] values = (int[]) ydesc.getConstraints(); 
    112                 minY = values[0]; 
    113                 maxY = values[values.length-1]; 
     137                minY = new FixedPointNumber( values[0] ); 
     138                maxY = new FixedPointNumber( values[values.length-1] ); 
    114139                break; 
    115140            default: 
    116141                throw new SaneException( "Cannod determinen scan glass area" ); 
    117142        } 
    118         dev.setOption( "tl-x", new FixedPointNumber( minX ) ); 
    119         dev.setOption( "tl-y", new FixedPointNumber( minY ) ); 
    120         dev.setOption( "br-x", new FixedPointNumber( maxX ) ); 
    121         dev.setOption( "br-y", new FixedPointNumber( maxY ) ); 
    122  
     143//        if ( maxX.toDouble() > 8 * 25.4 ) { 
     144//            maxX = FixedPointNumber.valueOf( 8 * 25.4 ); 
     145//        } 
     146//        if ( maxY.toDouble() > 10 * 25.4 ) { 
     147//            maxY = FixedPointNumber.valueOf( 10 * 25.4 ); 
     148//        } 
     149        minX = dev.setOption( "tl-x", minX ); 
     150        minY = dev.setOption( "tl-y", minY ); 
     151        maxX = dev.setOption( "br-x", maxX ); 
     152        maxY = dev.setOption( "br-y", maxY ); 
     153        previewArea = new Rectangle2D.Double( minX.toDouble(), minY.toDouble(),  
     154                maxX.subtract(minX).toDouble(), maxY.subtract(minY).toDouble() ); 
     155         
     156        ScanParameter param = dev.getScanParameter(); 
     157        System.out.println( "Scan parameters: " + param.getPixelsPerLine() + " x " + param.getLines() ); 
     158         
    123159        // Set gamma correction 
    124160        dev.setOption( "gamma-correction", "User defined" ); 
     
    177213        } 
    178214 
     215        dev.close(); 
    179216        return image; 
    180217         
  • src/main/pcapp/org/freecine/swingui/ScanProgressDlg.java

    r59 r60  
    3636import org.freecine.sane.SaneException; 
    3737import java.awt.Graphics; 
     38import java.awt.geom.Rectangle2D; 
    3839import java.beans.PropertyChangeEvent; 
    3940import java.beans.PropertyChangeListener; 
     
    247248 
    248249        } 
    249         scanTask = new ScanTask( dev, filmMover, null, prj ); 
     250        scanTask = new ScanTask( dev, filmMover, scanArea, prj ); 
    250251        scanTask.addPropertyChangeListener( new PropertyChangeListener() { 
    251252 
     
    350351     */ 
    351352    public boolean isFilmMoverReady() { 
    352         return filmMover != null; 
     353        // return filmMover != null; 
     354        return true; 
    353355    } 
    354356     
     
    372374    } 
    373375 
     376    Rectangle2D scanArea = null; 
     377     
    374378    /** 
    375379     Show the scan preview dialog 
    376380     */ 
    377     @Action 
     381    @Action ( block=Task.BlockingScope.ACTION ) 
    378382    public void adjustScanArea() { 
    379383        SaneDeviceDescriptor d = (SaneDeviceDescriptor) scannerCombo.getSelectedItem(); 
     
    382386            ScanPreviewDlg dlg = new ScanPreviewDlg( this, false ); 
    383387            dlg.setScanner( dev ); 
     388            dlg.setScanArea( new Rectangle2D.Double( 30.0, 48.0, 160.0, 7.0 ) ); 
     389            dlg.addPropertyChangeListener("scanArea", new PropertyChangeListener() { 
     390 
     391                public void propertyChange( PropertyChangeEvent ev ) { 
     392                    scanArea = (Rectangle2D) ev.getNewValue(); 
     393                } 
     394            }); 
    384395            dlg.setVisible( true ); 
     396             
    385397        } catch ( SaneException e ) { 
    386398            return; 
  • src/main/pcapp/org/freecine/swingui/ScanTask.java

    r50 r60  
    3636import org.freecine.sane.ScanParameter; 
    3737import java.awt.Point; 
    38 import java.awt.Rectangle; 
    3938import java.awt.RenderingHints; 
     39import java.awt.geom.Rectangle2D; 
    4040import java.awt.image.ColorModel; 
    4141import java.awt.image.DataBuffer; 
     
    4444import java.awt.image.RenderedImage; 
    4545import java.awt.image.SampleModel; 
     46import java.io.File; 
    4647import java.io.IOException; 
     48import java.util.Iterator; 
     49import java.util.logging.Logger; 
     50import javax.imageio.IIOImage; 
     51import javax.imageio.ImageIO; 
     52import javax.imageio.ImageWriteParam; 
     53import javax.imageio.ImageWriter; 
     54import javax.imageio.stream.ImageOutputStream; 
    4755import javax.media.jai.ImageLayout; 
    4856import javax.media.jai.JAI; 
     
    6068public class ScanTask extends Task<Void, Void> implements ScanAnalysisListener { 
    6169 
     70    private static Logger log = Logger.getLogger(ScanTask.class.getName() ); 
    6271    private SaneDevice dev; 
    63     private Rectangle scanArea; 
     72    private Rectangle2D scanArea; 
    6473    private Project prj; 
    6574    private FilmMover filmMover; 
     
    7180     @param prj the project in which scanned frames are added 
    7281     */ 
    73     public ScanTask( SaneDevice dev, FilmMover mover, Rectangle scanArea, Project prj ) { 
     82    public ScanTask( SaneDevice dev, FilmMover mover, Rectangle2D scanArea, Project prj ) { 
    7483        super( Application.getInstance() ); 
    7584        this.dev = dev; 
     
    106115        while ( true ) { 
    107116            PlanarImage img = scan(); 
     117            saveImage(img, new File( "/tmp/testimg.tif" ) ); 
    108118            img = TransposeDescriptor.create( img, TransposeDescriptor.ROTATE_90, null ); 
    109119            if ( isCancelled() ) { 
     
    146156        dev.setOption( "mode", "Color" ); 
    147157        dev.setOption( "depth", 16 ); 
    148         dev.setOption( "tl-x", new FixedPointNumber( 30 << 16 ) ); 
    149         dev.setOption( "tl-y", new FixedPointNumber( 48 << 16 ) ); 
    150         dev.setOption( "br-x", new FixedPointNumber( 190 << 16 ) ); 
    151         dev.setOption( "br-y", new FixedPointNumber( 55 << 16 ) ); 
     158        FixedPointNumber top = FixedPointNumber.valueOf( scanArea.getMinY() ); 
     159        FixedPointNumber left = FixedPointNumber.valueOf( scanArea.getMinX() ); 
     160        FixedPointNumber bot = FixedPointNumber.valueOf( scanArea.getMaxY() ); 
     161        FixedPointNumber right = FixedPointNumber.valueOf( scanArea.getMaxX() ); 
     162         
     163//        top = new FixedPointNumber( 48 << 16 ); 
     164//        left = new FixedPointNumber( 30 << 16 ); 
     165//        bot = new FixedPointNumber( 55 << 16 ); 
     166//        right = new FixedPointNumber( 190 << 16 ); 
     167 
     168        dev.setOption( "tl-x", left ); 
     169        dev.setOption( "tl-y", top ); 
     170        dev.setOption( "br-x", right ); 
     171        dev.setOption( "br-y", bot ); 
    152172        dev.setOption( "resolution", 4800 ); 
    153173        dev.setOption( "source", "Transparency Unit" ); 
     
    227247         
    228248    } 
    229  
     249    private void saveImage( RenderedImage img, File file ) { 
     250        // Find a writer for that file extensions 
     251        // Try to determine the file type based on extension 
     252        String ftype = "jpg"; 
     253        String imageFname = file.getName(); 
     254        int extIndex = imageFname.lastIndexOf( "." ) + 1; 
     255        if ( extIndex > 0 ) { 
     256            ftype = imageFname.substring( extIndex ); 
     257        } 
     258 
     259        ImageWriter writer = null; 
     260        Iterator iter = ImageIO.getImageWritersBySuffix( ftype ); 
     261        writer = (ImageWriter) iter.next(); 
     262 
     263        if ( writer != null ) { 
     264            ImageOutputStream ios = null; 
     265            try { 
     266                // Prepare output file 
     267                ios = ImageIO.createImageOutputStream( file ); 
     268                writer.setOutput( ios ); 
     269                // Set some parameters 
     270                ImageWriteParam param = writer.getDefaultWriteParam(); 
     271                writer.write( null, new IIOImage( img, null, null ), param ); 
     272 
     273                // Cleanup 
     274                ios.flush(); 
     275 
     276            } catch ( IOException ex ) { 
     277                log.severe( "Error saving image " + file.getAbsolutePath() + ": "  
     278                        + ex.getMessage() ); 
     279            } finally { 
     280                if ( ios != null ) { 
     281                    try { 
     282                        ios.close(); 
     283                    } catch ( IOException e ) { 
     284                        log.severe( "Error closing output stream: " + e.getMessage() ); 
     285                    } 
     286                } 
     287                writer.dispose(); 
     288            } 
     289        } 
     290    } 
    230291    /** 
    231292     Callback that is called by {@link ScanStrip} to inforrm about progress 
  • src/main/pcapp/org/freecine/swingui/resources/ScanPreviewDlg.properties

    r59 r60  
    33scanPreviewImage.Action.text=Scan Preview 
    44scanPreviewImage.Action.shortDescription=Scan a new preview image 
     5okBtn.text=jButton1 
     6ok.Action.shortDescription=Set the can area 
     7ok.Action.text=OK 
  • src/main/pcapp/org/freecine/swingui/resources/ScanTask.properties

    r48 r60  
    44initMessage = Initializing scanner 
    55scanProgressMessage = Strip %1$d: Scanning, %2$d of %3$d lines scanned... 
    6 analysisProgressMessage = Strip %1$d: Analyzing image, %1$d of %2$d lines ready... 
     6analysisProgressMessage = Strip %1$d: Analyzing image, %2$d of %3$d lines ready... 
    77analysisCompleteMessage = Strip %1$d: Analysis complete, %2$d perforations found 
    88movingFilmMsg = Moving film...