Linux-Fan

Revised Java Bitmap Inverter

Jan 31st, 2012
124
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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. }
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×