2012-04-09 2 views
8

Есть ли способ изменить цвета изображения, как в Flash/ActionScript, используя только HTML5/CSS/JavaScript?Canvas - Изменение цвета изображения с помощью HTML5/CSS/JS?

Вот пример во Flash: http://www.kirupa.com/developer/actionscript/color.htmEDIT: Это процесс, который я хочу дублировать.

Я пытаюсь сделать что-то вроде этого (изменение цвета аспекта, сохраняя освещение и тень): http://www.acura.com/ExteriorColor.aspx?model=TL без загрузки & замены нового изображения каждый раза; Я хочу иметь возможность просто изменить цветовой тон (т. Е. Сделать чистый метод HTML5/CSS/JS). EDIT: Это результат, которого я хочу достичь, а не процесс.

В основном я хочу изменить палитру/тон изображения, сохраняя при этом другие аспекты изображения (например, градиент, освещение и т. Д.). Я подошел близко, но не достаточно близко; Я дошел до того, что использую маску изображения и составную часть, которая поверх исходного изображения (вроде как прозрачное наложение изображений). Ниже приведен пример кода (обратите внимание, что это просто фрагмент кода, так что он может или не может работать, я только показывая пример кода, так что вы получите представление о том, что я пытаюсь сделать):

<div id='mask'> 
    <canvas id='canvas' width='100' height='100'></canvas> 
</div> 
<button data-rgba='255,0,0,0.5'>red</button> 
<button data-rgba='0,255,0,0.5'>green</button> 

<script> 
foo = {}; 
foo.ctx = jQuery('#canvas')[0]; 
foo.ctx_context = foo.ctx.getContext('2d'); 
foo.mask = jQuery('#mask')[0]; 
foo.img = new Image(); 
foo.img_path = '/path/to/image_mask.png'; // 100px x 100px image 

foo.changeColor = function(rgba){ 
    foo.ctx_context.clearRect(0, 0, 100, 100); 
    foo.ctx_context.fillStyle = 'rgba(' + rgba + ')'; 
    foo.ctx_context.fillRect(0, 0, 100, 100); 
    foo.ctx_context.globalCompositeOperation = 'destination-atop'; 
    foo.ctx_context.drawImage(foo.img, 0, 0); 
    foo.ctx_context.css({'background-image': "url(" + foo.ctx.toDataURL("image/png") + ")"}); 
}; 

jQuery("button").click(function(){ 
    foo.changeColor(jQuery(this).attr('data-rgba')); 
}); 
</script> 

Основная проблема с использованием этого подхода заключается в том, что изображения выглядят действительно плоскими. Там что-то еще отсутствует, или маска, которую я использую (которая является сплошным белым изображением неправильной формы), является неправильным подходом.

+0

Пожалуйста, отправьте завершенную скрипку после получения ответа. Благодаря! – iambriansreed

ответ

-1

Обычно делать что-то вроде изменения пикселя изображения по пикселям - это то, что вы делали бы на стороне сервера, так как оно очень тяжело для браузера. В случае с сайтом Acura нет ничего сложного - у них просто куча разных JPG. Вы также можете попробовать изучить Processing.js.

+0

Я не рисую пиксель за пикселем; Я компоную маску изображения по существующему изображению, что намного быстрее, чем запрос к серверу каждый раз, чтобы сделать изменение цвета. То, что делает Acura, - результат, которого я хочу достичь, но НЕ процесс. Flash меняет цвет/тона так хорошо (это сразу), но печальная реальность такова, вы не можете использовать Flash на iPad, поэтому я ищу решение HTML5. –

2

Несомненно, вы можете получить данные о пикселях и выполнить корректировки HSV на нем. Вы хотите метод getImageData (который возвращает UInt8Array, а не обычный массив js).

Есть хорошая запись here, которая должна вас начать. Вы можете сложить прозрачные элементы холста друг на друга, что должно помочь избежать проблем с настройкой базовых компонентов (например, в вашем автомобиле, шинах, окнах и т. Д.).

11

Эта функция требует, чтобы изображение, которое будет загружен, и он должен быть из того же домена (вследствие перекрестной политики домена)

function tintImage(imgElement,tintColor) { 
    // create hidden canvas (using image dimensions) 
    var canvas = document.createElement("canvas"); 
    canvas.width = imgElement.offsetWidth; 
    canvas.height = imgElement.offsetHeight; 

    var ctx = canvas.getContext("2d"); 
    ctx.drawImage(imgElement,0,0); 

    var map = ctx.getImageData(0,0,320,240); 
    var imdata = map.data; 

    // convert image to grayscale 
    var r,g,b,avg; 
    for(var p = 0, len = imdata.length; p < len; p+=4) { 
     r = imdata[p] 
     g = imdata[p+1]; 
     b = imdata[p+2]; 
     // alpha channel (p+3) is ignored   

     avg = Math.floor((r+g+b)/3); 

     imdata[p] = imdata[p+1] = imdata[p+2] = avg; 
    } 

    ctx.putImageData(map,0,0); 

    // overlay filled rectangle using lighter composition 
    ctx.globalCompositeOperation = "lighter"; 
    ctx.globalAlpha = 0.5; 
    ctx.fillStyle=tintColor; 
    ctx.fillRect(0,0,canvas.width,canvas.height); 

    // replace image source with canvas data 
    imgElement.src = canvas.toDataURL(); 
} 

Если предположить, что разметка выглядит следующим образом:

<img id='myimage' src='image.jpg'/> 

You мог бы использовать его, указав его со следующими параметрами:

tintImage(
    document.getElementById('myImage'), 
    "#550000" // for a redish tint 
); 

Рабочий пример здесь: http://jsfiddle.net/pHwmL/1/

+1

Обратите внимание, что когда вы говорите, перекрестный домен, люди, использующие хром для разработки локально, также не смогут увидеть эту работу (я всегда просто запускаю на локальном сквозном веб-сервере, чтобы убедиться, что он будет работать.) Мне понравился ваш метод , но обнаружил, что он переписывал любые альфа-каналы ... поэтому я добавил массив альфа, а затем написал их обратно. Работает хорошо. Код по адресу: https://github.com/jaycrossler/django-gamification/blob/master/gamification/static/themes/camping/badges.js#L711-L733 – JayCrossler

Смежные вопросы