I need a bitmap ARRAY ready to be used dynamically.
what i did is.
on Activity i put
public static Bitmap[] bitmapArray;
bitmapArray = new Bitmap[10];
then to use with a timer i do
public static Bitmap loadBitmap(String url) {
Bitmap bitmap = null;
InputStream in = null;
BufferedOutputStream out = null;
try {
in = new BufferedInputStream(new URL(url).openStream(),
IO_BUFFER_SIZE);
final ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
out = new BufferedOutputStream(dataStream, IO_BUFFER_SIZE);
copy(in, out);
out.flush();
final byte[] data = dataStream.toByteArray();
BitmapFactory.Options options = new BitmapFactory.Options();
// options.outHeight=50;
// options.outWidth=50;
// options.inScaled=true; //inSampleSize = 1;
// options.inSampleSize=3;
bitmap = BitmapFactory.decodeByteArray(data, 0, data.length,
options);
} catch (IOException e) {
e.printStackTrace();
} finally {
closeStream(in);
closeStream(out);
}
return bitmap;
}
for i.........
MyActivity.bitmapArray[i]= loadBitmap( url........
And this is the problem. if i have on the heap a block of 10 (Bitmap[10])
bitmaps buffers i want it to stay fix!!Same memory location.
but each timer iteration the program load the buffer to a DIFFERENT block location
which very soon the memory is finished.
any idea?
P.S i need the above solution fixed since i need the bitmap buffer to be used fast.
Related
i have made a listfield with images, the listfield is parsed from online xml file.
it seems that downloading the images into the listfield is blocking the process of parsing the content of the listfield "text" , i want to show the content of the listfield "text" and then start to proccess the download of the images and then show the images.
here is the code to call the downloader class:
Thread t = new Thread();
{
String imageFilename = imageurlStrin.substring(imageurlStrin.lastIndexOf('/') + 1);
String saveDire = "file:///store/home/user/pictures/listfield/"+imageFilename;
try {
FileConnection fconn = (FileConnection)Connector.open(saveDire);
if (fconn.exists()) {
// do nothing
}
if (!fconn.exists()) {
UrlToImage bit = new UrlToImage(imageurlStrin);
pic = bit.getbitmap();
}
}catch (Exception ioe) {
System.out.println("error 18");
}
};
t.start();
and this is the downloader class code:
public class UrlToImage implements Runnable{
String imageurlStrin=null;
BitmapDowloadListener listener=null;
public static Bitmap _bmap;
private EncodedImage eih1;
public void run() {
UrlToImage bit = new UrlToImage(imageurlStrin);
}
public UrlToImage(String imageurlStrin)
{
HttpConnection connection = null;
InputStream inputStream = null;
EncodedImage bitmap;
byte[] dataArray = null;
//byte[] data1 = null;
try
{
connection = (HttpConnection) Connector.open(imageurlStrin, Connector.READ, true);
inputStream = connection.openInputStream();
byte[] responseData = new byte[10000];
int length = 0;
StringBuffer rawResponse = new StringBuffer();
while (-1 != (length = inputStream.read(responseData)))
{
rawResponse.append(new String(responseData, 0, length));
}
int responseCode = connection.getResponseCode();
if (responseCode != HttpConnection.HTTP_OK)
{
throw new IOException("HTTP response code: "
+ responseCode);
}
final String result = rawResponse.toString();
dataArray = result.getBytes();
}
catch (final Exception ex)
{ }
finally
{
try
{
inputStream.close();
inputStream = null;
connection.close();
connection = null;
}
catch(Exception e){}
}
bitmap = EncodedImage.createEncodedImage(dataArray, 0,dataArray.length);
// this will scale your image acc. to your height and width of bitmapfield
int multH;
int multW;
int currHeight = bitmap.getHeight();
int currWidth = bitmap.getWidth();
int scrhi = Display.getWidth()/4;
int scrwe = Display.getWidth()/4;
multH= Fixed32.div(Fixed32.toFP(currHeight),Fixed32.toFP(scrhi));//height
multW = Fixed32.div(Fixed32.toFP(currWidth),Fixed32.toFP(scrwe));//width
bitmap = bitmap.scaleImage32(multW,multH);
Bitmap thefinal = bitmap.getBitmap();
//url = StringUtils.replaceAll(url ,"http://u.bbstars.com/i-", "");
final String imageFilename = imageurlStrin.substring(imageurlStrin.lastIndexOf('/') + 1);
String saveDire = "file:///store/home/user/pictures/listfield/"+imageFilename;
String Dire = "file:///store/home/user/pictures/listfield/";
JPEGEncodedImage finalJPEG = JPEGEncodedImage.encode(thefinal, 100);
byte[] raw_media_bytes = finalJPEG.getData();
int raw_length = finalJPEG.getLength();
int raw_offset = finalJPEG.getOffset();
FileConnection filecon = null;
OutputStream out = null;
try {
filecon = (FileConnection) Connector.open(Dire,Connector.READ_WRITE);
if(!filecon.exists()){
filecon.mkdir();
}
filecon = (FileConnection) Connector.open(saveDire,Connector.READ_WRITE);
if(!filecon.exists()){
filecon.create();
}
out = filecon.openOutputStream();
out.write(raw_media_bytes, raw_offset, raw_length);
out.close();
filecon.close();
System.out.println("----------------file saved"+imageFilename);
} catch (IOException e) {
System.out.println("---------------===================- error saving the file");
};
try {
FileConnection fconn = (FileConnection)Connector.open(saveDire);
if (fconn.exists()) {
InputStream input = fconn.openInputStream();
int available = input.available();
final byte[] data1=IOUtilities.streamToBytes(input);
input.read(data1, 0, available);
eih1 = EncodedImage.createEncodedImage(data1,0,data1.length);
}
}catch (Exception ioe) {
System.out.println("error gettin bitmap details from the piture");
}
_bmap=eih1.getBitmap();
}
public Bitmap getbitmap()
{
return _bmap;
}
}
what should i do to prevent UI blocking, i want the perfect why to call that downloader class without stoping the process of parsing the other listfield content?
I think you may just have a simple syntax problem with the way you declared your thread object. See the BlackBerry documentation on Thread here
When you create a Thread, you normally either extend the Thread class with a subclass of your own, that implements the run() method, or you pass a new Runnable object in to the constructor of your Thread object. In your code, you actually declare a Thread instance, and create it, but do not give it a Runnable, or override the default run() method. So, this thread won't do anything in the background.
You have essentially declared a chunk of code within a local scope. That's what happens if you just put some code within a set of curly brackets ({ and }) that are not attached to anything:
Thread t = new Thread();
// this next curly bracket starts a "local scope". it is NOT part of Thread t!
{
String imageFilename = imageurlStrin.substring(imageurlStrin.lastIndexOf('/') + 1);
// The rest of your code here will not be executed on Thread t. It will be executed
// on the thread where you instantiate Thread t, right before you call t.start();
// If this code is called on the main/UI thread (which it probably is), then the
// network request will block the UI thread, which will stop the loading of the rest
// of the list.
};
t.start();
What you probably want is this:
Thread t = new Thread(new Runnable() {
public void run() {
String imageFilename = imageurlStrin.substring(imageurlStrin.lastIndexOf('/') + 1);
String saveDire = "file:///store/home/user/pictures/listfield/"+imageFilename;
try {
FileConnection fconn = (FileConnection)Connector.open(saveDire);
if (fconn.exists()) {
// do nothing
}
if (!fconn.exists()) {
UrlToImage bit = new UrlToImage(imageurlStrin);
pic = bit.getbitmap();
}
} catch (Exception ioe) {
System.out.println("error 18");
}
}
});
t.start();
Try that, and see if that fixes the problem.
I am working on blackberry project where i want to download image & save it in sd card in blackberry. By going through many sites i got some code & based on that i wrote the program but when it is executed the output screen is displaying a blank page with out any response. The code i am following is..
code:
public class BitmapDemo extends UiApplication
{
public static void main(String[] args)
{
BitmapDemo app = new BitmapDemo();
app.enterEventDispatcher();
}
public BitmapDemo()
{
pushScreen(new BitmapDemoScreen());
}
static class BitmapDemoScreen extends MainScreen
{
private static final String LABEL_X = " x ";
BitmapDemoScreen()
{
//BitmapField bmpFld1=new BitmapField(connectServerForImage("http://images03.olx.in/ui/3/20/99/45761199_1.jpg"));
//add(bmpFld1);
setTitle("Bitmap Demo");
// method for saving image in sd card
copyFile();
// Add a menu item to display an animation in a popup screen
MenuItem showAnimation = new MenuItem(new StringProvider("Show Animation"), 0x230010, 0);
showAnimation.setCommand(new Command(new CommandHandler()
{
public void execute(ReadOnlyCommandMetadata metadata, Object context)
{
// Create an EncodedImage object to contain an animated
// gif resource.
EncodedImage encodedImage = EncodedImage.getEncodedImageResource("animation.gif");
// Create a BitmapField to contain the animation
BitmapField bitmapFieldAnimation = new BitmapField();
bitmapFieldAnimation.setImage(encodedImage);
// Push a popup screen containing the BitmapField onto the
// display stack.
UiApplication.getUiApplication().pushScreen(new BitmapDemoPopup(bitmapFieldAnimation));
}
}));
addMenuItem(showAnimation);
}
private static class BitmapDemoPopup extends PopupScreen
{
public BitmapDemoPopup(BitmapField bitmapField)
{
super(new VerticalFieldManager());
add(bitmapField);
}
protected boolean keyChar(char c, int status, int time)
{
if(c == Characters.ESCAPE)
{
close();
}
return super.keyChar(c, status, time);
}
}
}
public static Bitmap connectServerForImage(String url) {
System.out.println("image url is:"+url);
HttpConnection httpConnection = null;
DataOutputStream httpDataOutput = null;
InputStream httpInput = null;
int rc;
Bitmap bitmp = null;
try {
httpConnection = (HttpConnection) Connector.open(url,Connector.READ_WRITE);
rc = httpConnection.getResponseCode();
if (rc != HttpConnection.HTTP_OK) {
throw new IOException("HTTP response code: " + rc);
}
httpInput = httpConnection.openInputStream();
InputStream inp = httpInput;
byte[] b = IOUtilities.streamToBytes(inp);
EncodedImage hai = EncodedImage.createEncodedImage(b, 0, b.length);
return hai.getBitmap();
} catch (Exception ex) {
System.out.println("URL Bitmap Error........" + ex.getMessage());
} finally {
try {
if (httpInput != null)
httpInput.close();
if (httpDataOutput != null)
httpDataOutput.close();
if (httpConnection != null)
httpConnection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return bitmp;
}
public static void copyFile() {
// TODO Auto-generated method stub
EncodedImage encImage = EncodedImage.getEncodedImageResource("rim.png");
byte[] image = encImage.getData();
try {
// Create folder if not already created
FileConnection fc = (FileConnection)Connector.open("file:///SDCard/BlackBerry/images/");
if (!fc.exists())
fc.mkdir();
fc.close();
// Create file
fc = (FileConnection)Connector.open("file:///SDCard/BlackBerry/images/" + image, Connector.READ_WRITE);
if (!fc.exists())
fc.create();
OutputStream outStream = fc.openOutputStream();
outStream.write(image);
outStream.close();
fc.close();
System.out.println("image saved.....");
} catch (Exception e) {
// TODO: handle exception
//System.out.println("exception is "+ e);
}
}
}
This is the code which i am using. Not getting any response except blank page.. As i am new to blackberry development unable to find out what is the problem with my code. Can anyone please help me with this...... Actually i am having other doubt as like android & iphone does in blackberry simulator supports for SD card otherwise we need to add any SD card slots for this externally...
Waiting for your reply.....
To simply download and save that image to the SDCard, you can use this code. I changed your SDCard path to use the pictures folder, which I think is the standard location on BlackBerrys. If you really want to store it in images, you may just need to create the folder if it doesn't already exist.
package com.mycompany;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
import javax.microedition.io.file.FileConnection;
public class DownloadHelper implements Runnable {
private String _url;
public DownloadHelper(String url) {
_url = url;
}
public void run() {
HttpConnection connection = null;
OutputStream output = null;
InputStream input = null;
try {
// Open a HTTP connection to the webserver
connection = (HttpConnection) Connector.open(_url);
// Getting the response code will open the connection, send the request,
// and read the HTTP response headers. The headers are stored until requested.
if (connection.getResponseCode() == HttpConnection.HTTP_OK) {
input = new DataInputStream(connection.openInputStream());
int len = (int) connection.getLength(); // Get the content length
if (len > 0) {
// Save the download as a local file, named the same as in the URL
String filename = _url.substring(_url.lastIndexOf('/') + 1);
FileConnection outputFile = (FileConnection) Connector.open("file:///SDCard/BlackBerry/pictures/" + filename,
Connector.READ_WRITE);
if (!outputFile.exists()) {
outputFile.create();
}
// This is probably not a robust check ...
if (len <= outputFile.availableSize()) {
output = outputFile.openDataOutputStream();
// We'll read and write this many bytes at a time until complete
int maxRead = 1024;
byte[] buffer = new byte[maxRead];
int bytesRead;
for (;;) {
bytesRead = input.read(buffer);
if (bytesRead <= 0) {
break;
}
output.write(buffer, 0, bytesRead);
}
output.close();
}
}
}
} catch (java.io.IOException ioe) {
ioe.printStackTrace();
} finally {
try {
if (output != null) {
output.close();
}
if (connection != null) {
connection.close();
}
if (input != null) {
input.close();
}
} catch (IOException e) {
// do nothing
}
}
}
}
This class can download an image in the background, as I suggested. To use it, you can start a worker thread like this:
DownloadHelper downloader = new DownloadHelper("http://images03.olx.in/ui/3/20/99/45761199_1.jpg");
Thread worker = new Thread(downloader);
worker.start();
This will save the file as /SDCard/BlackBerry/pictures/45761199_1.jpg. I tested it on a 5.0 Storm simulator.
There are several problems with the code posted. It's also not completely clear what you're trying to do. From the question title, I assume you want to download a jpg image from the internet, and display it.
1) You implement a method called connectServerForImage() to download an image, but then it's commented out. So, the method isn't going to download anything if it's not called.
2) Even if it's uncommented, connectServerForImage() is called here
BitmapField bmpFld1=new BitmapField(connectServerForImage("http://images03.olx.in/ui/3/20/99/45761199_1.jpg"));
This will block the main (UI) thread while it downloads your image. Even though you can do it this way, it's not a good thing to do. Instead, you could create a Thread to download the image as a background task, and then use UiApplication.invokeLater() to load the image into your BitmapField on the main/UI thread.
3) Your copyFile() method tries to copy a file named rim.png, which must be an image bundled with your application, and saves it to the SDCard. Is this really what you want? Do you want to save the downloaded image instead? This method doesn't seem to be connected to anything else. It's not saving the image downloaded from the internet, and the image it does save is never used anywhere else.
4) In copyFile(), this line
fc = (FileConnection)Connector.open("file:///SDCard/BlackBerry/images/" + image, Connector.READ_WRITE);
is passing a byte[] in as part of the filename to open (your variable named image). You should probably be adding a String name to the end of your SDCard path. As the code is, it's probably opening a file in the /SDCard/BlackBerry/images/ folder with a very long name that looks like a number. Or it might fail entirely, if there are limits on the length of filenames.
5) In Java, it's not usually a good idea to make everything static. Static should normally be used for constants, and for a very few methods like the main() method, which must be static.
Try to clean these things up, and then repost the code, and we can try to help you with your problem. Thanks.
So, I'm working on my paint application. Every time I make changes, the current screen state is copied and saved as a bitmap image on my disk (so I can use it in my paint event).
The problem occurs when I minimize and return the window to its normal state and then try to draw. This triggers my event reacting to changes, the program tries to save the image ---->>> kabooom.
It says "A generic error occurred in GDI+".. So, I've been surfing through various forums in search for the answer but none of them gave me true answer, they all mention wrong paths etc. but I'm pretty sure that's not the problem. Do I have to dispose bitmap or do something with the stream?
int width = pictureBox1.Size.Width;
int height = pictureBox1.Size.Height;
Point labelOrigin = new Point(0, 0); // this is referencing the control
Point screenOrigin = pictureBox1.PointToScreen(labelOrigin);
int x = screenOrigin.X;
int y = screenOrigin.Y;
Rectangle bounds = this.Bounds;
using (Bitmap bitmap = new Bitmap(width, height))
{
using (Graphics g = Graphics.FromImage(bitmap))
{
g.CopyFromScreen(new Point(x, y), Point.Empty, bounds.Size);
}
bitmap.Save(_brojFormi + ".bmp", System.Drawing.Imaging.ImageFormat.Bmp);
}
You're saving an image to disk so you can use it in another event? Wow.
Why not just use a class-global variable to store the bitmap?
class MyForm
{
Bitmap currentImage = null;
Graphics gfx = null;
private void btnLoad_Click(object sender, EventArgs e)
{
// ...
currentImage = new Bitmap(fileName);
gfx = Graphics.FromImage(currentImage);
}
private void pbEditor_Paint(object sender, PaintEventArgs e)
{
if (currentImage != null && gfx != null)
{
lock(currentImage) e.Graphics.DrawImage(currentImage, ...);
}
}
private void pbEditor_Click(object sender, MouseEventArgs e)
{
// quick example to show bitmap drawing
if (e.Button == MouseButtons.Left)
lock(currentImage) currentImage.SetPixel(e.Location.X, e.Location.Y, Colors.Black);
}
}
Here is the paint method of my custom field:
protected void paint(Graphics graphics) {
new downloadImage();
Bitmap img = downloadImage.connectServerForImage(this.poster);
graphics.drawBitmap(0, 0, 100, 150, img, LEFT, TOP);
}
Here is the connectServerForImage method:
public static Bitmap connectServerForImage(String url) {
HttpConnection httpConnection = null;
DataOutputStream httpDataOutput = null;
InputStream httpInput = null;
int rc;
Bitmap bitmp = null;
try {
httpConnection = (HttpConnection) Connector.open(url);
rc = httpConnection.getResponseCode();
if (rc != HttpConnection.HTTP_OK) {
throw new IOException("HTTP response code: " + rc);
}
httpInput = httpConnection.openInputStream();
InputStream inp = httpInput;
byte[] b = IOUtilities.streamToBytes(inp);
EncodedImage hai = EncodedImage.createEncodedImage(b, 0, b.length);
return hai.getBitmap();
} catch (Exception ex) {
System.out.println("URL Bitmap Error........" + ex.getMessage());
} finally {
try {
if (httpInput != null)
httpInput.close();
if (httpDataOutput != null)
httpDataOutput.close();
if (httpConnection != null)
httpConnection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return bitmp;
}
I'm putting multiple instances of my custom field into a verticalfieldmanager, but the images slows the scrolling down. It seems as if every time I scroll it runs the paint method again even though the image has already been downloaded.
I'm thinking I will need to download the images in another thread? Someone lead me in the right direction.
You must start any HTTP interaction in a separate thread (no blocking call).
To avoid downloading same image multiple times cache already downloaded image. You can use image download URL as image tag to store
them.
Every time there is a event on screen, paint method will be called. So don't start download an image if it is already downloaded.
I've managed to get images into a custom drawListRow:
public void drawListRow(ListField listField, Graphics graphics, int index, int y, int width) {
graphics.drawBitmap(0, (index) * listField.getRowHeight(), firstrowPostion, rowHeight, thing.image, 0, 0);
graphics.setFont(titleFont);
graphics.drawText(thing.title, firstrowPostion, y, (DrawStyle.LEFT | DrawStyle.ELLIPSIS | DrawStyle.TOP ), 250);
}
The first time though everything works perfectly but once I get to the bottom of the list and start to scroll up again, the pictures have disappeared.
Any suggestions?
Edit: I've figured out the second time through this code:
try {
InputStream inputStream = Connector.openInputStream(ImagePath);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
int i = 0;
while ((i = inputStream.read()) != -1) {
outputStream.write(i);
}
byte[] data = outputStream.toByteArray();
EncodedImage eimg = EncodedImage.createEncodedImage(data, 0,
data.length);
Bitmap image = eimg.getBitmap();
inputStream.close();
outputStream.close();
return ImageUtility.resizeBitmap(image, 70, 70);
} catch (IOException e) {
return null;
} catch (IllegalArgumentException ex) {
return null;
}
}
that InputStream inputStream = Connector.openInputStream(ImagePath); is throwing an IOException. I understand from here
that IO will be thrown under these conditions: but I don't know which is the cause:
1. more than one openInputStream() on single instance of fileconnection.
2. openInputStream() on already closed fileconnection.
3. openInputStream() on a directory.
again any suggestions?
I figured out it's best to just create a separate array of fully formed images and send both that and the thing array to drawlistrow, instead of trying to form and draw them as every row is drawn.