Combining PNG Images Java - java

I am trying to loop through a file of png images and stitch them together to form one image. I have gotten it to work without using a for loop and just combining two images from the file. So I am assuming it is the looping that isn't working. The images are located in a file called "images".
I would appreciate your input!
File file = new File("images");
File [] moreFile = file.listFiles();
String [] images = new String [moreFile.length];
for(int i =0; i <images.length; i++)
{images[i] = moreFile[i].getName();
}
int x = 0;
int y = 0;
BufferedImage result = new BufferedImage(
controller.getSize().width*2, controller.getSize().height, //work these out
BufferedImage.TYPE_INT_RGB);
Graphics g = result.getGraphics();
for(String image : images){
System.out.println(image);
File path = new File("images");
try{ImageIO.read(new File(path, image));
System.out.println("it definitely goes here");
BufferedImage bi = new BufferedImage((2*510),(2*439),BufferedImage.TYPE_INT_ARGB);
bi =ImageIO.read(new File(path, image));
g.drawImage(bi, x, y, null);
g.dispose();
/// System.out.println(dafuck);
x += bi.getWidth();
if(x > result.getWidth()){
x = 0;
y += bi.getHeight();
}
}catch (Exception e) {
System.out.println("is it an exception>?");
}
}
try {
ImageIO.write(result,"png",new File("results"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

Related

NullPointerException when convert and save Image file on Android device

I'm trying to save a Image type data as a jpg file to SD card, what I plan to do is first converting it to Bitmap, compress bitmap as jpeg format, then use FileOutputStream to save it to SD card.
Here's my code:
File imagefile = new File(sdCardPath, "image.jpg");
Image image = fromFrame.getImage();
ByteBuffer bbuffer = image.getPlanes()[0].getBuffer();
byte[] byts = new byte[bbuffer.capacity()];
bbuffer.get(byts);
Bitmap bitmapImage = BitmapFactory.decodeByteArray(byts, 0, byts.length, null);
try{
FileOutputStream out = new FileOutputStream(imagefile);
bitmapImage.compress(Bitmap.CompressFormat.JPEG, 100, out);
out.flush();
out.close();
} catch (FileNotFoundException e) {
Log.v(TAG, "FileNotFoundExceptionError " + e.toString());
} catch (IOException e) {
Log.v(TAG, "IOExceptionError " + e.toString());
}
It gives error:
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean
android.graphics.Bitmap.compress(android.graphics.Bitmap$CompressFormat,
int, java.io.OutputStream)' on a null object reference
Is there anything I missed or did it wrong?
It turns out that the image file has to be re-organized and as for Depth16 file, every pixel has 16 bits of data, so the code to convert it into a jpg file is:
Image depthimage = fromFrame.getImage();
int imwidth = depthImage.getWidth();
int imheight = depthImage.getHeight();
Image.Plane plane = depthImage.getPlanes()[0];
ShortBuffer shortDepthBuffer = plane.getBuffer().asShortBuffer();
File sdCardFile = Environment.getExternalStorageDirectory();
File file = new File(sdCardFile, "depthImage.jpg");
Bitmap disBitmap = Bitmap.createBitmap(imwidth, imheight, Bitmap.Config.RGB_565);
for (int i = 0; i < imheight; i++) {
for (int j = 0; j < imwidth; j++) {
int index = (i * imwidth + j) ;
shortDepthBuffer.position(index);
short depthSample = shortDepthBuffer.get();
short depthRange = (short) (depthSample & 0x1FFF);
byte value = (byte) depthRange ;
disBitmap.setPixel(j, i, Color.rgb(value, value, value));
}
}
Matrix matrix = new Matrix();
matrix.setRotate(90);
Bitmap rotatedBitmap = Bitmap.createBitmap(disBitmap, 0, 0, imwidth, imheight, matrix, true);
try {
FileOutputStream out = new FileOutputStream(file);
rotatedBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
MainActivity.num++;
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
I also rotate the picture to make it easier to review on mobile devices

Unknown 16 bit gray image file format with no header

i only got the image data with NO header informations but i know several things like:
16 bit grayscale data
1200x1200 (although its 1200x900 but its likely to have a "bar" at the buttom)
the data are 2880000 bytes in size which fits 1200x1200 x 2bytes ->short
here is the raw image data
for visualizing i use this:
public static void saveImage(short[] pix, int width, int height, File outputfile) {
ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
int[] nBits = {16};
ComponentColorModel cm = new ComponentColorModel(cs, nBits,false, false, Transparency.OPAQUE, DataBuffer.TYPE_USHORT);
SampleModel sm = cm.createCompatibleSampleModel(width, height);
DataBufferShort db = new DataBufferShort(pix, width*height);
WritableRaster raster = Raster.createWritableRaster(sm, db, null);
BufferedImage bf = new BufferedImage(cm, raster, false, null);
if(outputfile!=null)
try {
if(!ImageIO.write(bf, "png", outputfile)) System.out.println("No writer found.");
System.out.println("Saved: "+outputfile.getAbsolutePath());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
else System.out.println("error");
}
The data are read like this (only experimental/bad code, its only for testing):
for(int tt=1; tt<20; tt++) {
pix = new short[1200*1200];
i = 0;
int z = 0;
int line = 0;
//loop
while(i<(1200*1200)) {
pix[i++] = buffer.getShort(z);
z += tt;
if(z>=(len-1)) {
line += 2;
z = line;
if(z>=(len-1)) {
System.out.println("break at "+z);
break;
}
System.out.println("test "+line);
}
}
System.out.println("img_"+imgcount+".png "+pix.length);
saveImage(pix, 1200, 1200, new File("img_"+imgcount+"_"+tt+".png"));
}
Where i can see something for tt=4,8,16 (images get multiplied) but i cant realy get the whole picture.image tt=8 image tt=16
Its like the solution is in front of me but i cant see it xD
Can someone help me with the algorithm/format the image is stored?
EDIT: Reading data consecutively with:
short[] pix = new short[1200*1200];
int i = 0;
while(i< (1200*1200) && buffer.remaining()>0) {
pix[i++] = buffer.getShort();
}
results in: noisy picture
EDIT 2:
Ok looks like its base64 encoded which makes sense due its stored in a xml file
I finaly solved it, its base64 encoded and little endian (thanks RealSkeptic for hinting to try little/big endian).

binary data image conversion does not equal jpg of the same image

I am trying to compare an embedded image located in a MP3 file with the exact same image saved as a JPG. If the images are identical then I would like to perform some further processing, however, when I compare the 2 images (RGB comparison) I keep getting false.
I am sure that the images are identical because I extracted the image from the same MP3 to originally create the JPG using the following code.
Artwork aw = tag.getFirstArtwork();
ByteArrayInputStream bis = new ByteArrayInputStream(aw.getBinaryData());
BufferedImage imgA = ImageIO.read(bis);
File outputfile = new File("expectedImage.jpg");
ImageIO.write(imgA, "jpg", outputfile);
After I ran that to get the image I just commented out that section, now I have the following code in place to compare the MP3 embedded image with the JPG
Extract the MP3 image and call the comparison method
try {
Artwork aw = tag.getFirstArtwork();
ByteArrayInputStream bis = new ByteArrayInputStream(aw.getBinaryData());
BufferedImage imgA = ImageIO.read(bis);
File expectedImageFile = new File("expectedImage.jpg");
BufferedImage imgB = ImageIO.read(expectedImageFile);
if(compareImages(imgA, imgB)) {
System.out.println("The Images Match.");
}else {
System.out.println("The Images Do Not Match.");
}
}
catch (IOException e) {
e.printStackTrace();
}
Compare The Images
The method fails when comparing the pixels for equality on the first pass through the loop.
public static boolean compareImages(BufferedImage imgA, BufferedImage imgB) {
// The images must be the same size.
if (imgA.getWidth() != imgB.getWidth() || imgA.getHeight() != imgB.getHeight()) {
return false;
}
int width = imgA.getWidth();
int height = imgA.getHeight();
// Loop over every pixel.
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
// Compare the pixels for equality.
if (imgA.getRGB(x, y) != imgB.getRGB(x, y)) {
return false;
}
}
}
return true;
}
I try you code and read the #Sami Kuhmonen comment and I understand.
When you use ImageIO.write(imgA, "jpg", outputfile) you pass by an other encoder and you can loss data.
You need change this by the standard technique.
Example [UPDATED]
public static void main(String[] args) {
try {
//Write the picture to BAOS
ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
byteBuffer.write(aw.getBinaryData(), 0, 1);
//New file target
File outputfile = new File("expectedImage.jpg");
OutputStream outputStream = new FileOutputStream(outputfile);
byteBuffer.writeTo(outputStream);
outputStream.close();
File expectedImageFile = new File("expectedImage.jpg");
ByteArrayInputStream bis = new ByteArrayInputStream(aw.getBinaryData());
BufferedImage imgA = ImageIO.read(bis);
FileInputStream fis = new FileInputStream(expectedImageFile);
BufferedImage imgB = ImageIO.read(fis);
if(compareImages(imgA, imgB)) {
System.out.println("The Images Match.");
}else {
System.out.println("The Images Do Not Match.");
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static boolean compareImages(BufferedImage imgA, BufferedImage imgB) {
// The images must be the same size.
if (imgA.getWidth() != imgB.getWidth() || imgA.getHeight() != imgB.getHeight()) {
return false;
}
int width = imgA.getWidth();
int height = imgA.getHeight();
// Loop over every pixel.
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
// Compare the pixels for equality.
if (imgA.getRGB(x, y) != imgB.getRGB(x, y)) {
return false;
}
}
}
return true;
}
I've been a little busy lately, but I finally got a chance to look back into this today and based on what was said above I figured that the main issue was that the image was being compressed in one case and in the other it wasn't. I am sure there is a better solution but a quick dirty fix was to just save a temporary JPEG version of the image that I would like to check for, then do the comparison using 2 buffered images, one that reads in the JPEG file I have saved to the directory and one that reads in the temp JPEG I just created and when the test is complete just use the File.delete() to remove the temp file.
Extract the MP3 image and call the comparison method
The Compare method is the same as originally stated
Artwork aw = tag.getFirstArtwork();
ByteArrayInputStream bis = new ByteArrayInputStream(aw.getBinaryData());
BufferedImage tempImg = ImageIO.read(bis);
File tempFile = new File("temp.jpg");
ImageIO.write(tempImg, "jpg", tempFile);
BufferedImage imgA = ImageIO.read(tempFile);
File expectedImageFile = new File("imgToCheckAgainst.jpg");
BufferedImage imgB = ImageIO.read(expectedImageFile);
if(compareImages(imgA, imgB)) {
System.out.println("The Images Match");
}else {
System.out.println("The images do not match.");
}
tempFile.delete();

java bufferedimage array data immediately changes

import javax.imageio.ImageIO;
import org.bytedeco.javacv.FFmpegFrameGrabber;
public class FrameData
{
int count = 0;
int picWidth;
int picHeight;
BufferedImage img = null;
//GET FRAME COUNT
public int gf_count(int numofFrames, BufferedImage[] frameArray, String fileLocationsent, String videoNamesent) throws IOException
{
String fileLocation = fileLocationsent;
String videoName = videoNamesent;
int frameNums = numofFrames;
int totFrames = 0;
FFmpegFrameGrabber grab = new FFmpegFrameGrabber(fileLocation + videoName);
try { grab.start(); }
catch (Exception e) { System.out.println("Unable to grab frames"); }
for(int i = 0 ; i < frameNums ; i++)
{
try
{
frameArray[i]= grab.grab().getBufferedImage();
totFrames = i;
File outputfile = new File(fileLocation + "GrayScaledImage" + i + ".jpg");
ImageIO.write(frameArray[i], "jpg", outputfile);
}
catch (Exception e) { /*e.printStackTrace();*/ }
}//END for
return totFrames;
}//END METHOD long getFrameCount()
Hope someone can explain this to me...
I am just learning java so here goes...
I wrote this code to count the number of frames in a .mov file and to test my buffered image array I generated files of the images. As the code is, it works as planned... The problem is immediately after the capturing, if I send the bufferedimages out as files, they all seem to be just the first image. see example below...
for(int i = 0 ; i < frameNums ; i++)
{
try
{
frameArray[i]= grab.grab().getBufferedImage();
totFrames = i;
File outputfile = new File(fileLocation + "GrayScaledImage" + i + ".jpg");
ImageIO.write(frameArray[i], "jpg", outputfile);
}
catch (Exception e) { /*e.printStackTrace();*/ }
}//END for
And now if I change that to...
for(int i = 0 ; i < frameNums ; i++)
{
try
{
frameArray[i]= grab.grab().getBufferedImage();
totFrames = i; catch (Exception e) { /*e.printStackTrace();*/ }}
for(int j = 0; j < frameNums; j++)
{
File outputfile = new File(fileLocation + "GrayScaledImage" + j + ".jpg");
ImageIO.write(frameArray[j], "jpg", outputfile);
}
I don't understand why I am getting the same image repeatedly.
If further information Is required, just lemme know, this is my first programming question online... Usually find what I am looking for that others have asked. Couldn't find this one.
Thanks for your time
Ken
The problem is that the grab().getBufferedImage() does its work in the same buffer every time. When you assign a reference to that buffer in your loop, you are assigning a reference to the same buffer numofFrames times. What you are writing then is not the first frame, but the last frame. In order to fix this you need to do a "deep copy" of the BufferedImage. See code below:
public class FrameData {
BufferedImage img;
Graphics2D g2;
// GET FRAME COUNT
public int gf_count(int numFrames, BufferedImage[] frameArray, String fileLocation, String videoName) throws Exception, IOException {
Java2DFrameConverter converter = new Java2DFrameConverter();
int totFrames = 0;
img = new BufferedImage(100, 50, BufferedImage.TYPE_INT_ARGB);
g2 = img.createGraphics();
FFmpegFrameGrabber grab = new FFmpegFrameGrabber(fileLocation + videoName);
grab.start();
for (int i = 0; i < numFrames; i++) {
frameArray[i] = deepCopy(converter.convert(grab.grab()));
totFrames = i;
}
for (int j = 0; j < totFrames; j++) {
File outputfile = new File(fileLocation + "TImage" + j + ".jpg");
ImageIO.write(frameArray[j], "jpg", outputfile);
}
return totFrames;
}// END METHOD long getFrameCount()
BufferedImage deepCopy(BufferedImage bi) {
ColorModel cm = bi.getColorModel();
boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
WritableRaster raster = bi.copyData(null);
return new BufferedImage(cm, raster, isAlphaPremultiplied, null);
}
// This does what the converter.convert seems to do, which
// is decode an image into the same place over and over.
// if you don't copy the result every time, then you end up
// with an array of references to the same last frame.
BufferedImage draw() {
g2.setColor(new Color(-1));
g2.fillRect(0, 0, 100, 50);
g2.setColor(new Color(0));
g2.drawLine(0, 0, (int)(Math.random()*100.0), (int)(Math.random()*50.0));
return img;
}
public static void main(String... args) throws Exception, IOException {
new FrameData().run();
}
private void run() throws Exception, IOException {
BufferedImage images[] = new BufferedImage[50];
gf_count(50, images, "C:/Users/karl/Videos/", "dance.mpg");
}
}
I have included a draw() method that shows by example how work is done in the same BufferedImage repeatedly, in case you want to replicate the problem.
There are certainly other ways to do a deep copy and there may be issues with the one shown. Reference: How do you clone a BufferedImage.
PS> I updated the code to use the 1.1 version of the bytedeco library.

Cant use setRGB() to write to png

public static void main(String[] args) {
String finalHex = "";
String input = "Hello There Sir.";
int pixelX = -1;
int pixelY = 0;
try{
BufferedImage bi = new BufferedImage(64, 64, BufferedImage.TYPE_INT_ARGB);
File out = new File("saved.png");
if(out.exists()==false){
ImageIO.write(bi, "png", out);
System.out.println("PNG WAS CREATED");
}else
System.out.println("ERROR: PNG WAS ALREADY THERE");
for (int i = 0;i < input.length(); i++){
char result = input.charAt(i);
int ascii = (int) result;
String num = Integer.toHexString(ascii).toUpperCase();
if(finalHex.length()==6){
System.out.println(finalHex);
pixelX += 1;
finalHex=("#"+finalHex);
Color c = Color.decode(finalHex);
int rgb = c.getRGB();
System.out.println(rgb);
if(pixelX==63){
pixelX=0;
pixelY+=1;
}
bi.setRGB(pixelX, pixelY, rgb);
finalHex="";
}
finalHex+=num;
}
}catch(IOException e){
System.out.println("ERROR: WELP... SOMETHING SCREWED UP.");
}
}
I am trying to use this to convert text into a png image but I cant get it to write to a png file. I am not that experienced in this area so if anyone could help me out i would be very much appreciated. :)
you should add ImageIO.write(bi, "png", out); after the end of for(int i = 0;i < input.length(); i++){...} this program will write some colored pixels is that what you want??
example:
result picture

Categories

Resources