Linux-Fan

Invert image colors

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