概要

Graphicsの論理ピクセル操作をXORモードで実行するように指定して、XOR変更色と現在の色のXORで生成したマスクでピクセルの色を再度XOR反転して描画します。

サンプルコード

@Override protected void paintComponent(Graphics g) {
  super.paintComponent(g);
  Graphics2D g2 = (Graphics2D) g.create();

  int iw = icon.getIconWidth();
  int ih = icon.getIconHeight();
  Dimension dim = getSize();
  int x = (dim.width - iw) / 2;
  int y = (dim.height - ih) / 2;
  g.drawImage(icon.getImage(), x, y, iw, ih, this);

  g2.setPaint(Color.RED);
  g2.fillOval(10, 10, 32, 32);

  g2.setPaint(Color.GREEN);
  g2.fillOval(50, 10, 32, 32);

  g2.setPaint(Color.BLUE);
  g2.fillOval(90, 10, 32, 32);

  g2.setPaint(Color.PINK);
  g2.fillOval(130, 10, 32, 32);

  g2.setPaint(Color.CYAN);
  g2.fillOval(170, 10, 32, 32);

  g2.setPaint(Color.ORANGE);
  g2.fillOval(210, 10, 32, 32);

  g2.setXORMode(Color.PINK);
  g2.fill(rubberBand);

  g2.setPaintMode();
  g2.setStroke(stroke);
  g2.setPaint(Color.WHITE);
  g2.draw(rubberBand);
  g2.dispose();
}
View in GitHub: Java, Kotlin

解説

  • 現在の色: Graphics#setPaint(...)で設定した色
    • このサンプルではColor.ORANGE#FFC8001111 1111 1100 1000 0000 0000
  • XOR変更色: Graphics#setXORMode(...)で設定した色
    • このサンプルではColor.PINK#FFAFAF1111 1111 1010 1111 1010 1111
  • マスク: 現在の色とXOR変更色の排他論理和
    • このサンプルではColor.ORANGE.getRGB() ^ Color.PINK.getRGB()#0067AF0000 0000 0110 0111 1010 1111

  • このサンプルでは現在の色がColor.ORANGEXOR変更色がColor.PINKなのでマウスドラッグで囲んだ範囲内のColor.ORANGEColor.PINKに、Color.PINKColor.ORANGEに反転する
  • その他のピクセルの色はマスクでXORした色に変換
  • XORなので2回反転すると元の色に戻る
  • 1: 赤(#FF0000)は#FF67AFになる
    マスク: 0000 0000 0110 0111 1010 1111
      赤: 1111 1111 0000 0000 0000 0000
    変換後: 1111 1111 0110 0111 1010 1111
  • 2: 青(#0000FF)は#006750になる
    マスク: 0000 0000 0110 0111 1010 1111
      青: 0000 0000 0000 0000 1111 1111
    変換後: 0000 0000 0110 0111 0101 0000

参考リンク

  • Graphics#setXORMode(...) (Java Platform SE 8)
  • Graphics2D (Java Platform SE 8)
    • GraphicsではなくGraphics2Dのドキュメントに「setXORMode(Color xorcolor)メソッドは、ソース・カラーのAlpha成分を無視し、デスティネーション・カラーをその値に設定する特殊なCompositeオブジェクトを設定するための簡易メソッドとして実装されます。 dstpixel = (PixelOf(srccolor) ^ PixelOf(xorcolor) ^ dstpixel);」と説明されている
    • このためGraphics#setComposite(...)を設定しているとsetXORMode(...)は無視される

コメント