So, I want you to make a PNG image that says "Hello world!" and nothing else on a distinguishable background using only an image making API (eg ImageMagick) and return the image. Fewest characters win, as usual. Oh, and you can use any color text.
41 Answers
Bash + ImageMagick: 35 33
Default font, default text size, default colours:
convert label:Hello\ world! a.png
and here's the result:
Thanks to DigitalTrauma and sch for the help :-D
-
14\$\begingroup\$ Great!! :-) I wanted to write something like that. Unbeatable! All the esoteric languages will finally get their ass kicked today! :-) \$\endgroup\$– TomasCommented Feb 1, 2014 at 20:57
-
7\$\begingroup\$
convert label:Hello\ world! a.png
is even shorter. \$\endgroup\$– schCommented Feb 1, 2014 at 22:10 -
5\$\begingroup\$ Also, if you make it
sh
, you don't have to worry about!
and you make it even less esoteric. \$\endgroup\$– schCommented Feb 1, 2014 at 22:17 -
4\$\begingroup\$ Frankly I don't think bash qualifies as a programming language here or that convert qualifies as an API. But in this case I'd throw
GNU hello
in and bring this contraption down to 29 with:convert label:"`hello`" h.png
\$\endgroup\$ Commented Feb 4, 2014 at 9:43 -
3\$\begingroup\$ Why do you even care for the extension of the file? Just call it
a
and the mime type will do the rest. \$\endgroup\$ Commented Feb 4, 2014 at 12:52
Mathematica 28 27
This creates and exports the sentence, "Hello world!", as a PNG image. 1 char saved by Mechanical snail.
".png"~Export~"Hello world!"
Testing
This imports the PNG image. The image was enlarged by dragging the image box handles.
-
4\$\begingroup\$ 27 bytes:
".png"~Export~"Hello world!"
\$\endgroup\$ Commented Feb 2, 2014 at 7:57 -
9
HTML, 1494
I know this won't win, but I didn't see this here before.
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEIAAAANEAYAAABNymQSAAAABmJLR0T///////8JWPfcAAAACXBIWXMAAABIAAAASABGyWs+AAAACXZwQWcAAABCAAAADQDi7GgjAAADvElEQVRYw+1YPa9pTRReRIJKEPHdiEJBoVVIRCenpCJBfCQEDeI3qAh/QCIRUchp0KCUaISgROO7QMRHSGS9xX73u+85592Xe47uepqJZ9bMrFnzrJm1MfBfwAsvAADzM8HhcDgczv2Bj9r9KRgMBoPBeJz/2/DdODwaV+bjU77wN+AliBc+4OmCmE6n0+kUwGKxWCwWAKFQKBQKAfR6vV6vBygWi8Vi8efr7Ha73W4H4HK5XC4XgFQqlUqlADKZTCaTAbjdbrfbTdndg8FgMBgMANVqtVqtUnwikUgkEgBisVgsFgOQFRfZkny/3+/3+z/3i7zC8/l8Pp8HkEgkEomE3u/tdrvdbgEcDofD4aDirVar1Wo1QCaTyWQyj8f1iyAul8vlcqEco2tJu88IBoPBYBDA7/f7/X6A5XK5XC4ByuVyuVwGSCaTyWQSYDAYDAaD7wsiHo/H43EAFovFYrEAxuPxeDwGGI1Go9GI4skDvYe3t7e3tzeAer1er9cpvtlsNptNAC6Xy+VyAYbD4XA4pPwnea1Wq9Vqn+dXu91ut9sAjUaj0WjQ28VisVgsRgl0MplMJhOAXq/X6/UAOp1Op9OhH8/j8Xg83i8EfgKbzWaz2XgXdHYCgUAgEJBfLfQtkQFfx/+/V195uVwul8sRV6vVarX6ak8IEVGpVCqVyvv7IQKISBwsIpHBiBqNRqPRIBIHiJhOp9PpNGIqlUqlUoihUCgUCj3PL3Kf6/V6vV7fjwNxAyEuFovFYvHVnuTp4moymUwmE/Wb9f0c/b3iut1ut9sFIDZO9c9ms9lsBsDn8/l8/s/Xu1c932632+12fx6dTqfT6QD2+/1+vwcolUqlUgnAaDQajUYAs9lsNpsBstlsNpulMjISiUQikef7JRKJRCLRfb+ZTCaT+ZuH/95XCflU/odHM/9Ru3A4HA6HEaPRaDQaRbxer9frFbHVarVaLURCMFSm3MsAOt7j8Xg8HkSfz+fz+RDP5/P5fEY8nU6n0wnR6/V6vV6qfRSBQCAQCFAZXCgUCoUC4vF4PB6PiMRBISoUCoVCgUg8nc/zi27/dP3kPHa73W63IxKCRjwcDofDAZGoWejnrdVqtVrtl/mfLQiiyEG02Ww2m416QogiB/H9/f39/f3xDdPx5DpOp9PpdCISxRfVkjxp9ygqlUqlUqHWm8/n8/mc6ievWKvVarVa6ff/Xb/+VBCbzWaz2VCCIOOtUqlUKhViLpfL5XKPx5XxseOFvx2v/yFe+ICXIF74gH8A5ia8gOmPT18AAAASdEVYdGxhYmVsAEhlbGxvIHdvcmxkIbl+3UEAAAAASUVORK5CYII=
Well apparently StackExchange will not allow data links so you must copy & paste it into your browser's address bar.
@squeamish ossifrage got it down to 176:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC0AAAAHAQAAAAC0VvlnAAAAOklEQVR4nGLIv/57/+9rDGDqAkPOterN0YIM3KG712pdZcgI3bW26gZD9lUwlRNWW1wtAAAAAP//AwCcyhjs3+7tWQAAAABJRU5ErkJggg
114
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAAEAQAAAAAhFcs9AAAAIElEQVQIHWOJit1f7szy58v9DAWWPaEMP7hZHHgi1aMB
@primo got it down to 112:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACYAAAAEAQAAAADKInA+AAAAH0lEQVR4nGOIj///7wVDZOBdoQ4G4dCrYWuA7JNiHQ
-
5\$\begingroup\$ You can easily compress this to 258 characters:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEIAAAANCAAAAAA4MeeNAAAAdklEQVR4Ac2QUQqFQAwDc9I5Ze6XB8HXXRFE8Mdg+zGEwa7yOurXdUb30ap+UIHkUSDRGg5K5D+SdRQ8iqbdTjmk043ihcQU9r8Y1aEY2A2Y1cte4KRIc1UYg58oIFYuhwQ5UgYp+yF+8Jz1Qgapsz/n23xE8QNxUbxuz+WqjAAAAABJRU5ErkJggg==
pastebin.com/5TQzNv3D \$\endgroup\$– MMMCommented Feb 3, 2014 at 16:03 -
2\$\begingroup\$ @squeamish ossifrage got it down to 176:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC0AAAAHAQAAAAC0VvlnAAAAOklEQVR4nGLIv/57/+9rDGDqAkPOterN0YIM3KG712pdZcgI3bW26gZD9lUwlRNWW1wtAAAAAP//AwCcyhjs3+7tWQAAAABJRU5ErkJggg
. Must strip the hidden spaces. \$\endgroup\$– ChloeCommented Feb 4, 2014 at 3:48 -
1\$\begingroup\$ 143 chars: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAAEAQAAAAAhFcs9AAAAIElEQVQIHWOJit1f7szy58v9DAWWPaEMP7hZHHgi1aMBegAI03/J+AQAAAAASUVORK5CYII= \$\endgroup\$– luxcemCommented Feb 4, 2014 at 10:54
-
1\$\begingroup\$ I got it down to 135 characters!
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAAEAQAAAAAhFcs9AAAAIElEQVQIHWOJit1f7szy58v9DAWWPaEMP7hZHHgi1aMBegAI03/J+AQAAAAASUV=
(btw, that's 83bytes for a png image that says "Hello World", thought I might throw that out there!) \$\endgroup\$ Commented Feb 6, 2014 at 5:15 -
2\$\begingroup\$ Valid png format - 140 bytes codepad.org/O0TwZbKF. No
IEND
- 124 bytes: codepad.org/QdutLeK1. NoIEND
, noIDAT
crc32, no zlib adler32 - 112 bytes: codepad.org/R4srHxhh. \$\endgroup\$– primoCommented Feb 6, 2014 at 10:29
C# - 168 chars
C# is better! ;)
using System.Drawing;class a{static void Main(){var s=new Bitmap(99,9);Graphics.FromImage(s).DrawString("Hello world!",new Font("",5),Brushes.Red,0,0);s.Save(".png");}}
Saves as .png in the current directory.
Rule abuse:
- Minimum font/image size has not been specified, so I settled for the minimum readable ;)
- Filename is empty (only extension!), but it works flawlessly.
To mirror the Java answer, here is the indented code:
using System.Drawing;
class a
{
static void Main()
{
var s = new Bitmap(99, 9);
Graphics.FromImage(s).DrawString("Hello world!", new Font("", 5), Brushes.Red, 0, 0);
s.Save(".png");
}
}
.net's API is a lot cleaner.
-
\$\begingroup\$ Thanks for the suggestion of making the file call just
.png
. :) \$\endgroup\$ Commented Feb 1, 2014 at 22:08 -
\$\begingroup\$ I don't see how this is much cleaner than the Java one. \$\endgroup\$ Commented Feb 3, 2014 at 1:48
-
\$\begingroup\$ It is much cleaner than the Java one. \$\endgroup\$ Commented Feb 3, 2014 at 8:10
-
6\$\begingroup\$ @immibis I can point the following: Character count is 28% lower, because of: no checked exceptions(
throws Exception
); thevar
keyword;Save
is a method of the image itself, in contrast tojavax.imageio.ImageIO.write(b...
; file type is automagically inferred from the extension, no need to specify a separate"png"
; No need to instantiate aFile
object as innew java.io.File("p")
;Main
method doesn't need to receive a parameter. The general idea is the same: create an image, useGraphics
to write to it, and save it - but here it is done with more clear and succint method calls. \$\endgroup\$ Commented Feb 3, 2014 at 9:33 -
\$\begingroup\$ But C# doesn't have wildcards in generics. And anonymous classes. And return type covariance. And some other things I'm too lazy to recall. \$\endgroup\$ Commented Feb 4, 2014 at 23:47
Linux shell + various utilities: 48 bytes
My first thought was to print Hello World!
in the console, and then take a screenshot (after a small delay to avoid the race condition) using scrot
:
echo Hello World\!;scrot -d1
(28 bytes). Unfortunately, this fails the "and nothing else" requirement: it will generally show other things like window decorations.
So instead, do it inside a full-screen xterm
. This covers up any other windows and hides window decorations. It also satisfies the background-color requirement, since xterm
defaults to a white background.
Because xterm
displays a black cursor, we also need to tell it to hide the cursor. That can be accomplished using a terminal escape sequence: ESC [
?
2
5
l
.
The option to make it full-screen is -fullscreen
. However, it seems to work if you abbreviate the option to the shortest unambiguous possibility, -fu
, saving 8 bytes.
The final code (48 bytes) is:
xterm -fu -e 'echo \x1b[?25lHello World!;scrot -d1'
(where \x1b
denotes a literal ESC character, which takes 1 byte). By default, scrot
writes the screenshot to a timestamped PNG file in the current directory.
It works on my system:
-
\$\begingroup\$ You missed some
scrot
options - I often use-s
(interactively select window), but in this case you can use-u
to grab the current (focused) window only. \$\endgroup\$– brynCommented Feb 4, 2014 at 19:36
Processing, 38 37
This might be considered cheating, but:
text("HeΠo World!",9,8);save(".png");
38 char solution:
text("Hello World!",9,9);save(".png");
Saves this image as .png
:
Java - 340 339 292 261 239 236 233 chars
This outputs a file just called p
with a transparent background and white text:
import java.awt.image.*;class R{public static void main(String[]y)throws Exception{BufferedImage b=new BufferedImage(80,9,2);b.getGraphics().drawString("Hello World!",5,9);javax.imageio.ImageIO.write(b,"png",new java.io.File("p"));}}
Here a properly-indented version. Should be pretty clear what is going on:
import java.awt.image.*;
class R {
public static void main(String[] y) throws Exception {
// 2 = BufferedImage.TYPE_INT_ARGB
BufferedImage b = new BufferedImage(80, 9, 2);
b.getGraphics().drawString("Hello world!", 5, 9);
javax.imageio.ImageIO.write(b, "png", new java.io.File("p"));
}
}
You might argue that white text in a transparent background is awful for reading and the file being called just p
without the .png
extension is awful too. So this longer variant version with 290 chars use red text and outputs a file called p.png
:
import java.awt.image.*;import java.awt.*;class R{public static void main(String[]y)throws Exception{BufferedImage b=new BufferedImage(80,9,2);Graphics g=b.getGraphics();g.setColor(Color.RED);g.drawString("Hello world!",5,9);javax.imageio.ImageIO.write(b,"png",new java.io.File("p.png"));}}
That properly-indented:
import java.awt.image.*;
import java.awt.*;
class R {
public static void main(String[] y) throws Exception {
// 2 = BufferedImage.TYPE_INT_ARGB
BufferedImage b = new BufferedImage(80, 9, 2);
Graphics g = b.getGraphics();
g.setColor(Color.RED);
g.drawString("Hello world!", 5, 9);
javax.imageio.ImageIO.write(b, "png", new java.io.File("p.png"));
}
}
-
2\$\begingroup\$ @user-12506 Yes, you can add
throws Exception
to other methods, but the compiler enforce this rule: if you call a method that might throw aThrowable
that is not aRuntimeException
or anError
, then the compiler will require that you either catch or rethrow it, and this includesException
. Further, although it is allowed, declaringthrows Exception
is a bad programming practice, becauseException
is way too generic to be effectively handled in practice and rethrowing it just spread the bad practice to elsewhere. \$\endgroup\$ Commented Feb 3, 2014 at 8:22 -
1\$\begingroup\$ @user-12506 It's called checked exceptions. Look it up. :) \$\endgroup\$– ntoskrnlCommented Feb 3, 2014 at 14:05
-
1\$\begingroup\$ @user-12506 Not everything is lower case in Java – classes are CamelCase just like in C#. Methods and fields are lowerCamelCase, and packages are alllowercase. Makes it somewhat easier to determine what a name refers to, in my opinion. \$\endgroup\$– ntoskrnlCommented Feb 3, 2014 at 20:55
-
1\$\begingroup\$ @ntoskrnl Yeah, things can and do get a bit confusing when classes, methods and other things are camel case. But in the case of methods, it either begins with an Identifier that allows you to immediately recognize it as such, and if you're calling a method, you'll know right away that it's a method because it ends in (); or (somethinginHere);. In C#, most things are CamelCase (when I'm typing anyway), except for variables. and (most)
types
. Either way, I'm going to have to get used to Java eventually. I've just started my first serious Android project. \$\endgroup\$ Commented Feb 3, 2014 at 21:02 -
2\$\begingroup\$ @Timtech, at least for me ỻ was rendered as a square in the resulting image. Here in the browser (using firefox), it renders as a box containing 1EFB. I strongly suspect that this is not portable. \$\endgroup\$ Commented Feb 4, 2014 at 5:19
Fortran 90, 104 94 bytes:
Aight, game on. Fortran 90, using the g2 graphics library and implict typing, so "d" is a real:
d=g2_open_gd('h',80.,12.,g2_gd_png)
call g2_string(d,1,1,'Hello world!')
call g2_close(d)
end
Needs to have the g2 library installed, then just compile with
gfortran -lg2 -fsecond-underscore p.f90
Thanks Kyle Kanos for suggesting to drop "program p"!
I'm pretty satisfied that I beat C#, C + Cairo, Java, Javascript, Python and Ruby! And now also Perl!
Example output:
-
1\$\begingroup\$ This can be shortened to 93 characters by eliminating
program p
as it is not necessary (the only necessary part of a F90 code isend
). \$\endgroup\$ Commented Feb 4, 2014 at 16:39
R, 52 39 chars
png()
frame()
text(.5,1,"Hello World!")
Saves as Rplot001.png in current directory. To be run as a script in non-interactive (batch) mode.
Thanks to Sven Hohenstein and Michael Hoffman for updates!
-
\$\begingroup\$ I count 52 characters... \$\endgroup\$ Commented Feb 2, 2014 at 2:47
-
\$\begingroup\$ @SvenHohenstein sorry you are correct. I made a mistake while attempting shorter versions (they didn't work). \$\endgroup\$– TomasCommented Feb 2, 2014 at 3:08
-
1\$\begingroup\$
dev.off()
is unnecessary when you run this as a script instead of interactively. \$\endgroup\$ Commented Feb 3, 2014 at 18:12
PHP + gd2 - 86 bytes
<?imagestring($i=imagecreatetruecolor(97,16),4,2,0,'Hello world!',65535);imagepng($i);
imagecreatetruecolor
is used instead of the shorter imagecreate
, because colors can used directly without having to allocate them with imagecolorallocate
. 65535
corresponds to hex color #00FFFF
, a.k.a. cyan. I could have used 255
for blue, but it's fairly hard to see on a black canvas.
If the requirement that the background must be white or transparent is to be strictly enforced, I think the best that can be done is 98 bytes:
<?imagestring($i=imagecreatetruecolor(97,16),4,2,0,'Hello world!',imagefilter($i,0));imagepng($i);
The 0
sent to imagefilter
is the value of the constant IMG_FILTER_NEGATE
, which of course negates the image. The result, 1
, is then used as the paint color (#000001
):
Another option at 108 bytes:
<?imagestring($i=imagecreatetruecolor(97,16),4,2,imagecolortransparent($i,0),'Hello world!',1);imagepng($i);
Setting black to be transparent, and drawing with #000001
instead.
PHP + No Library - 790+ bytes
<?
echo pack('CA3N2',137,'PNG',218765834,13);
echo $ihdr = pack('A4N2C5','IHDR',45,7,1,0,0,0,0);
echo hash('crc32b',$ihdr,true);
$data =
'--------0 0 0 0 0 0 0---'.
'--------0 0 0 0 0 0 0---'.
'--------0 0 00 0 0 00 0 0 00 0 0 0 000 0---'.
'--------0000 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0---'.
'--------0 0 0000 0 0 0 0 0 0 0 0 0 0 0 0 0 0---'.
'--------0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ---'.
'--------0 0 000 0 0 00 0 0 00 0 0 000 0---';
$bytes = join(array_map(chr,array_map(bindec,str_split(strtr($data,' -',10),8))));
$cmp = gzcompress($bytes);
echo pack('N',strlen($cmp));
echo $idat = 'IDAT'.$cmp;
echo hash('crc32b',$idat,true);
echo pack('NA4N',0,'IEND',2923585666);
Ahh, that's better. No bloat; exactly as much as required, and not a chunk more.
The result is this 109 byte png:
Or, URI encoded (which seems to be trending...) at 168 bytes:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC0AAAAHAQAAAAC0VvlnAAAANElEQVR4nGPIv/7//+8LDFAq51r15mgBBu7Q3Wu1LjBkhO5aW3WBIfsqkLrBkBNWW1wtAACw2RlgLInRogAAAABJRU5ErkJggg
Supposing we wanted to cut that down a bit more, let's say we replace the data string with this:
$data =
'--------0 0 0 0 0 0 0'.
'--------0 0 00 0 0 000 0 0 000 00 0 000 0'.
'--------0000 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0'.
'--------0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 '.
'--------0 0 000 0 0 000 00 00 000 0 0 000 0';
(and update the header to the new dimensions, 40x5), the output would be this 96 byte png:
Which URI encodes to 150 bytes:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAFAQAAAAAft5MoAAAAJ0lEQVR4nGPIv/7//y6GnCvlLosYuEJLQ1cxZF4tDV3NkBNS5LoIANqBDTt5Av0NAAAAAElFTkSuQmCC
I think that's about as small as you're going to be able to get, and still be considered "human readable".
Further Analysis
You may have noticed that we've been toting along an extra byte at the beginning of each scanline (denoted by --------
). This isn't solely for decoration. Each byte specifies the filtering used by each scanline. According to the PNG specification, "Filtering transforms the PNG image with the goal of improving compression." So let's try that.
The are five different filtering operations which can be applied independently to each scanline. The PHP implementation that I used for each can be seen here: http://codepad.org/xCQpBPC3 where $bytes
represents the raw bytes for the current scanline, and $prior
represents the raw, unfiltered bytes for the scanline above the current.
Let's start with the first 45x7 image. Seven scanlines each with 5 different filterings makes 78125 different possibilities to grind through. The initial encoding of the data block was 52 bytes in length, and after a bit of grinding zlib found a one byte improvement using filtering pattern [1, 1, 1, 1, 0, 0, 0] (that is, the first four scanlines with Sub filtering, and the last three unfiltered). The result is this 108 byte png:
Which of course looks identical to the last. But I'm not convinced that zlib is producing the best possible encoding, and I think i have good reason to be skeptical. I decided to try AdvanceComp (which uses the same DEFLATE engine used for 7-zip), and Zopfli, an implementation which claims to "find a low bit cost path through the graph of all possible deflate representations." Sure enough, Zopfli mananged to compress the same data data pattern [1, 1, 1, 1, 0, 0, 0] down to 50 bytes, producing this 107 byte png:
Once again, visually identical. (As a point of interest, it should probably be mentioned at this point that AdvanceComp with the setting -z3
(compress-extra (7z)) didn't manage to find anything shorter than 60 bytes - the data was left uncompressed. It seems it refuses to compress anything this short). The above URI encodes to 165 bytes:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC0AAAAHAQAAAAC0VvlnAAAAMklEQVR4AWPMz9Bg+HMVRuVkLbVYsZWR2yvtU+0yhozQXWurLjBkXwVSNxhywmqLqwUA+IMVKa7QjrYAAAAASUVORK5CYII
Fully 11 bytes shorter than squeamish ossifrage's attempt at more or less an identical image.
Onwards to the 40x5 image. Five lines with 5 filterings each means we only have 3125 possibilities this time. The original encoding was 39 bytes in length, and with a bit of grinding, zlib found quite a few 38s. The one I've chosen is [1, 0, 0, 2, 0], which contains the largest number of unfiltered lines, and Sub and Up filters on lines 0 and 4, which are the simplest. Zopfli wasn't able to improve this result any further. The result is this 95 byte png:
Which URI encodes to 149 bytes:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAFAQAAAAAft5MoAAAAJklEQVR4nGPMz9Bg2M2Qc6XcZREDV2hp6Cqm+AYGBkaGnJAi10UAju4JJ/1zkEIAAAAASUVORK5CYII
You might be tempted to think that the last 18 or so bytes of this aren't necessary. After all, this 121 byte URI will still display correctly, at least in Chromium:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAFAQAAAAAft5MoAAAAIUlEQVR4nGPMz9Bg2M2Qc6XcZREDV2hp6Cqm+AYGBkaGnJAi10U
But if you save it to a file, it will break in very many image viewers. In fact, any compliant decoder is required to report an error. So what have we chopped off?
From end towards beginning:
- 4 bytes - CRC32 for
IEND
chunk (always0xAE426082
) - 4 bytes -
IEND
chunk marker (alwaysIEND
) - 4 bytes -
IEND
chunk length (always0x00000000
) - 4 bytes - CRC32 for
IDAT
chunk - 4 bytes - Adler32 for zlib data
- 1 byte - Stop marker for zlib data
Additionally adjusting the IDAT
length marker down by 5 (to compensate for the bytes we deleted) seems to "fix" the image in Windows Previewer.
-
\$\begingroup\$ The question state that it should have a white or transparent background. I myself think that the rules should be relaxed to allow black too, but for now, it fails the spec at this point. \$\endgroup\$ Commented Feb 2, 2014 at 5:25
-
\$\begingroup\$ @Victor Unfortunately, the gd2 library - as exposed by PHP, at least - doesn't have an option to specify the default color. Setting black to be transparent does work, though. Or simply to negate the entire image before adding the text. \$\endgroup\$– primoCommented Feb 2, 2014 at 6:08
C + Cairo: 238 221 202 bytes
#include <cairo/cairo.h>
main(){cairo_surface_t*s=cairo_image_surface_create(0,99,50);cairo_t*c=cairo_create(s);cairo_move_to(c,0,9);cairo_show_text(c,"Hello world!");cairo_surface_write_to_png(s,"o");}
$ cc `pkg-config cairo --libs --cflags` mini.c && ./a.out && display o
Here is the un-minified version:
#include <cairo/cairo.h>
void main (int argc, char* argv[])
{
cairo_t *cr;
cairo_surface_t *surf;
surf = cairo_image_surface_create (0, 99, 50);
cr = cairo_create (surf);
cairo_move_to (cr, 0, 9);
cairo_show_text (cr, "Hello world!");
cairo_surface_write_to_png (surf, "out.png");
}
Best enjoyed while listening to this song :)
-
\$\begingroup\$ You can save some chars by removing the type declaraction, i.e. the
void
formain
and theint
forx
, and possibly thechar
for**a
(I'm not sure about the last one though). In C the type is default to beint
if no type is specified, and you don't necessarily need to return a value forint main
. This may produce compilation warning messages, but not errors and the program will still work. \$\endgroup\$ Commented Feb 2, 2014 at 10:54 -
1\$\begingroup\$ Shaved 17 bytes by removing the pointless
#define C(n,...) …
. Also,main
returnsint
, notvoid
(and as of C99 it's not required to explicitly "return 0
" at the end ofmain
; the implementation implicitly adds it for you). \$\endgroup\$ Commented Feb 3, 2014 at 2:09 -
\$\begingroup\$ @ace Thank you! I had forgotten that types defaults to int i C. But it looks like it's all-or-nothing; you can't have some variables in the call signature use default types while others don't. So I just changed it to
main()
and hardcode the filename too
instead of passing it to main. Now it's smaller than the Java version :) \$\endgroup\$ Commented Feb 3, 2014 at 2:35 -
\$\begingroup\$ @Quuxplusone Thanks! Did not know that C99 add an implicit
return 0
to main if not already there. That was why I choose to (incorrectly) returnvoid
instead ofint
. Since you got rid of the vararg macro, C99 is not required to compile the code anymore. <rant>Which makes it more portable to compilers who's vendors has chosen to not implement C99 [read: Microsoft] :)</rant> \$\endgroup\$ Commented Feb 3, 2014 at 2:45
make a PNG image that says "Hello world!" …
You'll hopefully excuse my very loose interpretation of the above requirement. :)
OSX bash:
printf '"Hello world!" and nothing else on a distinguishable background using only an image making API (eg ImageMagick) and return the image.' > hello.png
say -f hello.png
-
\$\begingroup\$ But it's not a PNG image, is it? \$\endgroup\$– RuslanCommented Feb 4, 2014 at 10:58
-
2\$\begingroup\$ Well, it's technically a .png file, and it does say what is needed. :-) \$\endgroup\$ Commented Feb 4, 2014 at 11:26
-
1\$\begingroup\$ PNG image is not "ASCII text, with no line terminators", as said by
file
. It's a .png file, but not PNG image. \$\endgroup\$– RuslanCommented Feb 4, 2014 at 11:28 -
2\$\begingroup\$ Fail point. I didn't manage to find a way to fool the
file
utility by pre-pending the whole thing with the relevant code (i.e. decimals137 80 78 71 13 10 26 10
). Perhaps you might know of a way? ;-) \$\endgroup\$ Commented Feb 4, 2014 at 12:27 -
\$\begingroup\$ seems you'd need to make full header with all information like dimensions, palette etc., because
file
prints this information. With your relevant code it only says "data". \$\endgroup\$– RuslanCommented Feb 4, 2014 at 14:47
Javascript! 105 104 101
c=document.createElement('canvas');open(c.toDataURL(c.getContext('2d').fillText('Hello world!',0,9)))
Outputs this size-optimized and pretty image:
Octave, 47
axis('off')
title("Hello World!")
print -dpng x.png
-
-
\$\begingroup\$ +1 now
:D
why bother keeping the bigger/broken ones though... \$\endgroup\$– Nick TCommented Feb 11, 2014 at 3:28
Sage notebook, 22
text("Hello world",0j)
Ruby, 138
I'm golfing this hole with just my putter. (I chose a PNG library without fonts or a string draw method.)
require'chunky_png';i=ChunkyPNG::Image.new 34,4
136.times{|v|i[*(v.divmod(4))]=9*(0xb0fae0f02e0eae0ece00eae0f0f0bf0f2f&1<<v)>>v};i.save ?h
Actual output is 34x4 pixels. (Enlarged below.) This plots very, very small and nearly transparent hand-drawn chars onto a very small transparent background. Image is saved to a PNG file named h
.
-
\$\begingroup\$ Would it be shorter in Ruby to store
0xb0...
in Base64 and call a decode function? \$\endgroup\$ Commented Feb 2, 2014 at 10:10 -
1\$\begingroup\$ @Mechanicalsnail, I think that would require another
require
and then some, so the savings would be blown. I think. I did look at Base 36 (since that can be done withto_i
alone) but that ends up a bit longer. \$\endgroup\$ Commented Feb 2, 2014 at 10:14
TI-BASIC, 22
Text(0,0,"HELLO WORLD!
White background. Use TI-Connect if you wish to retrieve it from the calculator. Resulting PNG:
-
8\$\begingroup\$ There's a PNG file on the calculator? \$\endgroup\$– skeeveyCommented Feb 1, 2014 at 20:29
-
22\$\begingroup\$ The calculator may have a 94 by 62 bitmap, stored in its own uncompressed format. I'll put my money on Ti-Connect converting it into a PNG when it's retrieved. \$\endgroup\$– TobiaCommented Feb 1, 2014 at 23:00
-
18\$\begingroup\$ Can you post the resulting PNG? \$\endgroup\$ Commented Feb 2, 2014 at 5:44
-
9\$\begingroup\$ This does not produce a .png image in the calculators memory. Retrieving it from the calculator converts it to a .png image. \$\endgroup\$– Rolf ツCommented Feb 4, 2014 at 13:13
-
12\$\begingroup\$ Personally, I think this is like displaying
Hello world!
on my computer screen and then saying "Oh, but I can easily convert it to a .png by taking a screenshot of it!" \$\endgroup\$ Commented Feb 7, 2014 at 1:12
BASH + RST + ImageMagick = 43 chars
Just for fun, here's another (quite ugly) one:
echo 'Hello World!'|rst2pdf|convert - a.png
Output:
Gnuplot
Not really a true competitor, just for fun. (homepage)
#!/usr/bin/gnuplot
set terminal pngcairo
set output "hw.png"
set label "Hello\nWorld!"
unset xtics
unset ytics
set yrange [-1:+1]
plot -1 notitle
or, as a oneliner (thanks to Phil H): 74 characters
se te pngc;se ou "q.png";se la "Hello world!";se yr[-1:1];uns ti;pl -1 not
-
1\$\begingroup\$ You can shorten each of those commands to the minimum unique stub - so
set te
works, andset out
etc. And you only need the top line to make it executable in the terminal, which is not a usual code golf requirement. So:se te pngc;se ou "q.png";se la "Hello world!";se yr[-1:1];uns ti;pl -1 not
- 74 chars \$\endgroup\$– Phil HCommented Feb 4, 2014 at 16:31 -
\$\begingroup\$ @Phil H: yeah, sure, thanks ;-) Actually I knew commands could be shortened, but as this contrib wasn't really designed to compete with more efficient solutions, I thought I might as well show full length commands for educational purposes. \$\endgroup\$– kebsCommented Feb 5, 2014 at 18:59
Perl, 95:
The whole command incantation:
perl -MGD::Simple -e'$i=new GD::Simple;moveTo$i 9,50;string$i "Hello world!";print$i->png'>.png
Because of (reasonable) module defaults, it's 95 characters (or 92 if single letter file name allowed).
On Windows we need to binmode STDOUT
, the shortest way I think can be -M-encoding
+ get rid of double colons:
perl -MGD'Simple -M-encoding -e"$i=new GD'Simple;moveTo$i 9,50;string$i 'Hello world!';print$i->png">.png
i.e. 105
Data URI: 446
Following Chloe's idea, applied some basic optimisation to the image.
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEEAAAALCAAAAAAFX7+TAAABBUlEQVQoz2P4Tylg+M8IohiRRUCIkC6E0sFlwhFBJo5kmPAdWSYmuTsgGa6y/3pMf/8yLYEJMcQwARXckmZi8YCawAAG//8L537ZxbEMaoKCwuvXCkogE2y0/nMyL1vC/BcmxKC6AqhAXurBc1kGkNUINzCBDIqFmsB84f//c8wgmcVs91j13d3U4EIMl0AKmM78/38GqJQXyQSWQ///H3sJMwGo7ALYhL/MQUq1wkK1cCEGsE+ZgSacAzKNkUxQ1/kygfEczBeKb18rKICDS4U58SUT8ye4EMQEBelHz+WAzEokE+6IM7HkI4ekLDgk/5cxnPrPK/4fLgQxARSSUdCQpBQAAFZKE8rQG60FAAAAAElFTkSuQmCC
Might be able to hack it further, but then would not be a perfectly conformant PNG and some viewers may not display it correctly.
-
\$\begingroup\$ Could you explain what kind of optimizations did you perform? \$\endgroup\$– svickCommented Feb 3, 2014 at 15:48
-
\$\begingroup\$ PNG2, stripped optional chunks, optimal (not streamed) compression \$\endgroup\$ Commented Feb 3, 2014 at 16:22
-
1\$\begingroup\$ If you reduce the font size slightly, remove the spacing, the actual binary size of the image would be smaller than some of the posted solutions. \$\endgroup\$ Commented Feb 3, 2014 at 16:24
-
1\$\begingroup\$ @OrangeDog I got it down to 179:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC0AAAAHAQAAAAC0VvlnAAAAOklEQVR4nGLIv/57/+9rDGDqAkPOterN 0YIM3KG712pdZcgI3bW26gZD9lUwlRNWW1wtAAAAAP//AwCcyhjs3+7tWQAAAABJRU5ErkJggg==
\$\endgroup\$– r3mainerCommented Feb 3, 2014 at 16:37 -
1\$\begingroup\$ @squeamishossifrage That doesn't load in Firefox for me. \$\endgroup\$ Commented Feb 3, 2014 at 17:05
Python and Matplotlib - 66 65 chars
from pylab import*;title('Hello world!');axis('off');savefig('X')
Bit of whitespace, but it has the text and nothing else. File is saved as X.png
:
-
-
\$\begingroup\$ @Timtech thanks, I'm a golfing noob clearly ;) \$\endgroup\$– Nick TCommented Feb 4, 2014 at 0:36
-
Ghostscript command line incantation, 84 (i.e. Postscript) :
gs -sDEVICE=png16 -oa.png -c '/ 72 selectfont 9 9 moveto(Hello world!)show showpage'
Missing font message is intentional ;-). And proper (i.e. not hidden) name for our PNG file, too :-)
Python with PIL 122 Chars
from PIL import Image,ImageDraw;d=Image.new("RGB",(70,9));i=ImageDraw.Draw(d);i.text((0,0),"Hello World!");d.save("a.png")
It could probably be much smaller but I haven't worked with PIL extensively and made this in 5 minutes.
Output:
-
2\$\begingroup\$ You beat me to it by 10 minutes! With about 10 less chars! +1 :D Lose another char by going from 10 to 9 in your
new
, but you left out the!
. \$\endgroup\$ Commented Feb 2, 2014 at 1:29 -
\$\begingroup\$ The question state that it should have a white or transparent background. I myself think that the rules should be relaxed to allow black too, but for now, it fails the spec at this point. \$\endgroup\$ Commented Feb 2, 2014 at 5:26
-
2\$\begingroup\$ Couldn't you save lots of characters with
from PIL import*
? \$\endgroup\$– TimtechCommented Feb 4, 2014 at 0:54 -
\$\begingroup\$ You would expect so, but you have to import them individually or else you get a not defined error
from PIL import Image,ImageDraw;d=Image.new("RGB",(66,10));i=ImageDraw.Draw(d);i.text((0,0),"Hello World");d.save("a.png")
NameError: name 'Image' is not defined
\$\endgroup\$– globbyCommented Feb 7, 2014 at 21:14
Bash + DOT, 46 41
dot -Tpng<<<'graph{label="Hello World!"}'
This outputs a png into the standard output. It is saving a file, but I don't think that was a requirement.
Outout:
-
\$\begingroup\$ I we allow them be in ellipses, it can be 8 chars shorter... \$\endgroup\$– BachCommented Feb 2, 2014 at 10:57
-
1\$\begingroup\$ I am not sure whether you should add the bash chars as well for compiling this dot script. This adds
dot -Tpng -op d
, which is 15 chars. \$\endgroup\$– BachCommented Feb 2, 2014 at 11:01 -
\$\begingroup\$ You should count the command line options/argument if they are needed to make your program solve the task. Normally the dashes are not counted, so I think you only should add
Tnpg
,op
andd
to the character count (+7), and specify how to run it in the answer itself. \$\endgroup\$– danieroCommented Feb 2, 2014 at 18:40 -
\$\begingroup\$ It can be better if you don't
echo
but instead write it in a file and rundot -Tpng
on the file; it makes it 38, but I don't know if it counts... \$\endgroup\$– BachCommented Feb 2, 2014 at 19:28 -
Python, with 118 115 117 116 114 chars
Here's a full criteria passing with white text on alpha background at 116 114 chars!:
from PIL import Image,ImageDraw as D
m=Image.new("LA",(99,9))
D.Draw(m).text((9,0),'Hello World!')
m.save('r.png')
(You can replace newlines with semicolons - count is the same regardless.)
-
\$\begingroup\$
ImageDraw as D
, and thenD.Draw
saves 3 chars. \$\endgroup\$– primoCommented Feb 2, 2014 at 3:02
PureBasic - 128 chars
UsePNGImageEncoder()
CreateImage(0,99,24)
StartDrawing(ImageOutput(0))
DrawText(0,0,"Hello World!")
SaveImage(0,"a.png",4673104)
Not the shortest here, but I have to support my favorite Basic language :)
edit: just in case there is a complain about the black background, at 133 chars:
UsePNGImageEncoder()
CreateImage(0,80,16)
StartDrawing(ImageOutput(0))
DrawText(0,0,"Hello World!",0,-1)
SaveImage(0,"a.png",4673104)
bash + netpbm: 31 chars
pbmtext "Hello world!"|pnmtopng
Will make:
Rebol/View 45
save/png %i to-image layout[h1"Hello World!"]
writes a png image file named i into current directory
-
2\$\begingroup\$ Clever! Google charts is more readable ;) chart.googleapis.com/chart?cht=tx&chl=Hello%5C+world%21 \$\endgroup\$– primoCommented Feb 5, 2014 at 1:15
Hello World
orHello World!
? \$\endgroup\$