madroneropaulo
@madroneropaulo
Фронтенд разработчик

Как нарисовать на Canvas без применения putImageData()?

Доброго времени суток. Есть такой старый баг на андроид устройствах https://code.google.com/p/android/issues/detail?id... В общем, если изменить цвет изображения с помощью методов getImageData() и putImageData() то полученный результат не равен ожидаемому результату.
var imgCanvas = document.createElement("canvas");
var ctx = imgCanvas.getContext("2d");
var imageObj.src = 'img/someImage.png';
imageObj.onload = function(){
	ctx.draw(imageObj,0,0);
	var imageData = ctx.getImageData(0,0,30,30);
	var data = imageData.data;          
	for(var i = 0, n = data.length; i < n; i += 4) {                                 
		data[i]+=20;//red	
		data[i+1]-=20;//green
		data[i+2]-=20;//blue
		//data[i+3]=0; //alpha, но я не трогаю этого параметра             
	}
	ctx.putImageData(imageData,0,0);
}


Если начальные параметры случайного пикселя были, допустим rgba = [100,50,200,200], то после применения этих изменений ожидается результат rgba = [120,30,180,200], однако в браузере андроида результат совсем другой. Я разрабатываю приложение на html5 и для сборки использую Phonegap, результат тот же, что и в браузере андроида. В хроме для андроида все работает нормально.

Поскольку я должен закончить разработку совсем скоро, и приложение должно работать в устройствах андроида 4.х+, то я хотел бы знать, как совершать те же действия но без применения putImageData()? Или какие у вас будут советы по этому поводу? Спасибо.
  • Вопрос задан
  • 2688 просмотров
Решения вопроса 1
madroneropaulo
@madroneropaulo Автор вопроса
Фронтенд разработчик
Решил проблему следующим образом:

var imgCanvas = document.createElement("canvas");
var ctx = imgCanvas.getContext("2d");
var imageObj.src = 'img/someImage.png';
imageObj.onload = function(){   
	ctx.draw(imageObj,0,0);
	var imageData = ctx.getImageData(0,0,30,30);
	var data = imageData.data;
        var countX=0;
        var countY=0;         
	for(var i = 0, n = data.length; i < n; i += 4) {                                 
		var red = data[i] + 50;
                var green = data[i+1] - 50;
                var blue = data[i+2] - 50;
                var alpha = (data[i+3]/255).toFixed(2);
            
                ctx.fillStyle = 'rgba('+red+','+green+','+blue+','+alpha+')'; 
                ctx.fillRect(countX,countY,1,1);

                countX++;
                if(countX>=imageHeight){
        	         countX=0;
        	         countY++;
        	         if(countY>=imageWidth){
        		         countY=0;
        	         }                
                }                   
	}	
}


Нарисовал квадрат в каждом пиксели с помощью fillRect(). А параметры rgba взял из исходного изображения с помощью метода getImageData(). В этом примере я добавляю немного красного и убираю синего и зеленого. Alpha не меняю, но fillStyle() принимает значение alpha от 0 до 1, поэтому делится на 255. Потом изображение в canvas доступно для использования, например, с помощью toDataUrl()

var imageUrl=imgCanvas.toDataURL(); 
    var pushImg = new Image();
    pushImg.src = imageUrl;
    pushImg.onload = function(){
      //Действия с новым изображением pushImg. 
    }
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
RadiationX
@RadiationX
Front-End разработчик
И ведь серьезно цвет отличается. Раньше не замечал.
Как вариант просто наложить на картинку "маску?" с определенным цветом.
Эту "маску"/слой можно сгенерировать, вроде при генерации нет искажений.

Походу ошибка в самом получении массива пикселей, потому-что даже если прибавлять 0, то цвет отличается.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы