1

I've been searching all over the web to resolve my problem, but I'm starting to think that I'm not searching in the right way.

Let's say I have the image below, what I am trying to do, is to replace the blue area with an image that the user uploads, but I don't know how to do it.

The closest I have found was this but this is drawing a red rectangle where specific coordinates are being given, and what I need (I think) is to find/detect those coordinates and replace them with an image. Has anyone ever came across this? can you point me in the right direction? really stuck here!

Dummy image

Note: the image I have put here is just for the purpose of the question, this is not my image. Thanks for your time, regards

EDIT:

Ok i should have putted the code here in the first place, for that my apologies, and as i said before, this an app that i´m doing using phonegap and jquery mobile, the app is using a navbar on the bottom, and one of the pages is called "preview" and this is where i need the image functionality to work, but i´m missing something, and i think is lack of knowledge:

My index.html:

 <div data-role="page" data-url="preview" id="preview">
      <div data-role="header" style="background-color: rgb(182, 202, 51)" data-position="fixed">
        <h1 id="titlePreview">PREVIEW</h1>
        <a href="#language" id="langBtn" style="width: 20px;height: 20px; background:none;  " href="#" data-icon="comment" data-iconpos="notext" class="ui-btn-left"></a>
      </div>
        <div id="previewSaco" class="containerPreviewSaco">//if i remove this div, the navbar on the bottom disapears. 
          <canvas id="myCanvas" width="200" height="200">//i´m testing with this size, but yes the image is supose to have a 100% with, in fact the image as 1940x2372. 
       </div>
      <div data-role="footer" data-position="fixed">
        <div data-role="navbar" class="ui-bar">
          <ul>
            //in here i have my several "li" for navegation and i think it´s irrelevant for my question.
          </ul>
        </div>
      </div>
    </div>

My .js file:

$(document).on("click", "#btnPreview", function (event) {

    var ctx = document.getElementById('myCanvas').getContext('2d');

    var img = new Image;
    img.onload = function(){
      ctx.drawImage(img,0,0);
      img2.src = 'img/capa.png'; 
    };

    var img2 = new Image;
    img2.onload = function(){
        ctx.globalCompositeOperation = 'destination-over';

      //ctx.scale(x, y);
      //ctx.rotate(angle);
      //ctx.translate(x, y);

      //or

      //ctx.transform(a, b, c, d, e, f);

      ctx.drawImage(img2,0,0);
    };

    var uri1 = 'img/previewSaco1.png'; //this is the main image, which is suppose to load when i click in the page "preview", **and it´s not happening** and i have create the transparent area to were the uploaded image by the user is also suppose to go.

    var uri2 = 'img/capa.png';//this image is a dummy logo to test in the bigger image
    img.src = uri1;
});

Note: when i run the app, the phonegap desktop is always saying this: undefined Content Security Policy has been modified to be: https://ssl.gstatic.com;style-src 'self' 'unsafe-inline' data: blob:;media-src *;img-src * 'self' data: content:;script-src * 'unsafe-inline' 'unsafe-eval' data: blob:;">

Japa
  • 632
  • 7
  • 30
  • You will have to loop over the individual pixels of your canvas image, and check their color. Likely you do not want to use one fixed color value, but implement a threshold of sorts. If the pixel matches your criteria for replacement, then you get the corresponding pixel value from the other image ... of course that would require that both images have the same dimensions, otherwise you would have to define how you want to handle that situation fist of all (scale one of the images up/down to match the other, which may also stretch/distort it, or apply the process to a limited section only, ...) – CBroe Aug 11 '17 at 10:27
  • Are you restricted to any version of any browser? Also, do you have the option to process the image in a backend service? – Jeremy Aug 11 '17 at 10:29
  • Could you overlay the image with an alpha masked image? Or do you need the final image to be 1 image with all the data? – Lars-Kristian Johansen Aug 11 '17 at 10:32
  • 1
    I have a solution, I am just not sure it cross browser, I am finishing the pen, gimme couple minutes. – ptts Aug 11 '17 at 10:33
  • Thank you all for responding, i forgot to say that this is for an app, i´m also using phonegap, i don´t know if this influences or not...Lars-Kristian Johansen, yes! the goal is to turn this in one image only. – Japa Aug 11 '17 at 10:38
  • This question has a lot of good information. https://stackoverflow.com/questions/18379818/canvas-image-masking-overlapping – Lars-Kristian Johansen Aug 11 '17 at 10:58
  • Thank you Lars-Kristian Johansen, i´m reading it at this point, but this also assumes that you draw the area which will be replaced by an image, in my case i will not draw anything, i need to "find" the area first and then replace it, i assume that this "finding" will be based on a color. ptts, i´m curious with what you have – Japa Aug 11 '17 at 11:13
  • @Japa I have edited my answer by adding a link to how you could set transparency based on color. – Lars-Kristian Johansen Aug 11 '17 at 11:53
  • @Japa Sorry, I have no experience with phonegap, so I can not help you there. – Lars-Kristian Johansen Aug 13 '17 at 12:45
  • Ok, thank you anyway, i think i have discouvered my problem, and i detected it when you said that maybe my image is too large, so i set the canvas to a bigger "with" and the image appeared!(the image is too large), but this raises the problem of not being responsive, the canvas does not adapt to the screen. i´m completly stuck and don´t know what to do. regards – Japa Aug 13 '17 at 14:30

2 Answers2

1

Ok here we go:

Use this as the HTML structur:

<div id="imageContainer" class="center">
<h2>Lets go and see how it goes</h2>
<img class="pic" src="https://moltopiccolo.files.wordpress.com/2012/01/cool-
drinks.jpg"> 
</div>

You can set any bg image on the container div, this will not change.

The image uses the CSS clip path, it needs many prefixes, but looks amazing, you can give your image any shape, there are clip path generators online and you can even animate the clip path.

Mine goes like:

#imageContainer img {
-webkit-clip-path: polygon(1% 3%, 3% 9%, 18% 21%, 54% 20%, 83% 63%, 66% 76%, 
15% 83%, 25% 45%);
clip-path: polygon(17% 13%, 33% 9%, 58% 21%, 84% 20%, 83% 63%, 66% 76%, 15% 
83%, 25% 45%);
-webkit-transition: -webkit-clip-path .6s ease-out;
transition: -webkit-clip-path .6s ease-out;
position:absolute;
border-radius: 5px;
width: 100%;
height:270px;

}

Now I have made an input button for file upload, and the following JS function:

var getval = document.querySelector("#getval");

getval.addEventListener("change", previewFile);

function previewFile() {
var reader = new FileReader();
var bgImage = document.querySelector(".pic");
var file = document.querySelector("input[type=file]").files[0];
reader.onloadend = function() {
bgImage.src = reader.result;
};

if (file) {
reader.readAsDataURL(file); //reads the data as a URL
 } else {
file.src = "";
}
}

Here is the link

https://codepen.io/damianocel/pen/KdobyK

ptts
  • 1,022
  • 8
  • 18
  • Thank you very much!!!! ptts, this takes me far and far, but i have one question, in this solution you are drawing that shape where the image will be replaced right?. My question is, is there a way where you don´t draw the shape but instead detect the shape(it´s coordinates, area etc..) and then replace that area with the image. – Japa Aug 11 '17 at 11:25
  • 1
    @Japa, you are welcome. To detect the shape would make this thing very very complicated. It's hardly necessary though, as you can pick the shape yourself, just generate a clip path. I would only accept regular pic shapes, if you think about it, twitter, pinterest etc, none of them care about the uploaded shapes, you are more flexible than them with this. You could give the users choice for differentpath/shapes. The shape is not exactly drawn, it's set beforehand, just check the css file, the image css on hover state and normal state. You can pick any default. – ptts Aug 11 '17 at 11:32
1

You could use Context2D.globalCompositeOperation = 'destination-over'; Read more about it here GlobalCompositeOperation .

First open you image in an editor. Cut out the area you want to replace. (make pixels transparent). Now load image and write it to the canvas.

Then load the image you want to put in. Set ctx.globalCompositeOperation = 'destination-over'; And write image to the canvas.

You could also set a transform on the canvas before the second write operation to better fit the image.

Example: jsfiddle.net

Edit 1: After loading the first image, you could set transparency based on color. Check this answer for that.

  • Hi Lars, i´ve been working with the code you provided in that jsfiddle and correct me if i´m worng on these steps: i have open my photoshop and created transparency on the area i want the second image to appear, then i went to my code editor, and tryied the code you provided, but i had to find the uri of the images, so i went here(http://dataurl.net/#dataurlmaker) and copied the uri of the images, but when i try to past the code in my editor, it appears black, i know this is a rookie question, but what´s wrong?. regards – Japa Aug 12 '17 at 00:10
  • First off you do not need to use data-uri's, (I used it to embed it into the snippet). I recommend you to load the image in a more optimal way. Just set the image src to a path that works for your setup. It is hard to know without seeing any code, but maybe this can help. Make sure that the image loads. Do a couple of `console.log(img)` inside the onload handler. Or use the network tab in the debug tools, the image should be visible there. The canvas size in the example is only 200x200px maybe you are using a very large image? – Lars-Kristian Johansen Aug 12 '17 at 12:36
  • Hi Lars, i have edited my question, and i have placed the code, could you help me pls?. thanks and regards – Japa Aug 12 '17 at 15:39