I need to decode an .png image to use it as a base to create some Rects and to use the image itself as a background for my application, but the try-catch keeps throwing me a Null Pointer Exception, this is the code:
try {
InputStream is = ParamsSingleton.assetManager.open("background.png");
figure = BitmapFactory.decodeStream(is);
height = figure.getHeight();
width = figure.getWidth();
src = new Rect(0, 0, width, height);
first = new Rect();
} catch (IOException e) {
Log.d(TAG, "Image decode fail!");
}
I've tried some logs and the try-catch break right on the InputStream line and prints the 'Log.d' in catch block, I checked the file name and it is alright.
You can directly use getAssets.open method inside decodeStream .
figure = BitmapFactory.decodeStream(getAssets.open("background.png"));
Related
I've managed to make a LineFollower program; added the feature of "memorizing" the path the robot just followed.
The next step is to draw that path and save the image file in the brick and read it in the PC with the NxjBrowse.
I thought I'd try using the classic java method, with BufferedImage and saving with ImageIO, but it didn't work and it kept giving me Java Heap Space:
My previous question
After that, I've made some research and found that there's a class called javax.microedition.lcdui.Image, so I've created an Image object and used GetGraphics and tried to draw on it; and save it using FileOutputStream, here's my code:
Image img = Image.createImage(300, 300);
Graphics g = img.getGraphics();
g.drawLine(0, 0, 100, 200);
File monFichier = new File("Image2.png");
FileOutputStream fOut = null;
try {
fOut = new FileOutputStream(monFichier);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
byte[] b = img.getData();
try {
fOut.write(b);
fOut.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
The problem is that it writes on the file which is not recognized as an image, when I connect to my PC; I can't open the created file (checked the size, not empty).
I don't know if the saving is wrong or the method i'm using to draw is wrong.
Short version of the question: How to draw lines with Lejos and save the resultat as an image file?
Thank you.
UPDATE:
I used an ImageOutputStream instead of FileOutputStream; and now it's giving me "Java Heap Space" error; after it got stuck in "linking" for a while.
Java Heap Space
Java.lang.OutOfMemoryError
Image.getData() is an access to the underlying DataBuffer and not a valid PNG or BMP image.
Try ImageIO.write(img, "png", outputfile).
I have a problem with Java application, particular in loading a image from a location in my computer.
Following this post I used a BufferedImage and a InputFileStream to load an image on my computer. First, I put the image (pic2.jpg) into the source code and that is working. However, if I put the image to another place (let's say C:\\ImageTest\pic2.jpg), Java IDE show me an IllegalArgumentException
return ImageIO.read(in);
here is the code:
public class MiddlePanel extends JPanel {
private BufferedImage img;
public MiddlePanel(int width) {
//img = getImage("pic2.jpg");
img = getImage("C:\\ImageTest\\pic2.jpg");
this.setPreferredSize(new Dimension(800,460));
}
public void paintComponent(Graphics g) {
// ...
}
private BufferedImage getImage(String filename) {
// This time, you can use an InputStream to load
try {
// Grab the InputStream for the image.
InputStream in = getClass().getResourceAsStream(filename);
// Then read it.
return ImageIO.read(in);
} catch (IOException e) {
System.out.println("The image was not loaded.");
//System.exit(1);
}
return null;
}
}
To read an .jpg file from non-relative path you could use this:
BufferedImage img = null;
try
{
img = ImageIO.read(new File("C:/ImageTest/pic2.jpg")); // eventually C:\\ImageTest\\pic2.jpg
}
catch (IOException e)
{
e.printStackTrace();
}
I do not have any Java environment at the moment, so hope it works and is written correctly.
getResource & getResourceAsStream do not work with file paths, but paths relative the code base. If the code base is C: then a relative path that would locate the resource is /ImageTest/pic2.jpg.
..difference between load file by FileInputStream and getResourceAsStream?
One major difference is that the getResource.. will work with a resource inside a Jar, which is no longer a File. Therefore FileInputStream cannot be used to access such a resource.
You cannot use Class#getResource(String) or Class#getResourceAsStream(String) in this case. The rules for searching resources associated with a given class are implemented by the defining class loader of the class. This method delegates to this object's class loader. If this object was loaded by the bootstrap class loader, the method delegates to ClassLoader.getSystemResourceAsStream(java.lang.String).
Before delegation, an absolute resource name is constructed from the given resource name using this algorithm:
If the name begins with a / (\u002f), then the absolute name of the resource is the portion of the name following the /.
Otherwise, the absolute name is of the following form:
modified_package_name/name
Where the modified_package_name is the package name of this object with / substituted for . (\u002e).
Generally, it is not a good thing to hard code the system location of your resources in your code. The neat and clean way is to put your resources in your classpath and access them. Hope this clarifies why it's not working
//This code snippet read an image from location on the computer and writes it to a different location on the disk
try {
byte[] imageInByte;
BufferedImage imageOnDisk = ImageIO.read(new File("C:\\ImageTest\\pic2.jpg"));
//Create a ByteArrayOutputStrea object to write image to
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//Write the image to the OutputStream
ImageIO.write(imageOnDisk, "jpg", baos);
baos.flush();
//Initialise the byte array object with the image that was written to the OutputStream
imageInByte = baos.toByteArray();
baos.close();
// convert byte array back to BufferedImage
InputStream in = new ByteArrayInputStream(imageInByte);
BufferedImage bImageFromConvert = ImageIO.read(in);
//write the image to a new location with a different file name(optionally)
ImageIO.write(bImageFromConvert, "jpg", new File(
"c:\\index.jpg"));
} catch (IOException e) {
e.printStackTrace();
}
To find the image Width, height and size
BufferedImage image = null;
int imageWidth = -1;
int imageHeight = -1;
int fileSize = -1;
try {
File imageFile = new File(imagePath);
int fileSize = (int) imageFile.length();
image = ImageIO.read(imageFile); // Reading the Image from the file system
imageWidth = image.getWidth();
imageHeight = image.getHeight();
} catch (IOException e) {
e.printStackTrace();
}
I am working with Java and combine two images. I save the combined image and want to delete the overlay, but it seems there are still streams open. And i don't know which and how to close them.
f_overlay and f_image are both Files.
// load source images
BufferedImage image = null;
BufferedImage overlay = null;
try {
log.debug(f_image.getAbsolutePath());
log.debug(f_overlay.getAbsolutePath());
image = ImageIO.read(f_image);
overlay = ImageIO.read(f_overlay);
} catch (IOException e) {
log.error(e.getMessage());
}
// create the new image, canvas size is the max. of both image sizes
int w = Math.max(image.getWidth(), overlay.getWidth());
int h = Math.max(image.getHeight(), overlay.getHeight());
BufferedImage combined = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
// paint both images, preserving the alpha channels
Graphics g = combined.getGraphics();
g.drawImage(image, 0, 0, null);
g.drawImage(overlay, 0, 0, null);
// Save as new image
try {
ImageIO.write(combined, "PNG", f_image);
} catch (IOException e) {
log.error(e.getMessage());
}
// we can delete the overlay now
log.debug("Delete overlay: " + f_overlay.delete());
Are there any suggestions?
I can't see anything wrong in your code.
However, I would only delete the file f_overlay if the reading was successful. Important, after you call delete() on the file object, you must not use the object for anything else, so best is to assign f_overlay=null
boolean state = f_overlay.delete();
f_overlay=null;
log.debug("Delete ... "+state);
SOLUTION
Thanks to #ChandraSekhar's suggestions the issue was that I was passing in an Immutable Bitmap to the canvas constructor. The solution is to create a copy of it when using BitmapFactory.decodeFile();
Bitmap bmp = BitmapFactory.decodeFile(imageURL).copy(Bitmap.Config.ARGB_8888, true);
So I have a bitmap that I am using bitmapFactory.decodeFile() for and this works. I am able to create the bitmap, then I need to create a canvas and this is where things get weird.
Here's the flow of what is happening.
I capture an image, then pass it to functionA that sizes it, and saves it out and returns its file path. ( I am using Phonegap Cordova )
I then pass that URL back to my java and use the previously saved image and manipulate it in functionB
CODE IN QUESTION:
// GET URL TO IMAGE
final JSONObject options = optionsArr.optJSONObject(0);
String imageURL = options.optString("image");
// create image bitmap
Bitmap bmp = BitmapFactory.decodeFile(imageURL);
bmp = Bitmap.createBitmap(bmp,0,0,655,655);
/* Everything works fine until this point */
// create image canvas
Canvas canvas = new Canvas(bmp);
Bitmap one = Bitmap.createBitmap(bmp);
canvas.drawBitmap(one,0,0,null);
I receive no errors, it just hangs. Here's the kick in the pants - if I run another function say functionB first that one works but the other doesn't.
I thought maybe I needed to flush and close my first FileOutputStream, but that didn't seem to have any effect. I've tried different variable names for all elements, bitmaps, canvas, and fileoutputstreams.
here is an example of the full function...
NOTE: Because I am using phonegap / cordova I am returning a string
public String none(JSONArray optionsArr) {
// SET FILE PATH
String filePath = "";
File path = new File(Environment.getExternalStorageDirectory()+"/myApp/");
// TMP.jpg is where we store our temporary version of the image
File NewFilePath = new File(path, "tmp_NBB.jpg");
// CREATE FOLDERS IF NEEDED
try{
boolean success = false;
if(!path.exists()){
success = path.mkdir();
}
if (!success){
Log.d("NONE","Folder not created.");
}
else{
Log.d("NONE","Folder created!");
}
}
catch (Exception e){
e.printStackTrace();
}
// GET URL TO IMAGE
final JSONObject options = optionsArr.optJSONObject(0);
String imageURL = options.optString("image");
// create image bitmap
Bitmap bmp = BitmapFactory.decodeFile(imageURL);
bmp = Bitmap.createBitmap(bmp,0,0,655,655);
// create image canvas
Canvas canvas = new Canvas(bmp);
Bitmap none = Bitmap.createBitmap(bmp);
canvas.drawBitmap(none,0,0,null);
// SAVE IMAGE
try {
// OUTPUT STREAM
FileOutputStream out = new FileOutputStream(NewFilePath);
none.compress(Bitmap.CompressFormat.JPEG, 100, out);
// GET FILE PATH
Uri uri = Uri.fromFile(NewFilePath);
filePath = uri.toString();
try{
out.flush();
out.close();
// RETURN FILE PATH
return filePath;
}
catch (Exception e){
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
return filePath;
}
Like I said this works for the first image, but when I attempt to open this image again, based on the returned filepath it chunks out at the create canvas line.
edit: The image path I am using looks like this:
/mtn/sdcard/myApp/tmp.jpg
thoughts?
Bitmap one = Bitmap.createBitmap(bmp);
In the above code bmp is a Bitmap and you are creating another Bitmap object one from bmp.
Remove that line and try by changing
canvas.drawBitmap(one,0,0,null);
to
canvas.drawBitmap(bmp,0,0,null);
Are you sure, the device on which you are running supports image size:655x655? Does bitmap get created?
I've to make a parallel image processing script in java, the idea is to divide the images into tiles of any size, process them, and reassemble the final image.
For now i've created a function:
public static BufferedImage readImg (String path, int startx, int starty, int w, int h)
that returns the region of an image as BufferedImage, then i'll process it and i want to place that region in the correct position of the final image.
So i've tried to make a function writeImg that uses replacePixels method to write just in the correct position without loading the whole image into memory:
public static void writeImg (String path, int startx, int starty, BufferedImage image){
File output = new File(path);
ImageOutputStream ios = null;
try {
ios = ImageIO.createImageOutputStream(output);
} catch (IOException e){
e.printStackTrace();
}
Iterator iter = ImageIO.getImageWritersByFormatName("JPEG");
ImageWriter writer = (ImageWriter)iter.next();
writer.setOutput(ios);
try{
if(writer.canReplacePixels(0)){
System.out.println("True");
}else{
System.out.println("False");
}
}catch (IOException e) {
e.printStackTrace();
}
ImageWriteParam param = writer.getDefaultWriteParam();
Point destinationOffset = new Point(startx,starty);
param.setDestinationOffset(destinationOffset);
try {
writer.replacePixels(image, param);
} catch (IOException e) {
e.printStackTrace();
}
}
The problem is that canReplacePixels is always set as false, and i've no idea what should i use to do that.
The images can be very big so it's impossible to load the whole image in memory as it will cause a OutOfMemory exception.
As long as you are fine with an 24 bit PNG file as output I have a working solution for you (under GPL license):
The class PngXxlWriter allows to write PNG files "line by line". That means that you can write an image of 10000x10000 (width * height) pixels in lines of e.g. 256 pixels (10000 * 256).
Usually this reduces the memory usage down to a level which is practically.
All required classes can be found here:
PngXxlWriter is the main class. By calling its method writeTileLine you can add a new line to the output image.
https://sourceforge.net/p/mobac/code/HEAD/tree/trunk/MOBAC/src/main/java/mobac/utilities/imageio/