putImageData(), how to keep old pixels if new pixels are transparent?










5














In html5, when you draw to a canvas using putImageData(), if some of the pixels you are drawing are transparent (or semi-transparent), how do you keep old pixels in the canvas unaffected?



example:



var imgData = context.createImageData(30,30);
for(var i=0; i<imgData.data.length; i+=4)

imgData.data[i]=255;
imgData.data[i+1]=0;
imgData.data[i+2]=0;
imgData.data[i+3]=255;
if((i/4)%30 > 15)imgData.data[i+3] = 0;

context.putImageData(imgData,0,0);


The right half of the 30x30 rect is transparent.
If this is drawn over something on the canvas, pixels behind the right half are removed (or become thransparent). How do I keep them?










share|improve this question




























    5














    In html5, when you draw to a canvas using putImageData(), if some of the pixels you are drawing are transparent (or semi-transparent), how do you keep old pixels in the canvas unaffected?



    example:



    var imgData = context.createImageData(30,30);
    for(var i=0; i<imgData.data.length; i+=4)

    imgData.data[i]=255;
    imgData.data[i+1]=0;
    imgData.data[i+2]=0;
    imgData.data[i+3]=255;
    if((i/4)%30 > 15)imgData.data[i+3] = 0;

    context.putImageData(imgData,0,0);


    The right half of the 30x30 rect is transparent.
    If this is drawn over something on the canvas, pixels behind the right half are removed (or become thransparent). How do I keep them?










    share|improve this question


























      5












      5








      5


      1





      In html5, when you draw to a canvas using putImageData(), if some of the pixels you are drawing are transparent (or semi-transparent), how do you keep old pixels in the canvas unaffected?



      example:



      var imgData = context.createImageData(30,30);
      for(var i=0; i<imgData.data.length; i+=4)

      imgData.data[i]=255;
      imgData.data[i+1]=0;
      imgData.data[i+2]=0;
      imgData.data[i+3]=255;
      if((i/4)%30 > 15)imgData.data[i+3] = 0;

      context.putImageData(imgData,0,0);


      The right half of the 30x30 rect is transparent.
      If this is drawn over something on the canvas, pixels behind the right half are removed (or become thransparent). How do I keep them?










      share|improve this question















      In html5, when you draw to a canvas using putImageData(), if some of the pixels you are drawing are transparent (or semi-transparent), how do you keep old pixels in the canvas unaffected?



      example:



      var imgData = context.createImageData(30,30);
      for(var i=0; i<imgData.data.length; i+=4)

      imgData.data[i]=255;
      imgData.data[i+1]=0;
      imgData.data[i+2]=0;
      imgData.data[i+3]=255;
      if((i/4)%30 > 15)imgData.data[i+3] = 0;

      context.putImageData(imgData,0,0);


      The right half of the 30x30 rect is transparent.
      If this is drawn over something on the canvas, pixels behind the right half are removed (or become thransparent). How do I keep them?







      javascript html5 canvas transparency pixel






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Mar 5 '14 at 10:52

























      asked Mar 5 '14 at 9:56









      Mohsin

      15429




      15429






















          4 Answers
          4






          active

          oldest

          votes


















          6














          You can use getImageData to create a semi-transparent overlay:



          • create a temporary offscreen canvas

          • getImageData to get the pixel data from the offscreen canvas

          • modify the pixels as you desire

          • putImageData the pixels back on the offscreen canvas

          • use drawImage to draw the offscreen canvas to the onscreen canvas

          enter image description here



          Here's example code and a Demo: http://jsfiddle.net/m1erickson/CM7uY/



          <!doctype html>
          <html>
          <head>
          <link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
          <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
          <style>
          body background-color: ivory;
          canvasborder:1px solid red;
          </style>
          <script>
          $(function()

          var canvas=document.getElementById("canvas");
          var context=canvas.getContext("2d");

          // draw an image on the canvas
          var img=new Image();
          img.onload=start;
          img.src="https://dl.dropboxusercontent.com/u/139992952/stack1/landscape1.jpg";
          function start()
          canvas.width=img.width;
          canvas.height=img.height;
          context.drawImage(img,0,0);

          // overlay a red gradient
          drawSemiTransparentOverlay(canvas.width/2,canvas.height)



          function drawSemiTransparentOverlay(w,h)

          // create a temporary canvas to hold the gradient overlay
          var canvas2=document.createElement("canvas");
          canvas2.width=w;
          canvas2.height=h
          var ctx2=canvas2.getContext("2d");

          // make gradient using ImageData
          var imgData = ctx2.getImageData(0,0,w,h);
          var data=imgData.data;
          for(var y=0; y<h; y++)
          for(var x=0; x<w; x++)
          var n=((w*y)+x)*4;
          data[n]=255;
          data[n+1]=0;
          data[n+2]=0;
          data[n+3]=255;
          if(x>w/2)
          data[n+3]=255*(1-((x-w/2)/(w/2)));




          // put the modified pixels on the temporary canvas
          ctx2.putImageData(imgData,0,0);

          // draw the temporary gradient canvas on the visible canvas
          context.drawImage(canvas2,0,0);




          ); // end $(function());
          </script>
          </head>
          <body>
          <canvas id="canvas" width=200 height=200></canvas>
          </body>
          </html>


          Alternatively, you might check out using a linear gradient to do your effect more directly.



          http://jsfiddle.net/m1erickson/j6wLR/






          share|improve this answer






















          • Thanks, drawing a canvas onto another using drawImage() is exactly what I need.
            – Mohsin
            Mar 6 '14 at 17:18


















          2














          Problem



          As you know, your statement



          if((i/4)%30 > 15)imgData.data[i+3] = 0;


          will make pixels on the right half of the image be transparent, so that any other object on the page behind the canvas can be seen through the canvas at that pixel position. However, you are still overwriting the pixel of the canvas itself with context.putImageData, which replaces all of its previous pixels. The transparency that you add will not cause the previous pixels of to show through, because the result of putImageData is not a second set of pixels on top of the previous pixels in the canvas, but rather the replacement of existing pixels.



          Solution



          I suggest that you begin your code not with createImageData which will begin with a blank set of data, but rather with getImageData which will give you a copy of the existing data to work with. You can then use your conditional statement to avoid overwriting the portion of the image that you wish to preserve. This will also make your function more efficient.



          var imgData = context.getImageData(30,30);
          for(var i=0; i<imgData.data.length; i+=4)

          if((i/4)%30 > 15) continue;
          imgData.data[i]=255;
          imgData.data[i+1]=0;
          imgData.data[i+2]=0;
          imgData.data[i+3]=255;

          context.putImageData(imgData,0,0);





          share|improve this answer






















          • Thanks. You are right, using getImageData() you can do whatever you want with old pixels, but you need to have a formula to blend new pixels with old ones. I've tried one and it was perfect, but soon when I began to use this in a for loop (for drawing), I got a strange result when I draw something that is transparent.
            – Mohsin
            Mar 6 '14 at 17:31


















          0














          I wanted to copy a CRISP, un modified version of the canvas on top of itself. I eventually came up with this solution, which applies.



          https://jsfiddle.net/4Le454ak/1/



          The copy portion is in this code:



          var imageData = canvas.toDataURL(0, 0, w, h);
          var tmp = document.createElement('img');
          tmp.style.display = 'none'
          tmp.src = imageData;
          document.body.appendChild(tmp);
          ctx.drawImage(tmp, 30, 30);


          What's happening:



          • copy image data from canvas

          • set image data to an unseen ( has to be in dom though)

          • draw that image back onto the canvas

          • you can delete or reuse the at this point





          share|improve this answer




























            0














            Something that tripped me up that may be of use... I had problems with this because I assumed that putImageData() and drawImage() would work in the same way but it seems they don't. putImageData() will overwrite existing pixels with its own transparent data while drawImage() will leave them untouched.



            When looking into this I just glanced at the docs for CanvasRenderingContext2D.globalCompositeOperation (should have read more closely), saw that source-over is the default and didn't realise this would not apply to putImageData()



            Drawing into a temporary canvas then and using drawImage() to add the temp canvas to the main context was the solution I needed so cheers for that.






            share|improve this answer




















              Your Answer






              StackExchange.ifUsing("editor", function ()
              StackExchange.using("externalEditor", function ()
              StackExchange.using("snippets", function ()
              StackExchange.snippets.init();
              );
              );
              , "code-snippets");

              StackExchange.ready(function()
              var channelOptions =
              tags: "".split(" "),
              id: "1"
              ;
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function()
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled)
              StackExchange.using("snippets", function()
              createEditor();
              );

              else
              createEditor();

              );

              function createEditor()
              StackExchange.prepareEditor(
              heartbeatType: 'answer',
              autoActivateHeartbeat: false,
              convertImagesToLinks: true,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: 10,
              bindNavPrevention: true,
              postfix: "",
              imageUploader:
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              ,
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              );



              );













              draft saved

              draft discarded


















              StackExchange.ready(
              function ()
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f22194267%2fputimagedata-how-to-keep-old-pixels-if-new-pixels-are-transparent%23new-answer', 'question_page');

              );

              Post as a guest















              Required, but never shown

























              4 Answers
              4






              active

              oldest

              votes








              4 Answers
              4






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes









              6














              You can use getImageData to create a semi-transparent overlay:



              • create a temporary offscreen canvas

              • getImageData to get the pixel data from the offscreen canvas

              • modify the pixels as you desire

              • putImageData the pixels back on the offscreen canvas

              • use drawImage to draw the offscreen canvas to the onscreen canvas

              enter image description here



              Here's example code and a Demo: http://jsfiddle.net/m1erickson/CM7uY/



              <!doctype html>
              <html>
              <head>
              <link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
              <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
              <style>
              body background-color: ivory;
              canvasborder:1px solid red;
              </style>
              <script>
              $(function()

              var canvas=document.getElementById("canvas");
              var context=canvas.getContext("2d");

              // draw an image on the canvas
              var img=new Image();
              img.onload=start;
              img.src="https://dl.dropboxusercontent.com/u/139992952/stack1/landscape1.jpg";
              function start()
              canvas.width=img.width;
              canvas.height=img.height;
              context.drawImage(img,0,0);

              // overlay a red gradient
              drawSemiTransparentOverlay(canvas.width/2,canvas.height)



              function drawSemiTransparentOverlay(w,h)

              // create a temporary canvas to hold the gradient overlay
              var canvas2=document.createElement("canvas");
              canvas2.width=w;
              canvas2.height=h
              var ctx2=canvas2.getContext("2d");

              // make gradient using ImageData
              var imgData = ctx2.getImageData(0,0,w,h);
              var data=imgData.data;
              for(var y=0; y<h; y++)
              for(var x=0; x<w; x++)
              var n=((w*y)+x)*4;
              data[n]=255;
              data[n+1]=0;
              data[n+2]=0;
              data[n+3]=255;
              if(x>w/2)
              data[n+3]=255*(1-((x-w/2)/(w/2)));




              // put the modified pixels on the temporary canvas
              ctx2.putImageData(imgData,0,0);

              // draw the temporary gradient canvas on the visible canvas
              context.drawImage(canvas2,0,0);




              ); // end $(function());
              </script>
              </head>
              <body>
              <canvas id="canvas" width=200 height=200></canvas>
              </body>
              </html>


              Alternatively, you might check out using a linear gradient to do your effect more directly.



              http://jsfiddle.net/m1erickson/j6wLR/






              share|improve this answer






















              • Thanks, drawing a canvas onto another using drawImage() is exactly what I need.
                – Mohsin
                Mar 6 '14 at 17:18















              6














              You can use getImageData to create a semi-transparent overlay:



              • create a temporary offscreen canvas

              • getImageData to get the pixel data from the offscreen canvas

              • modify the pixels as you desire

              • putImageData the pixels back on the offscreen canvas

              • use drawImage to draw the offscreen canvas to the onscreen canvas

              enter image description here



              Here's example code and a Demo: http://jsfiddle.net/m1erickson/CM7uY/



              <!doctype html>
              <html>
              <head>
              <link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
              <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
              <style>
              body background-color: ivory;
              canvasborder:1px solid red;
              </style>
              <script>
              $(function()

              var canvas=document.getElementById("canvas");
              var context=canvas.getContext("2d");

              // draw an image on the canvas
              var img=new Image();
              img.onload=start;
              img.src="https://dl.dropboxusercontent.com/u/139992952/stack1/landscape1.jpg";
              function start()
              canvas.width=img.width;
              canvas.height=img.height;
              context.drawImage(img,0,0);

              // overlay a red gradient
              drawSemiTransparentOverlay(canvas.width/2,canvas.height)



              function drawSemiTransparentOverlay(w,h)

              // create a temporary canvas to hold the gradient overlay
              var canvas2=document.createElement("canvas");
              canvas2.width=w;
              canvas2.height=h
              var ctx2=canvas2.getContext("2d");

              // make gradient using ImageData
              var imgData = ctx2.getImageData(0,0,w,h);
              var data=imgData.data;
              for(var y=0; y<h; y++)
              for(var x=0; x<w; x++)
              var n=((w*y)+x)*4;
              data[n]=255;
              data[n+1]=0;
              data[n+2]=0;
              data[n+3]=255;
              if(x>w/2)
              data[n+3]=255*(1-((x-w/2)/(w/2)));




              // put the modified pixels on the temporary canvas
              ctx2.putImageData(imgData,0,0);

              // draw the temporary gradient canvas on the visible canvas
              context.drawImage(canvas2,0,0);




              ); // end $(function());
              </script>
              </head>
              <body>
              <canvas id="canvas" width=200 height=200></canvas>
              </body>
              </html>


              Alternatively, you might check out using a linear gradient to do your effect more directly.



              http://jsfiddle.net/m1erickson/j6wLR/






              share|improve this answer






















              • Thanks, drawing a canvas onto another using drawImage() is exactly what I need.
                – Mohsin
                Mar 6 '14 at 17:18













              6












              6








              6






              You can use getImageData to create a semi-transparent overlay:



              • create a temporary offscreen canvas

              • getImageData to get the pixel data from the offscreen canvas

              • modify the pixels as you desire

              • putImageData the pixels back on the offscreen canvas

              • use drawImage to draw the offscreen canvas to the onscreen canvas

              enter image description here



              Here's example code and a Demo: http://jsfiddle.net/m1erickson/CM7uY/



              <!doctype html>
              <html>
              <head>
              <link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
              <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
              <style>
              body background-color: ivory;
              canvasborder:1px solid red;
              </style>
              <script>
              $(function()

              var canvas=document.getElementById("canvas");
              var context=canvas.getContext("2d");

              // draw an image on the canvas
              var img=new Image();
              img.onload=start;
              img.src="https://dl.dropboxusercontent.com/u/139992952/stack1/landscape1.jpg";
              function start()
              canvas.width=img.width;
              canvas.height=img.height;
              context.drawImage(img,0,0);

              // overlay a red gradient
              drawSemiTransparentOverlay(canvas.width/2,canvas.height)



              function drawSemiTransparentOverlay(w,h)

              // create a temporary canvas to hold the gradient overlay
              var canvas2=document.createElement("canvas");
              canvas2.width=w;
              canvas2.height=h
              var ctx2=canvas2.getContext("2d");

              // make gradient using ImageData
              var imgData = ctx2.getImageData(0,0,w,h);
              var data=imgData.data;
              for(var y=0; y<h; y++)
              for(var x=0; x<w; x++)
              var n=((w*y)+x)*4;
              data[n]=255;
              data[n+1]=0;
              data[n+2]=0;
              data[n+3]=255;
              if(x>w/2)
              data[n+3]=255*(1-((x-w/2)/(w/2)));




              // put the modified pixels on the temporary canvas
              ctx2.putImageData(imgData,0,0);

              // draw the temporary gradient canvas on the visible canvas
              context.drawImage(canvas2,0,0);




              ); // end $(function());
              </script>
              </head>
              <body>
              <canvas id="canvas" width=200 height=200></canvas>
              </body>
              </html>


              Alternatively, you might check out using a linear gradient to do your effect more directly.



              http://jsfiddle.net/m1erickson/j6wLR/






              share|improve this answer














              You can use getImageData to create a semi-transparent overlay:



              • create a temporary offscreen canvas

              • getImageData to get the pixel data from the offscreen canvas

              • modify the pixels as you desire

              • putImageData the pixels back on the offscreen canvas

              • use drawImage to draw the offscreen canvas to the onscreen canvas

              enter image description here



              Here's example code and a Demo: http://jsfiddle.net/m1erickson/CM7uY/



              <!doctype html>
              <html>
              <head>
              <link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
              <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
              <style>
              body background-color: ivory;
              canvasborder:1px solid red;
              </style>
              <script>
              $(function()

              var canvas=document.getElementById("canvas");
              var context=canvas.getContext("2d");

              // draw an image on the canvas
              var img=new Image();
              img.onload=start;
              img.src="https://dl.dropboxusercontent.com/u/139992952/stack1/landscape1.jpg";
              function start()
              canvas.width=img.width;
              canvas.height=img.height;
              context.drawImage(img,0,0);

              // overlay a red gradient
              drawSemiTransparentOverlay(canvas.width/2,canvas.height)



              function drawSemiTransparentOverlay(w,h)

              // create a temporary canvas to hold the gradient overlay
              var canvas2=document.createElement("canvas");
              canvas2.width=w;
              canvas2.height=h
              var ctx2=canvas2.getContext("2d");

              // make gradient using ImageData
              var imgData = ctx2.getImageData(0,0,w,h);
              var data=imgData.data;
              for(var y=0; y<h; y++)
              for(var x=0; x<w; x++)
              var n=((w*y)+x)*4;
              data[n]=255;
              data[n+1]=0;
              data[n+2]=0;
              data[n+3]=255;
              if(x>w/2)
              data[n+3]=255*(1-((x-w/2)/(w/2)));




              // put the modified pixels on the temporary canvas
              ctx2.putImageData(imgData,0,0);

              // draw the temporary gradient canvas on the visible canvas
              context.drawImage(canvas2,0,0);




              ); // end $(function());
              </script>
              </head>
              <body>
              <canvas id="canvas" width=200 height=200></canvas>
              </body>
              </html>


              Alternatively, you might check out using a linear gradient to do your effect more directly.



              http://jsfiddle.net/m1erickson/j6wLR/







              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited Mar 5 '14 at 19:22

























              answered Mar 5 '14 at 16:20









              markE

              81.3k9108126




              81.3k9108126











              • Thanks, drawing a canvas onto another using drawImage() is exactly what I need.
                – Mohsin
                Mar 6 '14 at 17:18
















              • Thanks, drawing a canvas onto another using drawImage() is exactly what I need.
                – Mohsin
                Mar 6 '14 at 17:18















              Thanks, drawing a canvas onto another using drawImage() is exactly what I need.
              – Mohsin
              Mar 6 '14 at 17:18




              Thanks, drawing a canvas onto another using drawImage() is exactly what I need.
              – Mohsin
              Mar 6 '14 at 17:18













              2














              Problem



              As you know, your statement



              if((i/4)%30 > 15)imgData.data[i+3] = 0;


              will make pixels on the right half of the image be transparent, so that any other object on the page behind the canvas can be seen through the canvas at that pixel position. However, you are still overwriting the pixel of the canvas itself with context.putImageData, which replaces all of its previous pixels. The transparency that you add will not cause the previous pixels of to show through, because the result of putImageData is not a second set of pixels on top of the previous pixels in the canvas, but rather the replacement of existing pixels.



              Solution



              I suggest that you begin your code not with createImageData which will begin with a blank set of data, but rather with getImageData which will give you a copy of the existing data to work with. You can then use your conditional statement to avoid overwriting the portion of the image that you wish to preserve. This will also make your function more efficient.



              var imgData = context.getImageData(30,30);
              for(var i=0; i<imgData.data.length; i+=4)

              if((i/4)%30 > 15) continue;
              imgData.data[i]=255;
              imgData.data[i+1]=0;
              imgData.data[i+2]=0;
              imgData.data[i+3]=255;

              context.putImageData(imgData,0,0);





              share|improve this answer






















              • Thanks. You are right, using getImageData() you can do whatever you want with old pixels, but you need to have a formula to blend new pixels with old ones. I've tried one and it was perfect, but soon when I began to use this in a for loop (for drawing), I got a strange result when I draw something that is transparent.
                – Mohsin
                Mar 6 '14 at 17:31















              2














              Problem



              As you know, your statement



              if((i/4)%30 > 15)imgData.data[i+3] = 0;


              will make pixels on the right half of the image be transparent, so that any other object on the page behind the canvas can be seen through the canvas at that pixel position. However, you are still overwriting the pixel of the canvas itself with context.putImageData, which replaces all of its previous pixels. The transparency that you add will not cause the previous pixels of to show through, because the result of putImageData is not a second set of pixels on top of the previous pixels in the canvas, but rather the replacement of existing pixels.



              Solution



              I suggest that you begin your code not with createImageData which will begin with a blank set of data, but rather with getImageData which will give you a copy of the existing data to work with. You can then use your conditional statement to avoid overwriting the portion of the image that you wish to preserve. This will also make your function more efficient.



              var imgData = context.getImageData(30,30);
              for(var i=0; i<imgData.data.length; i+=4)

              if((i/4)%30 > 15) continue;
              imgData.data[i]=255;
              imgData.data[i+1]=0;
              imgData.data[i+2]=0;
              imgData.data[i+3]=255;

              context.putImageData(imgData,0,0);





              share|improve this answer






















              • Thanks. You are right, using getImageData() you can do whatever you want with old pixels, but you need to have a formula to blend new pixels with old ones. I've tried one and it was perfect, but soon when I began to use this in a for loop (for drawing), I got a strange result when I draw something that is transparent.
                – Mohsin
                Mar 6 '14 at 17:31













              2












              2








              2






              Problem



              As you know, your statement



              if((i/4)%30 > 15)imgData.data[i+3] = 0;


              will make pixels on the right half of the image be transparent, so that any other object on the page behind the canvas can be seen through the canvas at that pixel position. However, you are still overwriting the pixel of the canvas itself with context.putImageData, which replaces all of its previous pixels. The transparency that you add will not cause the previous pixels of to show through, because the result of putImageData is not a second set of pixels on top of the previous pixels in the canvas, but rather the replacement of existing pixels.



              Solution



              I suggest that you begin your code not with createImageData which will begin with a blank set of data, but rather with getImageData which will give you a copy of the existing data to work with. You can then use your conditional statement to avoid overwriting the portion of the image that you wish to preserve. This will also make your function more efficient.



              var imgData = context.getImageData(30,30);
              for(var i=0; i<imgData.data.length; i+=4)

              if((i/4)%30 > 15) continue;
              imgData.data[i]=255;
              imgData.data[i+1]=0;
              imgData.data[i+2]=0;
              imgData.data[i+3]=255;

              context.putImageData(imgData,0,0);





              share|improve this answer














              Problem



              As you know, your statement



              if((i/4)%30 > 15)imgData.data[i+3] = 0;


              will make pixels on the right half of the image be transparent, so that any other object on the page behind the canvas can be seen through the canvas at that pixel position. However, you are still overwriting the pixel of the canvas itself with context.putImageData, which replaces all of its previous pixels. The transparency that you add will not cause the previous pixels of to show through, because the result of putImageData is not a second set of pixels on top of the previous pixels in the canvas, but rather the replacement of existing pixels.



              Solution



              I suggest that you begin your code not with createImageData which will begin with a blank set of data, but rather with getImageData which will give you a copy of the existing data to work with. You can then use your conditional statement to avoid overwriting the portion of the image that you wish to preserve. This will also make your function more efficient.



              var imgData = context.getImageData(30,30);
              for(var i=0; i<imgData.data.length; i+=4)

              if((i/4)%30 > 15) continue;
              imgData.data[i]=255;
              imgData.data[i+1]=0;
              imgData.data[i+2]=0;
              imgData.data[i+3]=255;

              context.putImageData(imgData,0,0);






              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited Mar 5 '14 at 16:51

























              answered Mar 5 '14 at 16:44









              Joseph Myers

              5,2291934




              5,2291934











              • Thanks. You are right, using getImageData() you can do whatever you want with old pixels, but you need to have a formula to blend new pixels with old ones. I've tried one and it was perfect, but soon when I began to use this in a for loop (for drawing), I got a strange result when I draw something that is transparent.
                – Mohsin
                Mar 6 '14 at 17:31
















              • Thanks. You are right, using getImageData() you can do whatever you want with old pixels, but you need to have a formula to blend new pixels with old ones. I've tried one and it was perfect, but soon when I began to use this in a for loop (for drawing), I got a strange result when I draw something that is transparent.
                – Mohsin
                Mar 6 '14 at 17:31















              Thanks. You are right, using getImageData() you can do whatever you want with old pixels, but you need to have a formula to blend new pixels with old ones. I've tried one and it was perfect, but soon when I began to use this in a for loop (for drawing), I got a strange result when I draw something that is transparent.
              – Mohsin
              Mar 6 '14 at 17:31




              Thanks. You are right, using getImageData() you can do whatever you want with old pixels, but you need to have a formula to blend new pixels with old ones. I've tried one and it was perfect, but soon when I began to use this in a for loop (for drawing), I got a strange result when I draw something that is transparent.
              – Mohsin
              Mar 6 '14 at 17:31











              0














              I wanted to copy a CRISP, un modified version of the canvas on top of itself. I eventually came up with this solution, which applies.



              https://jsfiddle.net/4Le454ak/1/



              The copy portion is in this code:



              var imageData = canvas.toDataURL(0, 0, w, h);
              var tmp = document.createElement('img');
              tmp.style.display = 'none'
              tmp.src = imageData;
              document.body.appendChild(tmp);
              ctx.drawImage(tmp, 30, 30);


              What's happening:



              • copy image data from canvas

              • set image data to an unseen ( has to be in dom though)

              • draw that image back onto the canvas

              • you can delete or reuse the at this point





              share|improve this answer

























                0














                I wanted to copy a CRISP, un modified version of the canvas on top of itself. I eventually came up with this solution, which applies.



                https://jsfiddle.net/4Le454ak/1/



                The copy portion is in this code:



                var imageData = canvas.toDataURL(0, 0, w, h);
                var tmp = document.createElement('img');
                tmp.style.display = 'none'
                tmp.src = imageData;
                document.body.appendChild(tmp);
                ctx.drawImage(tmp, 30, 30);


                What's happening:



                • copy image data from canvas

                • set image data to an unseen ( has to be in dom though)

                • draw that image back onto the canvas

                • you can delete or reuse the at this point





                share|improve this answer























                  0












                  0








                  0






                  I wanted to copy a CRISP, un modified version of the canvas on top of itself. I eventually came up with this solution, which applies.



                  https://jsfiddle.net/4Le454ak/1/



                  The copy portion is in this code:



                  var imageData = canvas.toDataURL(0, 0, w, h);
                  var tmp = document.createElement('img');
                  tmp.style.display = 'none'
                  tmp.src = imageData;
                  document.body.appendChild(tmp);
                  ctx.drawImage(tmp, 30, 30);


                  What's happening:



                  • copy image data from canvas

                  • set image data to an unseen ( has to be in dom though)

                  • draw that image back onto the canvas

                  • you can delete or reuse the at this point





                  share|improve this answer












                  I wanted to copy a CRISP, un modified version of the canvas on top of itself. I eventually came up with this solution, which applies.



                  https://jsfiddle.net/4Le454ak/1/



                  The copy portion is in this code:



                  var imageData = canvas.toDataURL(0, 0, w, h);
                  var tmp = document.createElement('img');
                  tmp.style.display = 'none'
                  tmp.src = imageData;
                  document.body.appendChild(tmp);
                  ctx.drawImage(tmp, 30, 30);


                  What's happening:



                  • copy image data from canvas

                  • set image data to an unseen ( has to be in dom though)

                  • draw that image back onto the canvas

                  • you can delete or reuse the at this point






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Apr 4 '17 at 14:24









                  Jacksonkr

                  17.7k34137234




                  17.7k34137234





















                      0














                      Something that tripped me up that may be of use... I had problems with this because I assumed that putImageData() and drawImage() would work in the same way but it seems they don't. putImageData() will overwrite existing pixels with its own transparent data while drawImage() will leave them untouched.



                      When looking into this I just glanced at the docs for CanvasRenderingContext2D.globalCompositeOperation (should have read more closely), saw that source-over is the default and didn't realise this would not apply to putImageData()



                      Drawing into a temporary canvas then and using drawImage() to add the temp canvas to the main context was the solution I needed so cheers for that.






                      share|improve this answer

























                        0














                        Something that tripped me up that may be of use... I had problems with this because I assumed that putImageData() and drawImage() would work in the same way but it seems they don't. putImageData() will overwrite existing pixels with its own transparent data while drawImage() will leave them untouched.



                        When looking into this I just glanced at the docs for CanvasRenderingContext2D.globalCompositeOperation (should have read more closely), saw that source-over is the default and didn't realise this would not apply to putImageData()



                        Drawing into a temporary canvas then and using drawImage() to add the temp canvas to the main context was the solution I needed so cheers for that.






                        share|improve this answer























                          0












                          0








                          0






                          Something that tripped me up that may be of use... I had problems with this because I assumed that putImageData() and drawImage() would work in the same way but it seems they don't. putImageData() will overwrite existing pixels with its own transparent data while drawImage() will leave them untouched.



                          When looking into this I just glanced at the docs for CanvasRenderingContext2D.globalCompositeOperation (should have read more closely), saw that source-over is the default and didn't realise this would not apply to putImageData()



                          Drawing into a temporary canvas then and using drawImage() to add the temp canvas to the main context was the solution I needed so cheers for that.






                          share|improve this answer












                          Something that tripped me up that may be of use... I had problems with this because I assumed that putImageData() and drawImage() would work in the same way but it seems they don't. putImageData() will overwrite existing pixels with its own transparent data while drawImage() will leave them untouched.



                          When looking into this I just glanced at the docs for CanvasRenderingContext2D.globalCompositeOperation (should have read more closely), saw that source-over is the default and didn't realise this would not apply to putImageData()



                          Drawing into a temporary canvas then and using drawImage() to add the temp canvas to the main context was the solution I needed so cheers for that.







                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered Nov 10 at 13:03









                          popClingwrap

                          1,30921431




                          1,30921431



























                              draft saved

                              draft discarded
















































                              Thanks for contributing an answer to Stack Overflow!


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid


                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.

                              To learn more, see our tips on writing great answers.





                              Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                              Please pay close attention to the following guidance:


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid


                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.

                              To learn more, see our tips on writing great answers.




                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function ()
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f22194267%2fputimagedata-how-to-keep-old-pixels-if-new-pixels-are-transparent%23new-answer', 'question_page');

                              );

                              Post as a guest















                              Required, but never shown





















































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown

































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown







                              Popular posts from this blog

                              𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

                              Edmonton

                              Crossroads (UK TV series)