Class CropBordersFilter

java.lang.Object
  extended by CropBordersFilter
All Implemented Interfaces:
java.io.Serializable, se.datadosen.jalbum.JAFilter, se.datadosen.jalbum.ModifiesSize

public class CropBordersFilter
extends java.lang.Object
implements se.datadosen.jalbum.JAFilter, se.datadosen.jalbum.ModifiesSize

This filter for JAlbum crops white or black borders from images, such as those produced by film scanners.

It is only active when used in stage 1 (prescale) of the filter process. Changed in 0.82: When a command file for ImageMagick is created (default), cropping is only active for those directories that have a subdirectory \cropped. Java 1.5 or higher is required.

The algorithm can handle black/white borders occurring together on a side of the image. The user has to define a range in percent of the image width/height that is to be searched for a border. The search range should not be chosen too narrow, because the innermost one-third of each side will be used to determine the real images' default luminosity.

The filter can write a command file with crop commands for ImageMagick. For best results, first create all pages with the uncleaned images. After checking if the borders are reasonable, run the ImageMagick command file to produce cropped images. Then manually put the cropped images back into source folder, replacing the original files for another run with CropBorderFilter disabled.

How to use it

Method 1:

Put the following code into your skin's init.bsh
 CropBordersFilter cb = new CropBordersFilter();
 engine.addFilter(cb, 1);
 

Method 2:

Add the filter as described in JAlbum.

Examples:

class=CropBordersFilter prescale

Minimal example using default parameters. When you forget the prescale option, no cropping will be done, because the filter cannot be used in any other stage than 1.

class=CropBordersFilter prescale aspectForce=1

This will activate the default 3:2 forced cropping after the borders were removed. By default, the lower part of the image is given preference (saveFeet is true). However, if the image is too far off the requested ratio (e.g. square), no additional cropping is done; a remark will be written into the ImageMagick command file in this case. The acceptable "off-ratio" can be set with parameter maxForceAspectRatio.

class=CropBordersFilter prescale aspectForce=1 saveFeet=false debug

The central 3/2 (default aspect ratio) part of the image is taken after border cropping, and debug output is sent to the console. (David, how do I retrieve the global debug checkbox setting?)

class=CropBordersFilter prescale aspectForce=2 largerPixels=3000 smallerPixels=2000

We force the output to a fixed pixel size, giving preference to the lower part ( option saveFeet is true by default).

Known problems

How it works

This adaptive method was used to suppress short image-lookalike strips in the border such as they occur when there is a white and a black border in the image. The filter can be used in window or in console mode. In console mode, debugging with Eclipse run really smooth.

Version:
0.82
Author:
Dieter Menne, menne-biomed
See Also:
Serialized Form

Field Summary
static int ASPECT_NONE
           
static int ASPECT_PIXELS
           
static int ASPECT_SMALL
           
 
Fields inherited from interface se.datadosen.jalbum.JAFilter
ALL_POSTSCALE_STAGE, ALL_PRESCALE_STAGE, CLOSEUPS_POSTSCALE_STAGE, THUMBNAILS_POSTSCALE_STAGE, THUMBNAILS_PRESCALE_STAGE
 
Constructor Summary
CropBordersFilter()
           
 
Method Summary
 java.awt.image.BufferedImage filter(java.awt.image.BufferedImage bi, java.util.Map vars)
           
 int getAspectForce()
           
 int getBorderPerc()
           
 int getBorderThresh()
           
 java.lang.String getCropCmd()
           
 java.lang.String getCropCmdFile()
           
 java.lang.String getDescription()
           
 int getLargerPix()
           
 int getLargerSide()
           
 double getMaxForceAspectRatio()
           
 java.awt.Dimension getModifiedSize(java.awt.Dimension originalSize, java.util.Map vars)
           
 java.lang.String getName()
           
 int getSmallerPix()
           
 int getSmallerSide()
           
 int getSmoothProfile()
           
 boolean isDebug()
           
 boolean isSaveFeet()
           
 boolean isWriteCropCommands()
           
 void setAspectForce(int aspectForce)
          Determines additional aspect-cropping operation after border cropping.
 void setBorderPerc(int borderPerc)
          The image border range to be searched.
 void setBorderThresh(int borderThresh)
          Threshold for border filtering.
 void setCropCmd(java.lang.String cropCmd)
          ImageMagick crop command template.
 void setCropCmdFile(java.lang.String cropCmdFile)
           
 void setDebug(boolean debug)
          Output a lot of decision paramters to the console.
 void setLargerPix(int largerPix)
          Fixed pixel cropping parameter.
 void setLargerSide(int largerSide)
           
 void setMaxForceAspectRatio(double maxForceAspectRatio)
          How far-off aspect ratios should be respected?
 void setSaveFeet(boolean saveFeet)
          What part of the image is cropped?
 void setSmallerPix(int smallerPix)
          Fixed pixel cropping parameter.
 void setSmallerSide(int smallerSide)
          Small ratio cropping parameter.
 void setSmoothProfile(int smoothProfile)
          Determines sensitivity to noise in the border.
 void setWriteCropCommands(boolean writeCropCommands)
          Will ImageMagick command file be written?
 void WriteMap(java.util.Map vars)
          For internal debugging only
 
Methods inherited from class java.lang.Object
equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

ASPECT_NONE

public static final int ASPECT_NONE
See Also:
Constant Field Values

ASPECT_PIXELS

public static final int ASPECT_PIXELS
See Also:
Constant Field Values

ASPECT_SMALL

public static final int ASPECT_SMALL
See Also:
Constant Field Values
Constructor Detail

CropBordersFilter

public CropBordersFilter()
Method Detail

filter

public java.awt.image.BufferedImage filter(java.awt.image.BufferedImage bi,
                                           java.util.Map vars)
Specified by:
filter in interface se.datadosen.jalbum.JAFilter

getAspectForce

public int getAspectForce()

getBorderPerc

public int getBorderPerc()

getBorderThresh

public int getBorderThresh()

getCropCmd

public java.lang.String getCropCmd()

getCropCmdFile

public java.lang.String getCropCmdFile()

getDescription

public java.lang.String getDescription()
Specified by:
getDescription in interface se.datadosen.jalbum.JAFilter

getLargerPix

public int getLargerPix()

getLargerSide

public int getLargerSide()

getMaxForceAspectRatio

public double getMaxForceAspectRatio()

getModifiedSize

public java.awt.Dimension getModifiedSize(java.awt.Dimension originalSize,
                                          java.util.Map vars)
Specified by:
getModifiedSize in interface se.datadosen.jalbum.ModifiesSize

getName

public java.lang.String getName()
Specified by:
getName in interface se.datadosen.jalbum.JAFilter

getSmallerPix

public int getSmallerPix()

getSmallerSide

public int getSmallerSide()

getSmoothProfile

public int getSmoothProfile()

isDebug

public boolean isDebug()

isSaveFeet

public boolean isSaveFeet()

isWriteCropCommands

public boolean isWriteCropCommands()

setAspectForce

public void setAspectForce(int aspectForce)
Determines additional aspect-cropping operation after border cropping. One of ASPECT_NONE=0, ASPECT_SMALL=1, ASPECT_PIXELS=2.

Parameters:
aspectForce - aspectForce = 0 (default) crops border with minimal loss of image, giving variable image aspects.

aspectForce = 1 forces an aspect as given by largerSide, smallerSide. Does not change aspect if the ratio between the aspects is larger than maxForceAspectRatio or smaller than 1/maxForceAspectRatio.

aspectForce = 2 Forces original image to smallerPix X largerPix pixels if this smaller than the cropped frame. Use this if you want force all images to a fixed size after cropping.


setBorderPerc

public void setBorderPerc(int borderPerc)
The image border range to be searched.

Parameters:
borderPerc - The percentage of the image width/height searched for a border to be cropped. Do not use a too small value, make sure that one-third of the strip is part of the real image.

setBorderThresh

public void setBorderThresh(int borderThresh)
Threshold for border filtering.

Parameters:
borderThresh - Threshold of recursively filtered 0(border zone)/1(image interquintile range) sequence for identification of image. Values between 60% and 95% of full scale (100%) are recommended. Use lower value to crop less, higher values to if remainders of the border are still visible.

setCropCmd

public void setCropCmd(java.lang.String cropCmd)
ImageMagick crop command template.

Parameters:
cropCmd - See printf documentation for details of the format used.

In my Windows system, I have renamed the ImageMagick command that does the cropping from convert to imconvert to avoid the clashes with system-secured convert.exe.

Parameters:

  • %1: width of cropped image
  • %2: height of cropped image
  • %3: uppper left corner horizontal offset
  • %4: upper left corner vertical offset
  • %5: path to directory
  • %6: filename

setCropCmdFile

public void setCropCmdFile(java.lang.String cropCmdFile)
Parameters:
cropCmdFile - Name of the command file in the root directory, default cropit.cmd. This file is deleted on each start of the program, but results from successive runs are appended.

If start and end of album creation should be available in console mode, I will make this a little more intelligent.

See Also:
JAlbum forum comment.

setDebug

public void setDebug(boolean debug)
Output a lot of decision paramters to the console.

Parameters:
debug - This will be removed when I find out how to determine the global debug setting.

setLargerPix

public void setLargerPix(int largerPix)
Fixed pixel cropping parameter.

Parameters:
largerPix - The larger side in pixels, only used if aspectForce=2; default smallerPix * 3/2;

setLargerSide

public void setLargerSide(int largerSide)
Parameters:
largerSide - The larger side of the requested aspect ratio, e.g. 3 when a ratio of 3:2 is requested. Values between 1 and 5 are valid. Only used when forceAspect = 1.

setMaxForceAspectRatio

public void setMaxForceAspectRatio(double maxForceAspectRatio)
How far-off aspect ratios should be respected?

Parameters:
maxForceAspectRatio -

Only active for forceAspect > 0. For a request aspect of 1.5 (i.e. smallerSide =2, largerSide = 2), aspects > 1.5*1.1 or < 1.5/1.1 are not honoured, so no additional cropping besides border removal will be done.

David: I could not get to work setting float parameters from the command line, so currently the default factor of 1.2 is fixed in the code.

setSaveFeet

public void setSaveFeet(boolean saveFeet)
What part of the image is cropped?

Parameters:
saveFeet -

If saveFeet = true (default), the lower part of the image is preferably kept if parts are cropped due to aspect constraints.

Otherwise, a central portion of the border-cropped image is used. This parameter is ineffective if aspectForce =0 (default).


setSmallerPix

public void setSmallerPix(int smallerPix)
Fixed pixel cropping parameter.

Parameters:
smallerPix - The larger side in pixels, only used if aspectForce=2; default = 2540

setSmallerSide

public void setSmallerSide(int smallerSide)
Small ratio cropping parameter.

Parameters:
smallerSide - The smaller side of the requested aspect ratio, as a small number, e.g. 3 when a ratio of 3:2 is requested. Values between 1 and 5 are valid. Only used when forceAspect = 1.

setSmoothProfile

public void setSmoothProfile(int smoothProfile)
Determines sensitivity to noise in the border.

Parameters:
smoothProfile - A value between 3 and 50 (default=10), giving the space-constant in pixels for a first order recursive filter applied to the luminosity profile. Larger value give more smoothing of the profile, less sensitivity to spurious colors in the border range, but may result in too much cutting.

setWriteCropCommands

public void setWriteCropCommands(boolean writeCropCommands)
Will ImageMagick command file be written?

Parameters:
writeCropCommands - If true (default) and a directory ./cropped of the working directory exists, an ImageMagick command file is created with the border parameters determined during album creation. Note that NO cropping will be done if no such directory exists, which can be used to speed up the processs when only a few directories need cropping.

WriteMap

public void WriteMap(java.util.Map vars)
For internal debugging only