XOR两个单色图像


28

挑战:

接受两个黑白(单色)图像的输入,然后将第一个像素的每个像素与第二个像素的每个像素进行异或,将它们添加到新图像中并输出新图像。

一些说明:

图片大小无关紧要。扩展名/图像格式无关紧要。您可以使其输入任何扩展名,并输出任何扩展名,只要该扩展名用于存储数字图像即可。如果需要,您还可以使用图形在例如画框中绘制输出。否则,将输出另存为文件。输入可以作为图像或url的路径。

但是,您无法做的一件事就是I / O阵列。三胞胎(R,G,B)。

不要篡改alpha。不应进行异或处理,每个像素应为255(最大值)。

每个像素的异或是什么意思?

您不必这样做,但是对两个像素进行异或运算的一种方法是将其RGB值和R1与R2,G1与G2,B1与B2并获取结果,这就是您的新颜色

由于我们只有两种颜色,因此在这种情况下,显然,当颜色相同时,结果将为(0,0,0),而当颜色不同时(白色为255,255,255,黑色为0,0,0),结果将为是255,255,255。

因此,当两个像素不同时,结果为白色像素,否则为黑色像素

I / O示例:


输入1:输入2:

输入1 输入2


输出:

输出量


这是因此最短的代码获胜。


我们可以将输入图像用作URL吗?
Kritixi Lithos

@KritixiLithos是的,我在挑战赛中为其他观看者进行了编辑。
P. Ktinos



@orlp我已经准备好了
二维

Answers:


20

Fx表达语言(ImageMagick), 8 4字节

编辑

  • 简化为u!=v-4个字节

由于“ Fx表达语言”显然已经完成了Turing的功能,因此我重新介绍了它的答案(使用Unix Shell + Image Magick)。

打高尔夫球

u!=v

Fx不支持按位XOR或按位NOT,所以我使用了!=它(对于纯BW图像来说效果很好)。

u=> stands for "first image in list"
v=> "second image in list"

输入和输出是隐式的(由解释器控制)。

用法

当通过调用ImageMagick 转换实用程序时,它充当“ Fx表达式语言”解释器,-fx如下所示:

convert $1 $2 -fx u!=v $3

参数为:

  1. 输入图像A
  2. 输入图像B
  3. 输出图像O(A ^ B)。

样品输出

convert a.png b.png -fx u!=v o.png

在此处输入图片说明


15

Mathematica,37 34 15字节

感谢Ian Miller将字节数减少了一半以上!

ImageDifference

最后,总会有一个内置函数。该功能将两个图像作为输入并输出一个图像。对于彩色图像,它做的事情比较复杂,但是对于黑白图像,它的确是XOR。

以前的提交:

感谢JungHwan Min节省了3个字节!

Image[BitXor@@Chop[ImageData/@#]]&

未命名函数,将一对有序的图像(具有兼容的尺寸)作为输入,并返回显示的图像。ImageData仅获取像素数据,而不获取所有包装器/元数据;不幸的是,它返回实数,因此Chop需要将其视为整数。BitXor完全按照锡罐上的说明(和嵌套列表中的线程)执行操作,并将Image生成的RGB重新转换为图像。

原始提交,其中输入了一对有序的URL或文件名:

Image[BitXor@@(#~Import~"Data"&/@#)]&

4
对于二进制图像,您可以使用 ImageDifference[#,#2]&
Ian Miller

10

Java中,336个 335 328字节

import static javax.imageio.ImageIO.*;import java.io.*;public class M{static void main(String[]y)throws Exception{java.awt.image.BufferedImage a=read(new File("a.png"));for(int i=0,j;i<a.getHeight();i++)for(j=0;j<a.getWidth();)a.setRGB(j,i,a.getRGB(j,i)^read(new File("b.png")).getRGB(j++,i));write(a,"png",new File("c.png"));}}

取消高尔夫:

import static javax.imageio.ImageIO.*;

import java.io.*;

class M {
    public static void main(String[]y) throws Exception {
        java.awt.image.BufferedImage a = read(new File("a.png"));
        for (int i = 0, j; i < a.getHeight(); i++)
            for (j = 0; j < a.getWidth(); ) a.setRGB(j, i, a.getRGB(j, i) ^ read(new File("b.png")).getRGB(j++, i));
        write(a, "png", new File("c.png"));
    }
}

1
您可以通过删除之间的空格来节省一个字节String[] y。只是一个小的高尔夫。
HyperNeutrino

哦,当你是对的。最近没打高尔夫球,完全忽略了那个。干杯。
Marv

3
您可以删除publicpublic class M以保存7个字节
Kritixi Lithos

.png不需要文件扩展名
Huntro

您可以通过执行以下操作来保存字节:“ i ++ <a.getHeight();)”

9

Python,64 60 57字节

我是打高尔夫球的新手,所以请多多怜悯!

from cv2 import*
r=imread;lambda a,b:imshow('c',r(a)^r(b))

感谢@Blender和@FlipTack为我节省了7个字节!


1
使用from cv2 import*应删除4个字符。
Blender

1
在这里,函数答案允许使用未命名的lambda,因此您也可以删除d=:),这样做r=imread然后使用r两次可能会更短
FlipTack

7

八度,43 38 34字节

@(a,b)imshow(imread(a)~=imread(b))

多亏了骗子为我节省了5个字节。

感谢Luis Mendo为我节省了建议使用的4个字节,a~=b而不是xor(a,b)

将两个输入图像作为输入文件名a,b并显示结果的函数。

写入文件的先前答案:

@(a,b,c)imwrite(imread(a)~=imread(b),c)

该函数将两个输入图像的输入文件名a,b和输出图像的文件名作为输入c

用法:

#two test images that used in the question
#https://i.stack.imgur.com/UbbfM.png
#https://i.stack.imgur.com/YyZG2.png
A = "UbbfM.png"; 
B = "YyZG2.png"; 
C = "out.png";
(@(a,b,c)imwrite(imread(a)~=imread(b),c))(A,B,C)

结果保存在 out.png


1
您不能使用imshow()代替imwrite()吗?
瑕疵

@flawr当然,这将节省一些字节:)
rahnema1

1
您不能使用imread(a)~=imread(b)(或+(imread(a)~=imread(b))如果不允许逻辑输入imshow)而不是xor(...)
路易斯·门多

1
@LuisMendo谢谢,我总是从您的评论中学到!
rahnema1年

7

的JavaScript(ES6),333个 320 308 299 297字节

- 12个由伊斯梅尔米格尔保存20字节
- 2个字节保存由user2428118

期望已经加载的图像,将第一个输入的大小作为输出大小,并返回canvas元素。

(i,j)=>{c=i=>{with(document.createElement(C='canvas')){width=i.width,height=i.height;return getContext`2d`}},g=i=>{x=c(i);x.drawImage(i,0,0);return x.getImageData(0,0,i.width,i.height)},a=g(i),b=g(j).data,d=a.data,r=c(i);d.forEach((e,i)=>{d[i]=i%4>2?255:e^b[i]});r.putImageData(a,0,0);return r[C]}

let func = (i,j)=>{c=i=>{with(document.createElement(C='canvas')){width=i.width,height=i.height;return getContext`2d`}},g=i=>{x=c(i);x.drawImage(i,0,0);return x.getImageData(0,0,i.width,i.height)},a=g(i),b=g(j).data,d=a.data,r=c(i);d.forEach((e,i)=>{d[i]=i%4>2?-1:e^b[i]});r.putImageData(a,0,0);return r[C]}

window.onload =_=>{
  document.body.appendChild(func(img1, img2));
  }
<img id="img1" crossOrigin="anonymous" src="https://dl.dropboxusercontent.com/s/nnfkzpvabk77pnl/UbbfM.png">
<img id="img2" crossOrigin="anonymous" src="https://dl.dropboxusercontent.com/s/58euf43vcb9pvpa/YyZG2.png">

不打高尔夫球

(i, j) => {
  c = i => { // an helper to create a canvas object
      with(document.createElement(C='canvas')) {
        width= i.width,
        height= i.height;
        return getContext`2d`
      }
    },
    g = i => { // an helper to get an imageData object
      x = c(i);
      x.drawImage(i, 0, 0);
      return x.getImageData(0, 0, i.width, i.height)
    },
    a = g(i),
    b = g(j).data,
    d = a.data,
    r = c(i);
  d.forEach((e, i) => { // loop through all rgba values
    d[i] = i % 4 > 2 ? 255 : e ^ b[i] // we need to avoid alpha channel...
  });
  r.putImageData(a, 0, 0);
  return r[C]
}

附言:第一次参加代码高尔夫球,所以它可能打得更多,而我的计数可能是错误的。

PP:canvas 2D上下文具有xor[合成模式(https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation),但是它适用于alpha值...

可以进一步处理(251字节),具有固定的300 * 150px大小(其余全部为黑色),如处理答案中所述

(i,j)=>{c=i=>{return document.createElement(C='canvas').getContext('2d')},g=i=>{x=c(i);x.drawImage(i,0,0);return x.getImageData(0,0,W=300,W)},a=g(i),b=g(j).data,d=a.data,r=c(i);d.forEach((e,i)=>{d[i]=i%4>2?W:e^b[i]});r.putImageData(a,0,0);return r[C]}


1
用替换该功能cc=i=>{with(document.createElement('canvas')){width=i.width,height=i.height;return getContext`2d`}}您将节省16个字节。
Ismael Miguel

您能不能在两个图像上xor的黑色矩形xor恢复到255 alpha?
尼尔

@IsmaelMiguel,谢谢,以前没有用过,with但是看起来很不错; ;-)另外,忘记了模板文字节省了2个字节...
Kaiido

@Neil,我不确定,这里我们有一个8bit的数组,也许有
32bits

1
节省4个字节:(i,j)=>{c=i=>{with(document.createElement(C='canvas')){width=i.width,height=i.height;return getContext`2d`}},g=i=>{x=c(i);x.drawImage(i,0,0);return x.getImageData(0,0,i.width,i.height)},a=g(i),b=g(j).data,d=a.data,r=c(i);d.forEach((e,i)=>{d[i]=i%4>2?255:e^b[i]});r.putImageData(a,0,0);return r[C]}
2013年

7

处理,124个 118 117字节

void m(PImage a,PImage q){for(int i=0,j;i<400;i++)for(j=0;j<400;point(i,j++))stroke((a.get(i,j)^q.get(i,j))<9?0:-1);}

用法:

注意:此代码最多可支持图像400px(经过修改,同一字节数最多可支持999)。任何“剩余”空间都将被涂成黑色,因此为了获得最佳效果,图像大小应与代码中的尺寸相同(也size()需要使用更新的尺寸进行更改)

m(loadImage("http://i.imgur.com/a0M6o9e.png"),loadImage("http://i.imgur.com/bP1TsjQ.png"));

在此处输入图片说明

m(loadImage("https://i.stack.imgur.com/UbbfM.png"),loadImage("https://i.stack.imgur.com/YyZG2.png"));

在此处输入图片说明

不打高尔夫球

void Q106945(PImage a,PImage q){     // takes two images as input
  for(int i=0,j;i<400;i++)           // looping through the x-coordinates
    for(j=0;j<400;point(i,j++))      // looping through the y-coordinates
      stroke((a.get(i,j)^q.get(i,j))<9?0:-1);
/*
Here we have to colour the point according to the xor. So we do a simple 
a.get(i,j)^q.get(i,j). But since the alpha gets xored, instead of outputting white, this
outputs a colour with alpha 0 (completely invisible). So to fix this I have a ternary that
checks the value and changes the colour accordingly. At the end of all this, the third 
statement of the for-loop with j gets triggered since all this code is in this for-loop. 
Now we draw a point over the coordinate with the colour we have chosen before.
*/
}

7

MATL,10字节

YiiYiY~1YG

说明

这与现有的Octave解决方案基本上是相同的答案:它以两个图像的文件名或URL作为输入并将结果显示在屏幕上。

Yi    % Read first image from the URL or filename (implicit input)
i     % Get the second URL or filename as input
Yi    % Read that second image
Y~    % XOR the two images
1     % Push 1 (needed to make YG act as imagesc)
YG    % Display result using the MATLAB imagesc function

用法

>> matl
 > YiiYiY~1YG
 > 
> 'https://i.stack.imgur.com/UbbfM.png'
> 'https://i.stack.imgur.com/YyZG2.png'

1
这是10个字节。
Erik the Outgolfer

3

Perl,260个字节

251个字节的代码+ 9个字节的-MImager

($i,$j)=map{new Imager(file,pop)}0,1;$p=getpixel;for$x(0..$i->getwidth()-1){$i->setpixel(x=>$x,y=>$_,color=>[map{($j->$p(%t)->rgba)[$c++%3]^$_?0:255}($i->$p(%t=(x=>$x,y=>$_,type=>'8bit'))->rgba)[0..2]])for 0..$i->getheight()-1}$i->write(file=>'a.png')

我不确定Perl是应对这一挑战的最佳语言,但我想知道@orlp的评论是什么。而且这使我使用了一些图形模块,这是一件好事。我喜欢编码!

更具可读性的版本:

使用Imager ; 
$ img1 = 新的Imager file => $ ARGV [ 1 ] ); 
$ img2 = 新的Imager file => $ ARGV [ 0 ] );   

$ X 0 .. $ IMG1 - > 的getWidth () - 1 { 对于$ Y 0 .. $ IMG1 - > 的getHeight () - 1 { $ R1 $ G1 $ B1 = $ IMG1 - > getpixel x => $ x y => $ y type => “ 8bit” )-> rgba (); $ r2 $ g2    
        
       
    $ b2 = $ img2- > getpixel x => $ x y => $ y type => “ 8bit” )-> rgba (); 
    $ r = $ r1 ^ $ r2 0 255 ; 
    $ g = $ g1 ^ $ g2 0 255 ; 
    $ b = $ b1 ^ $ b2 0 255 ; 
    $ img1               -> setpixel x => $ x y => $ y color => [ $ r $ g $ b ] ); } } 
$ img1- > file => 'a.png'   
    
  

如果要尝试,则需要安装Imager,但这很简单:只需(echo y;echo) | perl -MCPAN -e 'install Imager'在终端中运行即可。


3

LÖVE2D,199字节

u,c=... i=love.image.newImageData a=math.abs X=i(u)Y=i(c)Z=i(X:getDimensions())Z:mapPixel(function(x,y)r,g,b=X:getPixel(x,y)R,G,B=Y:getPixel(x,y)return a(r-R),a(g-G),a(b-B)end)Z:encode("png","Z")

足够简单,在命令行上获取两个图像文件,然后将一个名为“ Z”的文件输出到Love目录。也适用于全彩色图像!


1
@MDXF love2d.org
ATaco

2

J,54个字节

load'bmp'
'o'writebmp~256#.255*~:&*&((3#256)#:readbmp)

接受两个参数,其中每个参数都是bmp格式输入图像的路径。将每个图像读取为24位RGB整数矩阵,并解析为8位RGB值的三元组,获取每个符号,然后将两个矩阵进行XOR运算。然后将结果缩放255,从基数为256的三元组转换回整数,然后写入bmp名为的输出文件o


2

C,189字节

#include<stdio.h>
s,t[9];
#define o(f,p)int*f=fopen(p,"ab+");
#define f(p,q,r)o(a,p)o(b,q)o(c,r)fscanf(a,"%*s %*d %*d %n",&s);for(fwrite(t,1,fread(t,1,s,b),c);s=~getc(a);putc(~s^getc(b),c))

在PBM图像上运行。f(a, b, out)使用输入文件和输出文件的名称进行调用。

假设:

  • 两个输入图像标题都是相同的(包括空格),并且少于9 * sizeof(int)字符。

  • 我们使用的是一个不错的操作系统,可以刷新并关闭泄漏的文件。

  • EOF == -1

取消说明:(省略反斜杠)

// Scratch variable and "big enough" buffer
s, t[9];

// Opens a file in read/append binary mode
#define o(f,p)int*f=fopen(p,"ab+");

#define f(p, q, r)

    // Open the three file pointers a, b, c from the paths p, q, r
    o(a, p)
    o(b, q)
    o(c, r)

    // Read from a to locate the end of the PBM header
    fscanf(a, "%*s %*d %*d %n", &s);

    for(
        // Read the header from b into the buffer,
        // then write it back from the buffer to c
        fwrite(t, 1, fread(t, 1, s, b), c);

        // Loop condition: get the next byte from a
        // and check for EOF with a bitwise-not
        // (Assumes that EOF == -1)
        s = ~getc(a);

        // Loop increment: get the next byte from b,
        // flip s back, xor and write to c
        putc(~s ^ getc(b), c)

    ) // Snatch the semicolon from the call syntax :)

C(规范弯曲),149字节

#include<stdio.h>
t[7];
#define o(f,p,u)int*f=fopen(p,"ab+");u(t,1,7,f);
#define f(p,q,r)o(a,p,fread)o(b,q,fread)o(c,r,fwrite)putc(getc(a)^getc(b),c)

仍使用PBM文件,但现在:

  • 图像必须高一个像素,而宽度必须小于或等于8个像素,因为PBM在一个字节中压缩了8个像素。

  • 标头必须为7个字节(例如P4 8 1,尾随空格)。

在填充文件t头的同时向前搜索这两个文件,然后读取,异或将最后一个字节写回。利用freadfwrite具有相似的参数列表来将同一宏后面的标头上的所有三个操作都分解为因子。


2

R,45个字节

p=png::readPNG;plot(as.raster(+(p(a)!=p(b))))

ab代表两个图像文件的文件名。

例:

a <- "YyZG2.png"
b <- "UbbfM.png"
p=png::readPNG;plot(as.raster(+(p(a)!=p(b))))

输出:

在此处输入图片说明


2

处理中,82字节

void x(PImage a,PImage b){int x=b.width;b.blend(a,0,0,x,x,0,0,x,x,32);set(0,0,b);}

滥用处理的广泛绘图功能,以避免实际进行任何XORing。将两个图像与DIFFERENCE模式混合在一起,然后将它们绘制到屏幕上。

用法

x(loadImage("http://i.imgur.com/a0M6o9e.png"),loadImage("http://i.imgur.com/bP1TsjQ.png"));

不打高尔夫球

void xor(PImage a, PImage b) {
  int x = a.width;
  b.blend(a, 0, 0, x, x, 0, 0, x, x, DIFFERENCE);
  set(0, 0, b);
}

高尔夫不错!您使用32而不是真的很聪明DIFFERENCE。这将是打高尔夫球的好秘诀:codegolf.stackexchange.com/questions/26809/… :)
Kritixi Lithos

2

C#,233个字节

using System.Drawing;class C{static void Main(){Bitmap
a=new Bitmap("a"),b=new Bitmap("b");for(int
x=0,y=0;;)try{a.SetPixel(x,y,a.GetPixel(x,y)==b.GetPixel(x,y)?Color.Black:Color.White);x++;}catch{if(x<1)break;x=0;++y;}a.Save("c");}}

感谢Unknown6656的技巧,不需要命令行参数。该程序现在从文件“ a”和“ b”读取并以与“ a”相同的格式写入文件“ c”。因一个错误而关闭。

如果颜色相同,它将每个像素设置为黑色,否则为白色。

为了节省字节,它捕获了超出范围的异常,而不是检查位图的Width和Height属性。每次x超出范围时,它将重置为0,并且y递增。当y超出范围时,x为0,循环中断以保存图像并退出。

使用csc编译并使用mono运行的示例:

csc xor.cs

mono xor.exe

您可以将令牌(string[] v)放在主声明中,因为C#不需要显式令牌即可运行应用程序
unknown6656

1

Clojure,300字节

(ns s(:import[java.io File][java.awt.image BufferedImage][javax.imageio ImageIO]))(defn -main[](let[a(ImageIO/read(File."a.png"))](doseq[i(range(.getHeight a))j(range(.getWidth a))](.setRGB a j i(bit-xor(.getRGB a j i)(.getRGB(ImageIO/read(File."b.png")) j i))))(ImageIO/write a"png"(File."c.png"))))

公开剥夺Java答案。我不知道如何应对挑战,但很好奇Java解决方案如何转换成Clojure。这非常简单。实际的代码实际上很漂亮。

这是我所做的第一个代码高尔夫挑战,其中包括导入。可能存在一种优化它们以节省一些字节的方法。

取消高尔夫:

(ns bits.golf.bit-or-picts
  (:import [java.io File]
           [java.awt.image BufferedImage]
           [javax.imageio ImageIO]))

(defn -main []
  (let [^BufferedImage a (ImageIO/read (File. "a.png"))
        ^BufferedImage b (ImageIO/read (File. "b.png"))]
    (doseq [i (range (.getHeight a))
            j (range (.getWidth a))]
      (.setRGB a j i
                (bit-xor (.getRGB a j i)
                         (.getRGB b j i))))
    (ImageIO/write a "png" (File. "c.png"))))

1

PHP, 246 243字节

我可能可以进一步打下去。

$o=imagecreatetruecolor($w=max(imagesx($a=($i=imagecreatefrompng)($argv[1])),imagesx($b=$i($argv[2]))),$h=max(imagesy($a),imagesy($b)));for(;$k<$w*$h;)imagesetpixel($o,$x=$k%$w,$y=$k++/$w,($t=imagecolorat)($a,$x,$y)^$t($b,$x,$y));imagepng($o);

像这样从命令行运行它:

php -d error_reporting=0 -r "$o=imagecreatetruecolor($w=max(imagesx($a=($i=imagecreatefrompng)($argv[1])),imagesx($b=$i($argv[2]))),$h=max(imagesy($a),imagesy($b)));for(;$k<$w*$h;)imagesetpixel($o,$x=$k%$w,$y=$k++/$w,($t=imagecolorat)($a,$x,$y)^$t($b,$x,$y));imagepng($o);" "http://i.stack.imgur.com/UbbfM.png" "http://i.stack.imgur.com/YyZG2.png" > output.png

在函数名变量首次出现时进行定义会有所帮助:$i=imagecreatefrompng;$a=$i($argv[1])比时长一个字节$a=($i=imagecreatefrompng)($argv[1])。您可以尝试使用两种颜色的调色板。
泰特斯(Titus),

我试图在第一次出现时定义它,但我一直遇到致命错误。有时间我会再试。也许我做的不正确。
科多斯·约翰逊

($f=func)(params)需要PHP7。–
Titus

@Titus啊,好的,谢谢。那使我减少了3个字节。
科多斯·约翰逊

这里有7个以上字节:更换for(;$k<$w*$h;)for(;$y<$h;$y+=1/$w)$x=$k%$w, $y=$k++/$w$x, $y最后$x$x++。(假设任何合理的图像尺寸都没有取整错误)
Titus

0

Node.js,156135字节

(a,b)=>(f=require('fs')).writeFile(a+b,((s=f.readFileSync)(a)+'').replace(/\d+$/,(c,d)=>[...c].map((e,f)=>+!(e^(s(b)+b)[f+d])).join``))

输入和输出图像文件应采用PBM(P1)格式,其中第一行是P1 [width] [height],第二行是不带空格的b / w ascii值。

这是输入图像,然后是异或输出(32x32像素):

输入#1 输入#2 输出量

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.