load images dynamically on scroll in blackberry - image

How to display images in the form of pages where only one page is displayed at a time on blackberry screen. On scrolling down subsequent images will load at run time. So that loading of images do not consume time at startup.
Edit: I am using loadimage function which loads images from blackberry device memory which loads images from specified path and resizing them.As number of images increases, it increases the startup time during opening of window.There is an in-built application(Media) in blackberry phone, where images load without taking any extra time. My idea is to display particular number of images which fit to the blackberry screen. As user scroll down to bottom of screen, application will then load and display more images. So my question is how to detect when user reached to bottom of blackberry screen and display one more row images.

Keep array of images url and current image index. Put a BitmapField on screen. Add menu items for Next/Prev. On Next load Bitmap from incremented index url, set it to BitmapField and invalidate screen. On Prev do the same with decremented index.
you can use button as well (maybe in storm) but menu is obligatory
load images in separate threads (especially if they are stored in web)
you can implement caching (in app memory or by saving images on device storage)
some text field may be helpful (file name, type, size, dimentions etc)
UPDATE
For this purpose you can use ScrollChangeListener
try this code:
class Scr extends MainScreen implements ScrollChangeListener {
static int mRowNumber = 0;
public Scr() {
getMainManager().setScrollListener(this);
//preload some images on the start
for (int i = 0; i < 20; i++) {
mRowNumber = i;
add(new BitmapField(downloadBitmap(), FOCUSABLE));
}
}
public static Bitmap downloadBitmap() {
Bitmap result = new Bitmap(200, 80);
Graphics g = new Graphics(result);
g.drawRect(0, 0, 200, 80);
g.drawText("row #" + String.valueOf(mRowNumber), 30, 30);
return result;
}
public void scrollChanged(final Manager manager, int newHorizontalScroll,
int newVerticalScroll) {
int testBottomScroll = manager.getVirtualHeight()
- manager.getVisibleHeight();
if (testBottomScroll == newVerticalScroll) {
mRowNumber++;
(new Thread(new Runnable() {
public void run() {
// simulating download
Bitmap bitmap = downloadBitmap();
// update ui in thread safe way
addBitmap(bitmap);
}
})).start();
}
}
public void addBitmap(final Bitmap bitmap) {
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
getMainManager().add(new BitmapField(bitmap, FOCUSABLE));
}
});
}
}
PS the problem with this approach is you will be able to catch scroll event only if there are enough images on screen. Consider using Screen.navigationMovement(int, int, int, int) then. And don't forget to test it with trackwheel and touchscreen.
Btw my opinion is that it would be better to load all images at once using some thread queue (so images will be loaded asynchronously without locking ui)

Related

CodeName One - Image gets pixelated when scaling

I am getting an image dynamically from a webservice. Afterwards I am supposed to use it as background for the upper half of the screen. My problem is that I only get one size of the image (which should be approximately right for many smartphones phones) but when I resize it to make it fill half of the screen it gets pixelated.
I have tried putting it as background of a container (adding padding to the expected size) and using BACKGROUND_IMAGE_SCALED_FILL and/or using Image methods scaledHeight/scaledWidth, fill and scaled.
It doesn't matter if I scale it to a bigger or smaller size it still deteriorates noticeably.
Is this to be expected? Is there another way to scale images?
public class CopyOfVistaPantallaPrincipal extends VistaDisparaEventos {
private Container canvasPantallaPrincipal;
public CopyOfVistaPantallaPrincipal() {
canvasPantallaPrincipal = new Container();
canvasPantallaPrincipal.setName("canvasPantallaPrincipal");
super.canvas = this.canvasPantallaPrincipal;
initPantallaPrincipal();
}
private void initPantallaPrincipal() {
canvasPantallaPrincipal.setLayout(new LayeredLayout());
canvasPantallaPrincipal.getUnselectedStyle().setBgTransparency(0);
ModeloNovedades modelo = new ModeloNovedades();
Image imgPrincipal = createImagenPrincipal(modelo);
canvasPantallaPrincipal.setName("canvas pantalla principal");
Container otro = new Container(new BorderLayout());
if (imgPrincipal != null) {
img.getUnselectedStyle().setBorder(null);
img.getUnselectedStyle().setPadding(0, 0, 0, 0);
img.getUnselectedStyle().setMargin(0, 0, 0, 0);
canvasPantallaPrincipal.addComponent(img);
}
canvasPantallaPrincipal.addComponent(otro);
}
private Container createImagenPrincipal(ModeloNovedades modelo) {
return loadTopImage(modelo, modelo.getDestacado());
}
private Container loadTopImage(ModeloNovedades modelo, Hashtable destacado) {
int width = Display.getInstance().getDisplayWidth();
int imgHeight = (int) ((Display.getInstance().getDisplayHeight() / 2) * 0.95) ;
//Default image
Image foregroundImage = FormFactory.loadImage("/imagenPrincipaLogoOld.png");
if (! modelo.getDestacado().isEmpty()){
String destacadaURL = "" + destacado.get("imagen");
if (! destacadaURL.equals("")){
//After updating it loads the downloaded image here
byte[] data = (byte[]) DataCenter.getInstance().get(destacadaURL, false);
foregroundImage = FormFactory.loadImage(data, 100);
}
}
imageContainer.getAllStyles().setPadding(imgHeight/2, imgHeight/2, width/2, width()/2);
imageContainer.getAllStyles().setBgImage(foregroundImage);
imageContainer.getAllStyles().setBackgroundType(Style.BACKGROUND_IMAGE_SCALED_FILL);
return imageContainer;
}
}
If I'm not returning the image but a container having it as background I would add it to a Container like this:
imageContainer.getAllStyles().setPadding(imgHeight/2, imgHeight/2, width/2, width/2);
imageContainer.getAllStyles().setBgImage(foregroundImage);
imageContainer.getAllStyles().setBackgroundType(Style.BACKGROUND_IMAGE_SCALED); //only if it was scaled
Original image (please ignore the dark bar over it, it was added recently and I didn't save the previous version, as I said it comes dynamically):
http://i68.tinypic.com/16lmeqr.jpg
Scaled:
http://i68.tinypic.com/w7zafm.jpg
Cropped:
http://i65.tinypic.com/2nkp79l.png
Image as of the last update:
http://i68.tinypic.com/2ik7eiq.png
Remove all of your code that manipulates the image, needs scaling, scale etc... That is all redundant. Every pass you do on manipulating an image deteriorates it a little bit...
You need just one line change and you need to do it always so the image will always "fit" without cropping or any other changes:
imageContainer.getAllStyles().setBackgroundType(Style.BACKGROUND_IMAGE_SCALE_TO_FILL);
Notice that you can just use ScaleImageLabel instead of image container which does roughly the same thing.

Instantiate UI Image Not working

I'm trying to instantiate a UI image in unity 5 to display a players health. I've used a for loop to spawn a new health block image for every 10 health the player has remaining. However, I can't get the image to actually show on screen (it works when I set up the prefab, but as soon as I try to instantiate it through the code it vanishes). The code isn't finished yet as at the moment I understand all the images will stack on top of each other rather than in a row (which will be the finished result) but I want to make sure I can get the images to actually show first before taking this further. Any help would be appreciated!
Things to know:
Player health is set to 100,
Health per icon is set to 10,
I'm using a prefab (health that only contains a UI image component within my canvas.
code:
using UnityEngine.UI;
public class GameController : MonoBehaviour {
public GameObject player;
public int playerStartingHealth;
public Image healthBarGreen;
public int healthPerIcon;
void Start () {
score = 0;
UpdateScore ();
AddPlayerHealth (playerStartingHealth / healthPerIcon);
StartCoroutine (spawnWaves ());
}
public void AddPlayerHealth (int n) {
for (int i =0; i < n; i++) {
Instantiate(healthBarGreen.gameObject);
}
}
}
Bit of a necro, but this post is high on a google search on the subject. Solution:
Image newImage = Instantiate(prefabImage, Vector3.zero, Quaternion.identity);
newImage.transform.SetParent(canvas.transform, false);
newImage.rectTransform.anchoredPosition = Vector3.zero; // your new position here

Android convert Layout to Bitmap and save it

I'm trying to convert a RelativeLayout to Bitmap, and save it
But every time I run my code, I'm getting java.lang.IllegalArgumentException: width and height must be > 0, I think I'm getting this because the layout wasn't displayed.
Is there a way to convert a RelativeLayout which has a TextView to Bitmap and save it?
My codes are:
Activity code
///////// Activity
////////Activity
TextView text;
public bita(View view) {
text= (TextView) findViewById(R.id.text);
text.setText("aaatest");
}
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
text.setText("clicked");
}
To convert a view, first you need to measure the view, then assign a size for it.

Loading Images from sd card to grid view causes bitmap exceeds VM budget

In my Application im loading images from sd card almost 40 to 50 images in grid view for this i created adapter in which constructor loads images from sd card to global variable of array list of bitmaps with in get view im returning bitmap from array list the problem is from this activity user will move to other activity where he will delete image after deletion user will come back to grid activity and have to load the adapter again this creates "bitmap exceeds vm budget". so i don't know is this way to load images from sd card is there any better approach for that any libraries available for loading images from sd card with out memory leak
public class PicAdapter extends BaseAdapter {
int defaultItemBackground;
private Context galleryContext;
Bitmap placeholder;
public PicAdapter(Context c) {
// instantiate context
galleryContext = c;
// create bitmap array
bitmaplist=new ArrayList<Bitmap>();
GlobalData.imageBitmaps = new WeakReference<ArrayList<Bitmap>>(bitmaplist);
imageDescription = new ArrayList<String>();
imagetitle = new ArrayList<String>();
picturesCursor.moveToFirst();
int i = 0;
for (i = 0; i < picturesCursor.getCount(); i++) {
String imagepath = picturesCursor.getString(picturesCursor
.getColumnIndex("img"));
File cacheimage=new File(imagepath);
if(!cacheimage.exists())
{
dBopenHelper.deleteHappyMoments(imagepath);
}
else
{
Bitmap bitmap =
ViewUtils.decodeSampledBitmapFromResource(imagepath,
AppConstants.FRAME_WIDTH,
AppConstants.FRAME_HEIGHT);
ViewUtils.recycleBitmapFrame();
GlobalData.imageBitmaps.get().add(bitmap);
imageDescription.add(picturesCursor.getString(picturesCursor
.getColumnIndex("image_description")));
imagetitle.add(picturesCursor.getString(picturesCursor
.getColumnIndex("image_title")));
picturesCursor.moveToNext();
}
}
if (i == picturesCursor.getCount()) {
Bitmap bitmap = (Bitmap) BitmapFactory.decodeResource(getResources(), R.drawable.add_new);
GlobalData.imageBitmaps.get().add(bitmap);
imageDescription.add(
"Click Add to new Pictures..............");
}
// get the styling attributes - use default Andorid system resources
}
// BaseAdapter methods
// return number of data items i.e. bitmap images
public int getCount() {
return bitmaplist.size();
}
// return item at specified position
public Object getItem(int position) {
return position;
}
// return item ID at specified position
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = (ImageView) getLayoutInflater().inflate(
R.layout.item_grid_image, null);
convertView.setLayoutParams(new GridView.LayoutParams(
AppConstants.FRAME_WIDTH, AppConstants.FRAME_HEIGHT));
}
galleryImageView = (ImageView) convertView;
galleryImageView.setImageBitmap(GlobalData.imageBitmaps.get().get(position));
public void addPic(Bitmap newPic) {
// set at currently selected index
GlobalData.imageBitmaps.get().add(currentPic, newPic);
}
// return bitmap at specified position for larger display
public Bitmap getPic(int posn) {
// return bitmap at posn index
return GlobalData.imageBitmaps.get().get(posn);
}
}
sample code helps me alot
thanks in advance
If your images have high dimension- you need to display them one by one using some kind of queue.
Make sure that you decode them correctly.

Java - drawing many images with Graphics.drawImage() and 2-screen buffer strategy distorts and cuts images

I am using a loop to invoke double buffering painting. This, together with overriding my only Panel's repaint method, is designed to pass complete control of repaint to my loop and only render when it necessary (i.e. some change was made in the GUI).
This is my rendering routine:
Log.write("renderer painting");
setNeedsRendering(false);
Graphics g = frame.getBufferStrategy().getDrawGraphics();
g.setFont(font);
g.setColor(Color.BLACK);
g.fillRect(0, 0, window.getWidth(),window.getHeight());
if(frame != null)
window.paint(g);
g.dispose();
frame.getBufferStrategy().show();
As you can see, it is pretty standard. I get the grpahics object from the buffer strategy (initialized to 2), make it all black and pass it to the paint method of my "window" object.
After window is done using the graphics object, I dispose of it and invoke show on the buffer strategy to display the contents of the virtual buffer.
It is important to note that window passes the graphics object to many other children components the populate the window and each one, in turn, uses the same instance of the graphics object to draw something onto the screen: text, shapes, or images.
My problem begins to show when the system is running and a large image is rendered. The image appears to be cut into seveeal pieces and drawn again and again (3-4 times) with different offsets inside of where the image is supposed to be rendered. See my attached images:
This is the original image:
alt text http://img109.imageshack.us/img109/8308/controller.png
This is what I get:
alt text http://img258.imageshack.us/img258/3248/probv.png
Note that in the second picture, I am rendering shapes over the picture - these are always at the correct position.
Any idea why this is happening?
If I save the image to file, as it is in memory, right before the call to g.drawImage(...) it is identical to the original.
Uh, you are using Swing ?
Normally Swing automatically renders the image, you can't switch it off. The repaint()
method is out of bounds because Swing has a very complicated rendering routine due to
method compatibility for AWT widgets and several optimizations, inclusive drawing only
when necessary !
If you want to use the High-Speed Drawing API, you use a component with a BufferStrategy
like JFrame and Window, use
setIgnoreRepaint(false);
to switch off Swing rendering, set up a drawing loop and paint the content itself.
Or you can use JOGL for OpenGL rendering. The method you are using seems completely
at odds with correct Java2D usage.
Here the correct use:
public final class FastDraw extends JFrame {
private static final transient double NANO = 1.0e-9;
private BufferStrategy bs;
private BufferedImage frontImg;
private BufferedImage backImg;
private int PIC_WIDTH,
PIC_HEIGHT;
private Timer timer;
public FastDraw() {
timer = new Timer(true);
JMenu menu = new JMenu("Dummy");
menu.add(new JMenuItem("Display me !"));
menu.add(new JMenuItem("Display me, too !"));
JMenuBar menuBar = new JMenuBar();
menuBar.add(menu);
setJMenuBar(menuBar);
setIgnoreRepaint(true);
setVisible(true);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
super.windowClosing(evt);
timer.cancel();
dispose();
System.exit(0);
}
});
try {
backImg = javax.imageio.ImageIO.read(new File("MyView"));
frontImg = javax.imageio.ImageIO.read(new File("MyView"));
}
catch (IOException e) {
System.out.println(e.getMessage());
}
PIC_WIDTH = backImg.getWidth();
PIC_HEIGHT = backImg.getHeight();
setSize(PIC_WIDTH, PIC_HEIGHT);
createBufferStrategy(1); // Double buffering
bs = getBufferStrategy();
timer.schedule(new Drawer(),0,20);
}
public static void main(String[] args) {
new FastDraw();
}
private class Drawer extends TimerTask {
private VolatileImage img;
private int count = 0;
private double time = 0;
public void run() {
long begin = System.nanoTime();
Graphics2D g = (Graphics2D) bs.getDrawGraphics();
GraphicsConfiguration gc = g.getDeviceConfiguration();
if (img == null)
img = gc.createCompatibleVolatileImage(PIC_WIDTH, PIC_HEIGHT);
Graphics2D g2 = img.createGraphics();
// Zeichenschleife
do {
int valStatus = img.validate(gc);
if (valStatus == VolatileImage.IMAGE_OK)
g2.drawImage(backImg,0,0,null);
else {
g.drawImage(frontImg, 0, 0, null);
}
// volatile image is ready
g.drawImage(img,0,50,null);
bs.show();
} while (img.contentsLost());
time = NANO*(System.nanoTime()-begin);
count++;
if (count % 100 == 0)
System.out.println(1.0/time);
}
}

Resources