2011-05-09 23 views
6

Chcę pobrać nieregularny kształt z istniejącego obrazu i renderować go jako nowy obraz w JavaScript przy użyciu kanonów HTML5. Zatem skopiowane zostaną tylko dane wewnątrz granicy wielokąta. Podejście, na które się natknąłem:Maska dla putImageData z kanwą HTML5?

  1. Narysuj wielokąt w nowym obszarze roboczym.
  2. utworzyć maskę korzystając clip
  3. skopiować dane z oryginalnego płótna za pomocą getImageData (prostokąt)
  4. Zastosuj dane do nowego płótnie przy użyciu putImageData

to nie działa, cały prostokąt (np. rzeczy ze źródła poza granicą) wciąż się pojawia. This question wyjaśnia, dlaczego: "Specyfikacja mówi, że obszary przycinania nie będą miały wpływu na putImageData". Dang!

Próbowałem także rysować kształt, ustawiając context.globalCompositeOperation = "source-in", a następnie używając putImageData. Ten sam wynik: żadna maska ​​nie została zastosowana. Podejrzewam z podobnego powodu.

Wszelkie sugestie, jak osiągnąć ten cel? Oto podstawowy kod mojej pracy w toku, na wypadek, gdyby nie było jasne, co próbuję zrobić. (Nie próbuj zbyt mocno, aby to debugować, jest czyszczone/wyodrębniane z kodu, który używa wielu funkcji, których nie ma tutaj, po prostu próbując pokazać logikę).

// coords is the polygon data for the area I want 
    context = $('canvas')[0].getContext("2d"); 
    context.save(); 
    context.beginPath(); 
    context.moveTo(coords[0], coords[1]); 
    for (i = 2; i < coords.length; i += 2) { 
    context.lineTo(coords[i], coords[i + 1]); 
    } 
    //context.closePath(); 
    context.clip(); 

    $img = $('#main_image'); 
    copy_canvas = new_canvas($img); // just creates a new canvas matching dimensions of image 
    copy_ctx = copy.getContext("2d"); 

    tempImage = new Image(); 
    tempImage.src = $img.attr("src"); 
    copy_ctx.drawImage(tempImage,0,0,tempImage.width,tempImage.height); 

    // returns array x,y,x,y with t/l and b/r corners for a polygon 
    corners = get_corners(coords) 
    var data = copy_ctx.getImageData(corners[0],corners[1],corners[2],corners[3]); 
    //context.globalCompositeOperation = "source-in"; 
    context.putImageData(data,0,0); 
    context.restore(); 

Odpowiedz

10

nie używaj putImageData,

prostu zrobić dodatkową w pamięci płótnie z document.createElement stworzyć maskę i stosować że przy drawImage() i funkcji globalCompositeOperation (w zależności od kolejności trzeba wybrać tryb prawej;

zrobić something similar herecode is here (przeszkadza funkcję CasparKleijne.Canvas.GFX.Composite)

+0

Niesamowite! To działa! Dzięki wielkie. –

+0

Oh szybkie pytanie - czy możesz wymyślić sposób, aby to zrobić bez trzech tymczasowych. płótna? Mam 1, aby załadować kopię głównego obrazu, potem jeden, aby skopiować prostokąt na, a trzeci, który ma maskę, do której stosuję drugą. Czuję, że muszę gdzieś robić za dużo, ale nie mogę wymyślić sposobu, aby przejść bezpośrednio z pełnego obrazu do płótna zawierającego tylko prostokąt. –

+0

W kodzie, który zawierałem, możesz zbudować kompozyt, który może utworzyć listę tylu obrazów, ile chcesz, jednak radzę ci to robić ostrożnie z punktu widzenia wydajności. Testowanie i wypróbowywanie to dobra praktyka;) –