public static void main(String[] args) {
    final File swapDir = new File("swap");
    swapDir.mkdir();
    final Logger logger = Logger.getAnonymousLogger();
    final ConsoleHandler consoleHandler = new ConsoleHandler();
    consoleHandler.setLevel(Level.ALL);
    logger.addHandler(consoleHandler);
    logger.setLevel(Level.ALL);
    final DefaultSwapSpace swapSpace = new DefaultSwapSpace(swapDir, logger);
    final SwappingTileCache tileCache = new SwappingTileCache(64 * M, swapSpace);
    JAI.getDefaultInstance().setTileCache(tileCache);

    RenderedImage sourceImage;
    if (args.length == 0) {
      sourceImage = DFTTestMain.createTestImage(512, 512);
    } else {
      sourceImage = FileLoadDescriptor.create(args[0], null, false, null);
    }

    sourceImage = DFTConvolveRIF.toFloat(sourceImage, null);

    BorderExtender extender = BorderExtender.createInstance(BorderExtender.BORDER_COPY);
    RenderingHints hints = new RenderingHints(JAI.KEY_BORDER_EXTENDER, extender);
    KernelJAI kernel = createBlurrKernel(33);
    RenderedOp convolvedImage = ConvolveDescriptor.create(sourceImage, kernel, hints);
    RenderedOp dftConvolvedImage = DFTConvolveDescriptor.create(sourceImage, kernel, null, hints);
    RenderedOp deltaImage =
        MultiplyConstDescriptor.create(
            SubtractDescriptor.create(convolvedImage, dftConvolvedImage, null),
            new double[] {2},
            null);
    showImage(sourceImage, "sourceImage");
    showImage(convolvedImage, "convolvedImage");
    showImage(dftConvolvedImage, "dftConvolvedImage");
    showImage(deltaImage, "deltaImage");

    final Object o = dftConvolvedImage.getProperty("kernelFT");
    System.out.println("o = " + o);

    System.out.println("Kernel\tConvolve\tDFTConvolve\tPerfGain");
    for (int i = 3; i <= 201; i += 2) {
      KernelJAI k = createBlurrKernel(i);
      double t1 = getRenderTime(ConvolveDescriptor.create(sourceImage, k, hints));
      double t2 = getRenderTime(DFTConvolveDescriptor.create(sourceImage, k, null, hints));
      System.out.println(i + "\t" + t1 + "\t" + t2 + "\t" + t1 / t2);
    }
  }
  public static void main(String[] args) {
    String sourceFile = args[0];
    int m = Integer.parseInt(args[1]);

    String format = sourceFile.substring(1 + sourceFile.lastIndexOf('.'));
    String targetBase = sourceFile.substring(0, sourceFile.lastIndexOf('.'));
    String targetFile0 = targetBase + "_" + m + "_0." + format;
    String targetFile1 = targetBase + "_" + m + "_1." + format;
    String targetFile2 = targetBase + "_" + m + "_2." + format;

    KernelJAI gaussKernel = createGaussianKernel(m);
    dumpKernelData("Gaussian", gaussKernel);
    KernelJAI distKernel = createDistancesKernel(m);
    dumpKernelData("Distances", distKernel);

    RenderedOp source = FileLoadDescriptor.create(sourceFile, null, true, null);
    source = BandSelectDescriptor.create(source, new int[1], null);
    System.out.println("Writing " + targetFile0);
    FileStoreDescriptor.create(source, targetFile0, format, null, false, null);

    long t1 = System.currentTimeMillis();
    System.out.println("Computing " + targetFile1);
    BorderExtender borderExtender = BorderExtender.createInstance(BorderExtender.BORDER_COPY);
    RenderedOp target1 =
        ConvolveDescriptor.create(
            source, gaussKernel, new RenderingHints(JAI.KEY_BORDER_EXTENDER, borderExtender));
    RenderedOp mask = ClampDescriptor.create(source, new double[] {0}, new double[] {1}, null);
    mask = MultiplyConstDescriptor.create(mask, new double[] {255}, null);
    mask = NotDescriptor.create(mask, null);
    mask = ClampDescriptor.create(mask, new double[] {0}, new double[] {1}, null);
    target1 = MultiplyDescriptor.create(target1, mask, null);
    target1 = AddDescriptor.create(target1, source, null);
    System.out.println("Writing " + targetFile1);
    FileStoreDescriptor.create(target1, targetFile1, format, null, false, null);
    System.out.println("Done in " + (System.currentTimeMillis() - t1) + " ms");

    long t2 = System.currentTimeMillis();
    System.out.println("Computing " + targetFile2);
    BufferedImage target2 = convolveICOL(source, gaussKernel, distKernel);
    System.out.println("Writing " + targetFile2);
    FileStoreDescriptor.create(target2, targetFile2, format, null, false, null);
    System.out.println("Done in " + (System.currentTimeMillis() - t2) + " ms");
  }