7
\$\begingroup\$

Context:

Gynvael Coldwind, a famous security researcher, published a contest in his blog post (that is now complete). The goal was similar to the one described here, but with certain restrictions depending on which of the three allowed programming languages was chosen. I found the exercise fun and wanted to extend the challenge to all programming languages allowed.

Goal:

The goal of this golf is to write a program as short as possible that generates a PNG file which, after converting to bitmap shares the same resolution and pixel color values as the following image (alternate link, SHA256: ab18085a27c560ff03d479c3f32b289fb0a8d8ebb58c3f7081c0b9e1895213b6):

enter image description here

Rules:

  1. The program must work offline, i.e. when the language runtime/interpreter is installed, no internet connectivity is installed to build/run the program,
  2. The program may not rely on any external libraries (only use standard library of your language, as opposed to adding libraries from pip/npm/cargo/maven/whatever repositories),
  3. The program must complete its operation within 60 seconds on a regular desktop computer (i.e. no brute-forcing the results).
\$\endgroup\$
  • 4
    \$\begingroup\$ What do you mean by "external libraries?" \$\endgroup\$ – Esolanging Fruit May 26 at 7:36
  • 3
    \$\begingroup\$ These always end up being full of long strings being base64decoded. Can you tell us more about the image, to help facilitate other approaches? \$\endgroup\$ – Aaron F May 26 at 10:33
  • 10
    \$\begingroup\$ The secondary task of golfing a PNG encoder seems like it might overshadow the main thrust of the challenge. \$\endgroup\$ – gastropner May 26 at 11:15
  • 5
    \$\begingroup\$ @d33tah I believe this still fits the Cumbersome IO formats thing from "Things to avoid when writing challenges" extremely well. In particular, a PNG file has CRC checksums that have to be calculated. \$\endgroup\$ – someone May 26 at 12:12
  • 5
    \$\begingroup\$ Someone want to do this in Piet? \$\endgroup\$ – msh210 May 26 at 13:42
6
\$\begingroup\$

C#, 849 793 771 bytes

using System;using System.Drawing;using System.IO;class P{static void Main(){dynamic x,y,i=new Bitmap(Bitmap.FromStream(new MemoryStream(Convert.FromBase64String("iVBORw0KGgoAAAANSUhEUgAAAGAAAAA2BAMAAADKYYHhAAAAGFBMVEUAAABdAgSMAwb///+jBAfFgYLRgYOugIE5HrT9AAAA20lEQVR4AWKgHIwCQThAFmVECAsA2qsDk4qBGIzjD7qAn5ngvlvAJJ3AdyscTqAr3PqaQwMgVYATKvQPlED5kQaAng2QBVnoCywBVeFQqKu6im83gcP1GFgVqEMVqiIP25MIzRjlmgSPZNufK/Qj1wC+bSKk2w/gHkDUaFZrEXht+85jcDc6FAHcqgsqvX3fkCxfcFZiaK3xL8EckS0ArfVO8u31C4y+FAQBBgbLAOYE9v8HxgDAgiiPXgk6gPykz8ctOzPIgHl0f8mjB1aDGQuyxeDgx3KB37t6B3NXgUgfIi7ZAAAAAElFTkSuQmCC"),0,312))),d=new Bitmap(1920,1080),g=Graphics.FromImage(d);for(y=0;y<54;y++)for(x=0;x<96;x++)g.FillRectangle(new SolidBrush(i.GetPixel(x,y)),new Rectangle(x*20,y*20,20,20));d.Save("s.png");}}

Tested with the following code:

class P
{
    static void Main()
    {
        Bitmap a = new Bitmap(@"c:\projects\confidence_2019_golf.png");
        Bitmap b = new Bitmap(@"c:\projects\s.png");

        Console.WriteLine(a.Width + ", " + b.Width);
        Console.WriteLine(a.Height + ", " + b.Height);

        for (int y=0; y<a.Height; y++)
        {
            for (int x=0; x<a.Width; x++)
            {
                Color ca = a.GetPixel(x, y);
                Color cb = b.GetPixel(x, y);

                if (ca.R != cb.R || ca.G != cb.G || ca.B != cb.B)
                {
                    Console.WriteLine(x + ", " + y);
                    Console.WriteLine(ca.R + ", " + ca.G + ", " + ca.B);
                    Console.WriteLine(cb.R + ", " + cb.G + ", " + cb.B);
                }
            }
        }
    }
}

Ungolfed:

using System;
using System.Drawing;
using System.IO;
class P
{
    static void Main()
    {
        dynamic x = 0;
        dynamic y = 0;
        dynamic b = Convert.FromBase64String("iVBORw0KGgoAAAANSUhEUgAAAGAAAAA2BAMAAADKYYHhAAAAGFBMVEUAAABdAgSMAwb///+jBAfFgYLRgYOugIE5HrT9AAAA20lEQVR4AWKgHIwCQThAFmVECAsA2qsDk4qBGIzjD7qAn5ngvlvAJJ3AdyscTqAr3PqaQwMgVYATKvQPlED5kQaAng2QBVnoCywBVeFQqKu6im83gcP1GFgVqEMVqiIP25MIzRjlmgSPZNufK/Qj1wC+bSKk2w/gHkDUaFZrEXht+85jcDc6FAHcqgsqvX3fkCxfcFZiaK3xL8EckS0ArfVO8u31C4y+FAQBBgbLAOYE9v8HxgDAgiiPXgk6gPykz8ctOzPIgHl0f8mjB1aDGQuyxeDgx3KB37t6B3NXgUgfIi7ZAAAAAElFTkSuQmCC");
        dynamic i = new Bitmap(Bitmap.FromStream(new MemoryStream(b, 0, 312)));
        dynamic d = new Bitmap(1920, 1080);
        dynamic g = Graphics.FromImage(d);
        for (y = 0; y < 54; y++)
        {
            for (x = 0; x < 96; x++)
            {
                g.FillRectangle(new SolidBrush(i.GetPixel(x, y)), new Rectangle(x * 20, y * 20, 20, 20));
            }
        }
        d.Save(@"c:\projects\s.png");
    }
}
\$\endgroup\$
  • 2
    \$\begingroup\$ iVBORw0KGgoAAAANSUhEUgAAAGAAAAA2BAMAAADKYYHhAAAAGFBMVEUAAABdAgSMAwb///+jBAfFgYLRgYOugIE5HrT9AAAA20lEQVR4AWKgHIwCQThAFmVECAsA2qsDk4qBGIzjD7qAn5ngvlvAJJ3AdyscTqAr3PqaQwMgVYATKvQPlED5kQaAng2QBVnoCywBVeFQqKu6im83gcP1GFgVqEMVqiIP25MIzRjlmgSPZNufK/Qj1wC+bSKk2w/gHkDUaFZrEXht+85jcDc6FAHcqgsqvX3fkCxfcFZiaK3xL8EckS0ArfVO8u31C4y+FAQBBgbLAOYE9v8HxgDAgiiPXgk6gPykz8ctOzPIgHl0f8mjB1aDGQuyxeDgx3KB37t6B3NXgUgfIi7ZAAAAAElFTkSuQmCC should work for the image as well; produced with zopflipng, assuming I did everything right. \$\endgroup\$ – someone May 26 at 10:26
  • \$\begingroup\$ Cool! Thanks @someone \$\endgroup\$ – Johan du Toit May 26 at 10:38
  • \$\begingroup\$ You also most likely do know the length of the array "bytes" in advance; I believe it's 312 or something close. \$\endgroup\$ – someone May 26 at 10:41
  • 1
    \$\begingroup\$ You do not have to set y and x to 0 in the for loops as they are already 0. Doesn't the Bitmap constructor accept a Stream object directly? You might or might not be able to save bytes by placing the program in the System.Drawing namespace (automatically using System if my brain works right) and referring to MemoryStream directly. \$\endgroup\$ – someone May 26 at 11:00
  • \$\begingroup\$ Thanks, I'm moving on to a javascript based solution. C# is just too verbose... \$\endgroup\$ – Johan du Toit May 26 at 11:13
4
\$\begingroup\$

HTML + Javascript, 607 591 527 bytes

Thank you Epicness and Someone.

HTML, 436 bytes

<img id=a src=data:;base64,UklGRgABAABXRUJQVlA4TPMAAAAvX0ANALXIcSTJkST68N2Xs2p6ZJgUYgEpOVBwcYtMwGKJpBDAL5EUqioEEAAFTf8n4Akeel/aoYdx8E3jdbec+Bj0CQIKAqIiKqjd3hEU1L/CRATRBWhApHdtTIzZysYT0r794RjJEja6QbvdpUT9W1xDMYkxMQYEjWM4HPkrhiZRGjZoojYx0THU87bTZpWN2U6bJGMxF1qbRQ69BMYY48POObP4kX5/5753WXNeKm2SAFRBVRKqWK2CKkjmvG1VVbHY7K+aM7lk5mS1qqlaq2raKuh/9u1jI0BVVQNzzmJ3VRVcNluTcPxlBPR/7f3rMRIA><a id=b download>SAVE<canvas id=c width=1920 height=1080

Javascript, 91 bytes

b.href=c.toDataURL((d=c.getContext`2d`).drawImage(a,d.imageSmoothingEnabled=0,0,1920,1080))

JSFiddle

\$\endgroup\$
  • \$\begingroup\$ How are you counting bytes? I count 146 for Javascript and 543 for HTML (the total is correct though). I golfed the Javascript a bit; JSFiddle \$\endgroup\$ – someone May 27 at 12:16
  • \$\begingroup\$ Thanks, I'm not sure what happened. \$\endgroup\$ – Johan du Toit May 27 at 12:29
  • 1
    \$\begingroup\$ Are you sure you want the "SAVE" link at all? I think you can simply alert c.toDataUrl(). \$\endgroup\$ – someone May 27 at 13:50
  • \$\begingroup\$ Yes, I was not sure about that. alert does not show all the content, perhaps console.log? \$\endgroup\$ – Johan du Toit May 27 at 14:06
  • 1
    \$\begingroup\$ @JohanduToit , I was, unsurprisingly, able to reduce the images. Something I'd like to note is that I'm not a black box that shrinks your images in size (I simply feed them to zopflipng and similar stuff) and that other image formats can be better for compression. WebP is, AFAIK, supported by Firefox and Chrome, and is better than PNG. FLIF is even better, but supported by, AFAIK, nothing. I was extremely disappointed when the targz archive containing the resulting images didn't fit in a comment, so you can download it at s000.tinyupload.com/index.php?file_id=18210440611599235182 . \$\endgroup\$ – someone May 28 at 13:22
3
\$\begingroup\$

C# (Visual C# Interactive Compiler), 707 bytes

#r"System.Drawing"
using System.Drawing.Drawing2D;dynamic a=new Bitmap(new MemoryStream(Convert.FromBase64String("iVBORw0KGgoAAAANSUhEUgAAAGAAAAA2BAMAAADKYYHhAAAAGFBMVEUAAABdAgSMAwb///+jBAfFgYLRgYOugIE5HrT9AAAA20lEQVR4AWKgHIwCQThAFmVECAsA2qsDk4qBGIzjD7qAn5ngvlvAJJ3AdyscTqAr3PqaQwMgVYATKvQPlED5kQaAng2QBVnoCywBVeFQqKu6im83gcP1GFgVqEMVqiIP25MIzRjlmgSPZNufK/Qj1wC+bSKk2w/gHkDUaFZrEXht+85jcDc6FAHcqgsqvX3fkCxfcFZiaK3xL8EckS0ArfVO8u31C4y+FAQBBgbLAOYE9v8HxgDAgiiPXgk6gPykz8ctOzPIgHl0f8mjB1aDGQuyxeDgx3KB37t6B3NXgUgfIi7ZAAAAAElFTkSuQmCC"))),b=new Bitmap(1920, 1080),c=Graphics.FromImage(b);c.InterpolationMode=(InterpolationMode)5;c.PixelOffsetMode=(PixelOffsetMode)4;c.DrawImage(a,0,0,1920,1080);b.Save("b.png");

Only compiles in the interactive window, saves the result in a file called b.png

\$\endgroup\$
2
\$\begingroup\$

C (GCC/MinGW), 1439 1406 1386 1382 1092 807 806 800 789 787 786 777 bytes

-33 -4 -11 -9 bytes thanks to ceilingcat

-6 bytes thanks to someone's idea

Edit: Why even dynamically calculate CRCs when the output is static? Dropping that part really slimmed things down.

Somewhat beefier than other entries, but such is C life.

Assumes sizeof(unsigned int) == 4, i.e. 32-bit integers, and little-endianness.

The earlier RLE scheme is replaced by a slightly more complex one. Most of the image (except the "CONFIDENCE" text) is stored as a series of rectangles. Each rectangle is stored as four characters holding (x1, y1) and (x2 + 1, y2 + 1). We start with the lowest colour in the palette and upon hitting a space character in the image data, we increase the palette index.

I have a feeling further compression could be had by storing colours slightly differently and exploiting the additive nature of the colours of overlapping areas.

The "CONFIDENCE" text is stored as a series of characters holding 6 significant bits, each one of which corresponds to a "pixel" in the text.

#define Y*Q++-31
*o,C,x,i,W=5760,H=1080,Z[]={262749,394124,459939,8487086,8552901,8618449,~0};S(b,D,C,B,A,c)char*b;{for(B*=20;B<D*20;B++)for(x=A*20;x<C*20;)bcopy(Z+c,b+B*W+x++*3,3);}(*X)()=fwrite;main(j){char*p=calloc(W,H),d[]="\0\x81\26~\xe9",*Q="&&<57)V;22?E;9LOI3eI[%o7_1yA 7)<;2275;2?EC9I;I3V;I;LI[3_7_1o7_7eA 72<5;9?;_3e7 C;E?G;I?M;O?W;Y?[;]?GAIEMAOEWAYEaAcE??CA?ECG]EaG]9_;]?_ALEMG ?9C;L9M;_9a;_?aAa;c?=A?EIELG I9L;";for(;*Q;)S(p,Y,Y,Y,Y,C+=*Q<33&&Y);for(X("\x89PNG\r\n\32\n\0\0\0\rIHDR\0\0\a\x80\0\0\48\b\2\0\0\0g\xb1V\24\0_\5VIDAT\b\35",1,43,o=fopen("a.png","wb"));i<240;i++)"FStuybLGitTTJfRAaTuUzjBGiTVTJrRAFSTtybLG"[i/6]-64>>i%6&1&&S(p,C+1,j+1,C=17+i/48,j=26+i/6%8*6+i%6,6);for(;H--;p+=X(p,1,W,o))*d=!H,X(d,1,6,o);X("*vC\6\xc7\xe3\20W\0\0\0\0IEND\256B`\x82",1,20,o);}
\$\endgroup\$
  • \$\begingroup\$ this segfaults on my machine. \$\endgroup\$ – don bright May 27 at 19:12
  • 1
    \$\begingroup\$ @donbright some compilers/runtimes require #include<stdio.h> to avoid segfaulting. \$\endgroup\$ – ceilingcat May 27 at 19:32
  • \$\begingroup\$ is stdio considered an external library? if we can include header files like stdio.h then why cant we include header files like Lode Vandevenne's lodepng.h ? \$\endgroup\$ – don bright May 27 at 19:38
  • 1
    \$\begingroup\$ oh i see, "standard libraries" is acceptable. upvoted! \$\endgroup\$ – don bright May 27 at 19:49
  • \$\begingroup\$ Is 16777215 -1u>>8? That should save two bytes. \$\endgroup\$ – someone Jun 1 at 12:28
1
\$\begingroup\$

HTML + javascript, 504 bytes - Not competing

I still need to get the colors sorted out.

HTML, 35 bytes

<canvas id=g width=1920 height=1080

Javascript, 469 bytes

d=g.getContext`2d`
d[f='fillRect'](0,0,1920,1080)
d[a='globalAlpha']=.4
d[l='fillStyle']=`#a00`
'//>7|@2G:|;;5;|DB9>|R<D>|d.<:|h:B8'.split`|`.map(x=>x.split``.map(c=>(c[w='charCodeAt']()-40)*20)).map(x=>d[f](...x))
d[l]='#fff'
d[a]=1
q=(h,x,y,p,z)=>{b=atob(h).split``;for(var n in b){for(j=8;j--;)b[n][w]()&1<<j&&d[f](x+(n%p*8+j)*z,y+((n/p)|0)*z,z,z);}}
q('xkTXucgcKU1RiikFIVVXuiocKWVRiiwFxkTRucgc',520,340,6,20)
d[a]=.4
q('xgADKKEEKKEEBgADISEEISEExgAD',600,520,3,40)

JSFiddle

\$\endgroup\$
  • \$\begingroup\$ I believe you can replace the ...,y+((n/p)|0)*z... bit with ...,y+~~(n/p)*z, but I haven't really compared the images for equality. I was not offended by the second last your comment, but just noted that you could perform image compression as well as I could. \$\endgroup\$ – someone May 28 at 14:28
  • \$\begingroup\$ Without the |0 it calculates a floating point value that blurs the image. \$\endgroup\$ – Johan du Toit May 28 at 14:57
  • \$\begingroup\$ Doesn't ~~x basically cast to integer? I tried to find a color that matches the rectangles. An alpha value of 0.5 and the color #BA0408 produces extremely close, but wrong results, likely caused by the differences between various image editors. I think that is possible to get around that by tweaking these values slightly. Disclaimer: in case you are not aware of any good utilities for getting exact pixel colors from screen I could suggest gpick for Linux or ColorPix for Windows. \$\endgroup\$ – someone May 28 at 15:04
  • \$\begingroup\$ I will check that out, thanks. I'm hoping that all the rectangles are using the same color and alpha values. \$\endgroup\$ – Johan du Toit May 28 at 15:15
  • \$\begingroup\$ See Diff results for Chrome vs Firefox \$\endgroup\$ – Johan du Toit May 29 at 14:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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