Dropped Image not showing in the draw loop. (gotFile, createImg, image(...) )

I still have my weird problem with a dropped image, but now I think I have a better description of the problem! (And this time, it's not related with AdBlock)

Note: this used to work correctly in a previous version of the library (p5-v0.4.3 April 09, 2015)

To show you the problem, I started from the Drop example on the website (http://p5js.org/examples/examples/Dom_Drop.php).

I modified the code just a little bit :

Changes:

1) now the image is draw in the draw loop image(img, 0, 0, width, height);

2) the noLoop() was removed because I need the loop to perform an animation.

Problem: As you can see, the image is always hidden. If I remove the .hide(), the image is draw correctly in the loop but the original one is also not hidden and is displayed just below the canvas.

    var img = null;
    function setup() {
      var c = createCanvas(710, 400);
      background(100);
      c.drop(gotFile);
    }

    function draw() {
      background(0);
      fill(255);
      noStroke();
      textSize(24);
      textAlign(CENTER);
      text('Drag an image file onto the canvas.', width/2, height/2);
      if(img){
        image(img, 0, 0, width, height);   
      }
    }

    function gotFile(file) {
      if (file.type === 'image') {
        img = createImg(file.data).hide();
      } else {
        println('Not an image file!');
      }
    }

Answers

  • edited November 2015

    I did a test by cloning (using jQuery) the object so that now, img is not a reference to the same hidden object but really a new object not hidden :

    function gotFile(file) {
      if (file.type === 'image') {
        var dummyImg = p.createImg(file.data);
        img = jQuery.extend({}, dummyImg); //now img is a clone, not a reference
        dummyImg.hide(); //only the origin cloned image is hidden
      } else {
        println('Not an image file!');
      }
    }
    

    Because this work exacly as it should, and as it worked in a previous version of the library, I suggest that a programmer may have (by mistake) removed a cloning function in the createImg of gotFile code... should I log the bug in github ?

  • edited November 2015
    // forum.processing.org/two/discussion/13650/
    // dropped-image-not-showing-in-the-draw-loop-gotfile-createimg-image
    
    var img;
    
    function setup() {
      createCanvas(800, 600).drop(gotFile);
      noStroke().fill(0xff).noLoop();
      textSize(24).textAlign(CENTER);
    }
    
    function draw() {
      background(0200);
      if (img)  image(img, 0, 0, width, height);
      else      text('Drag an image file onto the canvas.', width>>1, height>>1);
    }
    
    function gotFile(file) {
      if (file.type == 'image')  img = createImg(file.data).hide(), redraw();
      else                       print('Not an image file!');
    }
    
  • edited November 2015

    All HTMLElement tags created by "p5.dom"'s methods are p5.Element wrapper objects.
    In order to access the actual HTMLElement object we do it via its elt property:
    http://p5js.org/reference/#/p5.Element/elt

  • edited November 2016 Answer ✓

    Found a much better option, replacing createImg(), which returns a p5.Element, w/ loadImage(), which returns a p5.Image instead.

    It even works w/o noLoop() + redraw()! But for something so event-driven, it's better keep noLoop() active so the canvas is refreshed only when something actually drop(). :P

    http://p5js.ProcessingTogether.com/sp/pad/export/ro.CYTkHWj9smgw8Q

    <script defer src=http://p5js.org/assets/js/p5.min.js></script>
    <script defer src=http://p5js.org/assets/js/p5.dom.min.js></script>
    <script async src=sketch.js></script>
    
    /**
     * Image Drop (v2.1)
     * GoToLoop (2015-Nov-25)
     *
     * forum.Processing.org/two/discussion/13650/
     * dropped-image-not-showing-in-the-draw-loop-gotfile-createimg-image#Item_4
     *
     * p5js.SketchPad.cc/sp/pad/view/ro.CYTkHWj9smgw8Q/latest
     */
    
    "use strict";
    
    let img, bg;
    
    function setup() {
      createCanvas(800, 600).drop(gotFile);
      noStroke().fill(0xff).frameRate(10).noLoop();
      textSize(24).textAlign(CENTER).blendMode(REPLACE);
      bg = color(0o200);
    }
    
    function draw() {
      background(bg);
      if (img)  image(img, 0, 0, width, height);
      else      text('Drag an image file onto the canvas.', width>>1, height>>1);
    }
    
    function gotFile(f) {
      if (f.type === 'image')  img = loadImage(f.data, redraw);
      else                     print(`"${f.name}" isn't an image file!`);
    }
    
  • edited November 2015

    The example with createImg(...) does not work if you remove the noLoop(): This is the problem. I want the loop. I want to animate the dropped image.

    For example:

       var img;
       var animate = 0;
    
        function setup() {
          createCanvas(800, 600).drop(gotFile);
          noStroke().fill(0xff); //noLoop() removed;
          textSize(24).textAlign(CENTER);
        }
    
        function draw() {
          background(0200);
          if (img)  image(img, animate++, 0, width, height);
          else      text('Drag an image file onto the canvas.', width>>1, height>>1);
        }
    
        function gotFile(file) {
          if (file.type == 'image')  img = createImg(file.data).hide(), redraw();
          else                       println('Not an image file!');
        }
    
  • edited November 2015

    It does not work if you remove the noLoop().

  • edited November 2015

    OK, so the solution is to use img = loadImage(file.data); instead of img = createImg(file.data).hide();. Thank you!

    Since the purpose of p5 is to animate something, the example could be modified to show an animated version on this page:

    http://p5js.org/examples/examples/Dom_Drop.php

    Or maybe show the 2 examples.

    var img;
    var animate = 0;
    
    function setup() {
      var c = createCanvas(710, 400);
      background(100);
      c.drop(gotFile);
    }
    
    function draw() {
      background(0);
      fill(255);
      noStroke();
      textSize(24);
      textAlign(CENTER);
      text('Drag an image file onto the canvas.', width/2, height/2);
      if(img){
        image(img, animate++, 0, width, height);   
      }
    }
    
     function gotFile(file) {
      if (file.type === 'image') {
        img = loadImage(file.data);  //here
      } else {
        println('Not an image file!');
      }
    }
    
  • Since the purpose of p5 is to animate something, the example could be modified to show an animated version...

    The example should just be changed: loading the image into a DOM element for storage purposes looks like a hack to me. It may be that historically there were issues with loadImage that meant it wasn't suitable; but now it obviously does work and seems much more sane...

    @GoToLoop: what console error do you see with noLoop? I don't appear to have any errors in Chrome...

  • edited October 2016

    What console error do you see with noLoop()?

    P.S.: http://p5js.org/reference/#/p5/clear is malfunctioning right now. :-&
    Seems like http://p5js.org/lib/p5.js isn't there anymore. And it's just http://p5js.org/js/p5.min.js http://p5js.org/assets/js/p5.min.js now.

  • edited November 2015

    It may be that historically there were issues with loadImage() that meant it wasn't suitable;

    I believe drop() is a very recent addition to p5.js' API.
    And although it's implemented in "p5.js", yet it depends on p5.File which is from "p5.dom.js"! 8-}

    Anyways, I remember loadImage() had this following if () block for a very long time now:
    https://GitHub.com/processing/p5.js/blob/master/src/image/loading_displaying.js#L94

    if (path.indexOf('data:image/') !== 0) {
      img.crossOrigin = 'Anonymous';
    }
    

    It means it could always deal w/ blobs like data URIs schemes besides regular URL paths. $-)

    Though absent from p5.File's reference page, its data property can also be some base64 encoded string:
    https://developer.Mozilla.org/en-US/docs/Web/API/FileReader/readAsDataURL

    And base64 is also a valid URI and thus can be assigned to an HTMLImageElement's src property:
    https://en.Wikipedia.org/wiki/Data_URI_scheme
    https://GitHub.com/processing/p5.js/blob/master/src/image/loading_displaying.js#L99

    //start loading the image
    img.src = path;
    

    In short, claiming there was a time loadImage() couldn't be used for drop() seems unfounded iMO.
    That http://p5js.org/examples/examples/Dom_Drop.php example is both poor and buggy! :O)

    P.S.: BtW, a very nice article about FileReader: :P
    https://www.nczOnline.net/blog/2012/05/15/working-with-files-in-javascript-part-2/

  • edited November 2015

    I am not really familiar with all the people involved in the project... Who is/are in charge of maintaining the examples (http://p5js.org/examples/) ?

Sign In or Register to comment.