Nativescript: ImageSource.saveToFile does not work with format 'jpg'

Created on 21 Sep 2017  ยท  14Comments  ยท  Source: NativeScript/NativeScript

Tell us about the problem

Trying to write an ImageSource to a file does not work on iOS when specifying 'jpg' as format ('jpeg' works fine).

Which platform(s) does your issue occur on?

iOS simulator (waiting for apple to approve my dev account to be able to deploy/test to real iOS device)

Please provide the following version numbers that your issue occurs with:

$ tns info
All NativeScript components versions information
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Component        โ”‚ Current version โ”‚ Latest version โ”‚ Information โ”‚
โ”‚ nativescript     โ”‚ 3.2.1           โ”‚ 3.2.1          โ”‚ Up to date  โ”‚
โ”‚ tns-core-modules โ”‚ 3.2.0           โ”‚ 3.2.0          โ”‚ Up to date  โ”‚
โ”‚ tns-android      โ”‚ 3.2.0           โ”‚ 3.2.0          โ”‚ Up to date  โ”‚
โ”‚ tns-ios          โ”‚ 3.2.0           โ”‚ 3.2.0          โ”‚ Up to date  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Is there code involved? If so, please share the minimal amount of code needed to recreate the problem.

const targetFilename = 'test.jpg';
const tempPath = fs.knownFolders.temp().path;
const localFullPath = fs.path.join(tempPath, targetFilename);
let saved = imageSrc.saveToFile(localFullPath, 'jpeg'); // format 'jpg' does NOT work on iOS!
backlog ios medium

Most helpful comment

The code seems to be identical but it's not :)

In the first solution I use source.saveToFile() and source is the reference to ImageSource used to load image by .fromAsset() method (and works on android returning TRUE).
In the second solution I use result.saveToFile() and result is the reference to a new ImageSource returned by the Promise.

What works on ANDROID (commented):

      const source = new imageSource.ImageSource(); // New instance of IMAGESOURCE
      source.fromAsset(picture).then((result) => { 
        const saved = source.saveToFile(path, "png"); // <= use **source**.saveToFile
        console.log(saved); //True on ANDROID but false on IOS
      });

What works on iOs (not tested on Android):

     const source = new imageSource.ImageSource();
      source.fromAsset(picture).then((result) => {

        const saved = result.saveToFile(path, "png"); // <= use the result which is returned by the Promise 
        console.log(saved); //True on IOS - not tested on android
      });

All 14 comments

Hi @abhayastudios,
I tested your scenario with saving the imageSource to external file while using saveToFile method, however, the file is saved properly while using jpg and jpeg file extensions.
For your convenience, I am attaching GIF file and sample project. You could review it and make the needed changes, which will allow us to recreate the problem.
Please provide some further info about the iOS device or emulator, which you are using while debugging.

screencast 2017-09-25 at 1 23 23 pm
Archive.zip

@tsonevn I am actually using the Angular 2 version, but even your example doesn't work for me. After tapping I don't see any image, and also changing these lines below in main-page.ts, will print CONSOLE LOG file:///app/main-page.js:45:16: saved: false

var saved = imagesourcetest.saveToFile(localFullPath, "jpg");
console.log(`saved: ${saved}`);

I am testing on iOS simulator Version 10.0 (SimulatorApp-745.10).

Hi @abhayastudios,
I tested the project with iOS 10.0 and indeed the saveToFile method will not save the image source to the specified path. We will research this problem and you could keep track on the issue for further info.

Camera.requestPermissions();
Camera.takePicture({saveToGallery: false}).then((picture) => {
      const folder = FileSystem.knownFolders.documents();
      const path = FileSystem.path.join(folder.path, MD5(new Date()) + ".png");
      const source = new imageSource.ImageSource();
      source.fromAsset(picture).then((result) => {
        const saved = source.saveToFile(path, "png");
        console.log(saved); //True on ANDROID but false on IOS
      });
});

Testing on physical device (IPhone 5) and on Samsung S6. It's ok on Samsung while fails on iPhone.
On iPhone the path that has to be written is something like:

/var/mobile/Containers/Data/Application/--SOME APP ID STRING--/Documents/thefilename.png

printed by console.log(path)

Hi @gepisolo,
if I understand you correctly you are able to recreate the same problem while using 'png', format.
Is that correct? Also, it would help if you provide sample project, which could be debugged locally and more info about your environment(CLI. modules, runtime versions.).

Yes exactly:

This is my environment:

{
  "description": "xxx",
  "license": "SEE LICENSE IN <your-license-filename>",
  "readme": "xxxx",
  "repository": "<fill-your-repository-here>",
  "nativescript": {
    "id": "org.nativescript.PsoApp",
    "tns-android": {
      "version": "3.2.0"
    },
    "tns-ios": {
      "version": "3.4.0"
    }
  },
  "scripts": {
    "lint": "tslint \"app/**/*.ts\""
  },
  "dependencies": {
    "@angular/animations": "4.2.5",
    "@angular/common": "4.2.5",
    "@angular/compiler": "4.2.5",
    "@angular/core": "4.2.5",
    "@angular/forms": "4.2.5",
    "@angular/http": "4.2.5",
    "@angular/platform-browser": "4.2.5",
    "@angular/router": "4.2.5",
    "angular2-jwt": "^0.2.3",
    "blueimp-md5": "^2.10.0",
    "crypto-js": "^3.1.9-1",
    "nativescript-angular": "4.2.0",
    "nativescript-background-http": "^3.1.0",
    "nativescript-camera": "^3.1.4",
    "nativescript-cardview": "^2.0.4",
    "nativescript-fancyalert": "^1.1.2",
    "nativescript-file-photoview": "^0.1.5",
    "nativescript-floatingactionbutton": "^4.1.3",
    "nativescript-permissions": "^1.2.3",
    "nativescript-photoviewer": "^1.2.0",
    "nativescript-pro-ui": "^3.2.0",
    "nativescript-theme-core": "1.0.4",
    "reflect-metadata": "0.1.10",
    "rxjs": "5.4.3",
    "tns-core-modules": "~3.3.0",
    "zone.js": "0.8.17"
  },
  "devDependencies": {
    "babel-traverse": "6.4.5",
    "babel-types": "6.4.5",
    "babylon": "6.4.5",
    "codelyzer": "3.2.0",
    "lazy": "1.0.11",
    "nativescript-dev-sass": "1.3.2",
    "nativescript-dev-typescript": "0.5.1",
    "node-sass": "4.5.3",
    "tslint": "5.7.0",
    "typescript": "2.5.2"
  }
}

Everything works fine on Android (emulators and devices).
As soon as I can I'll try to give you a sample project on github

Hi @abhayastudios,
I look forward to the sample project.
In the meantime would also suggest upgrading all dependencies in your project, while following the below-attached package.json file.

{
    "description": "NativeScript Application",
    "license": "SEE LICENSE IN <your-license-filename>",
    "readme": "NativeScript Application",
    "repository": "<fill-your-repository-here>",
    "nativescript": {
        "id": "org.nativescript.testNG",
        "tns-android": {
            "version": "3.4.1"
        },
        "tns-ios": {
            "version": "3.4.1"
        }
    },
    "dependencies": {
        "@angular/animations": "~5.2.0",
        "@angular/common": "~5.2.0",
        "@angular/compiler": "~5.2.0",
        "@angular/core": "~5.2.0",
        "@angular/forms": "~5.2.0",
        "@angular/http": "~5.2.0",
        "@angular/platform-browser": "~5.2.0",
        "@angular/platform-browser-dynamic": "~5.2.0",
        "@angular/router": "~5.2.0",
        "nativescript-angular": "~5.2.0",
        "nativescript-theme-core": "~1.0.4",
        "reflect-metadata": "~0.1.8",
        "rxjs": "~5.5.2",
        "tns-core-modules": "~3.4.0",
        "zone.js": "~0.8.2"
    },
    "devDependencies": {
        "babel-traverse": "6.26.0",
        "babel-types": "6.26.0",
        "babylon": "6.18.0",
        "lazy": "1.0.11",
        "nativescript-dev-typescript": "~0.6.0",
        "typescript": "~2.6.2"
    }
}

Here is the sample project:

https://github.com/gepisolo/NSHelloWorldWCamera

Tested on iphone 5 => Saved is false ... so the problem is still there even with dependencies upgraded.
I'm not going to update dependencies on my own project right now, unless it'is really needed. I've done it in the past (with other projects) and I had issues to fix

I can't know if the problem is about permissions on a test device (the iphone is plugged to PC with USB) ... but I can't go online on iTunes with untested functionalities...

I have found the possible solution:

WRONG way (but worked on Android anyway)

      const source = new imageSource.ImageSource();
      source.fromAsset(picture).then((result) => {
        const saved = source.saveToFile(path, "png");
        console.log(saved); //True on ANDROID but false on IOS
      });

RIGHT WAY (for ios)

     const source = new imageSource.ImageSource();
      source.fromAsset(picture).then((result) => {
        const saved = result.saveToFile(path, "png"); //Use the result imageSource not the original
        console.log(saved); //True on IOS - not tested on android
      });

Hi @gepisolo,
Thank you for the sample project,
I tested it and was able to recreate this scenario. Also, I review the provided solutions, however the code for Android and iOS seems to be identical. Could you provide some more info about the solution and what is the difference on both scenarios?

The code seems to be identical but it's not :)

In the first solution I use source.saveToFile() and source is the reference to ImageSource used to load image by .fromAsset() method (and works on android returning TRUE).
In the second solution I use result.saveToFile() and result is the reference to a new ImageSource returned by the Promise.

What works on ANDROID (commented):

      const source = new imageSource.ImageSource(); // New instance of IMAGESOURCE
      source.fromAsset(picture).then((result) => { 
        const saved = source.saveToFile(path, "png"); // <= use **source**.saveToFile
        console.log(saved); //True on ANDROID but false on IOS
      });

What works on iOs (not tested on Android):

     const source = new imageSource.ImageSource();
      source.fromAsset(picture).then((result) => {

        const saved = result.saveToFile(path, "png"); // <= use the result which is returned by the Promise 
        console.log(saved); //True on IOS - not tested on android
      });

The saveToFile method still does not work with .jpg on iOS.

@gepisolo You saved my Day!
I had also the problem that the imageSource is empty on iOS.
I now use the source that is returned from the "fromAsset()" Promise, as you suggested, and it works like a charm :-) (Tested on an iPhone SE 11.3.1)
I can confirm that this works for Android too (Tested on a real Device with 8.1.0)
Thanks a lot!

So i think there is still a bug open for "fromAsset()".

The code seems to be identical but it's not :)

In the first solution I use source.saveToFile() and source is the reference to ImageSource used to load image by .fromAsset() method (and works on android returning TRUE).
In the second solution I use result.saveToFile() and result is the reference to a new ImageSource returned by the Promise.

What works on ANDROID (commented):

      const source = new imageSource.ImageSource(); // New instance of IMAGESOURCE
      source.fromAsset(picture).then((result) => { 
        const saved = source.saveToFile(path, "png"); // <= use **source**.saveToFile
        console.log(saved); //True on ANDROID but false on IOS
      });

What works on iOs (not tested on Android):

     const source = new imageSource.ImageSource();
      source.fromAsset(picture).then((result) => {

        const saved = result.saveToFile(path, "png"); // <= use the result which is returned by the Promise 
        console.log(saved); //True on IOS - not tested on android
      });

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Leo-lay picture Leo-lay  ยท  3Comments

yclau picture yclau  ยท  3Comments

rLoka picture rLoka  ยท  3Comments

vtisnado picture vtisnado  ยท  3Comments

pocesar picture pocesar  ยท  3Comments