Moved bit input and output streams into Svjatoslav Commons library.
authorSvjatoslav Agejenko <n0@big-laptop.(none)>
Sun, 16 Sep 2012 08:25:44 +0000 (11:25 +0300)
committerSvjatoslav Agejenko <n0@big-laptop.(none)>
Sun, 16 Sep 2012 08:25:44 +0000 (11:25 +0300)
Added license and copyright notice to every source file.

23 files changed:
.classpath
.project
.settings/org.eclipse.core.resources.prefs [new file with mode: 0644]
.settings/org.eclipse.jdt.core.prefs
.settings/org.eclipse.m2e.core.prefs [new file with mode: 0644]
README.TXT [deleted file]
TODO [new file with mode: 0644]
pom.xml
src/main/java/eu/svjatoslav/imagesqueeze/codec/Approximator.java
src/main/java/eu/svjatoslav/imagesqueeze/codec/BitInputStream.java [deleted file]
src/main/java/eu/svjatoslav/imagesqueeze/codec/BitOutputStream.java [deleted file]
src/main/java/eu/svjatoslav/imagesqueeze/codec/Channel.java
src/main/java/eu/svjatoslav/imagesqueeze/codec/Color.java
src/main/java/eu/svjatoslav/imagesqueeze/codec/ColorStats.java
src/main/java/eu/svjatoslav/imagesqueeze/codec/Image.java
src/main/java/eu/svjatoslav/imagesqueeze/codec/ImageDecoder.java
src/main/java/eu/svjatoslav/imagesqueeze/codec/ImageEncoder.java
src/main/java/eu/svjatoslav/imagesqueeze/codec/ImageMetaData.java
src/main/java/eu/svjatoslav/imagesqueeze/codec/OperatingContext.java
src/main/java/eu/svjatoslav/imagesqueeze/codec/Table.java
src/main/java/eu/svjatoslav/imagesqueeze/sampleApplication/ImageFrame.java
src/main/java/eu/svjatoslav/imagesqueeze/sampleApplication/ImagePanel.java
src/main/java/eu/svjatoslav/imagesqueeze/sampleApplication/Main.java

index 3b25ab3..48ef814 100644 (file)
@@ -1,5 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-  <classpathentry kind="src" path="src/main/java" including="**/*.java"/>
-  <classpathentry kind="output" path="target/classes"/>
-  <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
-</classpath>
\ No newline at end of file
+       <classpathentry kind="src" output="target/classes" path="src/main/java"/>
+       <classpathentry excluding="**" including="**/*.java" kind="src" output="target/classes" path="src/main/resources"/>
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+       <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"/>
+       <classpathentry kind="output" path="target/classes"/>
+</classpath>
index cf45093..446ef18 100755 (executable)
--- a/.project
+++ b/.project
@@ -1,17 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
 <projectDescription>
-  <name>imagesqueeze</name>
-  <comment>ImageSqueeze - image codec optimized for photos. NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse.</comment>
-  <projects/>
-  <buildSpec>
-    <buildCommand>
-      <name>org.eclipse.jdt.core.javabuilder</name>
-    </buildCommand>
-    <buildCommand>
-      <name>org.maven.ide.eclipse.maven2Builder</name>
-    </buildCommand>
-  </buildSpec>
-  <natures>
-    <nature>org.maven.ide.eclipse.maven2Nature</nature>
-    <nature>org.eclipse.jdt.core.javanature</nature>
-  </natures>
-</projectDescription>
\ No newline at end of file
+       <name>imagesqueeze</name>
+       <comment>ImageSqueeze - image codec optimized for photos. NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse.</comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.maven.ide.eclipse.maven2Builder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.m2e.core.maven2Builder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.m2e.core.maven2Nature</nature>
+               <nature>org.maven.ide.eclipse.maven2Nature</nature>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+       </natures>
+</projectDescription>
diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs
new file mode 100644 (file)
index 0000000..8fb0e26
--- /dev/null
@@ -0,0 +1,3 @@
+eclipse.preferences.version=1
+encoding//src/main/java=UTF-8
+encoding//src/main/resources=UTF-8
index beb3db6..2e6e466 100644 (file)
@@ -1,10 +1,16 @@
-#Sun Aug 28 02:19:45 EEST 2011
+eclipse.preferences.version=1
 encoding//src/main/java=UTF-8
-org.eclipse.jdt.core.compiler.compliance=1.6
 encoding//src/main/resources=UTF-8
-encoding//src/test/resources=UTF-8
 encoding//src/test/java=UTF-8
-org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+encoding//src/test/resources=UTF-8
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
-eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
 org.eclipse.jdt.core.compiler.source=1.6
diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs
new file mode 100644 (file)
index 0000000..ff7698f
--- /dev/null
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=false
+version=1
diff --git a/README.TXT b/README.TXT
deleted file mode 100755 (executable)
index 5e92643..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-Imagesqueeze -- Lossy image codec. Optimized for photos and speed.
-By Svjatoslav Agejenko, svjatoslavagejenko@gmail.com, http://svjatoslav.eu
-
-See doc directory for more info.
-
-Todo:
-       * Javadoc
-       
-       * micro header possibility, 16 bits header version, 2x8 bits, image dimension   
-       
-       * Performance test
-       
\ No newline at end of file
diff --git a/TODO b/TODO
new file mode 100644 (file)
index 0000000..8dfe395
--- /dev/null
+++ b/TODO
@@ -0,0 +1,7 @@
+better documentation describing the idea
+
+JavaDoc
+       
+possibility for smaller image header, on smaller images
+
+runnable performance tests
diff --git a/pom.xml b/pom.xml
index c73ed5d..1875e57 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -1,82 +1,82 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-       <modelVersion>4.0.0</modelVersion>
-       <groupId>eu.svjatoslav</groupId>
-       <artifactId>imagesqueeze</artifactId>
-       <version>1.0-SNAPSHOT</version>
-       <name>imagesqueeze</name>
-       <packaging>jar</packaging>
+<project
+    xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>eu.svjatoslav</groupId>
+    <artifactId>imagesqueeze</artifactId>
+    <version>1.0-SNAPSHOT</version>
+    <name>imagesqueeze</name>
+    <packaging>jar</packaging>
 
-       <description>ImageSqueeze - image codec optimized for photos</description>
+    <description>ImageSqueeze - image codec optimized for photos</description>
 
-       <build>
-               <finalName>imagesqueeze</finalName>
-               <resources>
-                       <resource>
-                               <filtering>false</filtering>
-                               <directory>src/main/resources</directory>
-                       </resource>
-                       <resource>
-                               <filtering>true</filtering>
-                               <directory>src/main/resources</directory>
-                               <includes>
-                                       <include>*.xml</include>
-                               </includes>
-                       </resource>
-               </resources>
-               <testResources>
-                       <testResource>
-                               <filtering>true</filtering>
-                               <directory>src/test/resources</directory>
-                       </testResource>
-               </testResources>
-               <plugins>
-                       <plugin>
-                               <groupId>org.apache.maven.plugins</groupId>
-                               <artifactId>maven-compiler-plugin</artifactId>
-                               <version>2.3.1</version>
-                               <configuration>
-                                       <source>1.6</source>
-                                       <target>1.6</target>
-                                       <optimize>true</optimize>
-                                       <encoding>UTF-8</encoding>
-                               </configuration>
-                       </plugin>
-                       <plugin>
-                               <groupId>org.apache.maven.plugins</groupId>
-                               <artifactId>maven-resources-plugin</artifactId>
-                               <version>2.4.3</version>
-                               <configuration>
-                                       <encoding>UTF-8</encoding>
-                               </configuration>
-                       </plugin>
-               </plugins>
-       </build>
+    <build>
+        <finalName>imagesqueeze</finalName>
+        <resources>
+            <resource>
+                <filtering>false</filtering>
+                <directory>src/main/resources</directory>
+            </resource>
+            <resource>
+                <filtering>true</filtering>
+                <directory>src/main/resources</directory>
+                <includes>
+                    <include>*.xml</include>
+                </includes>
+            </resource>
+        </resources>
+        <testResources>
+            <testResource>
+                <filtering>true</filtering>
+                <directory>src/test/resources</directory>
+            </testResource>
+        </testResources>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>2.3.1</version>
+                <configuration>
+                    <source>1.6</source>
+                    <target>1.6</target>
+                    <optimize>true</optimize>
+                    <encoding>UTF-8</encoding>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-resources-plugin</artifactId>
+                <version>2.4.3</version>
+                <configuration>
+                    <encoding>UTF-8</encoding>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
 
+    <dependencies>
+        <dependency>
+            <groupId>eu.svjatoslav</groupId>
+            <artifactId>svjatoslavcommons</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+    </dependencies>
 
+    <repositories>
+        <repository>
+            <id>svjatoslav.eu</id>
+            <name>Svjatoslav repository</name>
+            <url>http://svjatoslav.eu/static/maven/</url>
+        </repository>
+    </repositories>
 
-       <repositories>
-
-               <repository>
-                       <id>svjatoslav.eu</id>
-                       <name>Svjatoslav repository</name>
-                       <url>http://svjatoslav.eu/maven/</url>
-               </repository>
-
-       </repositories>
-
-
-
-       <distributionManagement>
-               <!-- use the following if you're not using a snapshot version. <repository> <id>repo</id> <name>Repository Name</name> 
-                       <url>scp://host/path/to/repo</url> </repository> -->
-
-               <!-- use the following if you ARE using a snapshot version. -->
-               <snapshotRepository>
-                       <id>svjatoslav.eu</id>
-                       <name>svjatoslav.eu</name>
-                       <url>scp://svjatoslav.eu/opt/svjatoslav.eu/webcontent/maven</url>
-               </snapshotRepository>
-       </distributionManagement>
+    <distributionManagement>
+        <snapshotRepository>
+            <id>svjatoslav.eu</id>
+            <name>svjatoslav.eu</name>
+            <url>scp://svjatoslav.eu/var/lib/tomcat6/_svjatoslav.eu/static/maven</url>
+        </snapshotRepository>
+    </distributionManagement>
 
 </project>
index 622ae80..a4f78af 100755 (executable)
@@ -1,11 +1,22 @@
+/*
+ * Imagesqueeze - Image codec optimized for photos.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
 package eu.svjatoslav.imagesqueeze.codec;
 
 import java.io.IOException;
 
+import eu.svjatoslav.commons.data.BitInputStream;
+import eu.svjatoslav.commons.data.BitOutputStream;
+
 /**
- * Since it is a lossy codec, instead of storing
- * exact values, approximated values are stored
- * to save on bit count.
+ * Since it is a lossy codec, instead of storing exact values, approximated
+ * values are stored to save on bit count.
  */
 
 public class Approximator implements Comparable<Approximator> {
@@ -14,29 +25,38 @@ public class Approximator implements Comparable<Approximator> {
        public Table uTable = new Table();
        public Table vTable = new Table();
 
-       public Approximator(){
+       public Approximator() {
        }
 
-       public int compareTo(Approximator o) {
+       @Override
+       public int compareTo(final Approximator o) {
                int result = yTable.compareTo(o.yTable);
-               if (result != 0) return result;
+               if (result != 0)
+                       return result;
 
                result = uTable.compareTo(o.uTable);
-               if (result != 0) return result;
+               if (result != 0)
+                       return result;
 
                result = vTable.compareTo(o.vTable);
                return result;
        }
-       
-       public void initialize(){
+
+       public void computeLookupTables() {
+               yTable.computeLookupTables();
+               uTable.computeLookupTables();
+               vTable.computeLookupTables();
+       }
+
+       public void initialize() {
                yTable.reset();
                uTable.reset();
                vTable.reset();
-               
+
                yTable.addEntry(0, 6, 0);
                yTable.addEntry(27, 30, 4);
                yTable.addEntry(255, 255, 6);
-               
+
                uTable.addEntry(0, 9, 0);
                uTable.addEntry(27, 30, 4);
                uTable.addEntry(255, 255, 6);
@@ -44,26 +64,20 @@ public class Approximator implements Comparable<Approximator> {
                vTable.addEntry(0, 9, 0);
                vTable.addEntry(27, 30, 4);
                vTable.addEntry(255, 255, 6);
-               
+
                computeLookupTables();
        }
-       
-       public void save(BitOutputStream outputStream) throws IOException{
-               yTable.save(outputStream);
-               uTable.save(outputStream);
-               vTable.save(outputStream);              
-       }
-       
-       public void load(BitInputStream inputStream) throws IOException {
+
+       public void load(final BitInputStream inputStream) throws IOException {
                yTable.load(inputStream);
                uTable.load(inputStream);
-               vTable.load(inputStream);                               
+               vTable.load(inputStream);
        }
 
-       public void computeLookupTables(){
-               yTable.computeLookupTables();
-               uTable.computeLookupTables();
-               vTable.computeLookupTables();           
+       public void save(final BitOutputStream outputStream) throws IOException {
+               yTable.save(outputStream);
+               uTable.save(outputStream);
+               vTable.save(outputStream);
        }
-       
+
 }
diff --git a/src/main/java/eu/svjatoslav/imagesqueeze/codec/BitInputStream.java b/src/main/java/eu/svjatoslav/imagesqueeze/codec/BitInputStream.java
deleted file mode 100755 (executable)
index b5ba69a..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-package eu.svjatoslav.imagesqueeze.codec;
-
-/**
- * Read individual bits from the input stream.
- */
-
-import java.io.IOException;
-import java.io.InputStream;
-
-public class BitInputStream {
-
-
-       int currentByte;
-       int currentBytePointer = -1;
-
-       InputStream inputStream;
-
-       public BitInputStream(InputStream inputStream){
-               this.inputStream = inputStream;
-       }
-
-       public int readBits(int bitCount) throws IOException {
-
-               int readableByte = 0;
-               for (int i=0; i < bitCount; i++){
-
-                       readableByte = readableByte << 1;
-
-                       if (currentBytePointer == -1){
-                               currentBytePointer = 7;
-                               currentByte = inputStream.read();
-                       }
-
-                       int mask = 1;
-                       mask = mask << currentBytePointer;
-
-                       int currentBit = currentByte & mask;
-
-                       if (currentBit != 0){
-                               readableByte = readableByte | 1;
-                       }
-
-                       currentBytePointer--;
-               }
-               return readableByte;
-       }
-
-       public int readIntegerCompressed8() throws IOException{
-               if (readBits(1) == 0){
-                       return readBits(8);
-               } else {
-                       return readBits(32);                    
-               }               
-       }
-
-}
diff --git a/src/main/java/eu/svjatoslav/imagesqueeze/codec/BitOutputStream.java b/src/main/java/eu/svjatoslav/imagesqueeze/codec/BitOutputStream.java
deleted file mode 100755 (executable)
index 469bb7b..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-package eu.svjatoslav.imagesqueeze.codec;
-
-/**
- * Write individual bits to the output stream.
- */
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-public class BitOutputStream {
-
-       int currentByte;
-       int currentBytePointer;
-       
-       OutputStream outputStream;
-
-       public BitOutputStream(OutputStream outputStream){
-               currentByte = 0;
-               currentBytePointer = 0;
-               this.outputStream = outputStream;
-       };
-
-
-       public void storeBits(int data, int bitCount) throws IOException {
-               for (int i=bitCount-1; i >= 0; i--){
-
-                       int mask = 1;
-                       mask = mask << i;
-
-                       int currentBit = data & mask;
-                       currentByte = currentByte << 1;
-
-                       if (currentBit != 0){
-                               currentByte = currentByte | 1;
-                       }
-                       currentBytePointer++;
-
-                       if (currentBytePointer == 8){
-                               currentBytePointer = 0;
-                               outputStream.write(currentByte);
-                               currentByte = 0;
-                       }
-               }
-       }
-
-       public void storeIntegerCompressed8(int data) throws IOException{
-               if (data < 256){
-                       storeBits(0, 1);
-                       storeBits(data, 8);
-               } else {
-                       storeBits(1, 1);
-                       storeBits(data, 32);                    
-               }               
-       }
-
-       public void finishByte() throws IOException {
-               if (currentBytePointer != 0){
-                       outputStream.write(currentByte);                                        
-                       currentBytePointer = 0;
-               }
-       }       
-
-}
index 879326e..a4f01cc 100755 (executable)
@@ -1,52 +1,61 @@
+/*
+ * Imagesqueeze - Image codec optimized for photos.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
 package eu.svjatoslav.imagesqueeze.codec;
 
 public class Channel {
 
-       byte [] rangeMap;       
-       byte [] map;
+       byte[] rangeMap;
+       byte[] map;
 
-       byte [] decodedRangeMap;
-       byte [] decodedMap;
+       byte[] decodedRangeMap;
+       byte[] decodedMap;
 
        int bitCount;
-       
-       public Channel(int width, int height) {
+
+       public Channel(final int width, final int height) {
                rangeMap = new byte[width * height];
 
-               map = new byte[width * height];         
+               map = new byte[width * height];
 
                decodedRangeMap = new byte[width * height];
-               decodedRangeMap[0] = (byte)255;
+               decodedRangeMap[0] = (byte) 255;
 
                decodedMap = new byte[width * height];
        };
 
-       
-       public void reset(){
-               
-               for (int i=0; i < decodedMap.length; i++){
+       public void printStatistics() {
+               final float bitsPerPixel = (float) bitCount / (float) rangeMap.length;
+               System.out.println((bitCount / 8) + " bytes. " + bitsPerPixel
+                               + " bits per pixel.");
+       }
+
+       public void reset() {
+
+               for (int i = 0; i < decodedMap.length; i++) {
                        decodedMap[i] = 0;
                }
 
-               for (int i=0; i < decodedRangeMap.length; i++){
+               for (int i = 0; i < decodedRangeMap.length; i++) {
                        decodedRangeMap[i] = 0;
                }
-               decodedRangeMap[0] = (byte)255;
-               
-               for (int i=0; i < map.length; i++){
+               decodedRangeMap[0] = (byte) 255;
+
+               for (int i = 0; i < map.length; i++) {
                        map[i] = 0;
                }
 
-               for (int i=0; i < rangeMap.length; i++){
+               for (int i = 0; i < rangeMap.length; i++) {
                        rangeMap[i] = 0;
                }
-               
+
                bitCount = 0;
        }
-       
-       public void printStatistics(){
-               float bitsPerPixel = (float)bitCount / (float)rangeMap.length;
-               System.out.println( (bitCount/8) + " bytes. " + bitsPerPixel + " bits per pixel.");
-       }
-       
+
 }
index 1d8b7a6..08535a2 100755 (executable)
@@ -1,3 +1,12 @@
+/*
+ * Imagesqueeze - Image codec optimized for photos.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
 package eu.svjatoslav.imagesqueeze.codec;
 
 /**
@@ -13,37 +22,48 @@ public class Color {
        int u;
        int v;
 
-       public void YUV2RGB(){
+       public void RGB2YUV() {
 
-               b = (int)(y + 1.4075 * (v - 128));
-               g = (int)(y - 0.3455 * (u - 128) - (0.7169 * (v - 128)));
-               r = (int)(y + 1.7790 * (u - 128));
+               y = (int) ((r * 0.299000) + (g * 0.587000) + (b * 0.114000));
+               u = (int) ((r * -0.168736) + (g * -0.331264) + (b * 0.500000) + 128);
+               v = (int) ((r * 0.500000) + (g * -0.418688) + (b * -0.081312) + 128);
 
-               if (r < 0) r = 0;
-               if (g < 0) g = 0;
-               if (b < 0) b = 0;
+               if (y < 0)
+                       y = 0;
+               if (u < 0)
+                       u = 0;
+               if (v < 0)
+                       v = 0;
 
-               if (r > 255) r = 255;
-               if (g > 255) g = 255;
-               if (b > 255) b = 255;
+               if (y > 255)
+                       y = 255;
+               if (u > 255)
+                       u = 255;
+               if (v > 255)
+                       v = 255;
 
        }
 
-       public void RGB2YUV(){
+       public void YUV2RGB() {
+
+               b = (int) (y + (1.4075 * (v - 128)));
+               g = (int) (y - (0.3455 * (u - 128)) - (0.7169 * (v - 128)));
+               r = (int) (y + (1.7790 * (u - 128)));
 
-               y = (int)(r * 0.299000 + g * 0.587000 + b * 0.114000);
-               u = (int)(r * -0.168736 + g * -0.331264 + b * 0.500000 + 128);
-               v = (int)(r *  0.500000 + g * -0.418688 + b * -0.081312 + 128);
+               if (r < 0)
+                       r = 0;
+               if (g < 0)
+                       g = 0;
+               if (b < 0)
+                       b = 0;
 
-               if (y < 0) y = 0;
-               if (u < 0) u = 0;
-               if (v < 0) v = 0;
+               if (r > 255)
+                       r = 255;
+               if (g > 255)
+                       g = 255;
+               if (b > 255)
+                       b = 255;
 
-               if (y > 255) y = 255;
-               if (u > 255) u = 255;
-               if (v > 255) v = 255;
-               
        }
-       
-};
 
+};
index b856fe5..8d206cf 100755 (executable)
@@ -1,3 +1,12 @@
+/*
+ * Imagesqueeze - Image codec optimized for photos.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
 package eu.svjatoslav.imagesqueeze.codec;
 
 public class ColorStats {
@@ -5,33 +14,30 @@ public class ColorStats {
        int ySum;
        int uSum;
        int vSum;
-       
+
        int pixelCount;
-       
-       
-       public ColorStats(){            
+
+       public ColorStats() {
                reset();
        }
 
-       public void reset(){
-               ySum = 0;
-               uSum = 0;
-               vSum = 0;
-               pixelCount = 0;
-       }
-               
-       public int getAverageY(){
-               return ySum / pixelCount;
+       public int getAverageU() {
+               return uSum / pixelCount;
        }
 
-       public int getAverageU(){
-               return uSum / pixelCount;
+       public int getAverageV() {
+               return vSum / pixelCount;
        }
 
-       public int getAverageV(){
-               return vSum / pixelCount;               
+       public int getAverageY() {
+               return ySum / pixelCount;
        }
-       
-}
 
+       public void reset() {
+               ySum = 0;
+               uSum = 0;
+               vSum = 0;
+               pixelCount = 0;
+       }
 
+}
index c644eaa..6ba0d1b 100755 (executable)
@@ -1,3 +1,12 @@
+/*
+ * Imagesqueeze - Image codec optimized for photos.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
 package eu.svjatoslav.imagesqueeze.codec;
 
 import java.awt.image.BufferedImage;
@@ -10,6 +19,9 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 
+import eu.svjatoslav.commons.data.BitInputStream;
+import eu.svjatoslav.commons.data.BitOutputStream;
+
 /**
  * Main class representing compressed image.
  */
@@ -21,100 +33,104 @@ public class Image {
        public BufferedImage bufferedImage;
 
        ImageEncoder encoder;
-       
-       public Image(){};
+
+       public Image() {
+       };
 
        /**
-        * Initialize imagesqueeze image based on {@link BufferedImage}. {@link BufferedImage} must be of type BufferedImage.TYPE_3BYTE_BGR .
+        * Initialize imagesqueeze image based on {@link BufferedImage}.
+        * {@link BufferedImage} must be of type BufferedImage.TYPE_3BYTE_BGR .
         */
-       public Image(BufferedImage image){
+       public Image(final BufferedImage image) {
 
-               this.bufferedImage = image;
+               bufferedImage = image;
                metaData = new ImageMetaData();
 
                metaData.version = 1;
                metaData.width = image.getWidth();
-               metaData.height = image.getHeight();            
+               metaData.height = image.getHeight();
        }
 
        /**
         * Initialize empty imagesqueeze image.
         */
-       public Image(int width, int height){
+       public Image(final int width, final int height) {
 
-               this.bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
+               bufferedImage = new BufferedImage(width, height,
+                               BufferedImage.TYPE_3BYTE_BGR);
                metaData = new ImageMetaData();
 
                metaData.version = 1;
                metaData.width = width;
-               metaData.height = height;               
-       }
-
-       /**
-        * Load ImgSqz image from {@link InputStream}.
-        */
-       public void loadImage(InputStream source) throws IOException{
-               BitInputStream bitInputStream = new BitInputStream(source);
-
-               metaData = new ImageMetaData();
-               metaData.load(bitInputStream);
-
-               bufferedImage = new BufferedImage(metaData.width, metaData.height, BufferedImage.TYPE_3BYTE_BGR);
-
-               ImageDecoder imageDecoder = new ImageDecoder(this, bitInputStream);
-
-               imageDecoder.decode();
+               metaData.height = height;
        }
 
        /**
         * Load ImgSqz image from {@link File}.
         */
-       public void loadImage(File source) throws IOException{
+       public void loadImage(final File source) throws IOException {
 
-               byte [] fileContent = new byte[(int)source.length()];
+               final byte[] fileContent = new byte[(int) source.length()];
 
-               FileInputStream fileInputStream = new FileInputStream(source);
+               final FileInputStream fileInputStream = new FileInputStream(source);
 
                fileInputStream.read(fileContent);
 
                fileInputStream.close();
 
-               ByteArrayInputStream inputStream = new ByteArrayInputStream(fileContent);
+               final ByteArrayInputStream inputStream = new ByteArrayInputStream(
+                               fileContent);
 
                loadImage(inputStream);
        }
 
        /**
-        * Save image into ImgSqz file format.
+        * Load ImgSqz image from {@link InputStream}.
         */
-       public void saveImage(OutputStream outputStream) throws IOException{
+       public void loadImage(final InputStream source) throws IOException {
+               final BitInputStream bitInputStream = new BitInputStream(source);
 
-               BitOutputStream bitOutputStream = new BitOutputStream(outputStream);
+               metaData = new ImageMetaData();
+               metaData.load(bitInputStream);
 
-               metaData.save(bitOutputStream);
-               
-               if (encoder == null){
-                       encoder = new ImageEncoder(this);                       
-               }
+               bufferedImage = new BufferedImage(metaData.width, metaData.height,
+                               BufferedImage.TYPE_3BYTE_BGR);
 
-               encoder.encode(bitOutputStream);
+               final ImageDecoder imageDecoder = new ImageDecoder(this, bitInputStream);
 
-               bitOutputStream.finishByte();
+               imageDecoder.decode();
        }
 
-
        /**
         * Save image into ImgSqz file format.
         */
-       public void saveImage(File file) throws IOException{
-               ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+       public void saveImage(final File file) throws IOException {
+               final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                saveImage(outputStream);
 
-               byte [] buffer = outputStream.toByteArray();
-               FileOutputStream fileOutputStream = new FileOutputStream(file);
+               final byte[] buffer = outputStream.toByteArray();
+               final FileOutputStream fileOutputStream = new FileOutputStream(file);
                fileOutputStream.write(buffer);
                fileOutputStream.close();
        }
 
+       /**
+        * Save image into ImgSqz file format.
+        */
+       public void saveImage(final OutputStream outputStream) throws IOException {
+
+               final BitOutputStream bitOutputStream = new BitOutputStream(
+                               outputStream);
+
+               metaData.save(bitOutputStream);
+
+               if (encoder == null) {
+                       encoder = new ImageEncoder(this);
+               }
+
+               encoder.encode(bitOutputStream);
+
+               bitOutputStream.finishByte();
+       }
 
 }
index 37f3c0e..bfcaeb6 100755 (executable)
@@ -1,3 +1,12 @@
+/*
+ * Imagesqueeze - Image codec optimized for photos.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
 package eu.svjatoslav.imagesqueeze.codec;
 
 /**
@@ -8,77 +17,77 @@ import java.awt.image.DataBufferByte;
 import java.awt.image.WritableRaster;
 import java.io.IOException;
 
+import eu.svjatoslav.commons.data.BitInputStream;
+
 public class ImageDecoder {
 
        int width, height;
        Image image;
 
-       byte [] decodedYRangeMap;
-       byte [] decodedYMap;
+       byte[] decodedYRangeMap;
+       byte[] decodedYMap;
 
-       byte [] decodedURangeMap;
-       byte [] decodedUMap;
+       byte[] decodedURangeMap;
+       byte[] decodedUMap;
 
-       byte [] decodedVRangeMap;
-       byte [] decodedVMap;
+       byte[] decodedVRangeMap;
+       byte[] decodedVMap;
 
        Color tmpColor = new Color();
-       
+
        Approximator approximator;
        BitInputStream bitInputStream;
-       
+
        ColorStats colorStats = new ColorStats();
        OperatingContext context = new OperatingContext();
-       
-       public ImageDecoder (Image image, BitInputStream bitInputStream) {
+
+       public ImageDecoder(final Image image, final BitInputStream bitInputStream) {
                approximator = new Approximator();
 
-               this.image = image;     
+               this.image = image;
                this.bitInputStream = bitInputStream;
 
                width = image.metaData.width;
                height = image.metaData.height;
 
                decodedYRangeMap = new byte[width * height];
-               decodedYRangeMap[0] = (byte)(255);
+               decodedYRangeMap[0] = (byte) (255);
                decodedYMap = new byte[width * height];
 
                decodedURangeMap = new byte[width * height];
-               decodedURangeMap[0] = (byte)(255);
+               decodedURangeMap[0] = (byte) (255);
                decodedUMap = new byte[width * height];
 
                decodedVRangeMap = new byte[width * height];
-               decodedVRangeMap[0] = (byte)(255);
+               decodedVRangeMap[0] = (byte) (255);
                decodedVMap = new byte[width * height];
 
        }
 
-
        public void decode() throws IOException {
                approximator.load(bitInputStream);
                approximator.computeLookupTables();
-               
-               WritableRaster raster = image.bufferedImage.getRaster();
-               DataBufferByte dbi = (DataBufferByte)raster.getDataBuffer();
-               byte [] pixels = dbi.getData();
-
-               // load top-, left-most pixel. 
-               decodedYMap[0] = (byte)bitInputStream.readBits(8);
-               decodedUMap[0] = (byte)bitInputStream.readBits(8);
-               decodedVMap[0] = (byte)bitInputStream.readBits(8);
-               
-               Color color = new Color();
+
+               final WritableRaster raster = image.bufferedImage.getRaster();
+               final DataBufferByte dbi = (DataBufferByte) raster.getDataBuffer();
+               final byte[] pixels = dbi.getData();
+
+               // load top-, left-most pixel.
+               decodedYMap[0] = (byte) bitInputStream.readBits(8);
+               decodedUMap[0] = (byte) bitInputStream.readBits(8);
+               decodedVMap[0] = (byte) bitInputStream.readBits(8);
+
+               final Color color = new Color();
                color.y = ImageEncoder.byteToInt(decodedYMap[0]);
                color.u = ImageEncoder.byteToInt(decodedUMap[0]);
                color.v = ImageEncoder.byteToInt(decodedVMap[0]);
-               
+
                color.YUV2RGB();
-               
-               pixels[0] = (byte)color.r;
-               pixels[0+1] = (byte)color.g;
-               pixels[0+2] = (byte)color.b;                            
 
-                               
+               pixels[0] = (byte) color.r;
+               pixels[0 + 1] = (byte) color.g;
+               pixels[0 + 2] = (byte) color.b;
+
                // detect initial step
                int largestDimension;
                int initialStep = 2;
@@ -87,146 +96,154 @@ public class ImageDecoder {
                } else {
                        largestDimension = height;
                }
-               
-               while (initialStep < largestDimension){
+
+               while (initialStep < largestDimension) {
                        initialStep = initialStep * 2;
                }
 
                grid(initialStep, pixels);
        }
 
-
-       public void grid(int step, byte [] pixels) throws IOException {
+       public void grid(final int step, final byte[] pixels) throws IOException {
 
                gridDiagonal(step / 2, step / 2, step, pixels);
                gridSquare(step / 2, 0, step, pixels);
                gridSquare(0, step / 2, step, pixels);
 
-               if (step > 2) grid(step / 2, pixels);
-       }
-
-
-       public void gridSquare(int offsetX, int offsetY, int step, byte [] pixels) throws IOException{
-
-               for (int y = offsetY; y < height; y = y + step){
-                       for (int x = offsetX; x < width; x = x + step){
-
-
-                               int halfStep = step / 2;
-                               
-                               context.initialize(image, decodedYMap, decodedUMap, decodedVMap);
-                               context.measureNeighborEncode(x - halfStep, y);
-                               context.measureNeighborEncode(x + halfStep, y);
-                               context.measureNeighborEncode(x, y - halfStep);
-                               context.measureNeighborEncode(x, y + halfStep);
-                                                               
-                               loadPixel(step, offsetX, offsetY,  x, y, pixels,
-                                               context.colorStats.getAverageY(),
-                                               context.colorStats.getAverageU(),
-                                               context.colorStats.getAverageV());
-
-                       }                       
-               }               
+               if (step > 2)
+                       grid(step / 2, pixels);
        }
 
+       public void gridDiagonal(final int offsetX, final int offsetY,
+                       final int step, final byte[] pixels) throws IOException {
 
-       public void gridDiagonal(int offsetX, int offsetY, int step, byte [] pixels) throws IOException{
+               for (int y = offsetY; y < height; y = y + step) {
+                       for (int x = offsetX; x < width; x = x + step) {
 
-               for (int y = offsetY; y < height; y = y + step){
-                       for (int x = offsetX; x < width; x = x + step){
-
-                               int halfStep = step / 2;
+                               final int halfStep = step / 2;
 
                                context.initialize(image, decodedYMap, decodedUMap, decodedVMap);
                                context.measureNeighborEncode(x - halfStep, y - halfStep);
                                context.measureNeighborEncode(x + halfStep, y - halfStep);
                                context.measureNeighborEncode(x - halfStep, y + halfStep);
                                context.measureNeighborEncode(x + halfStep, y + halfStep);
-                                                               
-                               loadPixel(step, offsetX, offsetY,  x, y, pixels,
+
+                               loadPixel(step, offsetX, offsetY, x, y, pixels,
                                                context.colorStats.getAverageY(),
                                                context.colorStats.getAverageU(),
                                                context.colorStats.getAverageV());
 
-                       }                       
-               }               
+                       }
+               }
        }
 
+       public void gridSquare(final int offsetX, final int offsetY,
+                       final int step, final byte[] pixels) throws IOException {
 
-       public void loadPixel(int step, int offsetX, int offsetY, int x, int y, byte[] pixels,
-                       int averageDecodedY, int averageDecodedU, int averageDecodedV)
-       throws IOException{
-
-               int index = (y * width) + x;
-
-               int halfStep = step / 2;
-
-               int parentIndex;
-               if (offsetX > 0){
-                       if (offsetY > 0){
-                               // diagonal approach
-                               parentIndex = ((y - halfStep) * width) + (x - halfStep);                                                                                                        
-                       } else {
-                               // take left pixel
-                               parentIndex = (y * width) + (x - halfStep);                                                                     
-                       }                       
-               } else {
-                       // take upper pixel
-                       parentIndex = ((y - halfStep) * width) + x;                                                                             
-               }
-
+               for (int y = offsetY; y < height; y = y + step) {
+                       for (int x = offsetX; x < width; x = x + step) {
 
+                               final int halfStep = step / 2;
 
-               int colorBufferIndex = index * 3;
+                               context.initialize(image, decodedYMap, decodedUMap, decodedVMap);
+                               context.measureNeighborEncode(x - halfStep, y);
+                               context.measureNeighborEncode(x + halfStep, y);
+                               context.measureNeighborEncode(x, y - halfStep);
+                               context.measureNeighborEncode(x, y + halfStep);
 
-               Color color = new Color();
-               color.y = loadChannel(decodedYRangeMap, decodedYMap, approximator.yTable, averageDecodedY, index, parentIndex);
-               color.u = loadChannel(decodedURangeMap, decodedUMap, approximator.uTable, averageDecodedU, index, parentIndex);
-               color.v = loadChannel(decodedVRangeMap, decodedVMap, approximator.vTable, averageDecodedV, index, parentIndex);
-               
-               color.YUV2RGB();
-               
-               pixels[colorBufferIndex] = (byte)color.r;
-               pixels[colorBufferIndex+1] = (byte)color.g;
-               pixels[colorBufferIndex+2] = (byte)color.b;                             
+                               loadPixel(step, offsetX, offsetY, x, y, pixels,
+                                               context.colorStats.getAverageY(),
+                                               context.colorStats.getAverageU(),
+                                               context.colorStats.getAverageV());
 
+                       }
+               }
        }
 
-
-       private int loadChannel(byte [] decodedRangeMap, byte [] decodedMap, Table table, int averageDecodedValue, int index,
-                       int parentIndex) throws IOException {
+       private int loadChannel(final byte[] decodedRangeMap,
+                       final byte[] decodedMap, final Table table,
+                       final int averageDecodedValue, final int index,
+                       final int parentIndex) throws IOException {
                int decodedValue = averageDecodedValue;
 
-               int inheritedRange = ImageEncoder.byteToInt(decodedRangeMap[parentIndex]);
+               final int inheritedRange = ImageEncoder
+                               .byteToInt(decodedRangeMap[parentIndex]);
                int computedRange = inheritedRange;
 
-               int bitCount = table.proposeBitcountForRange(inheritedRange);
+               final int bitCount = table.proposeBitcountForRange(inheritedRange);
                int computedRangeBitCount = 0;
-               if ( bitCount > 0){
+               if (bitCount > 0) {
 
-                       int rangeDecreases = bitInputStream.readBits(1);
-                       if (rangeDecreases != 0){
+                       final int rangeDecreases = bitInputStream.readBits(1);
+                       if (rangeDecreases != 0) {
                                computedRange = table.proposeDecreasedRange(inheritedRange);
-                       }                               
+                       }
 
-                       decodedRangeMap[index] = (byte)computedRange;
-                       computedRangeBitCount = table.proposeBitcountForRange(computedRange);
+                       decodedRangeMap[index] = (byte) computedRange;
+                       computedRangeBitCount = table
+                                       .proposeBitcountForRange(computedRange);
 
-                       if (computedRangeBitCount > 0){
+                       if (computedRangeBitCount > 0) {
 
-                               int encodedDifference = bitInputStream.readBits(computedRangeBitCount);
+                               final int encodedDifference = bitInputStream
+                                               .readBits(computedRangeBitCount);
 
-                               int decodedDifference = ImageEncoder.decodeValueFromGivenBits(encodedDifference, computedRange, computedRangeBitCount);
+                               final int decodedDifference = ImageEncoder
+                                               .decodeValueFromGivenBits(encodedDifference,
+                                                               computedRange, computedRangeBitCount);
 
                                decodedValue = averageDecodedValue - decodedDifference;
-                               if (decodedValue > 255) decodedValue = 255;
-                               if (decodedValue < 0) decodedValue = 0;
+                               if (decodedValue > 255)
+                                       decodedValue = 255;
+                               if (decodedValue < 0)
+                                       decodedValue = 0;
                        }
                } else {
-                       decodedRangeMap[index] = (byte)inheritedRange;
+                       decodedRangeMap[index] = (byte) inheritedRange;
                }
-               decodedMap[index] = (byte)decodedValue;
+               decodedMap[index] = (byte) decodedValue;
                return decodedValue;
        }
 
+       public void loadPixel(final int step, final int offsetX, final int offsetY,
+                       final int x, final int y, final byte[] pixels,
+                       final int averageDecodedY, final int averageDecodedU,
+                       final int averageDecodedV) throws IOException {
+
+               final int index = (y * width) + x;
+
+               final int halfStep = step / 2;
+
+               int parentIndex;
+               if (offsetX > 0) {
+                       if (offsetY > 0) {
+                               // diagonal approach
+                               parentIndex = ((y - halfStep) * width) + (x - halfStep);
+                       } else {
+                               // take left pixel
+                               parentIndex = (y * width) + (x - halfStep);
+                       }
+               } else {
+                       // take upper pixel
+                       parentIndex = ((y - halfStep) * width) + x;
+               }
+
+               final int colorBufferIndex = index * 3;
+
+               final Color color = new Color();
+               color.y = loadChannel(decodedYRangeMap, decodedYMap,
+                               approximator.yTable, averageDecodedY, index, parentIndex);
+               color.u = loadChannel(decodedURangeMap, decodedUMap,
+                               approximator.uTable, averageDecodedU, index, parentIndex);
+               color.v = loadChannel(decodedVRangeMap, decodedVMap,
+                               approximator.vTable, averageDecodedV, index, parentIndex);
+
+               color.YUV2RGB();
+
+               pixels[colorBufferIndex] = (byte) color.r;
+               pixels[colorBufferIndex + 1] = (byte) color.g;
+               pixels[colorBufferIndex + 2] = (byte) color.b;
+
+       }
+
 }
index 46c2135..613064c 100755 (executable)
@@ -1,3 +1,12 @@
+/*
+ * Imagesqueeze - Image codec optimized for photos.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
 package eu.svjatoslav.imagesqueeze.codec;
 
 /**
@@ -8,6 +17,7 @@ import java.awt.image.DataBufferByte;
 import java.awt.image.WritableRaster;
 import java.io.IOException;
 
+import eu.svjatoslav.commons.data.BitOutputStream;
 
 public class ImageEncoder {
 
@@ -17,78 +27,81 @@ public class ImageEncoder {
        Channel yChannel;
        Channel uChannel;
        Channel vChannel;
-       
+
        Approximator approximator;
 
        int bitsForY;
        int bitsForU;
        int bitsForV;
-       
-       //ColorStats colorStats = new ColorStats();
+
+       // ColorStats colorStats = new ColorStats();
        OperatingContext context = new OperatingContext();
        OperatingContext context2 = new OperatingContext();
 
        BitOutputStream bitOutputStream;
 
-       public ImageEncoder(Image image){
+       public ImageEncoder(final Image image) {
                approximator = new Approximator();
 
-               //bitOutputStream = outputStream;
+               // bitOutputStream = outputStream;
 
                this.image = image;
 
        }
 
-
-       public void encode(BitOutputStream bitOutputStream) throws IOException {
+       public void encode(final BitOutputStream bitOutputStream)
+                       throws IOException {
                this.bitOutputStream = bitOutputStream;
-               
+
                approximator.initialize();
-               
+
                approximator.save(bitOutputStream);
-               
+
                width = image.metaData.width;
                height = image.metaData.height;
 
-               WritableRaster raster = image.bufferedImage.getRaster();
-               DataBufferByte dbi = (DataBufferByte)raster.getDataBuffer();
-               byte [] pixels = dbi.getData();
+               final WritableRaster raster = image.bufferedImage.getRaster();
+               final DataBufferByte dbi = (DataBufferByte) raster.getDataBuffer();
+               final byte[] pixels = dbi.getData();
 
-               if (yChannel == null){
-                       yChannel = new Channel(width, height);                  
+               if (yChannel == null) {
+                       yChannel = new Channel(width, height);
                } else {
                        yChannel.reset();
                }
-               
-               if (uChannel == null){
-                       uChannel = new Channel(width, height);                  
+
+               if (uChannel == null) {
+                       uChannel = new Channel(width, height);
                } else {
                        uChannel.reset();
                }
-               
-               if (vChannel == null){
-                       vChannel = new Channel(width, height);                  
+
+               if (vChannel == null) {
+                       vChannel = new Channel(width, height);
                } else {
                        vChannel.reset();
                }
-               
+
                // create YUV map out of RGB raster data
-               Color color = new Color();
-               
-               for (int y=0; y < height; y++){
-                       for (int x=0; x < width; x++){
+               final Color color = new Color();
+
+               for (int y = 0; y < height; y++) {
+                       for (int x = 0; x < width; x++) {
 
-                               int index = (y * width) + x;
-                               int colorBufferIndex = index * 3;
+                               final int index = (y * width) + x;
+                               final int colorBufferIndex = index * 3;
 
-                               int blue = pixels[colorBufferIndex];                            
-                               if (blue < 0) blue = blue + 256;
+                               int blue = pixels[colorBufferIndex];
+                               if (blue < 0)
+                                       blue = blue + 256;
 
-                               int green = pixels[colorBufferIndex+1];
-                               if (green < 0) green = green + 256;
+                               int green = pixels[colorBufferIndex + 1];
+                               if (green < 0)
+                                       green = green + 256;
 
-                               int red = pixels[colorBufferIndex+2];
-                               if (red < 0) red = red + 256;
+                               int red = pixels[colorBufferIndex + 2];
+                               if (red < 0)
+                                       red = red + 256;
 
                                color.r = red;
                                color.g = green;
@@ -96,19 +109,19 @@ public class ImageEncoder {
 
                                color.RGB2YUV();
 
-                               yChannel.map[index] = (byte)color.y;
-                               uChannel.map[index] = (byte)color.u;
-                               vChannel.map[index] = (byte)color.v;
+                               yChannel.map[index] = (byte) color.y;
+                               uChannel.map[index] = (byte) color.u;
+                               vChannel.map[index] = (byte) color.v;
                        }
                }
 
                yChannel.decodedMap[0] = yChannel.map[0];
                uChannel.decodedMap[0] = uChannel.map[0];
                vChannel.decodedMap[0] = vChannel.map[0];
-               
-               bitOutputStream.storeBits(byteToInt(yChannel.map[0]), 8);                                                               
-               bitOutputStream.storeBits(byteToInt(uChannel.map[0]), 8);                                                               
-               bitOutputStream.storeBits(byteToInt(vChannel.map[0]), 8);                                                               
+
+               bitOutputStream.storeBits(byteToInt(yChannel.map[0]), 8);
+               bitOutputStream.storeBits(byteToInt(uChannel.map[0]), 8);
+               bitOutputStream.storeBits(byteToInt(vChannel.map[0]), 8);
 
                // detect initial step
                int largestDimension;
@@ -118,364 +131,413 @@ public class ImageEncoder {
                } else {
                        largestDimension = height;
                }
-               
-               while (initialStep < largestDimension){
+
+               while (initialStep < largestDimension) {
                        initialStep = initialStep * 2;
                }
-                               
+
                rangeGrid(initialStep);
                rangeRoundGrid(2);
                saveGrid(initialStep);
        }
 
-       public void printStatistics(){
+       private void encodeChannel(final Table table, final Channel channel,
+                       final int averageDecodedValue, final int index, final int value,
+                       final int range, final int parentIndex) throws IOException {
+
+               final byte[] decodedRangeMap = channel.decodedRangeMap;
+               final byte[] decodedMap = channel.decodedMap;
+
+               final int inheritedRange = byteToInt(decodedRangeMap[parentIndex]);
+
+               final int inheritedBitCount = table
+                               .proposeBitcountForRange(inheritedRange);
+
+               if (inheritedBitCount > 0) {
+                       int computedRange;
+                       computedRange = table.proposeRangeForRange(range, inheritedRange);
+                       decodedRangeMap[index] = (byte) computedRange;
+
+                       channel.bitCount++;
+                       if (computedRange != inheritedRange) {
+                               // brightness range shrinked
+                               bitOutputStream.storeBits(1, 1);
+                       } else {
+                               // brightness range stayed the same
+                               bitOutputStream.storeBits(0, 1);
+                       }
+
+                       // encode brightness into available amount of bits
+                       final int computedBitCount = table
+                                       .proposeBitcountForRange(computedRange);
+
+                       if (computedBitCount > 0) {
+
+                               final int differenceToEncode = -(value - averageDecodedValue);
+                               final int bitEncodedDifference = encodeValueIntoGivenBits(
+                                               differenceToEncode, computedRange, computedBitCount);
+
+                               channel.bitCount = channel.bitCount + computedBitCount;
+                               bitOutputStream.storeBits(bitEncodedDifference,
+                                               computedBitCount);
+
+                               final int decodedDifference = decodeValueFromGivenBits(
+                                               bitEncodedDifference, computedRange, computedBitCount);
+                               int decodedValue = averageDecodedValue - decodedDifference;
+                               if (decodedValue > 255)
+                                       decodedValue = 255;
+                               if (decodedValue < 0)
+                                       decodedValue = 0;
+
+                               decodedMap[index] = (byte) decodedValue;
+                       } else {
+                               decodedMap[index] = (byte) averageDecodedValue;
+                       }
+
+               } else {
+                       decodedRangeMap[index] = (byte) inheritedRange;
+                       decodedMap[index] = (byte) averageDecodedValue;
+               }
+       }
+
+       public void printStatistics() {
                System.out.println("Y channel:");
                yChannel.printStatistics();
 
                System.out.println("U channel:");
                uChannel.printStatistics();
-               
+
                System.out.println("V channel:");
-               vChannel.printStatistics();             
+               vChannel.printStatistics();
        }
-       
-       public void rangeGrid(int step){
 
-               //gridSquare(step / 2, step / 2, step, pixels);
+       public void rangeGrid(final int step) {
+
+               // gridSquare(step / 2, step / 2, step, pixels);
 
                rangeGridDiagonal(step / 2, step / 2, step);
                rangeGridSquare(step / 2, 0, step);
                rangeGridSquare(0, step / 2, step);
 
-               if (step > 2) rangeGrid(step / 2);
+               if (step > 2)
+                       rangeGrid(step / 2);
        }
 
+       public void rangeGridDiagonal(final int offsetX, final int offsetY,
+                       final int step) {
+               for (int y = offsetY; y < height; y = y + step) {
+                       for (int x = offsetX; x < width; x = x + step) {
 
-       public void rangeRoundGrid(int step){
-
-               rangeRoundGridDiagonal(step / 2, step / 2, step);
-               rangeRoundGridSquare(step / 2, 0, step);
-               rangeRoundGridSquare(0, step / 2, step);
-
-               if (step < 1024) rangeRoundGrid(step * 2);
-       }
+                               final int index = (y * width) + x;
+                               final int halfStep = step / 2;
 
-       public void saveGrid(int step) throws IOException {
+                               context.initialize(image, yChannel.map, uChannel.map,
+                                               vChannel.map);
 
-               saveGridDiagonal(step / 2, step / 2, step);
-               saveGridSquare(step / 2, 0, step);
-               saveGridSquare(0, step / 2, step);
+                               context.measureNeighborEncode(x - halfStep, y - halfStep);
+                               context.measureNeighborEncode(x + halfStep, y - halfStep);
+                               context.measureNeighborEncode(x - halfStep, y + halfStep);
+                               context.measureNeighborEncode(x + halfStep, y + halfStep);
 
-               if (step > 2) saveGrid(step / 2);
+                               yChannel.rangeMap[index] = (byte) context.getYRange(index);
+                               uChannel.rangeMap[index] = (byte) context.getURange(index);
+                               vChannel.rangeMap[index] = (byte) context.getVRange(index);
+                       }
+               }
        }
 
+       public void rangeGridSquare(final int offsetX, final int offsetY,
+                       final int step) {
+               for (int y = offsetY; y < height; y = y + step) {
+                       for (int x = offsetX; x < width; x = x + step) {
 
-       public void rangeGridSquare(int offsetX, int offsetY, int step){
-               for (int y = offsetY; y < height; y = y + step){
-                       for (int x = offsetX; x < width; x = x + step){
+                               final int index = (y * width) + x;
+                               final int halfStep = step / 2;
 
-                               int index = (y * width) + x;
-                               int halfStep = step / 2;
+                               context.initialize(image, yChannel.map, uChannel.map,
+                                               vChannel.map);
 
-                               context.initialize(image, yChannel.map, uChannel.map, vChannel.map);
-                       
                                context.measureNeighborEncode(x - halfStep, y);
                                context.measureNeighborEncode(x + halfStep, y);
                                context.measureNeighborEncode(x, y - halfStep);
                                context.measureNeighborEncode(x, y + halfStep);
 
-                               yChannel.rangeMap[index] = (byte)context.getYRange(index);
-                               uChannel.rangeMap[index] = (byte)context.getURange(index);
-                               vChannel.rangeMap[index] = (byte)context.getVRange(index);
-                       }                       
-               }               
+                               yChannel.rangeMap[index] = (byte) context.getYRange(index);
+                               uChannel.rangeMap[index] = (byte) context.getURange(index);
+                               vChannel.rangeMap[index] = (byte) context.getVRange(index);
+                       }
+               }
        }
 
-       public void rangeGridDiagonal(int offsetX, int offsetY, int step){
-               for (int y = offsetY; y < height; y = y + step){
-                       for (int x = offsetX; x < width; x = x + step){
+       public void rangeRoundGrid(final int step) {
 
-                               int index = (y * width) + x;
-                               int halfStep = step / 2;
-
-                               context.initialize(image, yChannel.map, uChannel.map, vChannel.map);
-                               
-                               context.measureNeighborEncode(x - halfStep, y - halfStep);
-                               context.measureNeighborEncode(x + halfStep, y - halfStep);
-                               context.measureNeighborEncode(x - halfStep, y + halfStep);
-                               context.measureNeighborEncode(x + halfStep, y + halfStep);
+               rangeRoundGridDiagonal(step / 2, step / 2, step);
+               rangeRoundGridSquare(step / 2, 0, step);
+               rangeRoundGridSquare(0, step / 2, step);
 
-                               yChannel.rangeMap[index] = (byte)context.getYRange(index);
-                               uChannel.rangeMap[index] = (byte)context.getURange(index);
-                               vChannel.rangeMap[index] = (byte)context.getVRange(index);
-                       }                       
-               }               
+               if (step < 1024)
+                       rangeRoundGrid(step * 2);
        }
 
-       public void rangeRoundGridDiagonal(int offsetX, int offsetY, int step){
-               for (int y = offsetY; y < height; y = y + step){
-                       for (int x = offsetX; x < width; x = x + step){
+       public void rangeRoundGridDiagonal(final int offsetX, final int offsetY,
+                       final int step) {
+               for (int y = offsetY; y < height; y = y + step) {
+                       for (int x = offsetX; x < width; x = x + step) {
 
-                               int index = (y * width) + x;
+                               final int index = (y * width) + x;
 
-                               int yRange = byteToInt(yChannel.rangeMap[index]);
-                               int uRange = byteToInt(uChannel.rangeMap[index]);
-                               int vRange = byteToInt(vChannel.rangeMap[index]);
+                               final int yRange = byteToInt(yChannel.rangeMap[index]);
+                               final int uRange = byteToInt(uChannel.rangeMap[index]);
+                               final int vRange = byteToInt(vChannel.rangeMap[index]);
 
-                               int halfStep = step / 2;
+                               final int halfStep = step / 2;
 
-                               int parentIndex = ((y - halfStep) * width) + (x - halfStep);
+                               final int parentIndex = ((y - halfStep) * width)
+                                               + (x - halfStep);
 
-                               int parentYRange =  byteToInt(yChannel.rangeMap[parentIndex]);
+                               int parentYRange = byteToInt(yChannel.rangeMap[parentIndex]);
 
-                               if (parentYRange < yRange){
+                               if (parentYRange < yRange) {
                                        parentYRange = yRange;
-                                       yChannel.rangeMap[parentIndex] = (byte)parentYRange;
+                                       yChannel.rangeMap[parentIndex] = (byte) parentYRange;
                                }
 
                                int parentURange = byteToInt(uChannel.rangeMap[parentIndex]);
 
-                               if (parentURange < uRange){
+                               if (parentURange < uRange) {
                                        parentURange = uRange;
-                                       uChannel.rangeMap[parentIndex] = (byte)parentURange;
+                                       uChannel.rangeMap[parentIndex] = (byte) parentURange;
                                }
 
                                int parentVRange = byteToInt(vChannel.rangeMap[parentIndex]);
 
-                               if (parentVRange < vRange){
+                               if (parentVRange < vRange) {
                                        parentVRange = vRange;
-                                       vChannel.rangeMap[parentIndex] = (byte)parentVRange;
+                                       vChannel.rangeMap[parentIndex] = (byte) parentVRange;
                                }
-                       }                       
-               }               
+                       }
+               }
        }
 
-       public void rangeRoundGridSquare(int offsetX, int offsetY, int step){
-               for (int y = offsetY; y < height; y = y + step){
-                       for (int x = offsetX; x < width; x = x + step){
+       public void rangeRoundGridSquare(final int offsetX, final int offsetY,
+                       final int step) {
+               for (int y = offsetY; y < height; y = y + step) {
+                       for (int x = offsetX; x < width; x = x + step) {
 
-                               int index = (y * width) + x;
-                               
-                               int yRange = byteToInt(yChannel.rangeMap[index]);
-                               int uRange = byteToInt(uChannel.rangeMap[index]);
-                               int vRange = byteToInt(vChannel.rangeMap[index]);
+                               final int index = (y * width) + x;
 
-                               int halfStep = step / 2;
+                               final int yRange = byteToInt(yChannel.rangeMap[index]);
+                               final int uRange = byteToInt(uChannel.rangeMap[index]);
+                               final int vRange = byteToInt(vChannel.rangeMap[index]);
+
+                               final int halfStep = step / 2;
 
                                int parentIndex;
-                               if (offsetX > 0){
-                                       parentIndex = (y * width) + (x - halfStep);                                     
+                               if (offsetX > 0) {
+                                       parentIndex = (y * width) + (x - halfStep);
                                } else {
-                                       parentIndex = ((y - halfStep) * width) + x;                                                                             
+                                       parentIndex = ((y - halfStep) * width) + x;
                                }
 
-                               int parentYRange =  byteToInt(yChannel.rangeMap[parentIndex]);
+                               int parentYRange = byteToInt(yChannel.rangeMap[parentIndex]);
 
-                               if (parentYRange < yRange){
+                               if (parentYRange < yRange) {
                                        parentYRange = yRange;
-                                       yChannel.rangeMap[parentIndex] = (byte)parentYRange;
+                                       yChannel.rangeMap[parentIndex] = (byte) parentYRange;
                                }
 
                                int parentURange = byteToInt(uChannel.rangeMap[parentIndex]);
 
-                               if (parentURange < uRange){
+                               if (parentURange < uRange) {
                                        parentURange = uRange;
-                                       uChannel.rangeMap[parentIndex] = (byte)parentURange;
+                                       uChannel.rangeMap[parentIndex] = (byte) parentURange;
                                }
 
                                int parentVRange = byteToInt(vChannel.rangeMap[parentIndex]);
 
-                               if (parentVRange < vRange){
+                               if (parentVRange < vRange) {
                                        parentVRange = vRange;
-                                       vChannel.rangeMap[parentIndex] = (byte)parentVRange;
+                                       vChannel.rangeMap[parentIndex] = (byte) parentVRange;
                                }
 
-                       }                       
-               }               
+                       }
+               }
        }
 
-       public void saveGridSquare(int offsetX, int offsetY, int step) throws IOException{
-               for (int y = offsetY; y < height; y = y + step){
-                       for (int x = offsetX; x < width; x = x + step){
-
-                               int halfStep = step / 2;
+       public void saveGrid(final int step) throws IOException {
 
-                               context2.initialize(image, yChannel.decodedMap, uChannel.decodedMap,  vChannel.decodedMap);
-                               context2.measureNeighborEncode(x - halfStep, y);
-                               context2.measureNeighborEncode(x + halfStep, y);
-                               context2.measureNeighborEncode(x, y - halfStep);
-                               context2.measureNeighborEncode(x, y + halfStep);
-                       
-                               
-                               savePixel(step, offsetX, offsetY, x, y,
-                                               context2.colorStats.getAverageY(),
-                                               context2.colorStats.getAverageU(),
-                                               context2.colorStats.getAverageV());                             
+               saveGridDiagonal(step / 2, step / 2, step);
+               saveGridSquare(step / 2, 0, step);
+               saveGridSquare(0, step / 2, step);
 
-                       }                       
-               }               
+               if (step > 2)
+                       saveGrid(step / 2);
        }
 
-       public void saveGridDiagonal(int offsetX, int offsetY, int step) throws IOException {
-               for (int y = offsetY; y < height; y = y + step){
-                       for (int x = offsetX; x < width; x = x + step){
-                               
-                               int halfStep = step / 2;
+       public void saveGridDiagonal(final int offsetX, final int offsetY,
+                       final int step) throws IOException {
+               for (int y = offsetY; y < height; y = y + step) {
+                       for (int x = offsetX; x < width; x = x + step) {
 
-                               context2.initialize(image, yChannel.decodedMap, uChannel.decodedMap,  vChannel.decodedMap);
+                               final int halfStep = step / 2;
+
+                               context2.initialize(image, yChannel.decodedMap,
+                                               uChannel.decodedMap, vChannel.decodedMap);
                                context2.measureNeighborEncode(x - halfStep, y - halfStep);
                                context2.measureNeighborEncode(x + halfStep, y - halfStep);
                                context2.measureNeighborEncode(x - halfStep, y + halfStep);
                                context2.measureNeighborEncode(x + halfStep, y + halfStep);
-                       
-                               
+
                                savePixel(step, offsetX, offsetY, x, y,
                                                context2.colorStats.getAverageY(),
                                                context2.colorStats.getAverageU(),
-                                               context2.colorStats.getAverageV());                             
-                               
-                       }                       
-               }               
+                                               context2.colorStats.getAverageV());
+
+                       }
+               }
        }
 
-       public void savePixel(int step, int offsetX, int offsetY, int x, int y, int averageDecodedY, int averageDecodedU, int averageDecodedV) throws IOException {
+       public void saveGridSquare(final int offsetX, final int offsetY,
+                       final int step) throws IOException {
+               for (int y = offsetY; y < height; y = y + step) {
+                       for (int x = offsetX; x < width; x = x + step) {
 
-               int index = (y * width) + x;
+                               final int halfStep = step / 2;
 
-               int py = byteToInt(yChannel.map[index]);                
-               int pu = byteToInt(uChannel.map[index]);        
-               int pv = byteToInt(vChannel.map[index]);                
-               
-               int yRange = byteToInt(yChannel.rangeMap[index]);
-               int uRange = byteToInt(uChannel.rangeMap[index]);
-               int vRange = byteToInt(vChannel.rangeMap[index]);
+                               context2.initialize(image, yChannel.decodedMap,
+                                               uChannel.decodedMap, vChannel.decodedMap);
+                               context2.measureNeighborEncode(x - halfStep, y);
+                               context2.measureNeighborEncode(x + halfStep, y);
+                               context2.measureNeighborEncode(x, y - halfStep);
+                               context2.measureNeighborEncode(x, y + halfStep);
 
-               int halfStep = step / 2;
+                               savePixel(step, offsetX, offsetY, x, y,
+                                               context2.colorStats.getAverageY(),
+                                               context2.colorStats.getAverageU(),
+                                               context2.colorStats.getAverageV());
+
+                       }
+               }
+       }
+
+       public void savePixel(final int step, final int offsetX, final int offsetY,
+                       final int x, final int y, final int averageDecodedY,
+                       final int averageDecodedU, final int averageDecodedV)
+                       throws IOException {
+
+               final int index = (y * width) + x;
+
+               final int py = byteToInt(yChannel.map[index]);
+               final int pu = byteToInt(uChannel.map[index]);
+               final int pv = byteToInt(vChannel.map[index]);
+
+               final int yRange = byteToInt(yChannel.rangeMap[index]);
+               final int uRange = byteToInt(uChannel.rangeMap[index]);
+               final int vRange = byteToInt(vChannel.rangeMap[index]);
+
+               final int halfStep = step / 2;
 
                int parentIndex;
-               if (offsetX > 0){
-                       if (offsetY > 0){
+               if (offsetX > 0) {
+                       if (offsetY > 0) {
                                // diagonal approach
-                               parentIndex = ((y - halfStep) * width) + (x - halfStep);                                                                                                        
+                               parentIndex = ((y - halfStep) * width) + (x - halfStep);
                        } else {
                                // take left pixel
-                               parentIndex = (y * width) + (x - halfStep);                                                                     
-                       }                       
+                               parentIndex = (y * width) + (x - halfStep);
+                       }
                } else {
                        // take upper pixel
-                       parentIndex = ((y - halfStep) * width) + x;                                                                             
+                       parentIndex = ((y - halfStep) * width) + x;
                }
 
-               encodeChannel(
-                               approximator.yTable,
-                               yChannel,
-                               averageDecodedY,
-                               index,
-                               py,
-                               yRange,
-                               parentIndex);
-
-               encodeChannel(
-                               approximator.uTable,
-                               uChannel,
-                               averageDecodedU,
-                               index,
-                               pu,
-                               uRange,
-                               parentIndex);
-
-               encodeChannel(
-                               approximator.vTable,
-                               vChannel,
-                               averageDecodedV,
-                               index,
-                               pv,
-                               vRange,
-                               parentIndex);
+               encodeChannel(approximator.yTable, yChannel, averageDecodedY, index,
+                               py, yRange, parentIndex);
+
+               encodeChannel(approximator.uTable, uChannel, averageDecodedU, index,
+                               pu, uRange, parentIndex);
+
+               encodeChannel(approximator.vTable, vChannel, averageDecodedV, index,
+                               pv, vRange, parentIndex);
 
        }
 
+       public static int byteToInt(final byte input) {
+               int result = input;
+               if (result < 0)
+                       result = result + 256;
+               return result;
+       }
 
-       private void encodeChannel(Table table, Channel channel, int averageDecodedValue, int index,
-                       int value, int range, int parentIndex)
-                       throws IOException {
-               
-               byte[] decodedRangeMap = channel.decodedRangeMap;
-               byte[] decodedMap = channel.decodedMap;
-               
-               int inheritedRange = byteToInt(decodedRangeMap[parentIndex]);
+       public static int decodeValueFromGivenBits(final int encodedBits,
+                       final int range, final int bitCount) {
+               final int negativeBit = encodedBits & 1;
 
-               int inheritedBitCount = table.proposeBitcountForRange(inheritedRange);
+               final int remainingBitCount = bitCount - 1;
 
-               if (inheritedBitCount > 0){
-                       int computedRange;
-                       computedRange = table.proposeRangeForRange(range, inheritedRange);                                                                                                                              
-                       decodedRangeMap[index] = (byte)computedRange;
+               if (remainingBitCount == 0) {
+                       // no more bits remaining to encode actual value
 
-                       channel.bitCount++;
-                       if (computedRange != inheritedRange){
-                               // brightness range shrinked
-                               bitOutputStream.storeBits(1, 1);                        
+                       if (negativeBit == 0) {
+                               return range;
                        } else {
-                               // brightness range stayed the same
-                               bitOutputStream.storeBits(0, 1);                                                
+                               return -range;
                        }
 
+               } else {
+                       // still one or more bits left, encode value as precisely as
+                       // possible
 
-                       // encode brightness into available amount of bits
-                       int computedBitCount = table.proposeBitcountForRange(computedRange);
-
-                       if (computedBitCount > 0){
+                       final int encodedValue = (encodedBits >>> 1) + 1;
 
-                               int differenceToEncode = -(value - averageDecodedValue);
-                               int bitEncodedDifference = encodeValueIntoGivenBits(differenceToEncode, computedRange, computedBitCount);
+                       final int realvalueForThisBitcount = 1 << remainingBitCount;
 
-                               channel.bitCount = channel.bitCount + computedBitCount;
-                               bitOutputStream.storeBits(bitEncodedDifference, computedBitCount);                                                              
+                       // int valueMultiplier = range / realvalueForThisBitcount;
+                       int decodedValue = (range * encodedValue)
+                                       / realvalueForThisBitcount;
 
-                               int decodedDifference = decodeValueFromGivenBits(bitEncodedDifference, computedRange, computedBitCount);
-                               int decodedValue = averageDecodedValue - decodedDifference;
-                               if (decodedValue > 255) decodedValue = 255;
-                               if (decodedValue < 0) decodedValue = 0;
+                       if (decodedValue > range)
+                               decodedValue = range;
 
-                               decodedMap[index] = (byte)decodedValue;                 
-                       } else {                                
-                               decodedMap[index] = (byte)averageDecodedValue;                  
-                       }                       
+                       if (negativeBit == 0) {
+                               return decodedValue;
+                       } else {
+                               return -decodedValue;
+                       }
 
-               } else {
-                       decodedRangeMap[index] = (byte)inheritedRange;                  
-                       decodedMap[index] = (byte)averageDecodedValue;                  
                }
        }
 
-       public static int encodeValueIntoGivenBits(int value, int range, int bitCount){
+       public static int encodeValueIntoGivenBits(int value, final int range,
+                       final int bitCount) {
 
                int negativeBit = 0;
 
-               if (value <0){
+               if (value < 0) {
                        negativeBit = 1;
                        value = -value;
                }
 
-               int remainingBitCount = bitCount - 1;
+               final int remainingBitCount = bitCount - 1;
 
-               if (remainingBitCount == 0){                    
+               if (remainingBitCount == 0) {
                        // no more bits remaining to encode actual value
 
                        return negativeBit;
 
                } else {
-                       // still one or more bits left, encode value as precisely as possible
-
-                       if (value > range) value = range;
+                       // still one or more bits left, encode value as precisely as
+                       // possible
 
+                       if (value > range)
+                               value = range;
 
-                       int realvalueForThisBitcount = 1 << remainingBitCount;
+                       final int realvalueForThisBitcount = 1 << remainingBitCount;
                        // int valueMultiplier = range / realvalueForThisBitcount;
-                       int encodedValue = value * realvalueForThisBitcount / range;
+                       int encodedValue = (value * realvalueForThisBitcount) / range;
 
-                       if (encodedValue >= realvalueForThisBitcount) encodedValue = realvalueForThisBitcount - 1;
+                       if (encodedValue >= realvalueForThisBitcount)
+                               encodedValue = realvalueForThisBitcount - 1;
 
                        encodedValue = (encodedValue << 1) + negativeBit;
 
@@ -483,47 +545,4 @@ public class ImageEncoder {
                }
        }
 
-
-       public static int decodeValueFromGivenBits(int encodedBits, int range, int bitCount){
-               int negativeBit = encodedBits & 1;
-
-               int remainingBitCount = bitCount - 1;
-
-               if (remainingBitCount == 0){                    
-                       // no more bits remaining to encode actual value
-
-                       if (negativeBit == 0){
-                               return range;                           
-                       } else {
-                               return -range;                                                          
-                       }
-
-               } else {
-                       // still one or more bits left, encode value as precisely as possible
-
-                       int encodedValue = (encodedBits >>> 1) + 1;
-
-                       int realvalueForThisBitcount = 1 << remainingBitCount;
-
-                       // int valueMultiplier = range / realvalueForThisBitcount;
-                       int decodedValue = range * encodedValue / realvalueForThisBitcount;
-
-
-                       if (decodedValue > range) decodedValue = range;
-
-                       if (negativeBit == 0){
-                               return decodedValue;                            
-                       } else {
-                               return -decodedValue;                                                           
-                       }
-
-               }               
-       }
-
-       public static int byteToInt(byte input){
-               int result = input;
-               if (result < 0) result = result + 256;
-               return result;
-       }
-
 }
index 68b3bea..4b21a22 100755 (executable)
@@ -1,3 +1,12 @@
+/*
+ * Imagesqueeze - Image codec optimized for photos.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
 package eu.svjatoslav.imagesqueeze.codec;
 
 /**
@@ -7,6 +16,8 @@ package eu.svjatoslav.imagesqueeze.codec;
 
 import java.io.IOException;
 
+import eu.svjatoslav.commons.data.BitInputStream;
+import eu.svjatoslav.commons.data.BitOutputStream;
 
 public class ImageMetaData {
 
@@ -14,16 +25,15 @@ public class ImageMetaData {
        int width;
        int height;
 
+       public void load(final BitInputStream inputStream) throws IOException {
 
-       public void load(BitInputStream inputStream) throws IOException{
-
-               version = inputStream.readBits(16);
+               version = inputStream.readBits(16);
                width = inputStream.readIntegerCompressed8();
                height = inputStream.readIntegerCompressed8();
 
        }
 
-       public void save(BitOutputStream outputStream) throws IOException{
+       public void save(final BitOutputStream outputStream) throws IOException {
 
                outputStream.storeBits(version, 16);
                outputStream.storeIntegerCompressed8(width);
index bac1630..e96d610 100755 (executable)
@@ -1,3 +1,12 @@
+/*
+ * Imagesqueeze - Image codec optimized for photos.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
 package eu.svjatoslav.imagesqueeze.codec;
 
 public class OperatingContext {
@@ -7,45 +16,49 @@ public class OperatingContext {
        byte[] uMap;
        byte[] vMap;
        ColorStats colorStats = new ColorStats();
-       
-       public OperatingContext(){
+
+       public OperatingContext() {
        }
 
-       public void initialize(Image image, byte [] brightnessMap, byte [] colornessMap, byte [] colorMap){
-               this.image = image;
-               this.yMap = brightnessMap;
-               this.uMap = colornessMap;
-               this.vMap = colorMap;
-               
-               colorStats.reset();
+       public int getURange(final int index) {
+               final int colorness = ImageEncoder.byteToInt(uMap[index]);
+               return Math.abs(colorness - colorStats.getAverageU());
        }
-       
-       public void measureNeighborEncode(int x, int y){
-               if ((y >= 0) && (y < image.metaData.height) && (x >= 0) && (x < image.metaData.width)){
-
-                       int neighborIndex = y * image.metaData.width + x;
-                       
-                       colorStats.ySum = colorStats.ySum + ImageEncoder.byteToInt(yMap[neighborIndex]);
-                       colorStats.uSum = colorStats.uSum + ImageEncoder.byteToInt(uMap[neighborIndex]);
-                       colorStats.vSum = colorStats.vSum + ImageEncoder.byteToInt(vMap[neighborIndex]);
-                       colorStats.pixelCount++;
-               }
+
+       public int getVRange(final int index) {
+               final int color = ImageEncoder.byteToInt(vMap[index]);
+               return Math.abs(color - colorStats.getAverageV());
        }
 
-       public int getYRange(int index){
-               int brightness = ImageEncoder.byteToInt(yMap[index]);                           
-               return Math.abs(brightness - colorStats.getAverageY());         
+       public int getYRange(final int index) {
+               final int brightness = ImageEncoder.byteToInt(yMap[index]);
+               return Math.abs(brightness - colorStats.getAverageY());
        }
 
-       public int getURange(int index){
-               int colorness = ImageEncoder.byteToInt(uMap[index]);                            
-               return Math.abs(colorness - colorStats.getAverageU());          
+       public void initialize(final Image image, final byte[] brightnessMap,
+                       final byte[] colornessMap, final byte[] colorMap) {
+               this.image = image;
+               yMap = brightnessMap;
+               uMap = colornessMap;
+               vMap = colorMap;
+
+               colorStats.reset();
        }
 
-       public int getVRange(int index){
-               int color = ImageEncoder.byteToInt(vMap[index]);                                
-               return Math.abs(color - colorStats.getAverageV());              
+       public void measureNeighborEncode(final int x, final int y) {
+               if ((y >= 0) && (y < image.metaData.height) && (x >= 0)
+                               && (x < image.metaData.width)) {
+
+                       final int neighborIndex = (y * image.metaData.width) + x;
+
+                       colorStats.ySum = colorStats.ySum
+                                       + ImageEncoder.byteToInt(yMap[neighborIndex]);
+                       colorStats.uSum = colorStats.uSum
+                                       + ImageEncoder.byteToInt(uMap[neighborIndex]);
+                       colorStats.vSum = colorStats.vSum
+                                       + ImageEncoder.byteToInt(vMap[neighborIndex]);
+                       colorStats.pixelCount++;
+               }
        }
 
-               
 }
index 4e714f4..33637d7 100755 (executable)
+/*
+ * Imagesqueeze - Image codec optimized for photos.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
 package eu.svjatoslav.imagesqueeze.codec;
 
 import java.io.IOException;
 
+import eu.svjatoslav.commons.data.BitInputStream;
+import eu.svjatoslav.commons.data.BitOutputStream;
+
 /**
  * Quick lookup table.
  */
 
-public class Table implements Comparable<Table>{
+public class Table implements Comparable<Table> {
 
-       int [] range = new int[100];    
-       int [] switchTreshold = new int[100];
-       int [] bitcount = new int[100];
+       int[] range = new int[100];
+       int[] switchTreshold = new int[100];
+       int[] bitcount = new int[100];
 
+       int[] bitCountForRange = new int[256];
+       int[] proposedRangeForActualRange = new int[256];
+       int[] proposedRangeForActualRangeLow = new int[256];
+       int[] proposedRangeForActualRangeHigh = new int[256];
+       byte[] proposedDecreasedRange = new byte[256];
 
-       int [] bitCountForRange = new int[256];
-       int [] proposedRangeForActualRange = new int[256];
-       int [] proposedRangeForActualRangeLow = new int[256];
-       int [] proposedRangeForActualRangeHigh = new int[256];
-       byte [] proposedDecreasedRange = new byte[256];
+       int usedEntries = 0;
 
+       /**
+        * @param switchTreshold
+        *            - switch to this range when actual range in equal or below
+        *            this treshold
+        */
+       public void addEntry(int range, int switchTreshold, int bitcount) {
+               if (range < 0)
+                       range = 0;
+               if (range > 255)
+                       range = 255;
+
+               if (switchTreshold < 0)
+                       switchTreshold = 0;
+               if (switchTreshold > 255)
+                       switchTreshold = 255;
+
+               if (bitcount < 0)
+                       bitcount = 0;
+               if (bitcount > 8)
+                       bitcount = 8;
 
-       int usedEntries = 0;
+               this.range[usedEntries] = range;
+               this.switchTreshold[usedEntries] = switchTreshold;
+               this.bitcount[usedEntries] = bitcount;
+               usedEntries++;
+       }
 
+       /**
+        * Compares two tables. Ignores table initialization.
+        */
+       @Override
+       public int compareTo(final Table o) {
+               if (usedEntries < o.usedEntries)
+                       return -1;
+               if (usedEntries > o.usedEntries)
+                       return 1;
+
+               for (int i = 0; i < usedEntries; i++) {
+                       if (range[i] < o.range[i])
+                               return -1;
+                       if (range[i] > o.range[i])
+                               return 1;
+
+                       if (switchTreshold[i] < o.switchTreshold[i])
+                               return -1;
+                       if (switchTreshold[i] > o.switchTreshold[i])
+                               return 1;
+
+                       if (bitcount[i] < o.bitcount[i])
+                               return -1;
+                       if (bitcount[i] > o.bitcount[i])
+                               return 1;
+               }
 
-       public void computeLookupTables(){
+               return 0;
+       }
+
+       public void computeLookupTables() {
                int currentCheckPointer = 0;
 
-               for (int i=0; i<256; i++){
+               for (int i = 0; i < 256; i++) {
 
-                       if (range[currentCheckPointer] == i){
+                       if (range[currentCheckPointer] == i) {
                                currentCheckPointer++;
                        }
 
-                       if (currentCheckPointer > 0){
-                               bitCountForRange[i] = bitcount[currentCheckPointer-1];                          
+                       if (currentCheckPointer > 0) {
+                               bitCountForRange[i] = bitcount[currentCheckPointer - 1];
                        } else {
                                bitCountForRange[i] = 0;
                        }
 
                }
 
-               for (int i=0; i<256; i++){
+               for (int i = 0; i < 256; i++) {
 
                        int seek;
-                       seekLoop:{
-                               for (seek = 0; seek < usedEntries; seek ++){
+                       seekLoop: {
+                               for (seek = 0; seek < usedEntries; seek++) {
 
-                                       if (switchTreshold[seek] >= i) break seekLoop;
+                                       if (switchTreshold[seek] >= i)
+                                               break seekLoop;
 
                                }
                        }
 
-                       proposedRangeForActualRange[i] = range[seek];           
-                       if (seek == 0){
-                               proposedRangeForActualRangeLow[i] = 0;          
+                       proposedRangeForActualRange[i] = range[seek];
+                       if (seek == 0) {
+                               proposedRangeForActualRangeLow[i] = 0;
                        } else {
-                               proposedRangeForActualRangeLow[i] = switchTreshold[seek-1]+1;                                           
+                               proposedRangeForActualRangeLow[i] = switchTreshold[seek - 1] + 1;
                        }
-                       proposedRangeForActualRangeHigh[i] = switchTreshold[seek];                              
+                       proposedRangeForActualRangeHigh[i] = switchTreshold[seek];
                }
 
-
                currentCheckPointer = usedEntries - 2;
-               for (int i=255; i >= 0; i--){           
-                       if (range[currentCheckPointer] == i) currentCheckPointer--;
+               for (int i = 255; i >= 0; i--) {
+                       if (range[currentCheckPointer] == i)
+                               currentCheckPointer--;
 
-                       if (currentCheckPointer < 0){
+                       if (currentCheckPointer < 0) {
                                proposedDecreasedRange[i] = 0;
                        } else {
-                               proposedDecreasedRange[i] = (byte)(range[currentCheckPointer]);                         
+                               proposedDecreasedRange[i] = (byte) (range[currentCheckPointer]);
                        }
                }
 
        }
 
-       /**
-        * @param switchTreshold - switch to this range when actual range in equal or below this treshold
-        */
-       public void addEntry(int range, int switchTreshold, int bitcount){
-               if (range < 0) range = 0;
-               if (range > 255) range = 255;
-
-               if (switchTreshold < 0) switchTreshold = 0;
-               if (switchTreshold > 255) switchTreshold = 255;
-
-               if (bitcount < 0) bitcount = 0;
-               if (bitcount > 8) bitcount = 8;
-
-               
-               this.range[usedEntries] = range;
-               this.switchTreshold[usedEntries] = switchTreshold;
-               this.bitcount[usedEntries] = bitcount;
-               usedEntries++;
-       }
-
-
-       
-       
-       public int proposeRangeForRange(int actualRange, int inheritedRange){
+       public void load(final BitInputStream inputStream) throws IOException {
+               reset();
 
-               if (inheritedRange > 255) inheritedRange = 255;
-               if (inheritedRange < 0) inheritedRange = 0;
+               final int availableEntries = inputStream.readIntegerCompressed8();
 
-               if (proposedRangeForActualRangeLow[inheritedRange] <= actualRange){
-                       return inheritedRange;
+               for (int i = 0; i < availableEntries; i++) {
+                       addEntry(inputStream.readBits(8), inputStream.readBits(8),
+                                       inputStream.readBits(4));
                }
-
-               return proposeDecreasedRange(inheritedRange);
        }
 
-
-       public int proposeDecreasedRange(int range){
-               if (range > 255) range = 255;
-               if (range < 0) range = 0;
-
-               return ImageEncoder.byteToInt(proposedDecreasedRange[range]);
+       public int proposeBitcountForRange(int range) {
+               if (range > 255)
+                       range = 255;
+               if (range < 0)
+                       range = 0;
+               final int proposal = bitCountForRange[range];
+               return proposal;
        }
 
+       public int proposeDecreasedRange(int range) {
+               if (range > 255)
+                       range = 255;
+               if (range < 0)
+                       range = 0;
 
-       public int proposeBitcountForRange(int range){
-               if (range > 255) range = 255;
-               if (range < 0) range = 0;
-               int proposal = bitCountForRange[range];
-               return proposal;
+               return ImageEncoder.byteToInt(proposedDecreasedRange[range]);
        }
 
-       /**
-        * Compares two tables.
-        * Ignores table initialization.
-        */
-       public int compareTo(Table o) {
-               if (usedEntries < o.usedEntries) return -1;
-               if (usedEntries > o.usedEntries) return 1;
-
-               for (int i=0; i<usedEntries; i++){
-                       if (range[i] < o.range[i]) return -1;
-                       if (range[i] > o.range[i]) return 1;
+       public int proposeRangeForRange(final int actualRange, int inheritedRange) {
 
-                       if (switchTreshold[i] < o.switchTreshold[i]) return -1;
-                       if (switchTreshold[i] > o.switchTreshold[i]) return 1;
+               if (inheritedRange > 255)
+                       inheritedRange = 255;
+               if (inheritedRange < 0)
+                       inheritedRange = 0;
 
-                       if (bitcount[i] < o.bitcount[i]) return -1;
-                       if (bitcount[i] > o.bitcount[i]) return 1;
+               if (proposedRangeForActualRangeLow[inheritedRange] <= actualRange) {
+                       return inheritedRange;
                }
 
-               return 0;
+               return proposeDecreasedRange(inheritedRange);
        }
 
-       public void save(BitOutputStream outputStream) throws IOException {
-               outputStream.storeIntegerCompressed8(usedEntries);
-
-               for (int i=0; i < usedEntries; i++){
-                       outputStream.storeBits(this.range[i], 8);
-                       outputStream.storeBits(this.switchTreshold[i], 8);
-                       outputStream.storeBits(this.bitcount[i], 4);
-               }
-       }
-       
-       public void reset(){
-               range = new int[100];   
+       public void reset() {
+               range = new int[100];
                switchTreshold = new int[100];
                bitcount = new int[100];
 
-
                bitCountForRange = new int[256];
                proposedRangeForActualRange = new int[256];
                proposedRangeForActualRangeLow = new int[256];
@@ -171,17 +197,15 @@ public class Table implements Comparable<Table>{
 
                usedEntries = 0;
        }
-       
-       public void load(BitInputStream inputStream) throws IOException {
-               reset();
-               
-               int availableEntries = inputStream.readIntegerCompressed8();
-               
-               for (int i=0; i < availableEntries; i++){
-                       addEntry(inputStream.readBits(8), inputStream.readBits(8), inputStream.readBits(4));                    
-               }
-       }
 
+       public void save(final BitOutputStream outputStream) throws IOException {
+               outputStream.storeIntegerCompressed8(usedEntries);
 
+               for (int i = 0; i < usedEntries; i++) {
+                       outputStream.storeBits(range[i], 8);
+                       outputStream.storeBits(switchTreshold[i], 8);
+                       outputStream.storeBits(bitcount[i], 4);
+               }
+       }
 
 }
index 3da2f77..2b68ef7 100755 (executable)
@@ -1,35 +1,35 @@
+/*
+ * Imagesqueeze - Image codec optimized for photos.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
 package eu.svjatoslav.imagesqueeze.sampleApplication;
+
 import java.awt.BorderLayout;
 
-import javax.swing.WindowConstants;
 import javax.swing.SwingUtilities;
-
+import javax.swing.WindowConstants;
 
 public class ImageFrame extends javax.swing.JFrame {
        private ImagePanel imagePanel1;
 
-       /**
-       * Auto-generated main method to display this JFrame
-       */
-       public static void main(String[] args) {
-               SwingUtilities.invokeLater(new Runnable() {
-                       public void run() {
-                               ImageFrame inst = new ImageFrame("test");
-                               inst.setLocationRelativeTo(null);
-                               inst.setVisible(true);
-                       }
-               });
-       }
-       
-       public ImageFrame(String title) {
+       public ImageFrame(final String title) {
                super();
                setTitle(title);
                initGUI();
        }
-       
+
+       public ImagePanel getImagePanel() {
+               return imagePanel1;
+       }
+
        private void initGUI() {
                try {
-                       BorderLayout thisLayout = new BorderLayout();
+                       final BorderLayout thisLayout = new BorderLayout();
                        setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
                        getContentPane().setLayout(thisLayout);
                        {
@@ -37,13 +37,23 @@ public class ImageFrame extends javax.swing.JFrame {
                                getContentPane().add(getImagePanel(), BorderLayout.CENTER);
                        }
                        pack();
-               } catch (Exception e) {
+               } catch (final Exception e) {
                        e.printStackTrace();
                }
        }
-       
-       public ImagePanel getImagePanel() {
-               return imagePanel1;
+
+       /**
+        * Auto-generated main method to display this JFrame
+        */
+       public static void main(final String[] args) {
+               SwingUtilities.invokeLater(new Runnable() {
+                       @Override
+                       public void run() {
+                               final ImageFrame inst = new ImageFrame("test");
+                               inst.setLocationRelativeTo(null);
+                               inst.setVisible(true);
+                       }
+               });
        }
 
 }
index 749d558..c2ccead 100755 (executable)
+/*
+ * Imagesqueeze - Image codec optimized for photos.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
 package eu.svjatoslav.imagesqueeze.sampleApplication;
 
 import java.awt.BorderLayout;
-
 import java.awt.Dimension;
 import java.awt.image.BufferedImage;
-import java.io.BufferedReader;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 
-import javax.swing.JButton;
-
 import javax.swing.ImageIcon;
-import javax.swing.JPanel;
-import javax.swing.WindowConstants;
 import javax.swing.JFrame;
 import javax.swing.JLabel;
+import javax.swing.WindowConstants;
 
 import eu.svjatoslav.imagesqueeze.codec.Image;
 
-
 public class ImagePanel extends javax.swing.JPanel {
        private JLabel imageLabel;
 
        public BufferedImage bufferedImage;
 
-       /**
-        * Auto-generated main method to display this 
-        * JPanel inside a new JFrame.
-        */
-       public static void main(String[] args) {
-               JFrame frame = new JFrame();
-               frame.getContentPane().add(new ImagePanel());
-               frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
-               frame.pack();
-               frame.setVisible(true);
-       }
-
        public ImagePanel() {
                super();
                initGUI();
        }
 
+       public void createEmptyImage(final Dimension dimension) {
+
+               bufferedImage = new BufferedImage(dimension.width, dimension.height,
+                               BufferedImage.TYPE_3BYTE_BGR);
+
+               final ImageIcon icon = new ImageIcon(bufferedImage);
+
+               imageLabel.setIcon(icon);
+       }
+
+       public JLabel getImageLabel() {
+               return imageLabel;
+       }
+
        private void initGUI() {
                try {
-                       BorderLayout thisLayout = new BorderLayout();
-                       this.setLayout(thisLayout);
+                       final BorderLayout thisLayout = new BorderLayout();
+                       setLayout(thisLayout);
                        setPreferredSize(new Dimension(660, 500));
                        {
                                imageLabel = new JLabel();
                                this.add(getImageLabel(), BorderLayout.CENTER);
                        }
-               } catch (Exception e) {
+               } catch (final Exception e) {
                        e.printStackTrace();
                }
        }
 
-       public JLabel getImageLabel() {
-               return imageLabel;
-       }
+       public void loadImage(final File inputFile, final boolean isImgSqz)
+                       throws IOException {
+               final FileInputStream fileInputStream = new FileInputStream(inputFile);
 
-       public void loadImage(File inputFile, boolean isImgSqz) throws IOException{
-               FileInputStream fileInputStream = new FileInputStream(inputFile);
-       
-               loadImage(fileInputStream, isImgSqz);           
+               loadImage(fileInputStream, isImgSqz);
        }
 
-       public void loadImage(InputStream inputStream, boolean isImgSqz) throws IOException{
-               if (isImgSqz){
+       public void loadImage(final InputStream inputStream, final boolean isImgSqz)
+                       throws IOException {
+               if (isImgSqz) {
                        // load ImageSqueeze file
 
-                       Image image = new Image();
+                       final Image image = new Image();
                        image.loadImage(inputStream);
 
                        bufferedImage = image.bufferedImage;
 
-                       ImageIcon icon = new ImageIcon(bufferedImage);
-                       //ImageIcon icon = new ImageIcon("sample data/original.png");
+                       final ImageIcon icon = new ImageIcon(bufferedImage);
+                       // ImageIcon icon = new ImageIcon("sample data/original.png");
 
-                       imageLabel.setIcon(icon);                       
+                       imageLabel.setIcon(icon);
 
                } else {
                        // load JPEG, PNG, GIF file
-                       ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
-                       readLoop:{
-                               for (;;){                               
-                                       int b = inputStream.read();
-                                       if (b == -1) break readLoop;
+                       final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+                       readLoop: {
+                               for (;;) {
+                                       final int b = inputStream.read();
+                                       if (b == -1)
+                                               break readLoop;
                                        outputStream.write(b);
                                }
                        }
-                       
-                       ImageIcon icon = new ImageIcon(outputStream.toByteArray());
 
-                       bufferedImage = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_3BYTE_BGR);
+                       final ImageIcon icon = new ImageIcon(outputStream.toByteArray());
+
+                       bufferedImage = new BufferedImage(icon.getIconWidth(),
+                                       icon.getIconHeight(), BufferedImage.TYPE_3BYTE_BGR);
                        bufferedImage.getGraphics().drawImage(icon.getImage(), 0, 0, null);
 
-                       ImageIcon displayIcon = new ImageIcon(bufferedImage);
-                       imageLabel.setIcon(displayIcon);                        
+                       final ImageIcon displayIcon = new ImageIcon(bufferedImage);
+                       imageLabel.setIcon(displayIcon);
                }
        }
 
-
-       public void createEmptyImage(Dimension dimension){
-
-               bufferedImage = new BufferedImage(dimension.width, dimension.height, BufferedImage.TYPE_3BYTE_BGR);
-
-               ImageIcon icon = new ImageIcon(bufferedImage);
-
-               imageLabel.setIcon(icon);                       
-       }
-
-
-       public void saveImage(File outputFile){
-               Image image = new Image(bufferedImage);
+       public void saveImage(final File outputFile) {
+               final Image image = new Image(bufferedImage);
                try {
                        image.saveImage(outputFile);
-               } catch (Exception e) {
+               } catch (final Exception e) {
                        System.out.println("Error while saving image: " + e.toString());
                }
        }
 
+       /**
+        * Auto-generated main method to display this JPanel inside a new JFrame.
+        */
+       public static void main(final String[] args) {
+               final JFrame frame = new JFrame();
+               frame.getContentPane().add(new ImagePanel());
+               frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
+               frame.pack();
+               frame.setVisible(true);
+       }
+
 }
index f67ff3a..0e2ccce 100755 (executable)
@@ -1,45 +1,50 @@
+/*
+ * Imagesqueeze - Image codec optimized for photos.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
 package eu.svjatoslav.imagesqueeze.sampleApplication;
 
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 
-
-
 public class Main {
 
-       public static void main(String[] args) {
+       public static void main(final String[] args) {
 
                try {
 
-                       String image = "colorful photo";
-                       String sourceDirectory = "/eu/svjatoslav/imagesqueeze/sampleApplication/data/";
-                       
+                       final String image = "colorful photo";
+                       final String sourceDirectory = "/eu/svjatoslav/imagesqueeze/sampleApplication/data/";
+
                        // create visible frame
                        // load image into frame
-                       InputStream inputStream = Main.class.getResourceAsStream(sourceDirectory + image + ".png");
-                       
-                       ImageFrame frame = new ImageFrame("Original image");
-                       frame.getImagePanel().loadImage(inputStream, false);                    
-                       frame.setVisible(true);
+                       final InputStream inputStream = Main.class
+                                       .getResourceAsStream(sourceDirectory + image + ".png");
 
+                       final ImageFrame frame = new ImageFrame("Original image");
+                       frame.getImagePanel().loadImage(inputStream, false);
+                       frame.setVisible(true);
 
                        // encode image into file
                        frame.getImagePanel().saveImage(new File(image + ".ImgSqz"));
 
-
                        // create second frame for decoded image
-                       ImageFrame frame2 = new ImageFrame("Encoded -> Decoded");
+                       final ImageFrame frame2 = new ImageFrame("Encoded -> Decoded");
 
                        // decode image
                        frame2.getImagePanel().loadImage(new File(image + ".ImgSqz"), true);
                        frame2.setVisible(true);
 
-               } catch (IOException exception){
+               } catch (final IOException exception) {
                        System.out.println("Error while loading an image: " + exception);
                }
 
-
        }
 
 }