
有谁知道一个迭代和有效的洪水填充算法?
或者有没有办法实现递归填充算法没有堆栈溢出错误?
试过一个@ Flood fill using a stack
但我找不到一种方法来处理白色和黑色的图像.
解决方法:
有人将J. Dunlap’s Queue-linear Flood Fill算法移植到androID here.我已经尝试了它并且速度非常快.
我修改了copyImage()方法,该方法最初使用了作者未提供的名为UtilitIEs的类.
public class QueuelinearFloodFiller { protected Bitmap image = null; protected int[] tolerance = new int[] { 0, 0, 0 }; protected int wIDth = 0; protected int height = 0; protected int[] pixels = null; protected int fillcolor = 0; protected int[] startcolor = new int[] { 0, 0, 0 }; protected boolean[] pixelsChecked; protected Queue<FloodFillRange> ranges; // Construct using an image and a copy will be made to fill into, // Construct with BufferedImage and flood fill will write directly to // provIDed BufferedImage public QueuelinearFloodFiller(Bitmap img) { copyImage(img); } public QueuelinearFloodFiller(Bitmap img, int targetcolor, int newcolor) { useImage(img); setFillcolor(newcolor); setTargetcolor(targetcolor); } public voID setTargetcolor(int targetcolor) { startcolor[0] = color.red(targetcolor); startcolor[1] = color.green(targetcolor); startcolor[2] = color.blue(targetcolor); } public int getFillcolor() { return fillcolor; } public voID setFillcolor(int value) { fillcolor = value; } public int[] getTolerance() { return tolerance; } public voID setTolerance(int[] value) { tolerance = value; } public voID setTolerance(int value) { tolerance = new int[] { value, value, value }; } public Bitmap getimage() { return image; } public voID copyImage(Bitmap img) { // copy data from provIDed Image to a BufferedImage to write flood fill // to, use getimage to retrIEve // cache data in member variables to decrease overhead of property calls wIDth = img.getWIDth(); height = img.getHeight(); image = Bitmap.createBitmap(wIDth, height, Bitmap.Config.RGB_565); Canvas canvas = new Canvas(image); canvas.drawBitmap(img, 0, 0, null); pixels = new int[wIDth * height]; image.getPixels(pixels, 0, wIDth, 1, 1, wIDth - 1, height - 1); } public voID useImage(Bitmap img) { // Use a pre-existing provIDed BufferedImage and write directly to it // cache data in member variables to decrease overhead of property calls wIDth = img.getWIDth(); height = img.getHeight(); image = img; pixels = new int[wIDth * height]; image.getPixels(pixels, 0, wIDth, 1, 1, wIDth - 1, height - 1); } protected voID prepare() { // Called before starting flood-fill pixelsChecked = new boolean[pixels.length]; ranges = new linkedList<FloodFillRange>(); } // Fills the specifIEd point on the bitmap with the currently selected fill // color. // int x, int y: The starting coords for the fill public voID floodFill(int x, int y) { // Setup prepare(); if (startcolor[0] == 0) { // ***Get starting color. int startPixel = pixels[(wIDth * y) + x]; startcolor[0] = (startPixel >> 16) & 0xff; startcolor[1] = (startPixel >> 8) & 0xff; startcolor[2] = startPixel & 0xff; } // ***Do first call to floodfill. linearFill(x, y); // ***Call floodfill routine while floodfill ranges still exist on the // queue FloodFillRange range; while (ranges.size() > 0) { // **Get Next Range Off the Queue range = ranges.remove(); // **Check Above and Below Each Pixel in the Floodfill Range int downPxIDx = (wIDth * (range.Y + 1)) + range.startX; int uppxIDx = (wIDth * (range.Y - 1)) + range.startX; int upY = range.Y - 1;// so we can pass the y coord by ref int downY = range.Y + 1; for (int i = range.startX; i <= range.endX; i++) { // *Start Fill Upwards // if we're not above the top of the bitmap and the pixel above // this one is within the color tolerance if (range.Y > 0 && (!pixelsChecked[uppxIDx]) && CheckPixel(uppxIDx)) linearFill(i, upY); // *Start Fill Downwards // if we're not below the bottom of the bitmap and the pixel // below this one is within the color tolerance if (range.Y < (height - 1) && (!pixelsChecked[downPxIDx]) && CheckPixel(downPxIDx)) linearFill(i, downY); downPxIDx++; uppxIDx++; } } image.setPixels(pixels, 0, wIDth, 1, 1, wIDth - 1, height - 1); } // Finds the furthermost left and right boundarIEs of the fill area // on a given y coordinate, starting from a given x coordinate, filling as // it goes. // Adds the resulting horizontal range to the queue of floodfill ranges, // to be processed in the main loop. // int x, int y: The starting coords protected voID linearFill(int x, int y) { // ***Find left Edge of color Area int lFillLoc = x; // the location to check/fill on the left int pxIDx = (wIDth * y) + x; while (true) { // **fill with the color pixels[pxIDx] = fillcolor; // **indicate that this pixel has already been checked and filled pixelsChecked[pxIDx] = true; // **de-increment lFillLoc--; // de-increment counter pxIDx--; // de-increment pixel index // **exit loop if we're at edge of bitmap or color area if (lFillLoc < 0 || (pixelsChecked[pxIDx]) || !CheckPixel(pxIDx)) { break; } } lFillLoc++; // ***Find Right Edge of color Area int rFillLoc = x; // the location to check/fill on the left pxIDx = (wIDth * y) + x; while (true) { // **fill with the color pixels[pxIDx] = fillcolor; // **indicate that this pixel has already been checked and filled pixelsChecked[pxIDx] = true; // **increment rFillLoc++; // increment counter pxIDx++; // increment pixel index // **exit loop if we're at edge of bitmap or color area if (rFillLoc >= wIDth || pixelsChecked[pxIDx] || !CheckPixel(pxIDx)) { break; } } rFillLoc--; // add range to queue FloodFillRange r = new FloodFillRange(lFillLoc, rFillLoc, y); ranges.offer(r); } // Sees if a pixel is within the color tolerance range. protected boolean CheckPixel(int px) { int red = (pixels[px] >>> 16) & 0xff; int green = (pixels[px] >>> 8) & 0xff; int blue = pixels[px] & 0xff; return (red >= (startcolor[0] - tolerance[0]) && red <= (startcolor[0] + tolerance[0]) && green >= (startcolor[1] - tolerance[1]) && green <= (startcolor[1] + tolerance[1]) && blue >= (startcolor[2] - tolerance[2]) && blue <= (startcolor[2] + tolerance[2])); } // Represents a linear range to be filled and branched from. protected class FloodFillRange { public int startX; public int endX; public int Y; public FloodFillRange(int startX, int endX, int y) { this.startX = startX; this.endX = endX; this.Y = y; } }}@H_419_19@如果您不希望UI等待图像填充,您也可以使用线程.
public class FloodFillThread extends Thread { ProgressDialog mProgressDialog; Bitmap mBitmap; int mTargetcolor; int mNewcolor; Point mPoint; Runnable mCallback; public FloodFillThread(ProgressDialog pd, Runnable callback, Bitmap bitmap, Point pt, int targetcolor, int newcolor) { mBitmap = bitmap; mPoint = pt; mTargetcolor = targetcolor; mNewcolor = newcolor; mProgressDialog = pd; mCallback = callback; } @OverrIDe public voID run() { QueuelinearFloodFiller filler = new QueuelinearFloodFiller(mBitmap, mTargetcolor, mNewcolor); filler.setTolerance(10); filler.floodFill(mPoint.x, mPoint.y); handler.sendEmptyMessage(0); } private Handler handler = new Handler() { @OverrIDe public voID handleMessage(Message msg) { mProgressDialog.dismiss(); mCallback.run(); } };}@H_419_19@ 总结以上是内存溢出为你收集整理的java – Android泛洪填充算法全部内容,希望文章能够帮你解决java – Android泛洪填充算法所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)