【问题标题】:Comparing Bitmap images in Android比较 Android 中的位图图像
【发布时间】:2011-09-01 12:04:07
【问题描述】:

有没有办法检查位图是否相同?有人可以帮帮我吗?

【问题讨论】:

    标签: android bitmap


    【解决方案1】:

    Bitmap 类有方法“sameAs”,你可以使用该方法比较两个位图

    http://developer.android.com/reference/android/graphics/Bitmap.html#sameAs%28android.graphics.Bitmap%29

    【讨论】:

    • 请注意,直到 API v12(即 Android 3.1)才引入 sameAs 方法,因此这对旧版本并没有真正的帮助。
    • minSdk 14 所有的东西
    • minSdk 19 所有的东西
    • 差不多 2019 年所有的事情
    • 差不多 2020 年所有的事情
    【解决方案2】:

    应该是这样的:

    public boolean equals(Bitmap bitmap1, Bitmap bitmap2) {
        ByteBuffer buffer1 = ByteBuffer.allocate(bitmap1.getHeight() * bitmap1.getRowBytes());
        bitmap1.copyPixelsToBuffer(buffer1);
    
        ByteBuffer buffer2 = ByteBuffer.allocate(bitmap2.getHeight() * bitmap2.getRowBytes());
        bitmap2.copyPixelsToBuffer(buffer2);
    
        return Arrays.equals(buffer1.array(), buffer2.array());
    }
    

    【讨论】:

    • @Photon,这个方法我没有遇到任何异常
    • 即使在 Galaxy S3 上也会出现内存不足异常
    • 尝试在后台线程中调用此方法或使用AsyncTask
    • 上述方法非常占用内存。对于以 ARGB 存储的 20 兆像素图像,它将尝试使用至少 160 MB RAM 来比较它们(每张图像 80 MB = 20 MP * 每像素 4 字节)。
    【解决方案3】:

    这个问题似乎很老,但我今天花了一些时间在这个问题上,这就是我所做的。

    private static boolean compare(Bitmap b1, Bitmap b2) {
        if (b1.getWidth() == b2.getWidth() && b1.getHeight() == b2.getHeight()) {
            int[] pixels1 = new int[b1.getWidth() * b1.getHeight()];
            int[] pixels2 = new int[b2.getWidth() * b2.getHeight()];
            b1.getPixels(pixels1, 0, b1.getWidth(), 0, 0, b1.getWidth(), b1.getHeight());
            b2.getPixels(pixels2, 0, b2.getWidth(), 0, 0, b2.getWidth(), b2.getHeight());
            if (Arrays.equals(pixels1, pixels2)) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }
    

    【讨论】:

    • 您可以简化语句以返回 Arrays.equals(pixels1, pixel2);而是“如果(Arrays.equals(pixels1,pixels2)){ return true; } else { return false; }”
    【解决方案4】:

    取决于您如何定义。如果您的意思是完全相同的文件,您可以对文件进行 md5sum。我猜每种类型的文件都是一样的。

    因为您专门区分位图文件,所以您可能对大小不同的文件感兴趣。这有点难。如果它们的大小相同,但不完全相同(但看起来真的很像),您可以比较每个单独的像素,如果足够的像素(阈值 1)在颜色上彼此足够接近(阈值 2),您可以声明它们是一样的。

    你可以getPixel(int,int)获取颜色,见this page

    【讨论】:

      【解决方案5】:

      小于 12 的 API 的主要问题是我们在大文件解析时收到 OutOfMemory 错误。我通过将位图分成几块(示例中为 10 个)然后按字节比较它们来解决它:

      private boolean compareBitmaps(Bitmap bitmap1, Bitmap bitmap2)
      {
          if (Build.VERSION.SDK_INT > 11)
          {
              return bitmap1.sameAs(bitmap2);
          }
      
          int chunkNumbers = 10;
          int rows, cols;
          int chunkHeight, chunkWidth;
          rows = cols = (int) Math.sqrt(chunkNumbers);
          chunkHeight = bitmap1.getHeight() / rows;
          chunkWidth = bitmap1.getWidth() / cols;
      
          int yCoord = 0;
          for (int x = 0; x < rows; x++)
          {
              int xCoord = 0;
              for (int y = 0; y < cols; y++)
              {
                  try
                  {
                      Bitmap bitmapChunk1 = Bitmap.createBitmap(bitmap1, xCoord, yCoord, chunkWidth, chunkHeight);
                      Bitmap bitmapChunk2 = Bitmap.createBitmap(bitmap2, xCoord, yCoord, chunkWidth, chunkHeight);
      
                      if (!sameAs(bitmapChunk1, bitmapChunk2))
                      {
                          recycleBitmaps(bitmapChunk1, bitmapChunk2);
                          return false;
                      }
      
                      recycleBitmaps(bitmapChunk1, bitmapChunk2);
      
                      xCoord += chunkWidth;
                  }
                  catch (Exception e)
                  {
                      return false;
                  }
              }
              yCoord += chunkHeight;
          }
      
          return true;
      }
      
      private boolean sameAs(Bitmap bitmap1, Bitmap bitmap2)
      {
          // Different types of image
          if (bitmap1.getConfig() != bitmap2.getConfig())
              return false;
      
          // Different sizes 
          if (bitmap1.getWidth() != bitmap2.getWidth())
              return false;
      
          if (bitmap1.getHeight() != bitmap2.getHeight())
              return false;
      
          int w = bitmap1.getWidth();
          int h = bitmap1.getHeight();
      
          int[] argbA = new int[w * h];
          int[] argbB = new int[w * h];
      
          bitmap1.getPixels(argbA, 0, w, 0, 0, w, h);
          bitmap2.getPixels(argbB, 0, w, 0, 0, w, h);
      
          // Alpha channel special check 
          if (bitmap1.getConfig() == Bitmap.Config.ALPHA_8)
          {
              final int length = w * h;
              for (int i = 0; i < length; i++)
              {
                  if ((argbA[i] & 0xFF000000) != (argbB[i] & 0xFF000000))
                  {
                      return false;
                  }
              }
              return true;
          }
      
          return Arrays.equals(argbA, argbB);
      }
      
      private void recycleBitmaps(Bitmap bitmap1, Bitmap bitmap2)
      {
          bitmap1.recycle();
          bitmap2.recycle();
          bitmap1 = null;
          bitmap2 = null;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-10-27
        • 2023-03-11
        • 1970-01-01
        • 2013-01-29
        • 2012-04-04
        • 2016-09-19
        • 1970-01-01
        相关资源
        最近更新 更多