Guest
Public paste!

Untitled

By: a guest | Mar 21st, 2010 | Syntax: C# | Size: 5.80 KB | Hits: 82 | Expires: Never
This paste has a previous version, view the difference. Copy text to clipboard
  1. package org.svu;
  2.  
  3. import javax.imageio.ImageIO;
  4. import java.awt.image.BufferedImage;
  5. import java.io.File;
  6. import java.io.IOException;
  7. import java.util.Arrays;
  8. import java.util.concurrent.BrokenBarrierException;
  9. import java.util.concurrent.CyclicBarrier;
  10. import java.util.concurrent.TimeUnit;
  11.  
  12. public class EdgeDetector {
  13.     private final static int BORDER_WIDTH = 1;
  14.     private final static int NCOLORS = 3; // R G B
  15.  
  16.     private static final int[] H = {-1, 0, 1, -2, 0, 2, -1, 0, 1};
  17.     private static final int[] V = {-1, -2, -1, 0, 0, 0, 1, 2, 1};
  18.  
  19.     private int[] newPixels;
  20.  
  21.     private final File in;
  22.     private final File out;
  23.     private final CyclicBarrier barrier;
  24.  
  25.     public EdgeDetector(final String inName, final String outName, final int num) {
  26.         this.in = new File(inName).getAbsoluteFile();
  27.         this.out = new File(outName).getAbsoluteFile();
  28.         this.barrier = new CyclicBarrier(num + 1);
  29.         int numCores = Runtime.getRuntime().availableProcessors();
  30.         if (num != numCores) {
  31.             System.out.println(String.format(
  32.                     "WARNING: Thread count is not optimal, specified %d but can run %d", num, numCores
  33.             ));
  34.         }
  35.     }
  36.  
  37.     public void detect() throws IOException, BrokenBarrierException, InterruptedException {
  38.         final BufferedImage origImg = ImageIO.read(in);
  39.         final BufferedImage newImg = process(origImg);
  40.         ImageIO.write(newImg, "PNG", out);
  41.     }
  42.  
  43.     public BufferedImage process(BufferedImage image) throws BrokenBarrierException, InterruptedException {
  44.         final int width = image.getWidth();
  45.         final int height = image.getHeight();
  46.         newPixels = new int[width * height];
  47.  
  48.         int parts = barrier.getParties() - 1;
  49.         int step = height / parts;
  50.         int high = BORDER_WIDTH, low = step;
  51.         for (int i = 0; i < parts; i++) {
  52.             if (low > (height - BORDER_WIDTH)) {
  53.                 low = height - BORDER_WIDTH;
  54.             }
  55.             new Thread(new Processor(image, high, low)).start();
  56.             high = low;
  57.             low += step;
  58.         }
  59.         barrier.await();
  60.  
  61.         final BufferedImage newImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
  62.         newImage.setRGB(0, 0, width, height, newPixels, 0, width);
  63.         return newImage;
  64.     }
  65.  
  66.     public static void main(final String[] args) throws Exception {
  67.         final String in = args[0];
  68.         final String out = args[1];
  69.         final int times = Integer.parseInt(args[2]);
  70.         final int numThreads = Integer.parseInt(args[3]);
  71.  
  72.         System.out.println(String.format("Converting from %s to %s, repeat %s times, using %s threads", args));
  73.         final EdgeDetector ed = new EdgeDetector(in, out, numThreads);
  74.         System.out.println("Warming up...");
  75.         for (int i = times * 100; i-- > 0;) {
  76.             ed.detect();
  77.             System.out.print("  " + (100 - i / times) + "%\r");
  78.         }
  79.         System.out.print("Measure...");
  80.         long time = System.nanoTime();
  81.         for (int i = times; i-- > 0;) {
  82.             ed.detect();
  83.         }
  84.         time = System.nanoTime() - time;
  85.         System.out.println(String.format(
  86.                 "Done.\nElapsed %d ms (%.3f ms per each)",
  87.                 TimeUnit.NANOSECONDS.toMillis(time),
  88.                 (double) TimeUnit.NANOSECONDS.toMillis(time) / times
  89.         ));
  90.     }
  91.  
  92.     public class Processor implements Runnable {
  93.         private int high, low;
  94.         private BufferedImage image;
  95.  
  96.         public Processor(BufferedImage image, int high, int low) {
  97.             this.image = image;
  98.             this.high = high;
  99.             this.low = low;
  100.         }
  101.  
  102.         public void run() {
  103.             final int width = image.getWidth();
  104.             int newPixelsOffset = BORDER_WIDTH + (width * high);
  105.  
  106.             // [0]:B [1]:G [2]:R
  107.             final int[] colorValuesH = new int[NCOLORS];
  108.             final int[] colorValuesV = new int[NCOLORS];
  109.  
  110.             final int sampleWidth = 1 + (BORDER_WIDTH << 1);
  111.             final int sampleSize = sampleWidth * sampleWidth;
  112.             final int[] samplePixels = new int[sampleSize];
  113.  
  114.             for (int y = high; y < low; y++, newPixelsOffset += (BORDER_WIDTH << 1)) {
  115.                 for (int x = BORDER_WIDTH; x < width - BORDER_WIDTH; x++) {
  116.                     // TYPE_INT_ARGB
  117.                     image.getRGB(x - BORDER_WIDTH, y - BORDER_WIDTH, sampleWidth, sampleWidth, samplePixels, 0, sampleWidth);
  118.  
  119.                     Arrays.fill(colorValuesH, 0);
  120.                     Arrays.fill(colorValuesV, 0);
  121.                     for (int o = 0; o < sampleSize; o++) {
  122.                         int pixel = samplePixels[o];
  123.                         // Process bytes in B, G, R order
  124.                         for (int c = 0; c < NCOLORS; c++) {
  125.                             final int val = pixel & 0xFF;
  126.                             colorValuesH[c] += val * H[o];
  127.                             colorValuesV[c] += val * V[o];
  128.                             pixel >>= 8;
  129.                         }
  130.                     }
  131.                     int pixel = 0;
  132.                     // R, then G, then B
  133.                     for (int c = NCOLORS; --c >= 0;) {
  134.                         final int h = saturate(colorValuesH[c]);
  135.                         final int v = saturate(colorValuesV[c]);
  136.                         pixel <<= 8;
  137.                         pixel |= (h > v)? h: v;
  138.                     }
  139.                     newPixels[newPixelsOffset++] = pixel;
  140.                 }
  141.             }
  142.  
  143.             try {
  144.                 barrier.await();
  145.             } catch (Exception e) {
  146.                 // ignore
  147.             }
  148.         }
  149.  
  150.         private int saturate(int val) {
  151.             return (val < 0)? 0: (val >= 0x100)? 0xFF: val;
  152.         }
  153.     }
  154. }