Write a program that can validate a PNG file. Your program should follow the PNG spec and must validate the PNG signature and the 4 critical chunks: IHDR, IDAT, PLTE and IEND. Your program must not validate the contents of ancillary chunks, except for their CRC checksums.

Your program must validate the presence of the PLTE chunk (that is, This chunk shall appear for colour type 3, and may appear for colour types 2 and 6; it shall not appear for colour types 0 and 4. There shall not be more than one PLTE chunk. ref)

Your program must validate chunk order.

Your program must validate CRC checksums.

Your program must validate the compressed data.

You may use runtime code generation+execution (e.g. compress the program itself, or algorithmically write the program itself a la kolmogorov complexity). If any binary blobs are used, their source code will be considered when calculating size.

External library source code size counts towards program size. This is to discourage image-parsing external libraries while allowing e.g. a CRC32 library. Libraries defined in the language specification (aka "standard libraries") don't count as external.

No regex.

You must specify how to input the file. Your program must output to stdout "true" or "false" to answer the question "is the file a valid PNG?".

Failing test files:

This file is false.

(Yes, that's a plaintext file. Newline-terminated.)

Passing test files:

  • \$\begingroup\$ It looks like Mathematica (surprise!) has a built-in to import an image, so you could just wrap some error handling to get a solution. Unfortunately, I don't know Mathematica and I'm not able to run code without paying. \$\endgroup\$ Commented Nov 28, 2016 at 2:21
  • \$\begingroup\$ The ban on binary blobs seems to be imprecise. If their distinguishing feature is not being in ASCII, people will just use base64 or the like to make them not-binary. If their distinguishing feature is being unreadable, doesn't that apply to most golfing submissions? \$\endgroup\$
    – user62131
    Commented Nov 28, 2016 at 3:26
  • \$\begingroup\$ @ais523 Even tho code golf tends to be unreadable, a human can parse most of them without having to use an external tool such as a decompiler. \$\endgroup\$
    – SoniEx2
    Commented Nov 28, 2016 at 9:20
  • \$\begingroup\$ @Challenger5 Good thing you can't use it! Your program must not validate the contents of ancillary chunks, except for their CRC checksums. \$\endgroup\$
    – SoniEx2
    Commented Nov 28, 2016 at 9:21
  • 2
    \$\begingroup\$ @SoniEx2: I want to correct myself: there is a "standard Haskell" in regards to libraries which are described in the Haskell 2010 report. Ok problem solved for Haskell, sorry for the confusion. Still I think it's better to forbid specific libraries (here: "PNG libraries") than referring to vague terms such as "external library". \$\endgroup\$
    – nimi
    Commented Nov 28, 2016 at 20:45

1 Answer 1


Java - 1220 chars

import java.io.*;import java.util.zip.*;interface Q{static int i(byte[]b,int i){return java.nio.ByteBuffer.wrap(b).getInt(i);}static boolean v(int x,int...a){return java.util.stream.IntStream.of(a).anyMatch(y->x==y);}static void main(String[]a){byte[]b={-119,80,78,71,13,10,26,10},c={0,0,0,0},d=b.clone();OutputStream I=new InflaterOutputStream(new ByteArrayOutputStream());int l,k,i,t,r=k=i=l=0,H=1229472850,D=1229209940,P=1347179589,E=1229278788,L=8192;DataInputStream in=new DataInputStream(System.in);boolean v;CRC32 C=new CRC32();try{for(v=(in.read(b)>7&&java.util.Arrays.equals(b,d));v=v&&(l=in.readInt())>=0&&in.read(c)>3;){C.update(c);for(byte B:c)v&=(B|32)<123&&(B|32)>96;for(r=0;v&&(t=in.read(b=new byte[l-r>L?L:l-r]))>0;r+=t){C.update(b);if(i(c,0)==D)if(v=v(i,2,3))I.write(b);if(i(c,0)==H&&r==0)if(v=i==0&&t==13){v=i(b,0)>0&&i(b,4)>0&&b[10]==0&&b[11]==0&&v(b[12],0,1)&&((k=b[9])==0&&v(b[8],1,2,4,8,16))||(v(k,2,4,6)&&v(b[8],8,16))||(k==3&&v(b[8],1,2,4,8));i=(v&&k==3)?1:v?k&2:3;}}v&=(k=in.readInt())==(int)C.getValue();C.reset();if(v&(t=i(c,0))==P){v=v(i,1,2)&&l<=768&&l%3==0;i=3;}if(v&t==E){v=l==0;break;}if((t&L)!=0||((t&L<<16)==0&&!v(t,P,H,E,D)))v=0>1;}}catch(IOException e){v=0>1;}System.out.println(v);}}

Input is from stdin.

  • \$\begingroup\$ What happened to "External library source code size counts towards program size"? \$\endgroup\$ Commented Nov 28, 2016 at 14:44
  • \$\begingroup\$ @PeterTaylor The stdlib isn't an external library. \$\endgroup\$
    – SoniEx2
    Commented Nov 28, 2016 at 14:45
  • 1
    \$\begingroup\$ I can't tell if I'm impressed you golfed Java or scared. :P \$\endgroup\$
    – Downgoat
    Commented Nov 28, 2016 at 14:54
  • \$\begingroup\$ @Downgoat Java has built-in CRC32, inflate/deflate, etc. It was only logical. I hope I never have to debug this thing again... \$\endgroup\$
    – SoniEx2
    Commented Nov 28, 2016 at 14:58
  • 2
    \$\begingroup\$ @Downgoat, if one answer with golfed Java scares you, the almost 2000 on this site should terrify you. \$\endgroup\$ Commented Nov 28, 2016 at 15:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.