I am trying to download an image using this code in my unity project my an android game.
public static Texture2D userTexture=new Texture2D(64, 64, TextureFormat.DXT5, false); //TextureFormat must be DXT5
public static IEnumerator UserPictureCallback(){
Debug.Log("USerPicture called");
FbDebug.Log("USerPicture called");
WWW url = new WWW("http://i1.wp.com/a0.twimg.com/sticky/default_profile_images/default_profile_1_normal.png?resize=64%2C64");
yield return url;
//profilePic.renderer.material.mainTexture = textFb2;
Debug.Log(url);
url.LoadImageIntoTexture(userTexture);
Debug.Log("Working");
}
And then I am trying to draw it in GUI using DrawTexture.
GUI.DrawTexture(new Rect(5,0,50,50),FB.userTexture,ScaleMode.StretchToFill, false, 0.0f);
But the image texture is not getting downloaded or at least it is not showing in the GUI. Can somebody help me with this?
I recently faced the same problem. I was creating an scrollable image gallery in Unity, where images are downloaded in real-time from the a web server. On iOS devices I was reaching very fast the memory limit (with consequent app crash). That was caused due to a very big number of www objects leaved in the memory and never deleted or released. Also a very big number of Texture2D objects leaked.
The main misunderstanding is considering a Texture2D like a variable of an object that self-contained the image information. Texture2D only point to a referenced asset so we need to create one before assigning to our GUI object. Without creating one we will overwrite the referenced asset in our project, leading to very crazy behaviour.
So this the code that works for me on iOS and just use the minimum of memory
public void DownloadImage(string url)
{
StartCoroutine(coDownloadImage(url));
}
IEnumerator coDownloadImage(string imageUrl)
{
WWW www = new WWW( imageUrl );
yield return www;
thumbnail.mainTexture = new Texture2D(www.texture.width, www.texture.height, TextureFormat.DXT1, false);
www.LoadImageIntoTexture(thumbnail.mainTexture as Texture2D);
www.Dispose();
www = null;
}
A brief comment:
You receive a url you will download the image from.
Start the coroutine that manage the download
Create the www object in the local scope
yield waiting the download to complete
Create a new Texture2D object/asset with parameters and assign to your final object mainTexture or what do you want
Use the "www.LoadImageIntoTexture()" function to COPY the image inside the created asset (this is the fundamental part)
Dispose and set to null the www object to prevent memory leaking or orphans
Hope it helps who will face the same problem.
An interesting lecture is this website where they implement a WebImageCache system to avoid re-downloading the same image many times.
http://studiofive27.com/index.php/unity-cached-web-images/
Related
So I am displaying video files from specific folder when the folder is selected but in the video list I am showing file name with the video thumbnail and that's where the problem starts i am using this way to get the thumb
Bitmap bmThumbnail = ThumbnailUtils.
extractThumbnail(ThumbnailUtils.createVideoThumbnail(info.getFilename(),
MediaStore.Video.Thumbnails.MINI_KIND), 60, 60);
if(bmThumbnail != null) {
imageView.setImageBitmap(bmThumbnail);}
and even if I don't set the bitmap or not the process is taking way too much time to open the new fragment whereas just displaying the name is smooth if I call the following bitmap it takes around 6-7 sec to display the list. The following thing are happening in the adapter as I test the app in adapter then recycler view
so I would like to know what is the best way to do it .
For using image loader i need the url which is not there as i am getting the album art using the file url but it will not produce the album art url directly.
Dealing with images and videos like that takes time. Particularly when dealing with a large group of them. It's unlikely you can speed up the operation but you can make it so your application doesn't have to wait for it by sending it to the background. I recommend Kotlin coroutines if you are up for converting to Kotlin. Otherwise I recommend making a thumbnail work manager
public class VideoThumbnailWorker extends Worker {
}
There are the Bitmap for Android and UIImage for iOS. Is there a way to display both somehow in the Xamarin Forms Image control?
Obviously I need the Dependency Service. I will have two implementations that create either a bitmap or an uiimage using some source, but how do I bring those two products together to a single forms control? Both Android and iOS methods have to return something, that the image control can understand and display. I don't know what that might be.
Edit: I look for a way where I don't use storage space, if possible.
Edit2:
I tried Jasons suggestion and it works fine.
I create a bitmap in the Android project and return a MemoryStream object:
MemoryStream stream = new MemoryStream();
newImage.Compress(Bitmap.CompressFormat.Png, 0, stream);
return stream;
Then I consume it in my Xamarin.Forms Image control:
var stream = DependencyService.Get<ICrossPlatformImageProcesor>().Combine_Images(imagePath);
stream.Position = 0;
img_ImageView.Source = Xamarin.Forms.ImageSource.FromStream(() => stream);
I will have two implementations that create either a bitmap or an uiimage using some source, but how do I bring those two products together to a single forms control?
You can simply use Image Control of xamarin forms, images can be loaded specifically for each platform, or they can be downloaded for display.
For more information, you can refer to Working with Images.
I look for a way where I don't use storage space, if possible.
I'm not quite understand this, if you mean don't use memory, then I think it is not possible. If you mean your images are not saved in storage, then possibly you have an URL address on internet of your images?
Anyway, Image control in Xamarin.Forms support image source form ImageSource instance, file, Uri, and resources, to load image from uri, you can simply code like this:
var webImage = new Image { Aspect = Aspect.AspectFit };
webImage.Source = ImageSource.FromUri(new Uri("https://xamarin.com/content/images/pages/forms/example-app.png"));
Care: No code here, only text and some questions about bitmap caching
I'm currently developing an App which is almost finished. The only thing left, that I would like to do is caching images. Because, at the moment, when the user opens the app the app downloads images from a server. Those images are not static, that means they can change every minute/hour/day. I don't know when they change, because it's a list of images gathered by the amount of twitter shares, facebook likes etc. That means, when a picture has 100 likes and 100 tweets it is place 1. But when another picture gets more likes and tweets it gets rank 1 and the other one will be placed as rank 2. This isn't exactly my app, but just so you understand the principle.
Now I looked into Bitmap caching so the user doesn't have to download the same images over and over. The question I do have is how do I do it? I mean, i Understand HOW to cache bitmaps.
I looked into this documentation article: http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html
But, the problem is, how do I know if the Bitmap already got downloaded and has been cached or if I have to download it again? Don't I have to download the image first to check if I have this particular image already in my system?
I thought about getting the URL of the image, then convert it into a hash. And then, save the files to the cache with the hash as filename. Then, when the image URL comes it will be checked wether the image is available in the cache or not. If it is it will be loaded if not it will be downloaded. Would that the way to go be?
Or am I misunderstanding bitmap caching and it does it from its own already?
my best advice on those cases is: Do not try to re-invent the wheel.
Image loading/caching is a very complex task in Android and a lot of good developers already did that. Just re-use their work.
My personal preference is Picasso http://square.github.io/picasso/
to load stuff with it is one very simple line of code:
Picasso.with(context).load(url).into(imgView);
it's that simple!
It does both RAM and disk cache, handles all threading issues and use the excellent network layer okHttp.
edit:
and to get access directly to the Bitmap you can:
Picasso.with(context).load(url).into(new Target() {
void onBitmapLoaded(Bitmap bitmap, LoadedFrom from){
// this will be called on the UI thread after load finishes
}
void onBitmapFailed(Drawable errorDrawable){
}
void onPrepareLoad(Drawable placeHolderDrawable){
}
});
Check this library:
http://code.google.com/p/android-query/wiki/ImageLoading
It does caching automagically
example
//fetch a remote resource in raw bitmap
String url = "http://www.vikispot.com/z/images/vikispot/android-w.png";
aq.ajax(url, Bitmap.class, new AjaxCallback<Bitmap>() {
#Override
public void callback(String url, Bitmap object, AjaxStatus status) {
}
});.
http://code.google.com/p/android-query/wiki/AsyncAPI
You can try https://github.com/thest1/LazyList
the project code was designed for listviews, but still, its purpose is to download images from URLs in the backgroud so the user doesn't have to hold on the whole downloading time.
you take these JAVA classes : FileCache, ImageLoader, MemoryCache, import them into your project,
for downloading an image you just call imageLoader.DisplayImage(URL,ImageView);
the best part is that it takes care of the cache itself so you don't have to worry about that
hope this helps
orI have an app that is consistently downloading large images from a parse back-end. In android you can download the images as streams using their URI's and set a specific dimension size to the bitmap that I want to download. Usually this is done using the BitmapFactory libraries and allows me to download a bitmap that's of a scaled down size, saving my app from long loading times. Is there an equivalency to this method on the IOS platform? This is what I am currently doing, but when I download 15 full sized images I get a large amount of load time:
//where photoQuery is a Parse.com database query that returns the photo as the first object
PFObject *photoObject = [photoQuery getFirstObject];
PFFile *photoFile = (PFFile *)[photoObject objectForKey:#"fullSizedImage"];
UIImage *fullImage = [UIImage imageWithData:photoFile.getData];
Does IOS support something similar to BitmapFactory or this common android design pattern?
PFFile has a method called – getDataInBackgroundWithBlock:. Which can be used like this:
[photoFile getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
if(!error) {
[imageView setImage:[UIImage imageWithData:data];
}
}
Or you can use another method called - getDataStreamInBackgroundWithBlock:. It is similar as the one above. The difference is the first parameter of the block is a NSInputStream
PFImageView should help you load these images a synchronously. You may try thumbnailing images using Cloud Code.
I am downloading images from server into the ListView and storing it into SD Card.
And when next time listview appears i am accessing it from SD card only using Async method, i
use this approch so that every thing user does not need to access server.
But when all the images are being loaded into listview from SD Card and if i scroll it
pretty fast then every time it tries to access it from the SD Card only rather then from Caches i guess.
I was facing the same problem when images are being downloaded from server also , and thats why i thought to store it into SD Card. but i am facing the same issue.
here is my code ListImageDownloader . In that there is a function called downloadBitmap(String) and i have created another function named downloadSDBitmap(String) whose code is as follows
Bitmap downloadSDBitmap(String urlId) {
Bitmap bitmap = null;
File file = new File(
fileLoc +"/"+ urlId+".png");
if(file.exists()){
Log.d("PATH" , file.getAbsolutePath());
bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
}
return bitmap;
}
apart from this the whole caching code and all are same. so can anyone help me how can i improve it as in a Gtalk android application when i scroll fast it loads the images only once after that if i scroll fast the images remains as it is and doesnt fetch from network
Update
these are my parameters
final static int MAX_ENTRIES = 150;
private static final int HARD_CACHE_CAPACITY =50;
private static final int DELAY_BEFORE_PURGE = 10 * 1000; // in milliseconds
Caching fundamentally relies on available memory. If there is memory left for your application you will need to implement a good solution that caches your bitmaps.
In the past was SoftReference/WeakReference a popular method to cache bitmaps (I did try it a year ago, you can read about my question about this here). But in later APIs of Android the garbage collector has become more aggressive collecting those and therefore they are not no longer recommended.
Now it is recommended to use an LRU cache. There is an example available on the Android developers website.