How to filter a specific color from a bitmapData object (or byte array)

I am looking for an efficient way to filter a specific color from a bitmapData object in ActionScript 3. I am currently using a loop with readByte32 (). It takes about a second to process, which is unacceptable. I am trying to get paletteMap () to work, but still have not been able to understand its API (some really useful links? Google didn't help me ...).

Here is my current logic that I want to improve:

var n:int = bitmapData.width; for (var i:int = 0; i < n; i++) { var m:int = bitmapData.height; for (var j:int = 0; j < m; j++) { var color:int = bitmapData.getPixel(i, j); if (color == 0xCACACA) { bitmapData.setPixel32(i, j, 0x00000000); } } } 

I can get a little better performance from using vectors, but it's only a little better ...

 var v:Vector.<uint> = bitmapData.getVector(bitmapData.rect); var n:int = bitmapData.width * bitmapData.height; for (var i:int = 0; i < n; i++) { var color:uint = v[i]; v[i] = color == 0xFFCACACA ? 0x00000000 : color; } bitmapData.setVector(bitmapData.rect, v); 

I really think that there should be a better way to do this, which only takes a few milliseconds. If someone can unlock the secrets of bitmapData for me, you will become the new leader of my people.

PS I use bitmapData.lock () and unlock (); I just did not publish the contents of the template.

+4
source share
2 answers

A simple way is the threshold method. It's a little cumbersome at first, but it's pretty fast (as fast as you think, I think)

This will change every red pixel (given that only a red pixel whose value is exactly 0xffff0000) will be blue (0xff0000ff).

 var colorToReplace:uint = 0xffff0000; var newColor:uint = 0xff0000ff; var maskToUse:uint = 0xffffffff; var rect:Rectangle = new Rectangle(0,0,bitmapData.width,bitmapData.height); var p:Point = new Point(0,0); bitmapData.threshold(bitmapData, rect, p, "==", colorToReplace, newColor, maskToUse, true); 
+4
source

Flash has an API for a shader language called pixel bending , which may be useful in this case. Here is a tutorial from adobe on how to apply a pixel filter to an image in flash .

Otherwise, you can process the lines at a time. (Note that a small error in your code was to re-get the height at each iteration of the width):

 private var currentRow:Number = 0; private var timer:Timer; public function processImage(event:Event=null):void { var m:int = bitmapData.height; for (var j:int = 0; j < m; j++) { if (bitmapData.getPixel(currentRow, j) == 0xCACACA) { bitmapData.setPixel32(currentRow, j, 0x00000000); } } currentRow++; if(currentRow < bitmapData.width) { timer = new Timer(1, 500); timer.addEventListener(TimerEvent.COMPLETE, processImage); timer.start(); } } 

Processing will take a little longer, but at least your screen will not be locked.

+1
source

Source: https://habr.com/ru/post/1313491/


All Articles