Skip to content

Instantly share code, notes, and snippets.

@fxposter
Created February 27, 2010 21:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fxposter/316981 to your computer and use it in GitHub Desktop.
Save fxposter/316981 to your computer and use it in GitHub Desktop.
package org.fxposter.wavelets;
import com.sun.imageio.plugins.bmp.BMPImageReader;
import sun.awt.image.ByteInterleavedRaster;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.color.ColorSpace;
import java.awt.image.*;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
/**
* Created by IntelliJ IDEA.
* User: fxposter
* Date: 27.02.2010
* Time: 15:10:18
* To change this template use File | Settings | File Templates.
*/
public class ImagePanel extends JPanel {
private Image image;
public ImagePanel(String imagePath) throws IOException {
this(ImageIO.read(new File(imagePath)));
}
public ImagePanel(Image image) {
this.image = image;
}
public void paintComponent(Graphics g) {
g.drawImage(image, 0, 0, this);
}
public static void main(String[] args) throws IOException {
// double[] coefficients = new double[] { 0.5, 0.5 };
double[] coefficients = new double[] { 0.483, 0.837, 0.224, -0.129 };
BufferedImage image = ImageIO.read(new File("src/org/fxposter/wavelets/lena.bmp"));
ByteInterleavedRaster raster = ((ByteInterleavedRaster)image.getRaster());
byte[] imageData = raster.getDataStorage();
double[][][] data = splitRgbToColors(imageData, 512, 512);
double[][] blueData = data[0], greenData = data[1], redData = data[2];
// byte[] blueData = new byte[imageData.length / 3];
// byte[] greenData = new byte[imageData.length / 3];
// byte[] redData = new byte[imageData.length / 3];
// for (int i = 0; i < imageData.length; i += 3) {
// blueData[i / 3] = imageData[i];
// greenData[i / 3] = imageData[i + 1];
// redData[i / 3] = imageData[i + 2];
// }
double[][] newBlue = wavelet(blueData, coefficients, 512, 512, 1);
double[][] newGreen = wavelet(greenData, coefficients, 512, 512, 1);
double[][] newRed = wavelet(redData, coefficients, 512, 512, 1);
// for (int i = 256; i < 512; ++i)
// for (int j = 256; j < 512; ++j) {
// newBlue[i][j] = newGreen[i][j] = newRed[i][j] = 0;
// }
double[][] newBlue2 = reverseWavelet(newBlue, coefficients, 512, 512, 1);
double[][] newGreen2 = reverseWavelet(newGreen, coefficients, 512, 512, 1);
double[][] newRed2 = reverseWavelet(newRed, coefficients, 512, 512, 1);
JFrame frame = new JFrame("Window");
frame.setContentPane(new ImagePanel(createImage(joinFilteredToRgb(newBlue, newGreen, newRed, 512, 512), 512, 512)));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(600, 600));
frame.pack();
frame.setVisible(true);
// double[] data = new double[]{16, 14, 12, 10, 8, 6, 4, 2};
// double[] coefficients = new double[]{0.5, 0.5};
//
// System.out.println(Arrays.toString(wavelet(data, coefficients, 1)));
//
// double[][] matrix = new double[][] { {2, 4, 6, 8}, {10, 12, 14, 16}, {18, 20, 22, 24}, {26, 28, 30, 32} };
// double[][] newMatrix = wavelet(matrix, coefficients, 4, 4, 3);
// int i = 10;
}
public static BufferedImage createImage(byte[] imageData, int width, int height) {
ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
int[] nBits = {8, 8, 8};
ColorModel cm = new ComponentColorModel(cs, nBits, false, true,
Transparency.OPAQUE,
DataBuffer.TYPE_BYTE);
SampleModel sm = new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE, width, height,
cs.getNumComponents(),
width * cs.getNumComponents(),
new int[]{2, 1, 0});
DataBufferByte db = new DataBufferByte(imageData, width * height);
ByteInterleavedRaster newRaster = (ByteInterleavedRaster) Raster.createWritableRaster(sm, db, null);
return new BufferedImage(cm, newRaster, false, null);
}
public static double[][][] splitRgbToColors(byte[] imageData, int width, int height) {
double[][] blueData = new double[width][height];
double[][] greenData = new double[width][height];
double[][] redData = new double[width][height];
for (int i = 0; i < width; ++i)
for (int j = 0; j < height; ++j) {
int pos = 3 * (i * width + j);
blueData[i][j] = imageData[pos];
greenData[i][j] = imageData[pos + 1];
redData[i][j] = imageData[pos + 2];
}
return new double[][][]{blueData, greenData, redData};
}
public static byte[] joinFilteredToRgb(double[][] blueData, double[][] greenData, double[][] redData, int width, int height) {
byte[] imageData = new byte[3 * width * height];
for (int i = 0; i < width; ++i)
for (int j = 0; j < height; ++j) {
int pos = 3 * (i * width + j);
imageData[pos] = convertToPixelComponent(blueData[i][j]);
imageData[pos + 1] = convertToPixelComponent(greenData[i][j]);
imageData[pos + 2] = convertToPixelComponent(redData[i][j]);
// imageData[pos] = blueData[i][j];
// imageData[pos + 1] = greenData[i][j];
// imageData[pos + 2] = redData[i][j];
}
return imageData;
}
public static byte convertToPixelComponent(double value) {
if (value < -128.0) {
// System.out.println(value);
return -128;
}
if (value > 127.0) {
// System.out.println(value);
return 127;
}
return (byte)value;
}
public static double[] wavelet(double[] signal, double[] coefficients, int tries) {
int length = signal.length;
double[] result = new double[length];
double[] lowSignal = new double[length / 2], highSignal = new double[length / 2];
for (int i = 0; i < length / 2; ++i) {
for (int j = 0; j < coefficients.length; ++j) {
lowSignal[i] += coefficients[j] * signal[(2 * i + j) % length];
}
}
for (int i = 0; i < length / 2; ++i) {
for (int j = 0; j < coefficients.length; ++j) {
highSignal[i] += (j % 2 == 1 ? -1 : 1) * coefficients[coefficients.length - j - 1] * signal[(2 * i + j) % length];
}
}
double[] nextWavelet = (lowSignal.length >= coefficients.length && (tries > 1 || tries <= 0)) ? wavelet(lowSignal, coefficients, tries - 1) : lowSignal;
for (int i = 0; i < length / 2; ++i)
result[i] = nextWavelet[i];
for (int i = 0; i < length / 2; ++i)
result[length / 2 + i] = highSignal[i];
return result;
}
public static double[][] wavelet(double[][] signal, double[] coefficients, int rows, int columns, int tries) {
double[][] result = new double[rows][columns];
for (int j = 0; j < rows; ++j)
for (int k = 0; k < columns; ++k)
result[j][k] = signal[j][k];
double[][] r = null;
for (int i = 0; i < tries; ++i) {
if (rows < coefficients.length || columns < coefficients.length)
break;
r = processWavelet(result, coefficients, rows, columns);
for (int j = 0; j < rows; ++j)
for (int k = 0; k < columns; ++k)
result[j][k] = r[j][k];
rows /= 2;
columns /= 2;
}
return result;
}
public static double[][] processWavelet(double[][] signal, double[] coefficients, int rows, int columns) {
double[][] lowResult = new double[rows][], highResult = new double[rows][columns];
for (int i = 0; i < rows; ++i)
lowResult[i] = waveletRow(signal, coefficients, rows, i);
for (int i = 0; i < columns; ++i) {
double[] processed = waveletColumn(lowResult, coefficients, columns, i);
for (int j = 0; j < rows; j++)
highResult[j][i] = processed[j];
}
return highResult;
}
public static double[] waveletRow(double[][] signal, double[] coefficients, int columns, int row) {
int length = columns;
double[] result = new double[length];
double[] lowSignal = new double[length / 2], highSignal = new double[length / 2];
for (int i = 0; i < length / 2; ++i) {
for (int j = 0; j < coefficients.length; ++j)
lowSignal[i] += coefficients[j] * signal[row][(2 * i + j) % length];
}
for (int i = 0; i < length / 2; ++i) {
for (int j = 0; j < coefficients.length; ++j) {
highSignal[i] += (j % 2 == 1 ? -1 : 1) * coefficients[coefficients.length - j - 1] * signal[row][(2 * i + j) % length];
}
}
for (int i = 0; i < length / 2; ++i)
result[i] = lowSignal[i];
for (int i = 0; i < length / 2; ++i)
result[length / 2 + i] = highSignal[i];
return result;
}
public static double[] waveletColumn(double[][] signal, double[] coefficients, int rows, int column) {
int length = rows;
double[] result = new double[length];
double[] lowSignal = new double[length / 2], highSignal = new double[length / 2];
for (int i = 0; i < length / 2; ++i)
for (int j = 0; j < coefficients.length; ++j)
lowSignal[i] += coefficients[j] * signal[(2 * i + j) % length][column];
for (int i = 0; i < length / 2; ++i)
for (int j = 0; j < coefficients.length; ++j)
highSignal[i] += (j % 2 == 1 ? -1 : 1) * coefficients[coefficients.length - j - 1] * signal[(2 * i + j) % length][column];
for (int i = 0; i < length / 2; ++i)
result[i] = lowSignal[i];
for (int i = 0; i < length / 2; ++i)
result[length / 2 + i] = highSignal[i];
return result;
}
public static double[][] reverseWavelet(double[][] signal, double[] coefficients, int rows, int columns, int tries) {
double[][] result = new double[rows][columns];
for (int j = 0; j < rows; ++j)
for (int k = 0; k < columns; ++k)
result[j][k] = signal[j][k];
for (int i = 0; i < tries; ++i) {
rows /= 2;
columns /= 2;
}
double[][] r = null;
for (int i = 0; i < tries; ++i) {
rows *= 2;
columns *= 2;
r = reverseProcessWavelet(result, coefficients, rows, columns);
for (int j = 0; j < rows; ++j)
for (int k = 0; k < columns; ++k)
result[j][k] = r[j][k];
}
return result;
}
public static double[][] reverseProcessWavelet(double[][] signal, double[] coefficients, int rows, int columns) {
double[][] lowResult = new double[rows][], highResult = new double[rows][columns];
for (int i = 0; i < columns; ++i) {
double[] processed = reverseWaveletColumn(signal, coefficients, rows, i);
for (int j = 0; j < rows; j++)
highResult[j][i] = processed[j];
}
for (int i = 0; i < rows; ++i)
lowResult[i] = reverseWaveletRow(highResult, coefficients, columns, i);
return lowResult;
}
public static double[] reverseWaveletRow(double[][] signal, double[] coefficients, int columns, int rowNumber) {
double[] row = new double[columns];
for (int i = 0; i < columns; i += 2) {
row[i] = signal[rowNumber][i / 2];
row[i + 1] = signal[rowNumber][columns / 2 + i / 2];
}
int length = columns;
double[] result = new double[length];
for (int i = 0; i < length - 1; i += 2) {
result[i] = coefficients[2] * row[((i - 2) + length) % length] + coefficients[1] * row[((i - 1) + length) % length]
+ coefficients[0] * row[i] + coefficients[3] * row[i + 1];
result[i + 1] = coefficients[3] * row[((i - 2) + length) % length] - coefficients[0] * row[((i - 1) + length) % length]
+ coefficients[1] * row[i] - coefficients[2] * row[i + 1];
}
return result;
}
public static double[] reverseWaveletColumn(double[][] signal, double[] coefficients, int rows, int columnNumber) {
double[] column = new double[rows];
for (int i = 0; i < rows; i += 2) {
column[i] = signal[i / 2][columnNumber];
column[i + 1] = signal[rows / 2 + i / 2][columnNumber];
}
int length = rows;
double[] result = new double[length];
for (int i = 0; i < length - 1; i += 2) {
result[i] = coefficients[2] * column[((i - 2) + length) % length] + coefficients[1] * column[((i - 1) + length) % length]
+ coefficients[0] * column[i] + coefficients[3] * column[i + 1];
result[i + 1] = coefficients[3] * column[((i - 2) + length) % length] - coefficients[0] * column[((i - 1) + length) % length]
+ coefficients[1] * column[i] - coefficients[2] * column[i + 1];
}
return result;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment