并行化位图

时间:2011-07-30 17:13:38

标签: java android image-processing concurrency parallel-processing

我有一个应用程序循环通过位图并在其上放置一个失真。我重写了图像处理部分并行运行。失真的位图似乎只有顶行的像素集,其余的位图是黑色的,表明制作新位图的数组几乎是空的。我想我有一个循环问题。我使用executorservice来管理我的线程并创建了2个线程。线程一应该从0循环到bitmap.height / 2,线程2应该从bitmap.height / 2循环到bitmap.height。任何人都可以帮我解决循环问题。我没有包含很多处理位图的代码,但如果它有帮助,我会发布它。

public class MultiProcessorFilter {



    private static final String TAG = "mpf";





    public Bitmap barrel (Bitmap input, float k){
          if(input!=null){
        Log.e(TAG, "*********** bitmap input = "+input.toString());
          }
          int []arr = new int[input.getWidth()*input.getHeight()];
          // replace the j, i for loops:
          int jMax = input.getHeight();
          int jMid = jMax / 2;
          int iMax = input.getWidth();
          int iMid = iMax / 2;
          int nrOfProcessors = Runtime.getRuntime().availableProcessors();
          Log.e(TAG, "*********** NUM OF PROCESSORS = " + nrOfProcessors);
          ExecutorService threadPool = Executors.newFixedThreadPool(2);

          FutureTask<PartialResult> task1 = (FutureTask<PartialResult>) threadPool.submit(new PartialProcessing(0, jMid - 1, input, k)); 
          FutureTask<PartialResult> task2 = (FutureTask<PartialResult>) threadPool.submit(new PartialProcessing(jMid, jMax - 1,input, k)); 
          Log.e(TAG, "*********** about to call task1.get()");
          try{
          PartialResult result1 = task1.get();// blocks until the thread returns the result
          Log.e(TAG, "*********** just called task1.get()");
          result1.fill(arr);
          Log.e(TAG, "*********** result1 arr length = " + arr.length);

          Log.e(TAG, "*********** about to call task2.get()");
          PartialResult result2 = task2.get(); // blocks until the thread returns the result
          Log.e(TAG, "*********** just called task2.get()");
          result2.fill(arr);
          Log.e(TAG, "*********** result2 arr length = " + arr.length);
          }catch(Exception e){
              e.printStackTrace();
          }
          Bitmap dst2 = Bitmap.createBitmap(arr,input.getWidth(),input.getHeight(),input.getConfig());
          if(dst2!=null)
          Log.e(TAG, "*********** dst2 is not null" );
        return dst2;


        }




    public class PartialResult {
           int startP;
           int endP;
           int[] storedValues;

           public PartialResult(int startp, int endp, Bitmap input){

               this.startP = startp;
               this.endP = endp;
               this.storedValues = new int[input.getWidth()*input.getHeight()];
               Log.e(TAG, "*********** input  w = "+input.getWidth());
               Log.e(TAG, "*********** input dim  h = "+input.getHeight());
           }

           public void addValue(int p, int result) {
                 storedValues[p] = result;
                // Log.e(TAG, "*********** p = " + p + "result = " + result);
           }

           public void fill(int[] arr) {
               int x = 0;
              // Log.e(TAG, "*********** startP = "+startP + "  endP = " + endP);
              for (int p = startP; p < endP; p++, x++)
                 arr[p] = storedValues[p];

              Log.e(TAG, "*********** arr = " + arr[x]);
              }
           }




    public class PartialProcessing implements Callable<PartialResult> {
        int startJ;
        int endJ;

       // ... other members needed for the computation 

        public PartialProcessing(int startj, int endj, Bitmap input, float k) {

            this.startJ = startj;
            this.endJ = endj;
            this.input = input;
            this.k = k;


        }

        int [] getARGB(Bitmap buf,int x, int y){

            method for processing

        }

        //... add other methods needed for the computation that where in class Filters

        float getRadialX(float x,float y,float cx,float cy,float k){

            method for processing
          }

          float getRadialY(float x,float y,float cx,float cy,float k){

           method for processing
          }



          float calc_shift(float x1,float x2,float cx,float k){

           method for processing
          }


          void sampleImage(Bitmap arr, float idx0, float idx1)
          {

           method for processing
          }


        // this will be called on some new thread
        @Override public PartialResult call() { 

             PartialResult partialResult = new PartialResult(startJ, endJ,input);



            int p = startJ; // not 0! at the start since we don't start at j = 0
            int origPixel = 0;
            int color = 0;
            int i;
            for (int j = startJ; j <  endJ; j++){
                // Log.e(TAG, "*********** j = "+j );

                for ( i = 0; i < width; i++, p++){
                    //... copy the rest of the code
                    // Log.e(TAG, "*********** i = " + i);


             origPixel = input.getPixel(i,j);

             float x = getRadialX((float)j,(float)i,centerX,centerY,k);


             float y = getRadialY((float)j,(float)i,centerX,centerY,k);

             sampleImage(input,x,y);

             color = ((s[1]&0x0ff)<<16)|((s[2]&0x0ff)<<8)|(s[3]&0x0ff);

             if(((i-centerX)*(i-centerX) + (j-centerY)*(j-centerY)) <= 5500){

                //arr[p]=color;
                 partialResult.addValue(p, color);
                // Log.e(TAG, "*********** color = " + color);

            }else{

                //arr[p]=origPixel;
                partialResult.addValue(p, origPixel);



            }

                }
                     // partialResult.addValue(p, color);
        }
            return partialResult;
    }


}

}//end of MultiProcesorFilter

[更新1]

07-31 13:50:29.548: ERROR/mpf(3354): *********** bitmap input = android.graphics.Bitmap@43cd2780
07-31 13:50:29.553: ERROR/mpf(3354): *********** NUM OF PROCESSORS = 1
07-31 13:50:29.553: ERROR/mpf(3354): *********** about to call task1.call()
07-31 13:50:29.558: ERROR/mpf(3354): *********** input  w = 150
07-31 13:50:29.563: ERROR/mpf(3354): *********** input  h = 150
07-31 13:50:30.348: ERROR/mpf(3354): *********** just called part1.call()
07-31 13:50:30.348: ERROR/mpf(3354): *********** result1 arr length = 22500
07-31 13:50:30.348: ERROR/mpf(3354): *********** about to call part2.()
07-31 13:50:30.353: ERROR/mpf(3354): *********** input  w = 150
07-31 13:50:30.353: ERROR/mpf(3354): *********** input  h = 150
07-31 13:50:31.143: ERROR/mpf(3354): *********** just called part2.call()
07-31 13:50:31.143: ERROR/mpf(3354): *********** result2 arr length = 22500
07-31 13:50:31.173: DEBUG/WifiService(1911): ACTION_BATTERY_CHANGED pluggedType: 2
07-31 13:50:31.183: ERROR/mpf(3354): *********** dst2 is not null
07-31 13:50:31.188: ERROR/mpf(3354): *********** bitmap input = android.graphics.Bitmap@43ccb060
07-31 13:50:31.253: DEBUG/dalvikvm(3354): GC freed 652 objects / 124416 bytes in 65ms
07-31 13:50:31.258: ERROR/mpf(3354): *********** NUM OF PROCESSORS = 1
07-31 13:50:31.258: ERROR/mpf(3354): *********** about to call task1.call()
07-31 13:50:31.258: ERROR/mpf(3354): *********** input  w = 150
07-31 13:50:31.258: ERROR/mpf(3354): *********** input  h = 150
07-31 13:50:32.093: ERROR/mpf(3354): *********** just called part1.call()
07-31 13:50:32.093: ERROR/mpf(3354): *********** result1 arr length = 22500
07-31 13:50:32.093: ERROR/mpf(3354): *********** about to call part2.()
07-31 13:50:32.098: ERROR/mpf(3354): *********** input  w = 150
07-31 13:50:32.098: ERROR/mpf(3354): *********** input  h = 150
07-31 13:50:33.078: ERROR/mpf(3354): *********** just called part2.call()
07-31 13:50:33.078: ERROR/mpf(3354): *********** result2 arr length = 22500
07-31 13:50:33.083: ERROR/mpf(3354): *********** dst2 is not null

[UPDATE2]

 public void fill(int[] arr) {
               int x = 0;
               Log.e(TAG, "*********** startP = "+startP + "  endP = " + endP);

              for (int p = startP; p < endP; p++, x++){
                 arr[p] = storedValues[p];
              }

              Log.e(TAG, "*********** arr size = "+arr.length);
              Log.e(TAG, "*********** storedValues size = "+storedValues.length);
              }

           }

07-31 14:26:18.788: ERROR/mpf(6380): *********** just called task1.get()
07-31 14:26:18.788: ERROR/mpf(6380): *********** startP = 0  endP = 74
07-31 14:26:18.788: ERROR/mpf(6380): *********** arr size = 22500
07-31 14:26:18.788: ERROR/mpf(6380): *********** storedValues size = 22500
07-31 14:26:18.788: ERROR/mpf(6380): *********** result1 arr length = 22500
07-31 14:26:18.788: ERROR/mpf(6380): *********** about to call task2.get()
07-31 14:26:18.818: ERROR/mpf(6380): *********** just called task2.get()
07-31 14:26:18.818: ERROR/mpf(6380): *********** startP = 75  endP = 149
07-31 14:26:18.818: ERROR/mpf(6380): *********** arr size = 22500
07-31 14:26:18.818: ERROR/mpf(6380): *********** storedValues size = 22500
07-31 14:26:18.818: ERROR/mpf(6380): *********** result2 arr length = 22500
07-31 14:26:18.823: ERROR/mpf(6380): *********** dst2 is not null
07-31 14:26:18.823: ERROR/mpf(6380): *********** bitmap input = android.graphics.Bitmap@43ce62c0

[UPDATE3]

public void fill(int[] arr) {

               Log.e(TAG, "*********** startP = "+startP + "  endP = " + endP);

              for (int p = startP; p < endP; p++){
                  for(int b=0;b<150;b++,x++)
                 arr[x] = storedValues[x];
              }

              Log.e(TAG, "*********** arr size = "+arr.length);
              Log.e(TAG, "*********** storedValues size = "+storedValues.length);
              Log.e(TAG, "*********** x = "+x);
              }

           }

1 个答案:

答案 0 :(得分:2)

尚未完整答案,但评论太大了。

我无法真正测试您的程序,但出于调试目的,请更改此方法:

public Bitmap barrel (Bitmap input, float k){
    if(input!=null){
       Log.e(TAG, "*********** bitmap input = "+input.toString());
    }
    int []arr = new int[input.getWidth()*input.getHeight()];
      // replace the j, i for loops:
    int jMax = input.getHeight();
    int jMid = jMax / 2;
    int iMax = input.getWidth();
    int iMid = iMax / 2;
    int nrOfProcessors = Runtime.getRuntime().availableProcessors();
    Log.e(TAG, "*********** NUM OF PROCESSORS = " + nrOfProcessors);

    PartialProcessing part1 = new PartialProcessing(0, jMid - 1, input, k); 
    PartialProcessing part2 = new PartialProcessing(jMid, jMax - 1,input, k); 
    Log.e(TAG, "*********** about to call task1.call()");
    try{
       PartialResult result1 = part1.call();// blocks until the thread returns the result
       Log.e(TAG, "*********** just called part1.call()");
       result1.fill(arr);
       Log.e(TAG, "*********** result1 arr length = " + arr.length);

       Log.e(TAG, "*********** about to call part2.()");
       PartialResult result2 = part2.call(); // blocks until the thread returns the result
       Log.e(TAG, "*********** just called part2.call()");
       result2.fill(arr);
       Log.e(TAG, "*********** result2 arr length = " + arr.length);
    }catch(Exception e){
        e.printStackTrace();
    }
    Bitmap dst2 = Bitmap.createBitmap(arr,input.getWidth(),input.getHeight(),input.getConfig());
    if(dst2!=null)
        Log.e(TAG, "*********** dst2 is not null" );
    return dst2;
}

这将是您程序的一个系列变体。运行它,检查它是否有效。

  • 如果确实如此,我们就会遇到并发问题。
  • 如果它不起作用,问题出在您的实际实现中,与并发性无关。

  

几乎空的位图仍然是处理的结果

好的,我们知道这不是与并发相关的。让我们看看像素设置的点。 一个在这里,在PartialResult:

  public void fill(int[] arr) {
       int x = 0;
      // Log.e(TAG, "*********** startP = "+startP + "  endP = " + endP);
      for (int p = startP; p < endP; p++, x++)
         arr[p] = storedValues[p];

      Log.e(TAG, "*********** arr = " + arr[x]);
      }
  }

这会将arrstartPendP的元素设置为某些存储值。现在,请查看startPendP的实际值与storedValuesarr的尺寸进行比较,我想您会明白为什么只有第一行像素。


更新3之后:

变得更好。现在看一下x方法中fill开始的位置(在原来的0中,我不确定新的方法 - 它应该是startP*150 }},以及p方法中call开始的位置(从startJ开始 - 我认为它应该从startJ * 150开始。