【问题标题】:Android: how to execute this for loop fast as now it is?Android:如何像现在一样快速执行这个 for 循环?
【发布时间】:2012-03-23 09:03:44
【问题描述】:

我要将像素设置为我的位图到某个特定点。

为此,我正在使用 For 循环。但是因为它是扫描整个图像,所以需要时间。 那么有什么替代方法可以帮助我更快地执行它。

for循环如下:

public void drawLoop(){
    int ANTILAISING_TOLERANCE = 100;

    for(int x = 0; x < mask.getWidth(); x++){
        for(int y = 0; y < mask.getHeight(); y++){

            g = (mask.getPixel(x,y) & 0x0000FF00) >> 8;
            r = (mask.getPixel(x,y) & 0x00FF0000) >> 16;
            b = (mask.getPixel(x,y) & 0x000000FF);

            if(Math.abs(sR-r) < ANTILAISING_TOLERANCE && Math.abs(sG-g) < ANTILAISING_TOLERANCE && Math.abs(sB-b) < ANTILAISING_TOLERANCE)
                colored.setPixel(x, y, (colored.getPixel(x, y) & 0xFFFF0000));
        }
    }

    imageView.setImageBitmap(colored);
    coloreBitmap.add(colored.copy(Config.ARGB_8888, true));
    position = coloreBitmap.size()-1;
    System.out.println("Position in drawFunction is: "+position);
}

请帮助我。

谢谢。

【问题讨论】:

    标签: java android bitmap android-canvas pixels


    【解决方案1】:

    我也有这个问题。 我的程序检查位图上的每个像素,然后检查绿色 (RGB) 是否高于红色和蓝色,位图大小为 3264 x 2448(三星 Galaxy s2 相机尺寸)。 扫描和检查整个位图需要 3 秒,如果您问我的话,非常快。

    这是我的代码:

    try {
                    decoder_image = BitmapRegionDecoder.newInstance("yourfilepath",false);              
    
                } catch (IOException e) {
                    e.printStackTrace();
                }
    

    示例文件路径:/mnt/sdcard/DCIM/Camera/image.jpg

    try {
    
                        final int width = decoder_image.getWidth();
                        final int height = decoder_image.getHeight();
                        // Divide the bitmap into 1100x1100 sized chunks and process it.
                        // This makes sure that the app will not be "overloaded"
                        int wSteps = (int) Math.ceil(width / 1100.0);
                        int hSteps = (int) Math.ceil(height / 1100.0);
                        Rect rect = new Rect();
                        for (int h = 0; h < hSteps; h++) {
                            for (int w = 0; w < wSteps; w++) {
                                int w2 = Math.min(width, (w + 1) * 1100);
                                int h2 = Math.min(height, (h + 1) * 1100);
                                rect.set(w * 1100, h * 1100, w2, h2);
                                mask = decoder_image.decodeRegion(rect,
                                        null);
    
                                try {
                                    int bWidth = mask.getWidth();
                                    int bHeight = mask.getHeight();
                                    int[] pixels = new int[bWidth * bHeight];
                                    mask.getPixels(pixels, 0, bWidth, 0, 0,
                                            bWidth, bHeight);
                                    for (int y = 0; y < bHeight; y++) {
                                        for (int x = 0; x < bWidth; x++) {
    
                                            int index = y * bWidth + x;
                                            int r = (pixels[index] >> 16) & 0xff; //bitwise shifting
                                            int g = (pixels[index] >> 8) & 0xff;
                                            int b = pixels[index] & 0xff;
    
                                           if(Math.abs(sR-r) < ANTILAISING_TOLERANCE && Math.abs(sG-g) < ANTILAISING_TOLERANCE && Math.abs(sB-b) < ANTILAISING_TOLERANCE)
                                           colored.setPixel(x, y, (colored.getPixel(x, y) & 0xFFFF0000));
                                            }
                                    }
                                } finally {
                                    mask.recycle();
                                }
                            }
                        }
                        imageView.setImageBitmap(colored);
                        coloreBitmap.add(colored.copy(Config.ARGB_8888, true));
                        position = coloreBitmap.size()-1;
                        System.out.println("Position in drawFunction is: "+position);
                    } finally {
                        decoder_image.recycle();
                    }
    

    我也将它们切成块,因为三星 Galaxy S2 没有足够的内存来一次扫描整个位图。

    希望这会有所帮助。

    编辑:

    我只是注意到(我的错)这是关于设置一个像素,而不是仅仅读取它们。我现在要尝试使它适合您的代码,已经对您的代码进行了一些更改,我目前正在处理它。

    编辑 2: 对代码进行了调整,我希望这有效。 不要忘记更改代码顶部的"yourfilepath"

    【讨论】:

    • 感谢您的回答。我会试一试,请您根据我的图像转换此代码吗?
    【解决方案2】:

    只是建议将 for 循环减少一半。您应该尝试使用您的图像,看看它是否有效。

    想法:假设下一个像素与当前像素相同,我们只分析当前像素并将结果应用于当前和下一个像素。

    缺点:你有 50% 的机会有 1 个像素失真。

    示例:将颜色 1 变为 3

    原文:1 1 1 1 1 2 2 2 2 2 2 1 1 1

    for 循环后:3 3 3 3 3 3 2 2 2 2 2 2 3 3(仅执行 7 个循环。但颜色 2 移动了 1 个像素。 )

    使用原始逻辑,将执行14个循环。

    for(int x = 0; x < mask.getWidth(); x++){
        for(int y = 0; y < mask.getHeight() - 1; y+=2) { // Change point 1
    
            g = (mask.getPixel(x,y) & 0x0000FF00) >> 8;
            r = (mask.getPixel(x,y) & 0x00FF0000) >> 16;
            b = (mask.getPixel(x,y) & 0x000000FF);
    
            if(Math.abs(sR-r) < ANTILAISING_TOLERANCE && Math.abs(sG-g) < ANTILAISING_TOLERANCE && Math.abs(sB-b) < ANTILAISING_TOLERANCE)
                colored.setPixel(x, y, (colored.getPixel(x, y) & 0xFFFF0000));
                colored.setPixel(x, y+1, (colored.getPixel(x, y) & 0xFFFF0000)); // Change point 2
        }
    }
    

    【讨论】:

    • 感谢您的回答但是使用它,结果不正确,甚至速度没有任何增加。
    【解决方案3】:

    iDroid,

    你的处境非常艰难。每当您进行逐像素操作时,事情都会变得有些麻烦。所以,一堆小的优化是关键,我敢肯定很多人会在这里添加很多东西。我不确定它们会对您的整个流程产生多大影响,但我知道这些一般行为可以节省我优化大量代码的时间。

    public void drawLoop(){
        int ANTILAISING_TOLERANCE = 100;
    
    //EDIT: Moving this to outside the loop is FAR better
    // Saves you an object call and the number doesn't change in the loop anyway.
        int maskHeight = mask.getHeight();
    //EDIT: Reverse the loops. Comparisons vs. 0 are faster than any other number.
    //  and saves you a ton of method calls.
        for(int x = mask.getWidth(); --x >= 0 ; ){
            for(int y = maskHeight; --y >= 0 ; ){
            //EDIT: Saves you 2 method calls for the same result.
                int atPixel = mask.getPixel(x,y);
                g = (atPixel & 0x0000FF00) >> 8;
                r = (atPixel & 0x00FF0000) >> 16;
                b = (atPixel & 0x000000FF);
    
                if(Math.abs(sR-r) < ANTILAISING_TOLERANCE && Math.abs(sG-g) <     ANTILAISING_TOLERANCE && Math.abs(sB-b) < ANTILAISING_TOLERANCE)
                    colored.setPixel(x, y, (colored.getPixel(x, y) & 0xFFFF0000));
            }
        }
    
        imageView.setImageBitmap(colored);
        coloreBitmap.add(colored.copy(Config.ARGB_8888, true));
        position = coloreBitmap.size()-1;
        System.out.println("Position in drawFunction is: "+position);
    }
    

    除此之外,其他任何事情都会产生“有损”行为,但收益会高得多。

    希望对你有帮助,

    模糊逻辑

    【讨论】:

    • 是的,谢谢您的回答。但速度仍然没有任何变化。有没有其他办法可以提高它的速度?
    • 绝对!看看 Bigflow 的回答!它应用得很好。他只是将图像分成多个部分。如果您正在处理特别大的图像,这可以大大改善事情。并将其与上述内容结合起来应该会有所帮助。
    • OK 当然会试一试。并感谢您的建议。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-08
    • 1970-01-01
    • 2019-07-25
    • 1970-01-01
    相关资源
    最近更新 更多