Fresco using DataSubscriber to load gif - gif

I wanna get the gif through DataSubscriber by Fresco.But when i get the CloseableAnimatedImage, I don't know how to get the bitmap of it.
public void getBitmap(String url, final OnBitmapFetchedListener listener) {
ImageRequest request = ImageRequest.fromUri(Uri.parse(url));
final ImagePipeline imagePipeline = Fresco.getImagePipeline();
DataSource<CloseableReference<CloseableImage>>
dataSource = imagePipeline.fetchDecodedImage(request, null);
DataSubscriber dataSubscriber = new BaseDataSubscriber<CloseableReference<CloseableImage>>() {
#Override
protected void onNewResultImpl(DataSource<CloseableReference<CloseableImage>> closeableReferenceDataSource) {
CloseableReference<CloseableImage> imageReference = closeableReferenceDataSource.getResult();
if (imageReference != null) {
try {
CloseableImage image = imageReference.clone().get();
if (image instanceof CloseableAnimatedImage) {
//here i get the gif but i don't know how to get the bitmap
}
}
}
}
and i tried another way to get the bitmap of a pic:
fun getBitmap(uri: Uri, listener: OnBitmapFetchedListener) {
val request = ImageRequest.fromUri(uri)
val imagePipeline = Fresco.getImagePipeline()
val dataSource = imagePipeline.fetchEncodedImage(request, null)
val dataSubscriber = object : BaseDataSubscriber<CloseableReference<PooledByteBuffer>>() {
override fun onNewResultImpl(closeableReferenceDataSource: DataSource<CloseableReference<PooledByteBuffer>>) {
val imageReference = closeableReferenceDataSource.result
if (imageReference != null) {
try {
val image = imageReference.clone().get()
val inputStream = PooledByteBufferInputStream(image)
val imageFormat = ImageFormatChecker.getImageFormat(inputStream)
Log.e("ImageUtil", "imageFormat = ${ImageFormat.getFileExtension(imageFormat)}")
val bitmap = BitmapFactory.decodeStream(inputStream)
listener.onSuccess(bitmap)
} catch (e: IOException) {
Log.e("ImageUtil", "error:$e")
} finally {
imageReference.close()
}
}
}
override fun onFailureImpl(closeableReferenceDataSource: DataSource<CloseableReference<PooledByteBuffer>>) {
Log.e("ImageUtil", "fail")
listener.onFail()
}
}
It's kotlin code, what i do is using fetchEncodedImage and get the inputStream of a pic.
But it always go onFailImpl(), I don't know why.

It seems that the real question is how to statically display only the first frame of an animated image. This is not supported at the moment, but it would be very easy to implement.
Fresco already has ImageDecodeOptions object. You would just need to add another field there: public final boolean decodeAsStaticImage. Then in ImageDecoder.decodeGif you just need to change:
if (GifFormatChecker.isAnimated(is)) {
return mAnimatedImageFactory.decodeGif(...);
}
return decodeStaticImage(encodedImage);
to:
if (!options.decodeAsStaticImage && GifFormatChecker.isAnimated(is)) {
return mAnimatedImageFactory.decodeGif(...);
}
return decodeStaticImage(encodedImage);
Please feel free to implement this and make a pull request to our GitHub Fresco repository.
And then in the client code, you just need to set your decode options to the image request with ImageRequestBuilder.setImageDecodeOptions.

Related

Dart : change reference of object

This doesn't change the value of 'myStuff.stuff', its value is still 'start' :
void main() {
Thing myStuff = Thing();
myStuff.stuff = 'start';
doStuff(myStuff);
print(myStuff.stuff);
}
void doStuff(Thing theStuff) {
theStuff = Thing();
theStuff.stuff = 'test';
}
class Thing {
String stuff = '';
}
How can I replace the referenced object in a function ?
You cannot do this in the method that you show. Dart is not pass by reference. It is pass by value.
If you want to be able to do something similar to this, you can either wrap your Thing object with a another object or provide a callback that modifies your original object.
Something along these lines for the wrapper class method:
void main() {
Thing myStuff = Thing();
myStuff.stuff = 'start';
ThingWrap wrapper = ThingWrap();
wrapper.thing = myStuff;
doStuff1(wrapper);
print(wrapper.thing.stuff);
}
void doStuff1(ThingWrap theStuff) {
var newStuff = Thing();
newStuff.stuff = 'test';
theStuff.thing = newStuff;
}
class Thing {
String stuff = '';
}
class ThingWrap {
Thing thing = Thing();
}
or the callback method:
void main() {
Thing myStuff = Thing();
myStuff.stuff = 'start';
doStuff1((newVal) {
myStuff = newVal;
});
print(myStuff.stuff);
}
void doStuff1(Function(Thing) callback) {
var newStuff = Thing();
newStuff.stuff = 'test';
callback(newStuff);
}
class Thing {
String stuff = '';
}
It's not immediately clear why you would want to do this based on the example you provided. If this were provided, it may have been possible to provide a cleaner solution. Simply providing a return value for doStuff and assigning it to myStuff in main would seem like the obvious way to do the same thing.

How to get Audio track from JSON file in server?

Hello :) in my Project I want to get Audio track from a JSON file file which locate it in a Server.
my Audio. mp4 doesn't want to play, I don't know why ,, I made the same script for video and it works good just I thought if I have only the sound so it can work the same way as a video. this is my script:
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
using System.Collections;
using TMPro;
using UnityEngine.Video;
// Json dataaudio format
/*
{
"Title" : "..." ,
"AudioURL" : "..."
}
*/
public struct Dataudio
{
public string Title;
public string AudioURL;
}
public class getaudio : MonoBehaviour
{
[SerializeField] TextMeshPro TitleText;
[SerializeField] private VideoPlayer videoPlayer;
[SerializeField] private RawImage rawImage;
string jsonURL = "https://myserver";
IEnumerator Start()
{
using (var request = UnityWebRequest.Get(jsonURL))
{
yield return request.SendWebRequest();
if (request.isNetworkError || request.isHttpError)
{
// error ...
}
else
{
// success...
Dataaudio data = JsonUtility.FromJson<Dataaudio>(request.downloadHandler.text);
// print data in UI
uiTitleText.text = data.Title;
// The video player will take care of loading the video clip all by itself!
videoPlayer.url = data.AudioURL;
videoPlayer.Play();
}
}
}
}
I saw the Audio Source Game object but it doesn't support URL as Video player game object.
I hope someone help me. Thank you
By using a second UnityWebRequestMultimedia.GetAudioClip e.g.
IEnumerator Start()
{
Dataaudio data;
using (var request = UnityWebRequest.Get(jsonURL))
{
yield return request.SendWebRequest();
if (request.isNetworkError || request.isHttpError)
{
// error ...
yield break;
}
else
{
// success...
data = JsonUtility.FromJson<Dataaudio>(request.downloadHandler.text);
}
}
// print data in UI
uiTitleText.text = data.Title;
using (var clipRequest = UnityWebRequestMultimedia.GetAudioClip(data.AudioURL, AudioType.WAV /*TODO use correct audio type here*/))
{
yield return clipRequest.SendWebRequest();
if (clipRequest.isNetworkError || clipRequest.isHttpError)
{
// error ...
yield break;
}
else
{
// success...
var clip = DownloadHandlerAudioClip.GetContent(www);
someAudioSource.clip = clip;
someAudioSource.Play();
}
}
}
Note though that .mp4 is usually a video format, not a sound format.

StorageItemThumbnail to BitmapImage converter fails with MediaCapture mp4

I am using a ValueConverter to get the thumbnail for an m4 file that was recorded by directly with WinRT's MediaCapture. After much debugging and alternate approaches, I've settle on the converter code below. I am getting the following error The component cannot be found. (Exception from HRESULT: 0x88982F50) on the GetThumbnailAsync method.
I have confirmed that the thumbnail is being shown for the video in the Xbox Video app and the file explorer app when I use CopyTo(KnownFolders.VideosLibrary).
The converter seems to work fine when it's an external video file, but not with one of my app's mp4s. Is there something wrong with my converter or can you reproduce this?
SEE UPDATE 1 I try to get the thumbnail when the file is first created, same error occurs.
public class ThumbnailToBitmapImageConverter : IValueConverter
{
readonly StorageFolder localFolder = ApplicationData.Current.LocalFolder;
BitmapImage image;
public object Convert(object value, Type targetType, object parameter, string language)
{
if (Windows.ApplicationModel.DesignMode.DesignModeEnabled)
return "images/ExamplePhoto2.jpg";
if (value == null)
return "";
var fileName = (string)value;
if (string.IsNullOrEmpty(fileName))
return "";
var bmi = new BitmapImage();
bmi.SetSource(Thumb(fileName).Result);
return bmi;
}
private async Task<StorageItemThumbnail> Thumb(string fileName)
{
try
{
var file = await localFolder.GetFileAsync(fileName)
.AsTask().ConfigureAwait(false);
var thumbnail = await file.GetScaledImageAsThumbnailAsync(ThumbnailMode.ListView, 90, ThumbnailOptions.UseCurrentScale)
.AsTask().ConfigureAwait(false);
return thumbnail;
}
catch (Exception ex)
{
new MessageDialog(ex.Message).ShowAsync();
}
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
UPDATE 1
I decided to go back to where I save the video to a file and grab the thumbnail there, then save it to an image for use later. I get the same error, here is the code for grabbing and saving the thumbnail after the video is saved:
var thumb = await videoStorageFile.GetThumbnailAsync(ThumbnailMode.ListView);
var buffer = new Windows.Storage.Streams.Buffer(Convert.ToUInt32(thumb.Size));
var thumbBuffer = await thumb.ReadAsync(buffer, buffer.Capacity, InputStreamOptions.None);
using (var str = await thumbImageFile.OpenAsync(FileAccessMode.ReadWrite))
{
await str.WriteAsync(thumbBuffer);
}
I have not tested this out, but It should work. In your model that you are binding to, replace the property for your thumbnail with a new class named Thumbnail. Bind to that property rather than your video location. When the video location changes, create a new thumbnail.
public class VideoViewModel : INotifyPropertyChanged
{
public string VideoLocation
{
get { return _location; }
set
{
_location = value;
Thumbnail = new Thumbnail(value);
OnPropertyChanged();
}
}
public Thumbnail Thumbnail
{
get { return _thumbnail; }
set
{
_thumbnail = value;
OnPropertyChanged();
}
}
}
The Thumbnail class. This is just a shell, ready for you to fill out the rest
public class Thumbnail : INotifyPropertyChanged
{
public Thumbnail(string location)
{
Image = GetThumbFromVideoAsync(location);
}
private Task<BitMapSource> GetThumbFromVideoAsync(string location)
{
BitMapSource result;
// decode
// set it again to force
Image = Task.FromResult(result);
}
public Task<BitMapSource> Image
{
get { return _image; }
private set
{
_image = value;
OnPropertyChanged();
}
}
}
You can still have a value converter in place. It would check if the task has completed, if it has not, then show some default image. If the task has faulted, it can show some error image:
public class ThumbnailToBitmapImageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
var thumbnail = value as Thumbnail;
if (thumbnail == null) return GetDefaultBitmap();
if (thumbnail.Image.IsCompleted == false) return GetDefaultBitmap();
if (thumbnail.Image.IsFaulted) return GetBadImage();
return thumbnail.Image.Result;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
private BitMapSource GetDefaultBitmap()
{
// load a default image
}
private BitMapSource GetBadImage()
{
// load a ! image
}
}

Windows Phone 8 ImageSource cannot be serialized Error while sharing image

i am trying to share an image. I got a picture object and am getting the path from it. When I'm calling the ShareMediaTask it throw following error:
System.Windows.Media.ImageSource cannot be serialized.
I am still able to share the image, but the app crashes when returning from sharing.
Here is my code:
PictureModel picture = Singleton.Instance.BearPicture.Model.Images.Where(PictureModel => PictureModel.Bmp.UriSource == (Image_View.Source as BitmapImage).UriSource).FirstOrDefault();
var task = new ShareMediaTask();
task.FilePath = picture.Picture.GetPath();
task.Show();
My PictureModel looks like this:
public class PictureModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _uri;
public string Uri
{
get { return _uri; }
set
{
if (value != _uri)
{
_uri = value;
NotifyPropertyChanged("Uri");
}
}
}
private string _relativePath;
public string RelativePath
{
get { return _relativePath; }
set
{
if (_relativePath != value)
{
_relativePath = value;
NotifyPropertyChanged("RelativePath");
}
}
}
private BitmapImage _bmp;
public BitmapImage Bmp
{
get { return _bmp; }
set
{
if (value != _bmp)
{
_bmp = value;
NotifyPropertyChanged("Bmp");
}
}
}
private Picture _picture;
public Picture Picture
{
get { return _picture; }
set
{
if (value != _picture)
{
_picture = value;
NotifyPropertyChanged("Picture");
}
}
}
private void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Where does this error come from? I am only getting the Source of my image object but i am not doing anything else with it. My picture is also saved in the media library like this:
myFileStream = myStore.OpenFile(fileName, FileMode.Open, FileAccess.Read);
MediaLibrary library = new MediaLibrary();
Picture pic = library.SavePicture(fileName, myFileStream);
On Appstart im searching through my savedpicture folder, to get the picture object, which is then saved in my PictureModel.
Any help is appreciated.
Thanks in advance.
robidd
This may help: Crashes Back (WriteableBitmap cannot be serialized) windows phone 8. See the comment from KooKiz.
"Same symptoms, same cause. You've stored at some point an ImageSource in the phone state (probably PhoneApplicationService.Current.State or IsolatedStorageSettings.ApplicationSettings). You have to find where!"
Apparently we can cause this error indirectly. I'm having a similar problem and I found that answer and also your own question.
Hope it helps.
Cheers.

How can I save a JSON response to a file in unity3D for ios and android

I'm working on a 2D mobile game for ios and android using Unity3D.
The game requires to save a JSON response to a file.
I use NGUI and MiniJSON for that.
I want to know how to implement that starting from www function to get JSOn response and save it to a file(including path) and load it from other script.
if it is too much, just give me a example for that.
Thank you
I haven't tested the code yet, but it might give you an idea :-)
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;
public class WWWJsonTest : MonoBehaviour
{
private const float SECONDS_BEFORE_TIMEOUT = 10;
private const string URL = "INSERT URL HERE";
private const string FILE_PATH = "INSERT FILE PATH";
public void DownloadAndSave()
{
StartCoroutine(DownloadCoroutine());
}
public Dictionary<object, object> GetSavedData()
{
// Use ReadContents() and do your MiniJSON magic here
return null;
}
private IEnumerator DownloadCoroutine()
{
var requestHeaders = new Hashtable()
{
{ "Connection", "close"},
{ "Accept", "application/json"}
};
using(var request = new WWW(URL, null, requestHeaders))
{
float timeStarted = Time.realtimeSinceStartup;
while(!request.isDone)
{
// Check if the download times out
if(Time.realtimeSinceStartup - timeStarted > SECONDS_BEFORE_TIMEOUT)
{
Debug.Log("Download timed out");
yield break;
}
yield return null;
}
// Check for other errors
if(request.error != null)
{
Debug.Log(request.error);
yield break;
}
SaveContents(request.text);
}
}
private string ReadContents()
{
string ret;
using(FileStream fs = new FileStream(FILE_PATH, FileMode.Open))
{
BinaryReader fileReader = new BinaryReader(fs);
ret = fileReader.ReadString();
fs.Close();
}
return ret;
}
private void SaveContents(string text)
{
using(FileStream fs = new FileStream(FILE_PATH, FileMode.Create))
{
BinaryWriter fileWriter = new BinaryWriter(fs);
fileWriter.Write(text);
fs.Close();
}
}
}