Pixel access of BufferedImage - memory leak? - java

I want to build histograms from several images.
To perform this process, I get access to the DataBufferByte
I recognize that the GC doesn't free the memory after building the histogram.
What is wrong with this code?
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicInteger;
import javax.imageio.ImageIO;
public class Histogram {
HashMap<Color,AtomicInteger> histogram;
public Histogram() {
histogram = new HashMap<>();
}
public void build(BufferedImage image){
int pixelLength = 3;
byte[] pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
int red, green, blue;
Color color;
for ( int pixel = 0; pixel <= pixels.length - pixelLength; pixel+= pixelLength ) {
blue= ((int) pixels[pixel] & 0xff); // blue
green= (((int) pixels[pixel + 1] & 0xff) ); // green
red = (((int) pixels[pixel + 2] & 0xff) ); // red
color = new Color(red, green, blue);
if(histogram.containsKey(color)){
histogram.get(color).incrementAndGet();
}
else{
histogram.put(color, new AtomicInteger(1));
}
}
pixels = null;
}
public static void main(String[] args) {
String pathImage = "C://testjpg";
try {
for (int j = 0; j < 5000; j++) {
BufferedImage i = ImageIO.read(new File(pathImage));
Histogram h = new Histogram();
h.build(i);
i.flush();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
thanks for your support :)

The GC does not run automatically and recalls the memory only when it needs it. You can force it using System.gc(), but be careful to not do it too often, else it will slow down your program.
Your code runs fine, and here is what I've tested:
public static void buildColorHistogram(BufferedImage image)
{
final int pixelLength = 3;
byte[] pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
for (int pixel=0 ; pixel < pixels.length; pixel+=pixelLength)
{
final int blue = pixels[pixel] & 0xff ; // blue
final int green= pixels[pixel + 1] & 0xff ; // green
final int red = pixels[pixel + 2] & 0xff ; // red
Color color = new Color(red, green, blue) ;
if ( histogram.containsKey(color) )
histogram.get(color).incrementAndGet() ;
else
histogram.put(color, new AtomicInteger(1)) ;
}
pixels = null ;
}
Be careful that some color images have also an alpha channel, which means that pixelLength will be 4 instead of 3.
Do you empty out (flush) the histogram when you're done with it? Because there are 16 millions combinations/triplets of color.

Related

Changing Opacity of colors in an image Java

I've written a code that gets a specific RGB color from an image and stores that in a file.
Now I'm trying to change the opacity of each of the colors in the image. For example, decrease the red color gradually until it is not there, and each time the color has decreased, the change that happened will be saved in a file. How can that be done?
Here's the code that I've written to get a specific color
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import java.nio.Buffer;
import javax.imageio.ImageIO;
public class BMPtoArray {
public static void getBlue(BufferedImage image){}
public static void getGreen(BufferedImage image){}
public static void getRed(BufferedImage image){
int blue = 0x000000FF;
int green = 0x0000FF00;
ColorModel cm = image.getColorModel();
boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
WritableRaster raster =
image.copyData(image.getRaster().createCompatibleWritableRaster());
BufferedImage newImage = new BufferedImage(cm, raster, isAlphaPremultiplied, null);
for (int row = 0; row < newImage.getHeight(); row++) {
for (int col = 0; col < newImage.getWidth(); col++) {
int color = newImage.getRGB(col, row);
color &= ~green;
color &= ~blue;
newImage.setRGB(col, row, color);
}
}
try {
ImageIO.write(newImage, "bmp",new File("C:\\Users\\Mhamd\\Desktop\\3rd year
first semester\\Analysis and Coding\\labs\\2.2Java\\src\\newIMGRed"+".bmp") );
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void getBlack(BufferedImage image){
int red = 0x00FF0000;
int blue = 0x000000FF;
int green = 0x0000FF00;
ColorModel cm = image.getColorModel();
boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
WritableRaster raster =
image.copyData(image.getRaster().createCompatibleWritableRaster());
BufferedImage newImage = new BufferedImage(cm, raster,
isAlphaPremultiplied, null);
for(int count = 1; count<=8;count++) {
try {
ImageIO.write(newImage, "bmp", new
File("C:\\Users\\Mhamd\\Desktop\\3rd year first semester\\Analysis
and Coding\\labs\\2.2Java\\src\\newIMGBlack" + count + ".bmp"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for (int row = 0; row < newImage.getHeight(); row++) {
for (int col = 0; col < newImage.getWidth(); col++) {
int color = newImage.getRGB(col, row);
color &= ~blue * count / 8;
color &= ~red * count / 8;
color &= ~green * count / 8;
newImage.setRGB(col, row, color);
}
}
}
}
public static void main(String[] args) throws Exception {
BufferedImage image = ImageIO.read(new File("C:\\Users\\Mhamd\\Desktop\\3rd year
first semester\\Analysis and Coding\\labs\\2.2Java\\src\\circleRGB.bmp"));
getRed(image);
getBlue(image);
getGreen(image);
}
}
The getBlue and getGreen methods are the same as the getRed, just with different colors.
The picture below shows what I want to do. As you can see, the image starts with its colors, and gradually the red, green, and blue are decreasing until they are gone, and each time the color decreases, the change in the image is saved in a file.
Stepping through your method’s logic:
for(int count = 1; count<=8;count++) {
try {
ImageIO.write(newImage, "bmp", new File("C:\\Users\\Mhamd\\Desktop\\3rd year first semester\\Analysis and Coding\\labs\\2.2Java\\src\\newIMGBlack" + count + ".bmp"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Writing the image before you have made changes will not produce the intended result. You need to write the image after you have modified the pixels. Remove the Image.write call, and remove the try/catch.
for (int row = 0; row < newImage.getHeight(); row++) {
for (int col = 0; col < newImage.getWidth(); col++) {
int color = newImage.getRGB(col, row);
Do not read the pixel from newImage. Read it from the original image:
int color = image.getRGB(col, row);
Finally, these lines are incorrect:
color &= ~blue * count / 8;
color &= ~red * count / 8;
color &= ~green * count / 8;
~blue * count / 8 is performing math on the bit mask for all blue values in all pixels. It is not performing math on the actual pixel value.
First, isolate the blue value:
int blueValue = color & blue;
Now you have a value on which you can perform math:
blueValue = blueValue * count / 8;
blueValue &= blue;
You can update the color by first clearing the existing blue value:
color &= ~blue;
…and then updating the color with the new blue value:
color |= blueValue;
And of course, you’ll want to do the same with the red and green values.
Finally, after both for-loops are complete and all pixels have been updated, only then should you write your file:
newImage.setRGB(col, row, color);
}
}
}
try {
ImageIO.write(newImage, "bmp", new File("C:\\Users\\Mhamd\\Desktop\\3rd year first semester\\Analysis and Coding\\labs\\2.2Java\\src\\newIMGBlack" + count + ".bmp"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

Convert pixel data back to image in Java

I have a code that puts an image in a pixel matrix.I have to split this image into four parts and get 4 different image files for these parts.
Then I have to do some image processing on it and then join those parts back together in a single image.
Please help me in achieving this.
Note:the image is colored and we want to just split it into 4 equal parts and then get it back as one.No changes needed.Here is the code to get four matrices of intensities.But I don't know what to do with it.It might be that there is no need of it at all.
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
class Optimization
{
public static void main(String[] args) throws IOException
{
BufferedImage hugeImage = ImageIO.read(new File("comp.jpg"));
final byte[] pixels = ((DataBufferByte) hugeImage.getRaster().getDataBuffer()).getData();
int width = hugeImage.getWidth();
int height = hugeImage.getHeight();
if(width%2!=0)
width=width-1;
if(height%2!=0)
height=height-1;
//System.out.print(width+" "+height);
int intensity[][]=new int[width][height];
int b1[][]=new int[width/2][height/2];
int b2[][]=new int[width/2][height/2];
int b3[][]=new int[width/2][height/2];
int b4[][]=new int[width/2][height/2];
int x1=0,y1=0,x2=0,y2=0,x3=0,x4=0,y3=0,y4=0;
final int pixelLength = 3;
for (int pixel = 0, row = 0, col = 0; pixel < pixels.length; pixel += pixelLength)
{
int a1,a2,a3;
a3= ((int) pixels[pixel] & 0xff); // blue
a2= (((int) pixels[pixel + 1] & 0xff)); // green
a1= (((int) pixels[pixel + 2] & 0xff)); // red
int i=(a1+a2+a3)/3;
intensity[col][row]=i;
if((col<=width/2-1)&&(row<=height/2-1))
{
b1[x1][y1]=i;
x1++;
if(col==width/2-1)
{
x1=0;
y1++;
}
}
if((col<width)&&(row<=height/2-1)&&(col>width/2-1))
{
b2[x2][y2]=i;
x2++;
if(col==width-1)
{
x2=0;
y2++;
}
}
if((col<width/2)&&(row<height)&&(row>=height/2))
{
b3[x3][y3]=i;
x3++;
if(col==width/2-1)
{
x3=0;
y3++;
}
}
if((col>width/2-1)&&(row>height/2-1))
{
b4[x4][y4]=i;
x4++;
if(col==width-1)
{
x4=0;
y4++;
}
}
col++;
if (col == width)
{
col = 0;
row++;
}
}
for(int m=0;m<height/2;m++)
{
for(int n=0;n<width/2;n++)
{
System.out.print(b1[n][m]+" ");
}
System.out.println();
}
}
}
java.awt.Image provides you getSubimage(int x, int y, int w, int h)
"Returns a subimage defined by a specified rectangular region." You just return four equal regions and thats it.
You can use getSubImage(int x, int y, int w, int h), but you will get an image that shares the same raster than the original image, meaning that if you modify the new sub-image, then you also modify the original image. If it's not problematic for you, then use it.
Else, as you have already accessed the DataBuffer (good idea), here is a simple code to do what you want (I just make DataBuffer copies, and it works when the image dimensions are odd):
BufferedImage image = ... ;
BufferedImage q1 = new BufferedImage(image.getWidth()/2, image.getHeight()/2, image.getType()) ;
BufferedImage q2 = new BufferedImage(image.getWidth()-image.getWidth()/2, image.getHeight()/2, image.getType()) ;
BufferedImage q3 = new BufferedImage(image.getWidth()/2, image.getHeight()-image.getHeight()/2, image.getType()) ;
BufferedImage q4 = new BufferedImage(image.getWidth()-image.getWidth()/2, image.getHeight()-image.getHeight()/2, image.getType()) ;
byte[] bb = ((DataBufferByte)image.getRaster().getDataBuffer()).getData() ;
byte[] bbq1 = ((DataBufferByte)q1.getRaster().getDataBuffer()).getData() ;
byte[] bbq2 = ((DataBufferByte)q2.getRaster().getDataBuffer()).getData() ;
byte[] bbq3 = ((DataBufferByte)q3.getRaster().getDataBuffer()).getData() ;
byte[] bbq4 = ((DataBufferByte)q4.getRaster().getDataBuffer()).getData() ;
for (int y=0 ; y < q1.getHeight() ; y++) // Fill Q1 and Q2
{
System.arraycopy(bb, y*image.getWidth(), bbq1, y*q1.getWidth(), q1.getWidth()) ;
System.arraycopy(bb, y*image.getWidth()+q1.getWidth(), bbq2, y*q2.getWidth(), q2.getWidth()) ;
}
for (int y=0 ; y < q3.getHeight() ; y++) // Fill Q3 and Q4
{
System.arraycopy(bb, (y+q1.getHeight())*image.getWidth(), bbq3, y*q3.getWidth(), q3.getWidth()) ;
System.arraycopy(bb, (y+q1.getHeight())*image.getWidth()+q3.getWidth(), bbq4, y*q4.getWidth(), q4.getWidth()) ;
}

Get color of each pixel of an image using BufferedImages

I am trying to get every single color of every single pixel of an image.
My idea was following:
int[] pixels;
BufferedImage image;
image = ImageIO.read(this.getClass.getResources("image.png");
int[] pixels = ((DataBufferInt)image.getRaster().getDataBuffer()).getData();
Is that right? I can't even check what the "pixels" array contains, because i get following error:
java.awt.image.DataBufferByte cannot be cast to java.awt.image.DataBufferInt
I just would like to receive the color of every pixel in an array, how do i achieve that?
import java.io.*;
import java.awt.*;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
public class GetPixelColor {
public static void main(String args[]) throws IOException {
File file = new File("your_file.jpg");
BufferedImage image = ImageIO.read(file);
// Getting pixel color by position x and y
int clr = image.getRGB(x, y);
int red = (clr & 0x00ff0000) >> 16;
int green = (clr & 0x0000ff00) >> 8;
int blue = clr & 0x000000ff;
System.out.println("Red Color value = " + red);
System.out.println("Green Color value = " + green);
System.out.println("Blue Color value = " + blue);
}
}
of course you have to add a for loop for all pixels
The problem (also with the answer that was linked from the first answer) is that you hardly ever know what exact type your buffered image will be after reading it with ImageIO. It could contain a DataBufferByte or a DataBufferInt. You may deduce it in some cases via BufferedImage#getType(), but in the worst case, it has type TYPE_CUSTOM, and then you can only fall back to some instanceof tests.
However, you can convert your image into a BufferedImage that is guaranteed to have a DataBufferInt with ARGB values - namely with something like
public static BufferedImage convertToARGB(BufferedImage image)
{
BufferedImage newImage = new BufferedImage(
image.getWidth(), image.getHeight(),
BufferedImage.TYPE_INT_ARGB);
Graphics2D g = newImage.createGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
return newImage;
}
Otherwise, you can call image.getRGB(x,y), which may perform the required conversions on the fly.
BTW: Note that obtaining the data buffer of a BufferedImage may degrade painting performance, because the image can no longer be "managed" and kept in VRAM internally.
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
BufferedImage bufferedImage = ImageIO.read(new File("norris.jpg"));
int height = bufferedImage.getHeight(), width = bufferedImage.getWidth();
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int RGBA = bufferedImage.getRGB(x, y);
int alpha = (RGBA >> 24) & 255;
int red = (RGBA >> 16) & 255;
int green = (RGBA >> 8) & 255;
int blue = RGBA & 255;
}
}
}
}
Assume the buffered image represents an image with 8-bit RGBA color components packed into integer pixels, I search for "RGBA color space" on wikipedia and found following:
In the byte-order scheme, "RGBA" is understood to mean a byte R,
followed by a byte G, followed by a byte B, and followed by a byte A.
This scheme is commonly used for describing file formats or network
protocols, which are both byte-oriented.
With simple Bitwise and Bitshift you can get the value of each color and the alpha value of the pixel.
Very interesting is also the other order scheme of RGBA:
In the word-order scheme, "RGBA" is understood to represent a complete
32-bit word, where R is more significant than G, which is more
significant than B, which is more significant than A. This scheme can
be used to describe the memory layout on a particular system. Its
meaning varies depending on the endianness of the system.
byte[] pixels
not
int[] pixels
try this : Java - get pixel array from image
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class ImageUtil {
public static Color[][] loadPixelsFromImage(File file) throws IOException {
BufferedImage image = ImageIO.read(file);
Color[][] colors = new Color[image.getWidth()][image.getHeight()];
for (int x = 0; x < image.getWidth(); x++) {
for (int y = 0; y < image.getHeight(); y++) {
colors[x][y] = new Color(image.getRGB(x, y));
}
}
return colors;
}
public static void main(String[] args) throws IOException {
Color[][] colors = loadPixelsFromImage(new File("image.png"));
System.out.println("Color[0][0] = " + colors[0][0]);
}
}
I know this has already been answered, but the answers given are a bit convoluted and could use improvement.
The simple idea is to just loop through every (x,y) pixel in the image, and get the color of that pixel.
BufferedImage image = MyImageLoader.getSomeImage();
for ( int x = 0; x < image.getWidth(); x++ ) {
for( int y = 0; y < image.getHeight(); y++ ) {
Color pixel = new Color( image.getRGB( x, y ) );
// Do something with pixel color here :)
}
}
You could then perhaps wrap this method in a class, and implement Java's Iterable API.
class IterableImage implements Iterable<Color> {
private BufferedImage image;
public IterableImage( BufferedImage image ) {
this.image = image;
}
#Override
public Iterator<Color> iterator() {
return new Itr();
}
private final class Itr implements Iterator<Color> {
private int x = 0, y = 0;
#Override
public boolean hasNext() {
return x < image.getWidth && y < image.getHeight();
}
#Override
public Color next() {
x += 1;
if ( x >= image.getWidth() ) {
x = 0;
y += 1;
}
return new Color( image.getRGB( x, y ) );
}
}
}
The usage of which might look something like the following
BufferedImage image = MyImageLoader.getSomeImage();
for ( Color color : new IterableImage( image ) ) {
// Do something with color here :)
}

How can I load a bitmap image and manipulate individual pixels?

I want to load a single large bitmap image from a file, run a function that manipulates individual pixels and then re save the bitmap.
File formats can be either PNG or BMP, and the manipulating function is something simple such as:
if r=200,g=200,b=200 then +20 on all values, else -100 on all values
The trick is being able to load a bitmap and being able to read each pixel line by line
Is there standard library machinery in Java that can handle this I/O?
(The bitmap will need to be several megapixels, I need to be able to handle millions of pixels)
Thanks to MadProgrammer I have an answer:
package image_test;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class Image_test {
public static void main(String[] args) {
BufferedImage img = null;
try {
img = ImageIO.read(new File("test.bmp"));
} catch (IOException e) {
}
int height = img.getHeight();
int width = img.getWidth();
int amountPixel = 0;
int amountBlackPixel = 0;
int rgb;
int red;
int green;
int blue;
double percentPixel = 0;
System.out.println(height + " " + width + " " + img.getRGB(30, 30));
for (int h = 0; h<height; h++)
{
for (int w = 0; w<width; w++)
{
amountPixel++;
rgb = img.getRGB(w, h);
red = (rgb >> 16 ) & 0x000000FF;
green = (rgb >> 8 ) & 0x000000FF;
blue = (rgb) & 0x000000FF;
if (red == 0 && green == 0 && blue == 0)
{
amountBlackPixel ++;
}
}
}
percentPixel = (double)amountBlackPixel / (double)amountPixel;
System.out.println("amount pixel: "+amountPixel);
System.out.println("amount black pixel: "+amountBlackPixel);
System.out.println("amount pixel black percent: "+percentPixel);
}
}

Jpeg DCT and IDCT not calculated properly

I'm trying to calculate DCT and IDCT of an input image, and display the IDCT output as resultant image. But my IDCT values are going above 300. My input image is a '.rgb' image.
I am also considering the height and width of the input image as constant i.e., 352*288
I am representing my input red, green and blue integers of each pixels as rgb[3][64][1583] where [3] -> index of red/green/blue and [64] -> index of pixel in each block and the [1583]->
index of the 8*8 block i.e., one of the block in 1583 blocks.
And lastly im keeping my quantization table as which has uniform value -> 2^N where N is passed as parameter.In this code the quantLevel is the N above.
Following is my Code:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Jpeg {
double rgb[][][]=new double[3][64][1584];
double rgbfinal[][][]=new double[3][64][1584];
double R[][]=new double[64][1584];
double G[][]=new double[64][1584];
double B[][]=new double[64][1584];
public void go(String fname, int quantLevel){
int numBlocks=(352*288)/64;
String fileName = fname;
int width=352,height=288;
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
try {
File file = new File(fname);
InputStream is = new FileInputStream(file);
long len = file.length();
byte[] bytes = new byte[(int)len];
int offset = 0;
int numRead = 0;
while (offset < bytes.length && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
offset += numRead;
}
int ind = 0;
for(int y = 0; y < height; y++){
for(int x = 0; x < width; x++){
byte r = bytes[ind];
byte g = bytes[ind+height*width];
byte b = bytes[ind+height*width*2];
int pix = 0xff000000 | ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff);
img.setRGB(x,y,pix);
ind++;
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
int indexRow=0,indexCol=0,indexBlock=0,indexBits=0,indexPixelBlock=0,indexPixel=0;
long count=0L;
String binary="";
indexPixel=0;
indexBlock=0;
int i=0;
while(count!=(long)(numBlocks*64)){
int pix = img.getRGB(indexCol, indexRow);
int red = (pix >> 16) & 0x000000FF;
int green = (pix >>8 ) & 0x000000FF;
int blue = (pix) & 0x000000FF;
rgb[0][indexPixel][indexBlock]=red;
rgb[1][indexPixel][indexBlock]=green;
rgb[2][indexPixel][indexBlock]=blue;
count++;
indexPixel++;
if(indexCol==width-1 && indexRow==height-1)
break;
if(indexCol%7==0 && indexCol!=0 && indexPixel%8==0)
{
indexPixel=indexPixelBlock;
indexBlock++;
}
if(indexPixel%8==0 && indexCol%7!=0 && indexBlock!=1583)
{
indexPixel=indexPixelBlock;
indexBlock++;
}
if(indexCol==width-1)
{
indexCol=0;
indexRow++;
}
else
indexCol++;
if((indexPixel)%8==0 && indexBlock==numBlocks-1 && indexCol%7==0)
{
indexBlock=0;
indexPixelBlock=indexPixel;
}
}
calcQuantizedDCT(quantLevel);
calcInverseDCT(quantLevel);
JFrame frame = new JFrame();
frame.setLocation(0,0);
frame.setSize(1024, 720);
frame.getContentPane().setBackground(Color.WHITE);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel p=new JPanel();
p.setLayout(new FlowLayout(FlowLayout.LEFT));
p.setLocation(100,100);
JLabel label = new JLabel(new ImageIcon(img));
label.setLocation(0,0);
label.setSize(352,288);
p.add(label);
frame.add(p);
frame.setVisible(true);
return;
}
void calcQuantizedDCT(int quantLevel)
{
String binary="";
int indexBlock=0,indexPixel=0,indexBits=0,red=0,green=0,blue=0,x=0,y=0,indexPixelTemp=0,u=0,v=0;
double sumRed=0,sumGreen=0,sumBlue=0;
String substr="";
int i=0;
for(indexBlock=0;indexBlock<1584;indexBlock++)
{
indexPixel=0;
//
while(indexPixel!=64 && u<8)
{
while(indexPixelTemp<64 && x<8)
{
red=(int)rgb[0][indexPixelTemp][indexBlock];
green=(int)rgb[1][indexPixelTemp][indexBlock];
blue=(int)rgb[2][indexPixelTemp][indexBlock];
// System.out.println(red);
sumRed+=red*Math.cos((Math.PI*(2*y+1)*u)/(2*8))*Math.cos((Math.PI*(2*x+1)*v)/(2*8));
sumGreen+=green*Math.cos((Math.PI*(2*x+1)*u)/(2*8))*Math.cos((Math.PI*(2*y+1)*v)/(2*8));
sumBlue+=blue*Math.cos((Math.PI*(2*x+1)*u)/(16))*Math.cos((Math.PI*(2*y+1)*v)/(16));
indexPixelTemp++;
y++;
if(y==8)
{
x++;
y=0;
}
}
//System.out.println("SumRed :"+sumRed);
if(u==0 && v==0)
{
//System.out.println("U & V & Pixel & Block "+u+" "+v+" "+indexPixel+" "+indexBlock);
R[indexPixel][indexBlock]=(Math.sqrt(1.0/64.0)*sumRed)/Math.pow(2,quantLevel);
G[indexPixel][indexBlock]=(Math.sqrt(1.0/64.0)*sumGreen)/Math.pow(2,quantLevel);
B[indexPixel][indexBlock]=(Math.sqrt(1.0/64.0)*sumBlue)/Math.pow(2,quantLevel);
}
else
{
//System.out.println("U & V & Pixel & Block "+u+" "+v+" "+indexPixel+" "+indexBlock);
R[indexPixel][indexBlock]=(Math.sqrt(2.0/32.0)*sumRed)/Math.pow(2,quantLevel);
G[indexPixel][indexBlock]=(Math.sqrt(2.0/32.0)*sumGreen)/Math.pow(2,quantLevel);
B[indexPixel][indexBlock]=(Math.sqrt(2.0/32.0)*sumBlue)/Math.pow(2,quantLevel);
}
indexPixel++;
if(indexPixel==64)
break;
indexPixelTemp=0;
v++;
if(v==8)
{
v=0;
u++;
}
x=0;y=0;sumGreen=0;sumRed=0;sumBlue=0;
}
u=0;v=0;
}
/* for(int j=0;j<64;j++)
{
System.out.print(R[j][0]+" ");
if(j%7==0 && j!=0)
System.out.println();
}
*/
}
void calcInverseDCT(int quantLevel)
{
String binary="";
int indexBlock=0,indexPixel=0,indexBits=0,u=0,v=0,x=0,y=0,indexPixelTemp=0,sumRed=0,sumGreen=0,sumBlue=0,red=0,green=0,blue=0;
for(indexBlock=0;indexBlock<1584;indexBlock++)
{
for(indexPixel=0;indexPixel<64;indexPixel++)
{
R[indexPixel][indexBlock]=R[indexPixel][indexBlock]*Math.pow(2,quantLevel);
G[indexPixel][indexBlock]=G[indexPixel][indexBlock]*Math.pow(2,quantLevel);
B[indexPixel][indexBlock]=B[indexPixel][indexBlock]*Math.pow(2,quantLevel);
}
}
int i=0;
indexPixelTemp=0;
indexPixel=0;
for(indexBlock=0;indexBlock<1584;indexBlock++)
{
indexPixel=0;
while(indexPixel<64 && x<8)
{
indexPixelTemp=0;
while(indexPixelTemp<64 && u<8)
{
red=(int)R[indexPixelTemp][indexBlock];
if(u==0 && v==0)
sumRed+=Math.sqrt(1.0/2.0)*red*Math.cos((Math.PI*(2*x+1)*u)/(2*8))*Math.cos((Math.PI*(2*y+1)*v)/(2*8));
else
sumRed+=red*Math.cos((Math.PI*(2*x+1)*u)/(2*8))*Math.cos((Math.PI*(2*y+1)*v)/(2*8));
green=(int)G[indexPixelTemp][indexBlock];
if(u==0 && v==0)
sumGreen+=Math.sqrt(1.0/2.0)*green*Math.cos((Math.PI*(2*x+1)*u)/(2*8))*Math.cos((Math.PI*(2*y+1)*v)/(2*8));
else
sumGreen+=green*Math.cos((Math.PI*(2*x+1)*u)/(2*8))*Math.cos((Math.PI*(2*y+1)*v)/(2*8));
blue=(int)B[indexPixelTemp][indexBlock];
if(u==0 && v==0)
sumBlue+=Math.sqrt(1.0/2.0)*blue*Math.cos((Math.PI*(2*x+1)*u)/(2*8))*Math.cos((Math.PI*(2*y+1)*v)/(2*8));
else
sumBlue+=blue*Math.cos((Math.PI*(2*x+1)*u)/(2*8))*Math.cos((Math.PI*(2*y+1)*v)/(2*8));
indexPixelTemp++;
v++;
if(v==8)
{
u++;
v=0;
}
}
rgbfinal[0][indexPixel][indexBlock]=sumRed;
rgbfinal[1][indexPixel][indexBlock]=sumGreen;
rgbfinal[2][indexPixel][indexBlock]=sumBlue;
indexPixel++;
indexPixelTemp=0;
y++;
if(y==8)
{
y=0;
x++;
}
u=0;v=0;sumGreen=0;sumRed=0;sumBlue=0;
}
if(i==3)
break;
x=0;y=0;
}
System.out.println();
/*for(i=0;i<64;i++)
{
System.out.print(rgbfinal[0][i][0]+" ");
if(i%7==0 && i!=0)
System.out.println();
}*/
}
public static void main(String args[]){
Jpeg a = new Jpeg();
a.go("src/image2.rgb",0);
}
}
I am not trying to display the output image as the ouput of IDCT for Red which i checked goes above 255.
Please help.
First, are you hoping the create a JPEG-compatible codec? Or are you just toying with multimedia coding concepts? If the latter, then more power to you. If the former, you have a lot of work ahead.
To directly answer your question: It's normal to transform an 8x8 block using a 2D forward DCT and get numbers that go above 255. Low-level implementations of the forward DCT usually take an 8x8 vector of unsigned 8-bit samples as input and output an 8x8 vector of signed 16-bit samples.
If you actually are hoping to create a JPEG-compatible codec, you still have a few topics to study. For starters, JPEG does not compress RGB. RGB data is converted to YUV and those blocks get transformed (then quantized, zigzagged, and entropy coded).

Categories

Resources