-1

I'm a beginner and trying to learn to code html here by playing around the codes I found online. And I came across a javascript that basically snip image into several boxes. The code goes like this:

$(function() {

  var canvas = document.getElementById("canvas");
  var ctx = canvas.getContext("2d");
  var cw, ch;

  // background definition
  // OPTION: look at the top-left pixel and assume == background
  //         then set these vars automatically
  var isTransparent = false;
  var bkColor = {
    r: 255,
    g: 255,
    b: 255
  };
  var bkFillColor = "rgb(" + bkColor.r + "," + bkColor.g + "," + bkColor.b + ")";

  // load test image
  var img = new Image();
  img.crossOrigin = "anonymous";
  img.onload = start;
  img.src = "http://nedroid.com/comics/2010-09-06-guest-comic-jay-fuller.png";

  function start() {
    // draw the test image on the canvas
    cw = canvas.width = img.width / 2;
    ch = canvas.height = img.width / 2;
    ctx.drawImage(img, 0, 0, cw, ch);
  }


  function clipBox(data) {
    var pos = findEdge(data);
    if (!pos.valid) {
      return;
    }
    var bb = findBoundary(pos, data);
    clipToImage(bb.x, bb.y, bb.width, bb.height);
    if (isTransparent) {
      // clear the clipped area
      // plus a few pixels to clear any anti-aliasing
      ctx.clearRect(bb.x - 2, bb.y - 2, bb.width + 4, bb.height + 4);
    } else {
      // fill the clipped area with the bkColor
      // plus a few pixels to clear any anti-aliasing
      ctx.fillStyle = bkFillColor;
      ctx.fillRect(bb.x - 2, bb.y - 2, bb.width + 4, bb.height + 4);
    }
  }

  function xyIsInImage(data, x, y) {
    // find the starting index of the r,g,b,a of pixel x,y
    var start = (y * cw + x) * 4;
    if (isTransparent) {
      return (data[start + 3] > 25);
    } else {
      var r = data[start + 0];
      var g = data[start + 1];
      var b = data[start + 2];
      var a = data[start + 3]; // pixel alpha (opacity)
      var deltaR = Math.abs(bkColor.r - r);
      var deltaG = Math.abs(bkColor.g - g);
      var deltaB = Math.abs(bkColor.b - b);
      return (!(deltaR < 5 && deltaG < 5 && deltaB < 5 && a > 25));
    }
  }

  function findEdge(data) {
    for (var y = 0; y < ch; y++) {
      for (var x = 0; x < cw; x++) {
        if (xyIsInImage(data, x, y)) {
          return ({
            x: x,
            y: y,
            valid: true
          });
        }
      }
    }
    return ({
      x: -100,
      y: -100,
      valid: false
    });
  }

  function findBoundary(pos, data) {
    var x0 = x1 = pos.x;
    var y0 = y1 = pos.y;
    while (y1 <= ch && xyIsInImage(data, x1, y1)) {
      y1++;
    }
    var x2 = x1;
    var y2 = y1 - 1;
    while (x2 <= cw && xyIsInImage(data, x2, y2)) {
      x2++;
    }
    return ({
      x: x0,
      y: y0,
      width: x2 - x0,
      height: y2 - y0 + 1
    });
  }

  function drawLine(x1, y1, x2, y2) {
    ctx.beginPath();
    ctx.moveTo(x1, y1);
    ctx.lineTo(x2, y2);
    ctx.strokeStyle = "red";
    ctx.lineWidth = 0.50;
    ctx.stroke();
  }

  function clipToImage(x, y, w, h) {
    // don't save anti-alias slivers
    if (w < 3 || h < 3) {
      return;
    }
    // save clipped area to an img element
    var tempCanvas = document.createElement("canvas");
    var tempCtx = tempCanvas.getContext("2d");
    tempCanvas.width = w;
    tempCanvas.height = h;
    tempCtx.drawImage(canvas, x, y, w, h, 0, 0, w, h);
    var image = new Image();
    image.width = w;
    image.height = h;
    image.src = tempCanvas.toDataURL();
    $("#clips").append(image);
  }

  $("#unbox").click(function() {
    var imgData = ctx.getImageData(0, 0, cw, ch);
    var data = imgData.data;
    clipBox(data);
  });

}); // end $(function(){});
body {
  background-color: ivory;
}

canvas {
  border: 1px solid red;
}

#clips {
  border: 1px solid blue;
  padding: 5px;
}

img {
  margin: 3px;
}
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js">
</script>
<button id="unbox">Clip next sub-image</button><br>
<canvas id="canvas" width=300 height=150></canvas><br>
<h4>Below are images clipped from the canvas above.</h4><br>
<div id="clips"></div>

Nothing happen when I click the button, not even the image is loaded onto the canvas. I searched through various online tutorials and that leads to nothing. I have tried forcefully call out the function using start(); in the <body> section but still it's not working.

T.PC
  • 59
  • 8
  • `Nothing happen when I click the button` not true at all, I'm getting a pretty clear error message in the browser console. Also, stack overflow isn't a "fix the code I found online" website. And: [How much research effort is expected of Stack Overflow users?](https://meta.stackoverflow.com/a/261593/5734311) –  May 30 '18 at 14:10
  • 1
    In order to understand why it's not working, you'll need to learn a bit about CORS https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS. If you were to replace the img.src line with `img.src="https://cors-anywhere.herokuapp.com/http://nedroid.com/comics/2010-09-06-guest-comic-jay-fuller.png";` you'll find that the code seems to work. – thmsdnnr May 30 '18 at 14:12
  • https://codepen.io/anon/pen/YvPZzv in my pen, the code was blocking at a failed cross-origin request when trying to load the image onto the canvas. – thmsdnnr May 30 '18 at 14:14
  • @thmsdnnr That codepen works fine for me. In fact, other than getting a 404 for reset.css, it all works perfectly. – Reinstate Monica Cellio May 30 '18 at 14:15
  • @thmsdnnr This isn't a CORS issue; the problem is that browsers won't load `http` images in a `https` environment. The CORS proxy happened to fix it because it's served with `https`. –  May 30 '18 at 14:16
  • @ChrisG my understanding was that the http/https made it cross-origin https://stackoverflow.com/a/19542686/7316502 as well due to differing protocol. Perhaps both issues are at play here? – thmsdnnr May 30 '18 at 14:25
  • @thmsdnnr This is about loading images, and loading them from other domains is not a problem and never has been. So yes, strictly speaking the http/https issue can be labeled a cors issue, but it's misleading to say the least. The true issue is including non-https resources in https served documents, something that has nothing to do with cors. –  May 30 '18 at 14:29

1 Answers1

0

Problem is not in the code,

it is in the location of Image, put the image on the same domain or use the image as data uri check CODEPEN for working example.

https://codepen.io/mastersmind/pen/bKNqNP?editors=0011

remove this line

img.crossOrigin = "anonymous";
mastermind
  • 1,057
  • 1
  • 8
  • 15
  • thanks, it works when I removed the `img.crossOrigin = "anonymous";` in Codepen. But when I edit the html code in notepad and save it into .html file, it doesn't work even though the image was located in my local drive. Is there any additional permission required in the case of .html file? – T.PC Jun 03 '18 at 02:50
  • also I can't help but notice that the addres in `img.src` in your pen is very different. Is it because you upload the image into Codepen or Google Drive? If I uses the image URL, image is loaded into the canvas but I was unable to cut the image. I apologize for the repeated question but is it again about the security problem and do I need additional permission for this? – T.PC Jun 03 '18 at 03:15
  • to overcome the security i convert the image in to [Data URI](http://blog.teamtreehouse.com/using-data-uris-speed-website) – mastermind Jun 03 '18 at 09:43
  • is there any other way to solve this security problem without using Data URI? – T.PC Jun 04 '18 at 12:09