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).
Related
So I'm fairly new to Java, so I'm not sure that this my method of doing this is actually a good idea, but basically I am trying to check for an instance of an image inside another image. So for my testing to see if this would work, I had a 200x148 jpg, got the bytes from that, then got the bytes from a screenshot of the window, and got the bytes from that, and then compared them.
Now, since normally the first image wouldn't be in that screenshot, I opened it in my photos app and put it in while the program was sleeping (before it took the screenshot). And yes, I can confirm that the first image was in the screenshot by looking at the screenshot. However, when I compare the strings (to check if a String with all of the byte data of image one is in a String with all of the byte data of image two), it turns out negative.
Here's the code that I'm trying to use so far:
public static void main(String[] args) throws IOException, HeadlessException, AWTException, InterruptedException {
// Get the first image
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(ImageIO.read(new File("profile.jpg")), "jpg", baos);
byte[] bytes = baos.toByteArray();
String bytes1S = "";
for (int i = 0; i < bytes.length; i++) {
bytes1S += bytes[i];
}
// Give yourself enough time to open the other image
TimeUnit.SECONDS.sleep(6);
// Take the screenshot
BufferedImage image = new Robot().createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));
ImageIO.write(image, "jpg", new File("screenshot.jpg"));
baos = new ByteArrayOutputStream();
ImageIO.write(ImageIO.read(new File("screenshot.jpg")), "jpg", baos);
byte[] bytes2 = baos.toByteArray();
String bytes2S = "";
for (int i = 0; i < bytes2.length; i++) {
bytes2S += bytes2[i];
}
// Check if the second String of bytes contains the first String of bytes.
if (bytes2S.contains(bytes1S))
System.out.println("Yes");
else
System.out.println("No");
}
And for reference, here's the first image, and the screenshot that it took:
What's the reason behind it not detecting the first image in the screenshot, and is there a better way to do this (preferably without another library)?
A brute-force approach is to simply load both images as BufferedImage objects, and then walk through the "main" image, pixel by pixel, and see if the "sub image" can be found there.
I have implemented this a while ago, and will post the code below as a MCVE.
But note: When you save images as JPG files, then they are compressed, and this compression is lossy. This means that the pixels will not have the perfectly same colors, even if they have been equal on the screen. In the example below, this is solved pragmatically, with a "threshold" that defines how different the pixels may be. But this is a bit arbitrary and not so reliable. (A more robust solution would require more effort).
I'd strongly recommend to save the images as PNG files. They use a lossless compression. So for PNG files, you can set threshold=0 in the code below.
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.net.URL;
import java.util.function.IntBinaryOperator;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class FindImageInImage
{
public static void main(String[] args) throws Exception
{
BufferedImage mainImage =
ImageIO.read(new URL("https://i.stack.imgur.com/rEouF.jpg"));
BufferedImage subImage =
ImageIO.read(new URL("https://i.stack.imgur.com/wISyn.jpg"));
int threshold = 100;
Point location = findImageLocation(
mainImage, subImage, threshold);
System.out.println("At " + location);
SwingUtilities.invokeLater(() -> showIt(mainImage, subImage, location));
}
private static void showIt(
BufferedImage mainImage, BufferedImage subImage, Point location)
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(new JPanel()
{
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(mainImage, 0, 0, null);
if (location != null)
{
g.setColor(Color.RED);
g.drawRect(location.x, location.y,
subImage.getWidth(), subImage.getHeight());
}
}
});
f.setSize(1500, 800);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
static Point findImageLocation(
BufferedImage mainImage,
BufferedImage subImage,
int threshold)
{
return findImageLocation(mainImage, subImage, (rgb0, rgb1) ->
{
int difference = computeDifference(rgb0, rgb1);
if (difference > threshold)
{
return 1;
}
return 0;
});
}
private static int computeDifference(int rgb0, int rgb1)
{
int r0 = (rgb0 & 0x00FF0000) >> 16;
int g0 = (rgb0 & 0x0000FF00) >> 8;
int b0 = (rgb0 & 0x000000FF);
int r1 = (rgb1 & 0x00FF0000) >> 16;
int g1 = (rgb1 & 0x0000FF00) >> 8;
int b1 = (rgb1 & 0x000000FF);
int dr = Math.abs(r0 - r1);
int dg = Math.abs(g0 - g1);
int db = Math.abs(b0 - b1);
return dr + dg + db;
}
static Point findImageLocation(
BufferedImage mainImage,
BufferedImage subImage,
IntBinaryOperator rgbComparator)
{
int w = mainImage.getWidth();
int h = mainImage.getHeight();
for (int x=0; x < w; x++)
{
for (int y = 0; y < h; y++)
{
if (isSubImageAt(mainImage, x, y, subImage, rgbComparator))
{
return new Point(x, y);
}
}
}
return null;
}
static boolean isSubImageAt(
BufferedImage mainImage, int x, int y,
BufferedImage subImage,
IntBinaryOperator rgbComparator)
{
int w = subImage.getWidth();
int h = subImage.getHeight();
if (x + w > mainImage.getWidth())
{
return false;
}
if (y + h > mainImage.getHeight())
{
return false;
}
for (int ix=0; ix < w; ix++)
{
for (int iy = 0; iy < h; iy++)
{
int mainRgb = mainImage.getRGB(x + ix, y + iy);
int subRgb = subImage.getRGB(ix, iy);
if (rgbComparator.applyAsInt(mainRgb, subRgb) != 0)
{
return false;
}
}
}
return true;
}
}
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.
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()) ;
}
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);
}
}
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.*;
import java.io.*;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Video implements ActionListener
{
static int width=480;
static int height=368;
static JFrame frame = new JFrame();
static JButton button = new JButton("Submit");
static BufferedImage img = new BufferedImage((int) (width), (int) (height), BufferedImage.TYPE_INT_RGB);
static BufferedImage img1[] = new BufferedImage[60];
static {
for (int i = 0; i < img1.length; i++) {
img1[i] = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
}
}
public static void main(String[] args)
{
Video V1 = new Video();
String fileName = args[0];
try {
File file = new File(fileName);
InputStream is = new FileInputStream(file);
long len = file.length();
byte[] bytes = new byte[(int)len];
int offset = 0;
int numRead = 0;
int ind =0;
int[][] pixarray=new int[height+100][width+100];
int[][] red=new int[width*2][height*2];
int[][] green=new int[width*2][height*2];
int[][] blue=new int[width*2][height*2];
while (offset < bytes.length && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
offset += numRead;
}
for(int frames=0;frames<60;frames++)
{
ind=height*width*frames*3;
for(int y = 0; y < height; y++)
{
for(int x = 0; x < width; x++)
{
byte a = 0;
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);
pixarray[y][x]=pix;
red[y][x] = (pix >>> 16) & 0xff;
green[y][x] = (pix >>> 8) & 0xff;
blue[y][x] = pix & 0xff;
img1[frames].setRGB(x,y,pix);
ind++;
}
}
}
}
catch (IOException e) {
e.printStackTrace();
}
JLabel label = new JLabel(new ImageIcon(img1[50]));
frame.setLayout(new FlowLayout());
//frame.setSize(200,100);
frame.setVisible(true);
// Button button = new Button("Submit");
// frame.add(button);
frame.getContentPane().add(label, BorderLayout.CENTER);
frame.getContentPane().add(button, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
button.addActionListener(V1);
}
public void actionPerformed(ActionEvent e) {
System.out.println("1");
for(int i=0;i<img1.length;i++)
{
try {
Thread.sleep(500);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.println(img1.length);
}
}
}
Is my code. My img1 is an array of frames. in this instance my video has 60 frames.
I wanna add each frame to my panel with a time gap. i am unable to do it because every time i add it to the panel in my ActionEvent its acting weird. help me out please.
Use a Swing Timer (not a TimerTask). When the Timer fires the code will execute in the EDT so you can safely reset the icon of your JLabel. So I would first create ImageIcons from your BufferedImages and store the Icons in your array.
Read the secton from the Swing tutorial on How to Use Timers for more information. You may also want to check out the section on Concurreny to understand why executing code in the EDT is important.
You can create a TimerTask
class VideoTask extends TimerTask {
private Frame frame;
private int frameId;
public void run() {
frame.drawImage(....);
frameId++;
}
}
And in the action listener for the button - schedule the task:
VideoTask videoTask = new VideoTask(frame);
videoTask.schedule(..);