Pastebin launched a little side project called HostCabi.net, check it out ;-)Don't like ads? PRO users don't see any ads ;-)

Revised Java Bitmap Inverter

By: Linux-Fan on Jan 31st, 2012  |  syntax: Java 5  |  size: 12.23 KB  |  hits: 92  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
This paste has a previous version, view the difference. Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. package test;
  2.  
  3. /*
  4.  * A simple example of how to invert/modify bitmaps with java.
  5.  *
  6.  * Copyright (C) 2012  Ma_Sys.ma
  7.  *
  8.  * This program is free software: you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License as published by
  10.  * the Free Software Foundation, either version 3 of the License, or
  11.  * (at your option) any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  * GNU General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  20.  */
  21.  
  22. // Basic Imports that could be helpful
  23. import javax.imageio.*;
  24. import java.awt.*;
  25. import java.awt.image.*;
  26. import java.io.*;
  27. import java.lang.*;
  28. import java.lang.reflect.*;
  29. import java.util.*;
  30.  
  31. public class InvertColors {
  32.  
  33.         public static class LoopInverter extends DistributedLoopThread {
  34.  
  35.                 private BufferedImage img;
  36.        
  37.                 public LoopInverter(Integer start, Integer end, DistributedLoop ownerLoop) {
  38.                         super(start, end, ownerLoop);
  39.                 }
  40.                
  41.                 public void pass(Object...data) {
  42.                         img = (BufferedImage)data[0];
  43.                 }
  44.  
  45.                 protected void execLoop() {
  46.                         int width = img.getWidth();
  47.                         int ems = END - START; // end minus start
  48.                         // Get an area of pixels
  49.                         int[] pixels = img.getRGB(0, START, img.getWidth(), ems, null, 0, width);
  50.                         for(int j = 0; j < pixels.length; j++) {
  51.                                 // Actual inversion
  52.                                 pixels[j] = 0xffffff ^ pixels[j];
  53.                         }
  54.                         // Store the pixels back into the image
  55.                         img.setRGB(0, START, width, ems, pixels, 0, width);
  56.                 }
  57.  
  58.         }
  59.  
  60.         public static void main(String[] args) {
  61.                 System.out.println("Invert Colors 1.0, Copyright (c) 2012 Ma_Sys.ma.");
  62.                 System.out.println("For further info send an e-mail to Ma_Sys.ma@web.de.");
  63.                 System.out.println();
  64.                 if(args.length != 1) {
  65.                         System.out.println("Usage: java test.InvertColors [image]");
  66.                         System.exit(1);
  67.                 }
  68.  
  69.                 int extensionPosition = args[0].lastIndexOf('.');
  70.                 if(extensionPosition == -1) {
  71.                         System.out.println("Unable to determine input filetype.");
  72.                         System.exit(1);
  73.                 }
  74.  
  75.                 // Read image data
  76.                 BufferedImage img;
  77.                 try {
  78.                         img = ImageIO.read(new File(args[0]));
  79.                 } catch(IOException ex) {
  80.                         System.err.println("Unable to read image from " + args[0]);
  81.                         ex.printStackTrace();
  82.                         System.exit(2);
  83.                         return; // "Variable might not have been initialized."
  84.                 }
  85.  
  86.                 long start = System.currentTimeMillis(); // Measure time
  87.  
  88.                 // Invert all pixels using all processors
  89.                 // See LoopInverter for the actual calculation
  90.                 DistributedLoop loop;
  91.                 try {
  92.                         loop = new DistributedLoop(DistributedLoop.AUTO_DETERMINE_THREADS, 0, img.getHeight(), LoopInverter.class, null, null);
  93.                 } catch(InstantiationException ex) {
  94.                         System.err.println("Unable to create distributed loop.");
  95.                         ex.printStackTrace();
  96.                         System.exit(4);
  97.                         return; // s. o.
  98.                 }
  99.                 loop.passArgumentsOnAll(img);
  100.                 loop.startAll();
  101.  
  102.                 System.out.println("Took " + (System.currentTimeMillis() - start) + " ms for the actual calculation.");
  103.  
  104.                 // Write image data
  105.                 try {
  106.                         ImageIO.write(img, "png", new File(args[0].substring(0, extensionPosition) + "_inverted.png"));
  107.                 } catch(IOException ex) {
  108.                         System.err.println("Unable to write PNG image file.");
  109.                         ex.printStackTrace();
  110.                         System.exit(3);
  111.                 }
  112.         }
  113.  
  114. }
  115.  
  116. // ---------------------------------------
  117. //  From the Tools Library in Version 2.0
  118. // ---------------------------------------
  119.  
  120. /**
  121.  * <p>
  122.  * Ermöglicht es, Rechenlast auf mehrere Kerne zu verteilen, indem eine
  123.  * Schleife in mehrere Teile aufgesplittet wird. Somit lassen sich Schleifen
  124.  * mit mehr Einträgen als Kerne vorhanden sind problemlos parallelisieren, wenn
  125.  * innerhalb der Schleife kein Ergebnis des vorherigen Durchganges benötigt wird.
  126.  * </p><p>
  127.  * Die Nutzung ist alles andere als einfach und soll deshalb am Beispiel gezeigt
  128.  * werden.
  129.  * </p><p>
  130.  * Alle Werte eines Arrays sollen initialisiert werden, indem
  131.  * komplexe Objekte erzeugt werden, deren Erstellung lange dauert:
  132.  * <br />
  133.  * <pre>
  134.         package ma.tools.concurrent;
  135.        
  136.         import ma.tools.concurrent.DistributedLoop;
  137.         import ma.tools.concurrent.DistributedLoopThread;
  138.        
  139.         public class DistributedLoopExample {
  140.        
  141.                 private static int nr = 1;
  142.        
  143.                 public DistributedLoopExample() {
  144.                         super();
  145.                         int objects = 32;
  146.                         long start;
  147.                        
  148.                         // 1. Test mit normaler Schleife
  149.                         start = System.currentTimeMillis();
  150.                         ComplexObject[] allObjects = new ComplexObject[objects];
  151.                         for(int i = 0; i < objects; i++) {
  152.                                 allObjects[i] = new ComplexObject();
  153.                         }
  154.                         System.out.println("Normalerweise braucht man " + (System.currentTimeMillis() - start) + " ms zum Erstellen der Objekte.");
  155.                        
  156.                         // 2. Test mit verteilter Schleife
  157.                         start = System.currentTimeMillis();
  158.                         allObjects = new ComplexObject[objects];
  159.                         DistributedLoop loop;
  160.                         try {
  161.                                 loop = new DistributedLoop(DistributedLoop.AUTO_DETERMINE_THREADS, 0, objects, CreatorInstance.class, null, this);
  162.                         } catch(InstantiationException ex) {
  163.                                 ex.printStackTrace();
  164.                                 return;
  165.                         }
  166.                         // Wir wollen das Array nicht als mehrere Argumente übergeben
  167.                         loop.passArgumentsOnAll((Object)allObjects);
  168.                         loop.startAll();
  169.                         System.out.println("Verteilt dauert es (nur?) " + (System.currentTimeMillis() - start) + " ms");
  170.                 }
  171.                
  172.                 public class CreatorInstance extends DistributedLoopThread {
  173.  
  174.                         private ComplexObject[] allObjects;
  175.                        
  176.                         public CreatorInstance(Integer start, Integer end, DistributedLoop ownerLoop) {
  177.                                 super(start, end, ownerLoop);
  178.                         }
  179.                        
  180.                         protected void pass(Object...data) {
  181.                                 allObjects = (ComplexObject[])data[0];
  182.                         }
  183.  
  184.                         protected void execLoop() {
  185.                                 for(int i = START; i &lt; END; i++) {
  186.                                         allObjects[i] = new ComplexObject();
  187.                                 }
  188.                         }
  189.                        
  190.                 }
  191.                
  192.                 private class ComplexObject {
  193.                
  194.                         public ComplexObject() {
  195.                                 int cnr = nr++;
  196.                                 System.out.println("Komplexes Objekt " + cnr + " erstellen...");
  197.                                 // Zeit die es braucht um ein Objekt zu erstellen (hier künstlich verlangsamt)
  198.                                 try {
  199.                                         Thread.sleep(250);
  200.                                 } catch(InterruptedException ex) {
  201.                                         System.out.println("Komplexes Objekt " + cnr + ": Erstellung abgebrochen: " + ex.toString());
  202.                                 }
  203.                                 System.out.println("Komplexes Objekt " + cnr + " fertig.");
  204.                         }
  205.                 }
  206.        
  207.                 public static void main(String[] args) {
  208.                         new DistributedLoopExample();
  209.                 }
  210.        
  211.         }
  212.  * </pre>
  213.  * <br />
  214.  * Wenn man die "künstlich verlängernden" Zeilen wegnimmt, sieht man
  215.  * sehr gut, dass es einen Overhead (auf dem Testsystem rund 3ms) durch
  216.  * die Paralelisierung gibt. Deshalb lohnt es sich nur bei der Erstellung
  217.  * von Objekten, die zusammen "relativ lange" brauchen, was auch schon bei
  218.  * z.B. 200 ms der Fall ist. Dadurch lohnt sich das Verteilte Rechnen an
  219.  * vielen Stellen.
  220.  * </p>
  221.  * <p>
  222.  * Hinweis #1: Bei Spiecherintensiven Anwendungen könnte es anders sein.
  223.  * Hier hilft es, beides zu testen.
  224.  * Das ist sehr einfach möglich, indem man dem Constructor als
  225.  * "preferredThreadCount" die Zahl 1 (keine parallelisierung)
  226.  * übergibt. Dies vermindert den Overhead aber nur sehr geringfügig.
  227.  * Wenn es knapp ist, sollte man eine "richtige" Schleife testen.
  228.  * </p><p>
  229.  * Hinweis #2: Rechenintensive Anwendungen profitieren eventuell vom
  230.  * Java Native Interface.
  231.  * </p><p>
  232.  * Hinweis #3: Optimieren Sie auch den Inhalt der Schleifen
  233.  * Sollte eigentlich klar sein.
  234.  * </p>
  235.  *
  236.  * @version 1.0.1
  237.  * @author Linux-Fan, Ma_Sys.ma
  238.  */
  239. class DistributedLoop {
  240.  
  241.         public static final int AUTO_DETERMINE_THREADS = -1;
  242.        
  243.         private DistributedLoopThread[] allThreads;
  244.        
  245.         private int readyThreads;
  246.        
  247.         private boolean started;
  248.        
  249.         private DistributedLoopUser owner;
  250.        
  251.         private ArrayList<Exception> theExceptions;
  252.        
  253.         public DistributedLoop(int preferredThreadCount, int lStart, int lEnd, Class<? extends DistributedLoopThread> threadClass, DistributedLoopUser owner, Object enclosing) throws InstantiationException {
  254.                 super();
  255.                 this.owner = owner;
  256.                 theExceptions = new ArrayList<Exception>();
  257.                 int realThreadCount = 0;
  258.                 if(preferredThreadCount == AUTO_DETERMINE_THREADS) {
  259.                         realThreadCount = Runtime.getRuntime().availableProcessors();
  260.                 } else {
  261.                         realThreadCount = preferredThreadCount;
  262.                 }
  263.                 int range = lEnd - lStart;
  264.                 if(range < realThreadCount) {
  265.                         realThreadCount = range;
  266.                 }
  267.                 allThreads = new DistributedLoopThread[realThreadCount];
  268.                 readyThreads = 0;
  269.                 started = false;
  270.                 int perThread = range / allThreads.length;
  271.                 for(int i = 0; i < allThreads.length; i++) {
  272.                         final int cStart = lStart + perThread * i;
  273.                         final int cEnd;
  274.                         if(i == (allThreads.length - 1)) {
  275.                                 cEnd = lEnd;
  276.                         } else {
  277.                                 cEnd = lStart + perThread * (i + 1);
  278.                         }
  279.                         try {
  280.                                 if(enclosing == null) {
  281.                                         allThreads[i] = threadClass.getConstructor(Integer.class, Integer.class, getClass()).newInstance(cStart, cEnd, this);
  282.                                 } else {
  283.                                         allThreads[i] = threadClass.getConstructor(enclosing.getClass(), Integer.class, Integer.class, getClass()).newInstance(enclosing, cStart, cEnd, this);
  284.                                 }
  285.                                 allThreads[i].setName("Distributed Loop Thread " + (i + 1));
  286.                         } catch(Exception ex) {
  287.                                 InstantiationException er = new InstantiationException("Unable to create distributed loop thread.");
  288.                                 er.initCause(ex);
  289.                                 throw er;
  290.                         }
  291.                 }
  292.         }
  293.        
  294.         public Iterator<Exception> startAll() {
  295.                 if(!started) {
  296.                         started = true;
  297.                         for(int i = 0; i < allThreads.length; i++) {
  298.                                 allThreads[i].start();
  299.                         }
  300.                         if(owner == null) {
  301.                                 for(int i = 0; i < allThreads.length; i++) {
  302.                                         try {
  303.                                                 allThreads[i].join();
  304.                                         } catch(InterruptedException ex) {
  305.                                                 System.err.println("ma.tools.concurrent.DistributedLoop: Thread interrupted: " + ex.toString());
  306.                                         } catch(IllegalThreadStateException ex) {
  307.                                                 System.err.println("ma.tools.concurrent.DistributedLoop: " + ex.toString());
  308.                                         }
  309.                                 }
  310.                                 return theExceptions.iterator();
  311.                         } else {
  312.                                 return null;
  313.                         }
  314.                 } else {
  315.                         throw new IllegalThreadStateException("Distributed loop was already started.");
  316.                 }
  317.         }
  318.        
  319.         public void interruptAll() {
  320.                 for(int i = 0; i < allThreads.length; i++) {
  321.                         if(allThreads[i].isAlive()) {
  322.                                 allThreads[i].interrupt();
  323.                         }
  324.                 }
  325.         }
  326.        
  327.         public Object[] callOnAll(Method m, Object...params) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
  328.                 Object[] allRets = new Object[allThreads.length];
  329.                 for(int i = 0; i < allThreads.length; i++) {
  330.                         allRets[i] = m.invoke(allThreads[i], params);
  331.                 }
  332.                 return allRets;
  333.         }
  334.        
  335.         public DistributedLoopThread[] getThreads() {
  336.                 return allThreads;
  337.         }
  338.        
  339.         public void passArgumentsOnAll(Object...data) {
  340.                 for(int i = 0; i < allThreads.length; i++) {
  341.                         allThreads[i].pass(data);
  342.                 }
  343.         }
  344.        
  345.         protected void readyCountUp() {
  346.                 readyThreads++;
  347.                 if(readyThreads == allThreads.length && owner != null) {
  348.                         owner.distributedThreadsReady(theExceptions.toArray(new Exception[theExceptions.size()]));
  349.                 }
  350.         }
  351.        
  352.         protected void passException(Exception ex) {
  353.                 theExceptions.add(ex);
  354.         }
  355.        
  356.         public Iterator<Exception> getExceptions() {
  357.                 return theExceptions.iterator();
  358.         }
  359.        
  360. }
  361.  
  362. abstract class DistributedLoopThread extends Thread {
  363.  
  364.         protected final int START;
  365.         protected final int END;
  366.         protected final DistributedLoop OWNER;
  367.        
  368.         public DistributedLoopThread(Integer start, Integer end, DistributedLoop ownerLoop) {
  369.                 super();
  370.                 this.START = start;
  371.                 this.END   = end;
  372.                 this.OWNER = ownerLoop;
  373.         }
  374.        
  375.         public void run() {
  376.                 try {
  377.                         execLoop();
  378.                 } catch(Exception ex) {
  379.                         OWNER.passException(ex);
  380.                 }
  381.                 OWNER.readyCountUp();
  382.         }
  383.        
  384.         protected void pass(@SuppressWarnings("unused") Object...data) {}
  385.        
  386.         protected abstract void execLoop() throws Exception;
  387.        
  388. }
  389.  
  390. /**
  391.  * <p>Veraltetes Interface.</p>
  392.  * <p>
  393.  * Kann genutzt werden, wenn man beim beenden alle Threads in
  394.  * eine andere Methode springen will.
  395.  * </p>
  396.  *
  397.  * @version 1.0.0.1
  398.  * @author Linux-Fan, Ma_Sys.ma
  399.  * @deprecated
  400.  *              Mittlerweile ist es möglich, dass {@link DistributedLoop#startAll()}
  401.  *              auf das Beenden der Threads wartet, ohne einen eigenen Wartethread zu
  402.  *              erzeugen.
  403.  */
  404. interface DistributedLoopUser {
  405.  
  406.         public void distributedThreadsReady(Exception[] passed);
  407.        
  408. }