Image not initialized fast enough?


#1

Inside of my application when I visit one of my html pages I want the code inside of the controller to execute as fast as possible. The problem is I am recieveing the error:

Error: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The source width is 0.

The controller is taking an image and then applying a filter to it and then creating a brand new image. This brand new image is then stored in a variable. When I click one of the buttons, the appropriate filter is applied by taking the image stored in the variable and applying it to $scope.mainImage in which then angularjs takes over with its 2 way data binding and shows the new filtered image on the screen. The problem is when the view loads initially the original image (img/testing.jpg) appears, but the error is in the console and non of the new images are created.

CONTROLLER:

app.controller(‘PhotoController’, function($ionicPlatform,$scope,$state,$localstorage,$ionicHistory,$http,$cordovaCapture,$cordovaFile) {

$ionicPlatform.ready(function($cordovaStatusbar) {

if(window.cordova && window.cordova.plugins.Keyboard) {
    cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);

     $scope.mainImage = 'img/testing.jpg';


    /*
         Alot more code here
    */

//piece of code where the error is occurring:
.
.
.
.
filterImage: function(filter, args) {
console.log("Filter = " + filter);
if(this.pixelData) { // if multiple filters are applied
console.log(“inside this.pixelData”);
this.ctx.putImageData(this.pixelData, 0, 0);
}
// !!!ERROR OCCUR HERE!!! var params = [this.ctx.getImageData(0, 0, this.c.width, this.c.height)]; // !!!ERROR OCCUR HERE!!!

                for (var i = 1; i <arguments.length; i++) {
                    params.push(arguments[i]);
                }
                this.pixelData =  this[filter].apply(this, params);
            }

.
.
.
.

    $scope.img1 = null;
    $scope.img2 = null;

        var originalPhoto = document.getElementById('originalPhoto');

        $scope.img1 = ApplyEffects['reset'](originalPhoto, 'jpeg').src;
        $scope.changeReset = function () {
            $scope.mainImage = $scope.img1;
        };

        $scope.img2 = ApplyEffects['memphis'](originalPhoto, 'jpeg').src;
        $scope.changeMemphis = function () {
            $scope.mainImage = $scope.img2;
        };  

});
});

HTML:

        <figure>
            <img id="originalPhoto" ng-src="{{$parent.mainImage}}" width="200" height="200">
        </figure>

        <button ng-click="$parent.changeReset()">Reset</button>
        <button ng-click="$parent.changeMemphis()">Memphis</button>

    </section>
</ion-content>

If I wrap this seciton of code:

    var originalPhoto = document.getElementById('originalPhoto');

        $scope.img1 = ApplyEffects['reset'](originalPhoto, 'jpeg').src;
        $scope.changeReset = function () {
            $scope.mainImage = $scope.img1;
        };

        $scope.img2 = ApplyEffects['memphis'](originalPhoto, 'jpeg').src;
        $scope.changeMemphis = function () {
            $scope.mainImage = $scope.img2;
        };  

});
});

inside of a timeout function of say 2 seconds then it will work, but it is very slow. If I set it to a lower timeout of say 0.5 seconds then it is a little quicker, but on some devices it works and other devices it doesn’t. I would like this code though to execute as fast as possible.

It seems to me that maybe the original image is not being initialized since it works with the timeout function, but with $ionicPlatform.ready I think it should only run when this is initialized. My timeout solution though to me is too slow and unreliable


#2

you should wait until the image is ready and loaded:

create a image tag (not connected to the dom)

var img = new Image();

Add a callback-function if the image is loaded -->

img.onload = function () { // do something with the image  };

After you defined the onload function --> set the image source

img.src = 'PATH';

And wait^^


#3

you should use ng-src on the image tag and use your variable on the view, it’s designed to solve this problem.


#4

@delta98
yeah but it seems that the image is used to fill a canvas or something… so the load event is easy to get recognized if it is ready.


#5

@delta98 am I not already doing that? I have the ng-src on the img tag and setting iit as the variable mainImage?


#6

@bengtler thanks for the suggestion I will give it a try later today and let everyone know how it goes. Cheers