g | x | w | all
Bytes Lang Time Link
nan140202T182657Zkebs
033Bash + ImageMagick140201T204620Zr3mainer
114Python140202T014345ZAaron Ha
1494HTML140203T042418ZChloe
nan140201T230940Zmarczell
055Shell + Graphviz140206T175908Zgrim
122Python with PIL 122 Chars140202T011724Zglobby
094Fortran 90140202T231223Zsemi-ext
086PHP + gd2140202T021841Zprimo
101Javascript!140202T183207Zjas
037Here is a cool trick140205T105912ZIsmael M
192Ruby140206T080729Zuser1342
037Processing140202T131354ZThe Guy
011Internet140204T192532ZHL-SDK
133Groovy140204T191927Zkrs
041MATLAB140204T181844Z0not
nanGroovy140204T093501ZGuillaum
041Bash + DOT140202T105231ZBach
039R140201T205218ZTomas
000Mouse140204T103844ZAnthony
028EPL140203T141337Zkoko
043BASH + RST + ImageMagick =140202T200002ZBach
065Python and Matplotlib140203T223004ZNick T
022TIBASIC140201T201029ZTimtech
045Rebol/View140203T184747Zsqlab
031bash + netpbm140203T214646ZF. Hauri
092Bash140203T180648ZAdam Dav
027Mathematica140201T225430ZDavidC
nanChloe used a Base64 encoded approach with 1494 characters140203T161950ZMMM
nan140203T131103ZDenis de
022Sage notebook140203T144513Zboothby
128PureBasic140203T140241ZFozzedou
446Data URI140203T133835ZOrangeDo
047Matlab140203T101235Zgerrit
202C + Cairo140202T083635ZTorkel B
084Ghostscript command line incantation140202T185930Zuser2846
095Perl140202T113440Zuser2846
138Ruby140202T100605ZDarren S
048Linux shell + various utilities140202T100721ZMechanic
233Java140201T201422ZVictor S
168C#140201T211349ZNothings

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, in a gnuplot shell (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

Bash + ImageMagick: 35 33

Default font, default text size, default colours:

convert label:Hello\ world! a.png

and here's the result:

Hello, World!

Thanks to DigitalTrauma and sch for the help :-D

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.)

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

Octave, 47

axis('off')
title("Hello World!")    
print -dpng x.png

Shell + Graphviz (55)

echo 'graph{a[label="Hello World!"]}'|dot -Tpng>h.png

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: enter image description here

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: example PNG produced by Fortran

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:

Additionally adjusting the IDAT length marker down by 5 (to compensate for the bytes we deleted) seems to "fix" the image in Windows Previewer.

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:

Hello world!

Here is a cool trick, only 37 chars: placehold.it/png/99&text=Hello+world! (+7 chars for the protocol).

This generates a 239 bytes long png image with 99px of width and height.

I know it's not programming, but this is a website that generates placeholder images.

You should visit http://placehold.it.

Ruby 192 chars:

I use RMagick RVG (Ruby Vector Graphics).

require 'rvg/rvg';include Magick;RVG::dpi = 72;RVG.new(1.5.in, 1.5.in){|canvas|canvas.background_fill = '#C0C0C0';canvas.text(10, 100){|title|;title.tspan("Hello World!")}}.draw.write('hw.png')

output:
enter image description here

Processing, 38 37

This might be considered cheating, but:

text("HeΠo World!",9,8);save(".png");

enter image description here


38 char solution:

text("Hello World!",9,9);save(".png");

Saves this image as .png:

enter image description here

Internet 11

Internet is an API!

ow.ly/thgUJ -> http://dummyimage.com/99x9/f/0.png&text=Hello+world!

Groovy, 133

Not going to win any points for size here as it's just an abbreviated Java.

No color setting:

i=new java.awt.image.BufferedImage(75,30,2);i.graphics.drawString('Hello World',5,20);javax.imageio.ImageIO.write(i,'PNG',System.out)

With setting color (164):

i=new java.awt.image.BufferedImage(75,30,2);g=i.graphics;g.color=java.awt.Color.RED;g.drawString('Hello World',5,20);javax.imageio.ImageIO.write(i,'PNG',System.out)

Formatted:

i = new java.awt.image.BufferedImage(75,30,2)
g = i.graphics
g.color = java.awt.Color.RED
g.drawString('Hello World',5,20)
javax.imageio.ImageIO.write(i,'PNG',System.out)

hw.png

MATLAB, 41 chars

@gerrit posted a MATLAB solution as well, but since I don't have enough rep to comment, I'll post mine too. (The output is the same as his, so I don't want to take up more space with the resulting PNG).

axis off,title 'Hello world!',print -dpng

Groovy, 151 (or 202 with a black text)

a rewrite of the proposed Java version. Resulting image is with white text on a transparent background. Add 50 chars to have black text !

import java.awt.image.BufferedImage as B
B b=new B(80,9,2)
b.graphics.drawString("Hello world!",5,9)
javax.imageio.ImageIO.write(b,"png",new File("p"))

The version with black text:

import java.awt.*
import java.awt.image.BufferedImage as B
B b=new B(80,9,2)
b.graphics.with {setColor(new Color(0)); drawString("Hello world!",5,9); }
javax.imageio.ImageIO.write(b,"png",new File("p"))

enter image description here

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: Hello World!

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!

Mouse: 0 chars

"right click" > "save image as"

Result:

enter image description here

EPL, 28

0,0,0,1,1,1,N,"Hello World!"

BASH + RST + ImageMagick = 43 chars

Just for fun, here's another (quite ugly) one:

echo 'Hello World!'|rst2pdf|convert - a.png

Output:

Hello World!

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:

enter image description here

TI-BASIC, 22

Text(0,0,"HELLO WORLD!

White background. Use TI-Connect if you wish to retrieve it from the calculator. Resulting PNG:

enter image description here

Rebol/View 45

save/png %i to-image layout[h1"Hello World!"]  

writes a png image file named i into current directory

bash + netpbm: 31 chars

pbmtext "Hello world!"|pnmtopng

Will make:

Hello world by netPBM

Bash, using Google's chart API: 92 characters

curl http://chart.googleapis.com/chart?chst=d_text_outline&chld=|9|h|||Hello+world! > h.png

enter image description here

Further optimization: 33 characters

curl http://goo.gl/a8ntA4 > h.png

enter image description here

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.

png

Chloe used a Base64 encoded approach with 1494 characters, however you can easily reduce the size:

Anchor link - 166 chars

data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAD8AAAAFAQAAAADaxQm5AAAAM0lEQVQIW2Mo0a+w3iKQz8NQ+r56r+71/BIGlnwg40J+GUhkz9lr78sYShQ57O6IKfIAAJypEkNzAX3zAAAAAElFTkSuQmCC

Paste this into your browser

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

Sage notebook, 22

text("Hello world",0j)

PureBasic - 128 chars

UsePNGImageEncoder()
CreateImage(0,99,24)
StartDrawing(ImageOutput(0))
DrawText(0,0,"Hello World!")
SaveImage(0,"a.png",4673104)

enter image description here

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)

enter image description here

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.

Matlab: 47 characters

I'm not sure what exactly an Image making API is. This uses a figure/graph making API, which is arguably an image.

text(1,1,'Hello World!');axis off;print -dpng f

Matlab example

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 :)

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 :-)

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

enter image description here

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.

output

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:

output

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"));
    }
}

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:

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.