微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

java – 如何使用Floyd-Steinberg抖动将24位PNG转换为3位PNG?

如何使用 Floyd–Steinberg dithering将24位PNG转换为3位PNG?应该使用java.awt.image.BufferedImage来获取和设置RGB值.

在维基百科上,给出了如何将16位转换为8位图像的示例:

find_closest_palette_color(oldpixel) = (oldpixel + 128) / 256

基于此,有没有想到如何适应上面的例子来实现目标?

解决方法

使用 image.getRGB(x,y)image.setRGB(x,y,color),并从 wikipedia article使用 pseudocode.请注意,维基上的代码不会说如何“减”,“添加”和“乘”颜色. (下面的T3类处理“颜色”操作.)

下面的代码将会产生这个截图:

class Test {
  private static BufferedImage floydSteinbergDithering(BufferedImage img) {

    C3[] palette = new C3[] {
        new C3(  0,0),new C3(  0,255),255,new C3(255,255)
    };

    int w = img.getWidth();
    int h = img.getHeight();

    C3[][] d = new C3[h][w];

    for (int y = 0; y < h; y++) 
      for (int x = 0; x < w; x++) 
        d[y][x] = new C3(img.getRGB(x,y));

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

        C3 oldColor = d[y][x];
        C3 newColor = findClosestPaletteColor(oldColor,palette);
        img.setRGB(x,newColor.toColor().getRGB());

        C3 err = oldColor.sub(newColor);

        if (x+1 < w)         d[y  ][x+1] = d[y  ][x+1].add(err.mul(7./16));
        if (x-1>=0 && y+1<h) d[y+1][x-1] = d[y+1][x-1].add(err.mul(3./16));
        if (y+1 < h)         d[y+1][x  ] = d[y+1][x  ].add(err.mul(5./16));
        if (x+1<w && y+1<h)  d[y+1][x+1] = d[y+1][x+1].add(err.mul(1./16));
      }
    }

    return img;
  }

  private static C3 findClosestPaletteColor(C3 c,C3[] palette) {
    C3 closest = palette[0];

    for (C3 n : palette) 
      if (n.diff(c) < closest.diff(c))
        closest = n;

    return closest;
  }

  public static void main(String[] args) throws IOException {

    final BufferedImage normal  = ImageIO.read(new URL("http://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png")).getSubimage(100,100,300,300);
    final BufferedImage dietered = floydSteinbergDithering(ImageIO.read(new URL("http://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png"))).getSubimage(100,300);

    JFrame frame = new JFrame("Test");
    frame.setLayout(new GridLayout(1,2));

    frame.add(new JComponent() {
      @Override
      protected void paintComponent(Graphics g) {
         super.paintComponent(g);
         g.drawImage(normal,this);
      }
    });
    frame.add(new JComponent() {
      @Override
      protected void paintComponent(Graphics g) {
         super.paintComponent(g);
         g.drawImage(dietered,this);
      }
    });

    frame.setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(400,400);
    frame.setVisible(true);
  }


  static class C3 {
    int r,g,b;

    public C3(int c) {
      Color color = new Color(c);
      this.r = color.getRed();
      this.g = color.getGreen();
      this.b = color.getBlue();
    }
    public C3(int r,int g,int b) {
      this.r = r;
      this.g = g;
      this.b = b;
    }

    public C3 add(C3 o) {
      return new C3(r + o.r,g + o.g,b + o.b);
    }
    public C3 sub(C3 o) {
      return new C3(r - o.r,g - o.g,b - o.b);
    }
    public C3 mul(double d) {
      return new C3((int) (d * r),(int) (d * g),(int) (d * b));
    }
    public int diff(C3 o) {
      return Math.abs(r - o.r) +  Math.abs(g - o.g) +  Math.abs(b - o.b);
    }

    public int toRGB() {
      return toColor().getRGB();
    }
    public Color toColor() {
      return new Color(clamp(r),clamp(g),clamp(b));
    }
    public int clamp(int c) {
      return Math.max(0,Math.min(255,c));
    }
  }
}

原文地址:https://www.jb51.cc/java/124027.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐