Invert png image

15

2

Create program or function that takes file name as an argument or reads it from standard input, and completes the following task:

  1. Read image from a png file (name given as argument).
  2. Reverse colors in that image, so that for example dark green (0, 75, 30) would become (255, 180, 225) (because 255-0=255, 255-75=180 and 255-30=225). You should not change alpha channel value.
  3. Output that image to a file called a.png (in png format), or show it in GUI window.

This is . Standard loopholes apply.

Hannes Karppila

Posted 2016-03-28T22:33:56.237

Reputation: 3 090

Is it required to support any optional png features? Are built-in png loading/writing functions acceptable? – Sparr – 2016-03-28T22:42:14.330

@Sparr Optional feature support is optional. Built-in functions are not explicitly disallowed, so I'll assume they are allowed. – Hannes Karppila – 2016-03-28T22:44:51.970

5

PNG files can be indexed (each pixel contains a pointer to a color in the colormap) or truecolor (each pixel contains the actual color). Which one do we need to support? Can we choose? In fact, there are five different subformats regarding color. So... ?

– Luis Mendo – 2016-03-28T23:20:11.100

@DonMuesli I think any method that provides correct result will be fine. You can assume that the color isn't greyscale, and supporting alpha-channel is optional. I think that using any other mode is acceptable, as long as the task will still be reversing the colors, and colors have (r,g,b)-values. – Hannes Karppila – 2016-03-29T09:10:06.047

1Can I use just CSS? – Rizze – 2016-09-08T08:36:38.353

Answers

30

ImageMagick display -fx, 3 7 18 24 bytes

1-u

The ImageMagick tool display with the fx parameter can apply the above program to a png given as the parameter and display the results on screen.

Check out my post on meta about ImageMagick as a programming language. I wrote a prime tester over there as a proof of concept.

Re byte counting, display -fx code filename is equivalent to perl -e code filename, where we traditionally count just code for length.

Sparr

Posted 2016-03-28T22:33:56.237

Reputation: 5 758

Is this not a standard loophole? It's gotten plenty of upvotes, but it seems like it should be. I guess if Mathematica can have a bunch of these functions built-in, then using any pre-released application (before the asking of the question) to do it for you is fair game, so long as it accepts command-line arguments? – Nate Diamond – 2016-03-29T16:01:02.963

1@NateDiamond Give me about 5 minutes to finish my meta post about "is imagemagick a programming language" and I'll cut this down to 7 bytes and address your question at the same time :) – Sparr – 2016-03-29T16:03:04.070

21

Pyth, 16 15 13 bytes

.w-LLL255'z\a

Outputs to a.png.

          z    read input
         '     read as RGB triples from file
   LLL         map over rows, then triples, then individual values...
  -   255      ...subtract from 255
.w         \a  write as image to a.png

Thanks to Jakube for 2 bytes!

Doorknob

Posted 2016-03-28T22:33:56.237

Reputation: 68 138

4man, i've gotta learn pyth – undergroundmonorail – 2016-03-28T22:53:29.887

1Does Pyth not have bitwise negation (~ or similar)? – Peter Taylor – 2016-03-29T07:33:10.327

@PeterTaylor I don't think it does, surprisingly. (In any case, it would have to be restricted to 8 bits.) – Doorknob – 2016-03-29T10:55:41.703

is there no way to deeply-map with a pfn? – Ven – 2016-03-29T11:09:38.467

@ven Nope, I don't think so (or at least not the ways I've tried). You can't nest Ls or Rs. – Doorknob – 2016-03-29T11:11:26.483

too bad, that'd be very fun :D. I remember having tried such things. – Ven – 2016-03-29T11:13:07.347

1@ven @Doorknob Actually you can do it: .w-LLL255'z\a. But don't ask me how this works or why you need LLL and not something like LMM. – Jakube – 2016-03-29T12:32:34.983

paging @isaacg, maybe? – Ven – 2016-03-29T12:43:39.150

@ven Pinging only works for users that have authored, commented or edited the post

– Luis Mendo – 2016-03-29T13:44:43.187

haha, okay, noted :P. (note: to page exists)

– Ven – 2016-03-29T13:46:16.697

@Jakube from looking at the code, it seems to require that because L parses in a kind of odd way with other sugar parsing. The L parse seems to keep the other Ls as part of the body of the map, so after the first parse you get: .wm-LL255d'z\a and so on. I'm not sure what's up with M though, I'll ping isaac in the Pyth chatroom. – FryAmTheEggman – 2016-03-29T15:30:51.877

@Jakube O_o I have no idea why that works, but thanks! – Doorknob – 2016-03-29T19:08:43.950

18

MATL, 10 bytes

255iYi-IYG

There are five different subformats of PNG, depending on how color is encoded. None of them seems to be more "optional" than the others. I chose the most flexible one, Truecolor, in which each pixel can have an arbitrary color. The above code also supports Truecolor with alpha, ignoring the alpha channel.

To know the color subformat of a PNG file: look for the byte sequence [73 72 68 82] near the beginning of the file; and the tenth byte from there will have one of the five values in the table linked above.

How the code works

Pretty straightforward:

255    % push 255 to the stack
i      % input filename with extension '.png'
Yi     % read contents of that file as (truecolor) image
-      % subtract
IYG    % show image

Example

I couldn't resist seeing myself inverted, so I downloaded this image (which is in subformat Truecolor with alpha), ran the code (second line is user input)

>> matl 255iYi-IYG
> 'C:\Users\Luis\Desktop\me.png'

and got

enter image description here

Luis Mendo

Posted 2016-03-28T22:33:56.237

Reputation: 87 464

1Your avatar is actually you? I thought it was just your helmet! :P – Downgoat – 2016-03-29T22:15:47.713

1I thought PNG and all means long code, but 10 bytes? Wow. – Buffer Over Read – 2016-09-04T17:02:31.820

17

Java, 295

import javax.imageio.*;class V{public static void main(String[]a)throws
Exception{java.awt.image.BufferedImage m=ImageIO.read(new
java.io.File(a[0]));for(int
x=m.getWidth(),y;x-->0;)for(y=m.getHeight();y-->0;)m.setRGB(x,y,m.getRGB(x,y)^-1>>>8);ImageIO.write(m,"png",new
java.io.File("a.png"));}}

aditsu quit because SE is EVIL

Posted 2016-03-28T22:33:56.237

Reputation: 22 326

1I like how x-- and x>0 together make a litte arrow showing that x goes up to 0. Why have I never seen/used that before? – LuWi – 2016-03-29T14:41:41.467

Import java.io.File? – nickb – 2016-03-29T14:56:51.687

1

@LuWi hehe, I've seen and used it before, some people call it the "goes to" operator, and it's pretty golfy :)

– aditsu quit because SE is EVIL – 2016-03-29T15:40:47.487

@nickb even if you use the shorter import java.io.*;, it doesn't save any bytes but actually increases the size. – aditsu quit because SE is EVIL – 2016-03-29T15:42:07.207

4

R, 124 bytes

p=png::readPNG(readline());p[,,-4]=1-p[,,-4];png("a.png",h=nrow(p),w=ncol(p));par(mar=rep(0,4));plot(as.raster(p));dev.off()

Reads in file name through stdin (readline()).

p=png::readPNG(readline()) #Reads in png as an RGBA array on range [0,1]
p[,,-4]=1-p[,,-4] #Takes the opposite value except on alpha layer
png("a.png",h=nrow(p),w=ncol(p)) #Prepares output png of same size as input
par(mar=rep(0,4)) #Makes the png take the full space of the figure region
plot(as.raster(p)) #Transforms p as a raster so that it can be plotted as is.
dev.off() #Closes the plotting device.

Example Input/Output using the first png I found on this computer :)

Input Output

plannapus

Posted 2016-03-28T22:33:56.237

Reputation: 8 610

3

CSS, 19 Bytes

*{filter:invert(1)}

http://output.jsbin.com/suqayudoyu

Rizze

Posted 2016-03-28T22:33:56.237

Reputation: 195

The two images don't appear to have any change. – clismique – 2016-09-08T12:07:49.223

Use Firefox, http://caniuse.com/#feat=css-filters

– Rizze – 2016-09-08T12:27:38.177

2

Tcl, 176 bytes

foreach r [[image c photo -file {*}$argv] d] {set x {}
foreach c $r {lappend x [format #%06X [expr "0xFFFFFF-0x[string ra $c 1 end]"]]}
lappend y $x}
image1 p $y
image1 w a.png

Loads the PNG via the photo image type, gets the image data, converting each row and color by subtracting from #FFFFFF, then writes the file back to disk (as "a.png").

For best results, use TrueColor PNGs, since Tk will try to use the same color resolution as the source image data.

To see the image without sampling problems, add

pack [label .i -image image1]

to the end. (Obviously, this is longer than the disk-save option.)

Dúthomhas

Posted 2016-03-28T22:33:56.237

Reputation: 541

You can ave bytes replacing foreachby lmap – sergiol – 2017-02-15T02:15:44.053

2

Mathematica, 140 bytes

Export["a.png",SetAlphaChannel[ColorCombine[Most@#],Last@#]&@MapAt[Image[1-ImageData@#]&,ColorSeparate[Import[#],{"R","G","B","A"}],{;;3}]]&

Jason B.

Posted 2016-03-28T22:33:56.237

Reputation: 151

Note that you can save two bytes by changing Import[#] to Import@#, and same for ColorCombine[Most@#]. – numbermaniac – 2017-04-06T07:39:07.990

Why wouldn't a simple ColorNegate@*Import be a complete answer? – LegionMammal978 – 2018-12-31T03:19:20.100

2

cmd + IrfanView, 19 characters

i_view32 %1 /invert

Just the expensive alternative of Sparr's answer.

manatwork

Posted 2016-03-28T22:33:56.237

Reputation: 17 865

2

Julia, 94 79 bytes

using FileIO
save(ARGS[1],map(x->typeof(x)(1-x.r,1-x.g,1-x.b,1),load(ARGS[1])))

This is a full program that takes a file name as a command line argument and overwrites the given file with the inverted image. It requires that the FileIO and Image package be installed. The latter doesn't need to be imported though.

Call the program from the command line like julia filename.jl /path/to/image.png.

Ungolfed:

using FileIO # required for reading and writing image files

# Load the given image into a matrix where each element is an RGBA value
a = load(ARGS[1])

# Construct a new image matrix as the inverse of `a` by, for each element
# `x` in `a`, constructing a new RGBA value as 1 - the RGB portions of
# `x`, but with an alpha of 1 to avoid transparency.
b = map(x -> typeof(x)(1 - x.r, 1 - x.g, 1 - x.b, 1), a)

# Save the image using the same filename
save(ARGS[1], b)

Example:

regular inverted

Alex A.

Posted 2016-03-28T22:33:56.237

Reputation: 23 761

1The magpie (?) looks seriously depressed on the second image. – Bálint – 2016-05-03T07:33:33.927

1

MATLAB / Octave, 31 bytes

Code:

imshow(imcomplement(imread(x)))

Example:

imshow(imcomplement(imread('balloons.png')))

enter image description here              enter image description here

Explanation:

Read the image, x, from a graphics file, complement the image, and then display the image.

Grant Miller

Posted 2016-03-28T22:33:56.237

Reputation: 706

The code assumes that x is predefined, which is not allowed. You can turn it into a lambda function for +4 bytes with @(x). – Mego – 2018-12-31T22:14:54.207

1

Python + PIL, 85 bytes

from PIL import Image
lambda a:Image.eval(Image.open(a),lambda x:255-x).save('a.png')

This defines an anonymous function that takes a filename as a string and saves the resultant image to a.png.

Test run:

llama llama out

Mego

Posted 2016-03-28T22:33:56.237

Reputation: 32 998

1-3 bytes: from PIL import Image as I, followed by replacing Image in the function with I – Tim Čas – 2016-08-30T23:50:34.920

I'm fairly sure that simply import Image will work, shaving off a whole load of bytes – Beta Decay – 2016-08-31T10:36:46.037

save 11 bytes with from PIL.Image import* – Aaron – 2016-09-08T14:14:40.257

I think this accidentally inverts the alpha channel as well. Apparently the eval function runs against all "bands", including the alpha one. Here is what I get when inverting the Firefox logo - https://imgur.com/a/wV3MSQX

– dana – 2018-12-31T20:12:30.237

1

@dana Per the OP's comment, supporting alpha channels is optional.

– Mego – 2018-12-31T22:12:46.130

OK - Cool deal :) I might update my answer to reflect this. – dana – 2018-12-31T22:18:59.007

1

C + stb_image + stb_image_write, 175 162 bytes (or +72=247 234)

My first submission on this site ever.

#include"stb_image.h"
#include"stb_image_write.h"
x,y,c,i;f(char*d){d=stbi_load(d,&x,&y,&c,i=0);for(;i<x*y*c;i++)d[i]=255-d[i];stbi_write_png("a.png",x,y,c,d,0);}

Could probably shave off a few bytes. Needs stb_* implementation to either be in a separate library, or at the start of this file with:

#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION

I didn't include it in the count because it's essentially part of the library (esp. if it's compiled separately). +72 bytes to add that if required, however.


Update 1:

Realized only a function (as opposed to an entire program) is acceptable, shaving off 15 bytes. The old implementation (which is an entire program), for reference:

x,y,i;main(int c,char**d){*d=stbi_load(d[1],&x,&y,&c,0);for(;i<x*y*c;i++)i[*d]=255-i[*d];stbi_write_png("a.png",x,y,c,*d,0);}

Tim Čas

Posted 2016-03-28T22:33:56.237

Reputation: 139

1

Java, 300 298 bytes

import javax.swing.*;void c(String f)throws Exception{java.awt.image.BufferedImage r=javax.imageio.ImageIO.read(new java.io.File(f));for(int i=0;i++<r.getWidth();)for(int j=0;j++<r.getHeight();)r.setRGB(i,j,(0xFFFFFF-r.getRGB(i,j))|0xFF000000);JOptionPane.showMessageDialog(null,new ImageIcon(r));}

Shaun Wild

Posted 2016-03-28T22:33:56.237

Reputation: 2 329

0

Python 2 + OpenCV, 55 bytes

import cv2
cv2.imwrite('a.png',255-cv2.imread(input()))

The OpenCV library uses NumPy arrays to read, process, and write images. Below is an example of this script inverting an image found on mozilla.org.

Edge Artwork Inverted

All channels, including the alpha channel, will be inverted. This is problematic for images that have transparency. But as @Mego pointed out, support for the alpha channel is optional.

Below is an 82 byte commented version that property handles the alpha channel.

import cv2                # import OpenCV library
i=cv2.imread(input(),-1)  # image file name is specified from stdin
                          # read with the IMREAD_UNCHANGED option
                          # to preserve transparency
i[:,:,:3]=255-i[:,:,:3]   # invert R,G,B channels
cv2.imwrite('a.png',i)    # output to a file named a.png

As shown below, this properly handles inverting the Firefox logo while preserving the transparent background.

Firefox Logo Inverted

dana

Posted 2016-03-28T22:33:56.237

Reputation: 2 541

0

FFmpeg, 10 bytes

Edit: Taking a cue from @Sparr's answer

-vf negate

(the above when passed to ffplay alongwith the image name, will display the negated image)


ffplay %1 -vf negate

The above is saved as a batch file.

Gyan

Posted 2016-03-28T22:33:56.237

Reputation: 521

1Is FFmpeg a programming language by our standards? I don't know enough about it to be sure. Perhaps ask on meta? – Mego – 2016-05-03T07:55:45.963

0

Racket 282 bytes

(λ(fname)(let*((i(make-object bitmap% fname))(w(send i get-width))(h(send i get-height))(pixels(make-bytes(* w h 4)))(i2(make-object bitmap% w h)))
(send i get-argb-pixels 0 0 w h pixels)(send i2 set-argb-pixels 0 0 w h(list->bytes(map(lambda(x)(- 255 x))(bytes->list pixels))))i2))

More readable form:

(define(f fname)
  (let*(
        (i (make-object bitmap% fname))
        (w (send i get-width))
        (h (send i get-height))
        (pixels (make-bytes(* w h 4)))
        (i2 (make-object bitmap% w h)))
    (send i get-argb-pixels 0 0 w h pixels)
    (send i2 set-argb-pixels 0 0 w h
          (list->bytes
           (map
            (lambda(x) (- 255 x))
            (bytes->list pixels))))
    i2))

Usage:

(f "myimg.png")

rnso

Posted 2016-03-28T22:33:56.237

Reputation: 1 635

0

Golang, 311 bytes

package main
import("image"
."image/png"
."image/color"
."os")
func main(){f,_:=Open(Args[1])
i,_:=Decode(f)
q:=i.Bounds()
n:=image.NewRGBA(q)
s:=q.Size()
for x:=0;x<s.X;x++{for y:=0;y<s.Y;y++{r,g,b,a:=i.At(x,y).RGBA()
n.Set(x,y,RGBA{byte(255-r),byte(255-g),byte(255-b),byte(a)})}}
o,_:=Create("o")
Encode(o,n)}

ungolfed

package main
import(
    "image"
    "image/png"
    "image/color"
    "os"
)

func main(){
    // open a png image.
    f, _ := os.Open(Args[1])

    // decode the png image to a positive image object(PIO).
    p, _ := png.Decode(f)

    // get a rectangle from the PIO.
    q := p.Bounds()

    // create a negative image object(NIO).
    n := image.NewRGBA(q)

    // get the size of the PIO.
    s := q.Size()

    // invert the PIO.
    for x := 0; x < s.X; x++ {
        for y := 0; y < s.Y; y++ {
            // fetch the value of a pixel from the POI.
            r, g, b, a := p.At(x, y).RGBA()

            // set the value of an inverted pixel to the NIO.
            // Note: byte is an alias for uint8 in Golang.
            n.Set(x, y, color.RGBA{uint8(255-r), uint8(255-g), uint8(255-b), uint8(a)})
        }
    }

    // create an output file.
    o, _ := os.Create("out.png")


    // output a png image from the NIO.
    png.Encode(o, n)
}

cia_rana

Posted 2016-03-28T22:33:56.237

Reputation: 441