I have 100 images on external memory which i do these two following tasks in a for loop .
Loading every item as a bitmap and merging it with another bitmap
Saving result in as a new file in memory
And for 100 images it takes too much time . Merging bitmaps is quit fast and OK but saving the result in file takes too much time . Is there anyway to boost this issue ? Keeping the bitmaps in memory and batch save files can cause OutOfMemoryException .
This is how i merge bitmaps :
how to merge to two bitmap one over another
This is how i save the bitmap to file :
File imageFileFolder = new File(Statics.TEMP_PATH);
imageFileFolder.mkdirs();
FileOutputStream out = null;
File imageFileName = new File(imageFileFolder, imageName);
try {
out = new FileOutputStream(imageFileName);
imageBitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
out.flush();
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Note that all of these are in a AsyncTask block .
Finally i came with the solution to save Bitmap as jpeg. Saving a 250k png bitmap took almost 500 milliseconds . The same bitmap in jpeg format took about 50 milliseconds. Although the qualities wont be the same but it looks like it is a tradeoff between quality and performance.
Related
I have an android application and I am capturing every frame produced. I want to save each frame to disk. I know I could do video (i.e. using the MediaRecorder), but this is not what I want.
As you can imagine, writing 30 bitmaps to disk per second is pretty slow...
With the frames being produced at run-time, I do not know in advance how many will be produced.
Here is my write to disk function:
public static void store(Bitmap bm, String fileName){
File file = new File(fileName);
try {
FileOutputStream fOut = new FileOutputStream(file);
bm.compress(Bitmap.CompressFormat.PNG, 85, fOut);
fOut.flush();
fOut.close();
} catch (Exception e) {
e.printStackTrace();
}
}
What is the fastest way to save bitmaps to disk?
I am developing a swing application where i am displaying profile information along with their photo, after loading about 120 photos i get the exception
java.lang.OutOfMemoryError: Java heap space
I need to display around 1000+ profile informations.
This is how i load my images onto the jtable
try{
byte[] imageAsByteArray = getImageAsByteArray("E:\\Project\\WinPak\\Database\\UserImage\\"+employee.getLink3().trim()+"-1.jpg");
if(imageAsByteArray != null)
{
InputStream imageInputStream =new ByteArrayInputStream(imageAsByteArray);
Image img = ImageIO.read(imageInputStream);
ImageIcon imgIcon = new ImageIcon(img.getScaledInstance(100,100,Image.SCALE_AREA_AVERAGING));
data[index][10] =imgIcon; // data is of type object which i use to populate the jtable
imageInputStream.close();
}
}
catch(Exception e)
{
e.printStackTrace();
}
public byte[] getImageAsByteArray(String url)
{
try
{
InputStream is = new BufferedInputStream(new FileInputStream(url));
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[16384];
while ((nRead = is.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
buffer.flush();
is.close();
return buffer.toByteArray();
}
catch(Exception e)
{
e.printStackTrace();
return null;
}
}
How do i overcome this problem. Is there any other way to display the information in swing?
If you are not aware of -Xmx command line argument to Java, you should learn about that and try that as a short term workaround. See documentation here.
The larger issue, though, is whether you really need to keep all of these images in memory at the same time. For a table that is displaying images, you might want to load the image only if it is currently supposed to be displayed or in a row near to what is being displayed.
I don't see anything obviously wrong with the way that you are reading the images, but I haven't worked with I/O of images in Java much, so perhaps that could be improved too.
In outline,
Create thumbnail-sized copies of your images, as shown here and here, to make instances of ImageIcon; use a background thread, as shown here, to keep the GUI responsive.
In your TableModel, return ImageIcon from getColumnClass() for the image column; the default renderer will display it automatically.
Use an adjacent component or popup to display the full size image on demand.
I've been searching for some solutions from the internet yet I still haven't found an answer to my problem.
I've been working or doing a program that would get an image file from my PC then will be edited using Java Graphics to add some text/object/etc. After that, Java ImageIO will save the newly modified image.
So far, I was able to do it nicely but I got a problem about the size of the image. The original image and the modified image didn't have the same size.
The original is a 2x3inches-image while the modified one which supposedly have 2x3inches too sadly got 8x14inches. So, it has gone BIGGER than the original one.
What is the solution/code that would give me an output of 2x3inches-image which will still have a 'nice quality'?
UPDATE:
So, here's the code I used.
public Picture(String filename) {
try {
File file = new File("originalpic.jpg");
image = ImageIO.read(file);
width = image.getWidth();
}
catch (IOException e) {
throw new RuntimeException("Could not open file: " + filename);
}
}
private void write(int id) {
try {
ImageIO.write(image, "jpg", new File("newpic.jpg"));
} catch (IOException e) {
e.printStackTrace();
}
}
2nd UPDATE:
I now know what's the problem of the new image. As I check it from Photoshop, It has a different image resolution compared to the original one. The original has a 300 pixels/inch while the new image has a 72 pixels/inch resolution.
How will I be able to change the resolution using Java?
I am trying to get Image object real file size though I don't have opportunity to get this image from HDD to read it with File :S
...OK I write code in this logical direction as
ByteArrayOutputStream tmp = new ByteArrayOutputStream();
try {
ImageIO.write((BufferedImage) image, "png", tmp);
} catch (IOException ex) {
}
Integer contentLength = tmp.size();
tmp.close();
... but the thing is OS shows file size as 65.8KB but tmp.size(); in my case returns 63098 :( I am not pretty sure where the ~2KB do skipped; So my question is how to get Image object real file size?
I'm new to Java. I've been able to read a "raw" image file with short data, display it, and save it as a .jp2 file but the 150.000 byte file gets compressed to just over 50,000 bytes. Some years ago I used a propriatry library to in C/C++ to do this and achieved lossless compression of the same type of images in the range of 10:1.
My image data is in a BufferedImage and I save it thus:
...
// biGray is the BufferedImage and dest the file name
Iterator writers = ImageIO.getImageWritersByFormatName("JPEG2000");
ImageWriter writer = (ImageWriter)writers.next();
try {
ImageIO.write(biGray, "JPEG 2000", dest);
} catch (IOException e) {
e.printStackTrace();
}
Is it possible to get greater lossless reversable compression? How?
Thanks, Nate.