public static BufferedImage doFilter(BufferedImage img) {
    BufferedImage img2 =
        new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
    // img.getSubimage(0, 0, img.getWidth(), img.getHeight());
    for (int i = 0; i < img2.getWidth(); i++) {
      for (int j = 0; j < img2.getHeight(); j++) {
        img2.setRGB(i, j, img.getRGB(i, j));
        // img2.setRGB(i, j, Color.BLACK.getRGB());
      }
    }
    int a = 32;
    for (int j = 0; j < img2.getHeight(); j++) {
      for (int i = 0; i < img2.getWidth(); i++) {
        int c = img.getRGB(i, j);
        Color c2 = new Color(c);
        Error er = new Error();

        er.r = (int) (a * matrix[i % 2][j % 2]);
        er.g = er.r;
        er.b = er.r;
        c2 = addToPixel(c2, er, 1);
        Color c3 = getClosestPixel(c2);
        setPixel(img2, i, j, c3);

        // oldpixel := pixel[x][y] + threshold_map_4x4[x mod 4][y mod 4]
        // newpixel := find_closest_palette_color(oldpixel)
        // pixel[x][y] := newpixel
      }
    }
    return img2;
  }
 private static Error getError(Color c1, Color c2) {
   int r = c1.getRed();
   int g = c1.getGreen();
   int b = c1.getBlue();
   r = r - c2.getRed();
   g = g - c2.getGreen();
   b = b - c2.getBlue();
   Error er = new Error();
   er.r = r;
   er.g = g;
   er.b = b;
   return er;
 }