[QUIZ] Text Image (#50)

I tried this one out. I'm not sure if I was successful or not...

My first instinct was to rank characters for intensity levels
programmaticly. I then came to the realization that not all
characters have the same distribution of intensity, so I thought I
would try splitting them up, and matching them with sets of pixel
intensities (instead of just one).

ruby create_tables.rb num [extended]
does the first part - pass it a number (number of pixels sqare that
will be replaced by one character). uses extended ASCII if the second
argument is applied.

ruby i2a.rb src_img outfile num [normalized]
does the second part. takes num x num clumps of pixels from src_image
and finds the closest character from the appropriate table (by
Euclidean distance), puts it out to outfile. If normalized is
supplied, the image is normalized for maximum contrast in the source
image.

You can find the code here:
http://www.rabble-rooster.org/rubyquiz/50/

Results are in the results folder.

The underscore also rendered to pure white, so I had to remove it
manully from the YAML tables. Those tables are available also.

I know this code needs some refactoring/reengineering, and I didn't
take the time to look into how *Magick did things like scaling. Feel
free to chide me on any points that are inefficient/bad/wrong/stupid.

···

--
Rob

Hi,

Best quiz yet. Er, well, quiz which held my attention longest anyway. :slight_smile:

My solution is um, less... elegant, than some of the others, but in a lot of
ways, like a parent who mistakenly thinks their ugly child is cute I kinda
like it. I don't really share my code a lot (maybe for obvious reasons) but
I'm just so pleased with how easily ruby lets me hack things to high heaven
and this one in particular makes me smile. Take special note that it only
works on 24 bit .bmp files and put your hard hat on if you think you're
going to feed anything but that into it. :wink: Okay, enough blather, without
further ado, the first code I've shared with you guys:

#It only supports 24bit bmp files, and it even chokes on most of them :wink:
#It creates one character per pixel (which has obvious implications)
#But it's 40 lines of pure ruby no lib use binary file up-hackery...
#And quite frankly, thats what I do.

MyPixel = Struct.new( 'MyPixel', :r, :g, :b )

the_gradient = %w|D Y 8 S 6 5 J j t c + i ! ; : .|
###############PUT YOUR FILENAME
HERE#########################################
the_file = File.new('ducky.bmp', 'rb')
the_file.read(2) #BM
the_file.read(4).unpack('V')[0] #filesize
the_file.read(4) #unused
the_file.read(4).unpack('V')[0] #offset from beginning to bitmap data
the_file.read(4).unpack('V')[0] #size of bitmap header
image_x = the_file.read(4).unpack('V')[0] #width x in pixels
image_y = the_file.read(4).unpack('V')[0] #height y in pixels
the_file.read(2).unpack('v')[0] #planes?
the_file.read(2).unpack('v')[0] #bits per pixel
the_file.read(24) #unused

the_bitmap = []
puts "CRRRRUNCHHHH --- please wait, reading file..."
image_y.times do |row|
the_bitmap[row] = []
image_x.times do |col|
the_bitmap[row][col] = MyPixel.new( 0, 0, 0 )
the_bitmap[row][col].b = the_file.read(1).unpack('c')[0]
the_bitmap[row][col].g = the_file.read(1).unpack('c')[0]
the_bitmap[row][col].r = the_file.read(1).unpack('c')[0]
end
end

puts "output coming:"
the_output = File.new('output.asciiart', 'w')
(image_y-1).downto(0) do |row|
image_x.times do |col|
the_avg =
(the_bitmap[row][col].b+the_bitmap[row][col].g+the_bitmap[row][col].r)/3
the_output.write(the_gradient[the_avg>>4])
end
the_output.write("\n")
end

Harold Hausman:
#It only supports 24bit bmp files, and it even chokes on most of them :wink:

Thanks for submitting this - well done, Harold.

(If I was going to solve this quiz, I'd have done a BMP-reader.)

Cheers,
Dave

Harold Hausman wrote:

Hi,

[...] the first code I've shared with you guys:

Hi Harold - and thanks for doing that.

#It creates one character per pixel (which has obvious implications)

Not obvious to me until I tried it.
That's a fair-sized hunk of duck ;-))

#But it's 40 lines of pure ruby no lib use binary file up-hackery...

Excellent.
I refactored a bit:

···

#------------------------------------------------------------------------
Gradient = %w{ D Y 8 S 6 5 J j t c + i ! ; : . }

# http://www.d10.karoo.net/ruby/quiz/50/duck.bmp (NOTE: 800KB BMP)
bmp = File.open('duck.bmp', 'rb') { |fi| fi.read }
bmo = bmp[10, 4].unpack('V')[0] # offset to bitmap data
image_x, image_y = bmp[18, 8].unpack('VV') # width x / height y (pixels)
by_start = bmo + ((image_y - 1) * (image_x * 3))

File.open('output.txt', 'w') do |fo|
  by_start.step(bmo, -(image_x * 3)) do |by_ptr|
    image_x.times do |x|
      t = 0; 3.times {|n| t += bmp[by_ptr + (x * 3) + n] }
      fo.putc( Gradient[ (t / 3 ) >> 4 ] )
    end
    fo.puts
  end
end
#------------------------------------------------------------------------

There's one change in effect from your original and I suspect
you may have intended it differently ...

  the_file.read(1).unpack('c')[0]

.... gives a signed byte so, when you take the average by adding and
dividing by 3, you can be adding negatives. Replacing those with ('C')
gives you unsigned bytes and the overall result matches the output from
the code above.

Maybe we'll see a smaller fowl soon :slight_smile:

daz

thank you very very much. I've been struggling with a problem in the
graphics library I'm using for lisp (lispworks capi library) which requires
me to generate a bitmap file from an array of pixels. I couldn't decipher
any of the specs I've found for the format because they go into loads of
extraneous detail about color tables and compression which I don't need to
know about. Your code is the clearest definition of the spec I need
(assuming it's correct). So thanks

···

On 10/12/05, Harold Hausman <hhausman@gmail.com> wrote:

Hi,

Best quiz yet. Er, well, quiz which held my attention longest anyway. :slight_smile:

My solution is um, less... elegant, than some of the others, but in a lot
of
ways, like a parent who mistakenly thinks their ugly child is cute I kinda
like it. I don't really share my code a lot (maybe for obvious reasons)
but
I'm just so pleased with how easily ruby lets me hack things to high
heaven
and this one in particular makes me smile. Take special note that it only
works on 24 bit .bmp files and put your hard hat on if you think you're
going to feed anything but that into it. :wink: Okay, enough blather, without
further ado, the first code I've shared with you guys:

#It only supports 24bit bmp files, and it even chokes on most of them :wink:
#It creates one character per pixel (which has obvious implications)
#But it's 40 lines of pure ruby no lib use binary file up-hackery...
#And quite frankly, thats what I do.

MyPixel = Struct.new( 'MyPixel', :r, :g, :b )

the_gradient = %w|D Y 8 S 6 5 J j t c + i ! ; : .|
###############PUT YOUR FILENAME
HERE#########################################
the_file = File.new('ducky.bmp', 'rb')
the_file.read(2) #BM
the_file.read(4).unpack('V')[0] #filesize
the_file.read(4) #unused
the_file.read(4).unpack('V')[0] #offset from beginning to bitmap data
the_file.read(4).unpack('V')[0] #size of bitmap header
image_x = the_file.read(4).unpack('V')[0] #width x in pixels
image_y = the_file.read(4).unpack('V')[0] #height y in pixels
the_file.read(2).unpack('v')[0] #planes?
the_file.read(2).unpack('v')[0] #bits per pixel
the_file.read(24) #unused

the_bitmap =
puts "CRRRRUNCHHHH --- please wait, reading file..."
image_y.times do |row|
the_bitmap[row] =
image_x.times do |col|
the_bitmap[row][col] = MyPixel.new( 0, 0, 0 )
the_bitmap[row][col].b = the_file.read(1).unpack('c')[0]
the_bitmap[row][col].g = the_file.read(1).unpack('c')[0]
the_bitmap[row][col].r = the_file.read(1).unpack('c')[0]
end
end

puts "output coming:"
the_output = File.new('output.asciiart', 'w')
(image_y-1).downto(0) do |row|
image_x.times do |col|
the_avg =
(the_bitmap[row][col].b+the_bitmap[row][col].g+the_bitmap[row][col].r)/3
the_output.write(the_gradient[the_avg>>4])
end
the_output.write("\n")
end

Man, the output of this is very cool with large files and tiny font
sizes. Excellent.

···

On 10/11/05, Harold Hausman <hhausman@gmail.com> wrote:

Hi,

Best quiz yet. Er, well, quiz which held my attention longest anyway. :slight_smile:

My solution is um, less... elegant, than some of the others, but in a lot of
ways, like a parent who mistakenly thinks their ugly child is cute I kinda
like it. I don't really share my code a lot (maybe for obvious reasons) but
I'm just so pleased with how easily ruby lets me hack things to high heaven
and this one in particular makes me smile. Take special note that it only
works on 24 bit .bmp files and put your hard hat on if you think you're
going to feed anything but that into it. :wink: Okay, enough blather, without
further ado, the first code I've shared with you guys:

Harold Hausman wrote:

Hi,

[...] the first code I've shared with you guys:

Hi Harold - and thanks for doing that.

Yes, a really nice solution.

...

Maybe we'll see a smaller fowl soon :slight_smile:

I am not sure if you meant golfing by "a smaller fowl", but anyway here are my attempts:

The first version version is just a refactoring like yours:

GRADIENT = %w|D Y 8 S 6 5 J j t c + i ! ; : .|
file = File.new(ARGV.shift || "ducky.bmp", "rb")
file.read(2+4+4+4+4) # headers
image_x, image_y = file.read(8).unpack("VV") # width / height
file.read(2+2+24) # headers

puts((0...image_y).collect do |row|
   (0...image_x).collect do |col|
     GRADIENT[(file.read(3).unpack("CCC").inject { |a,b| a+b } / 3) >> 4]
   end.join
end.reverse)

It writes to stdout and optionally uses ARGV.shift as input.

And here are two different short version, they need ARGV[0] and also write to stdout:

f=open$*[0],"rb";w,h=f.read(54)[18,8].unpack"VV"
puts((1..h).collect{(1..w).collect{"DY8S65Jjtc+i!;:."[f.read(3).unpack(
"CCC").inject{|a,b|a+b}/48,1]}.join}.reverse)

d=IO.read$*[0];puts d[54..-1].scan(/.../m).map{|s|"DY8S65Jjtc+i!;:."[s.unpack(
"CCC").inject{|a,b|a+b}/48,1]}.join.scan(/.{#{d[18,4].unpack"V"}}/).reverse

The second one might be problematic on Windows (I am not sure if IO.read reads binary or not).

Dominik

···

On Wed, 12 Oct 2005 14:07:08 +0200, daz <dooby@d10.karoo.co.uk> wrote:

Harold Hausman wrote:
> Hi,
>
> [...] the first code I've shared with you guys:

Hi Harold - and thanks for doing that.

Hey, np, I'm glad I did now! (:

> #But it's 40 lines of pure ruby no lib use binary file up-hackery...

Excellent.
I refactored a bit:

...snip your most excellent code...

There's one change in effect from your original and I suspect
you may have intended it differently ...

the_file.read(1).unpack('c')[0]

.... gives a signed byte so, when you take the average by adding and
dividing by 3, you can be adding negatives. Replacing those with ('C')
gives you unsigned bytes and the overall result matches the output from
the code above.

Ah, great point. I was vaguely wondering where the solarization effect was
coming from.
Unfortunately my attention span is painfully short. :wink:

Maybe we'll see a smaller fowl soon :slight_smile:

But what of the majesty of the whole thing?! (:

daz

···

On 10/12/05, daz <dooby@d10.karoo.co.uk> wrote:

I had trouble installing the RMagick gem, so I went ahead and did a bmp reader.
In retrospect, it probably would have a better use of my time to
figure out what was wrong with the install.
My biggest gotcha in writing the BMP reader was forgetting about the
padding bytes in the raw data. I made the mistake of doing my early
tests with an 80x80 square file, which worked fine without handling
padding. Oh, and unpack is weird. Why can't I extract bits and
nibbles as integers instead of strings?

···

On 10/11/05, Dave Burt <dave@burt.id.au> wrote:

Harold Hausman:
#It only supports 24bit bmp files, and it even chokes on most of them :wink:
(If I was going to solve this quiz, I'd have done a BMP-reader.)

---
# iview.rb
# Adam Shelly
# for ruby quiz #50
#usage iview file [screenwidth] [threshold] [disable_optimization]
# Displays BMP files as ascii art. resizes to screenwidth (default=80)
# threshold controls edge sensitivity. Lower for more detail, raise
for less. (default 500)
# File must be BMP.
# supports bit depths of 2,4,8,24
# maybe 16, but I didn't test any
# converts image to greyscale, resizes to screenwidth, does sobel edge
detection, displays edges as 'x'
# unless disable_optimization is non-nil, re-runs the edge detector
several times to improve pixel density
require 'Matrix'

class BMFile
    def initialize filename
        @f = File.open(filename, "rb")
    end
    def read size, spec
        @f.sysread(size).unpack(spec)
    end
    def parse spec
        rslt = spec.inject({}){|h,v| h[v.first]=read(v.last,
v.last==2?'S':'L').first; h}
        rslt.each {|tag,v| puts "Read #{tag} = #{v}"} if $DEBUG
        rslt
    end
end

class BmpView
    attr_reader :show
    FileHeaderSpec = %w( type size reserved offset).zip [2,4,4,4]
    InfoHeaderSpec = %w( size width height planes bpp compression
        imgSize xppm yppm colorsUsed clrimp).zip [4,4,4,2,2,4,4,4,4,4,4]

    def initialize filename, screenwidth = 80
        @file = BMFile.new filename
        file_h = @file.parse FileHeaderSpec
        info_h = @file.parse InfoHeaderSpec
        throw "#{filename} is Not a BMP file: #{file_h['type']}" if
file_h['type'] != 19778 #=='BM'
        @width,@height = info_h['width'], info_h['height']
        @bpp = info_h['bpp']
        @size = (@width*@height*@bpp/8.0).ceil
        @image = resize( load_data , screenwidth)
        @show = edgefind @image
    end

    def greyscale a
        (a[0]+a[1]+a[2])/3
    end

    def load_ctab #load color table, convert to greyscale right away.
        @ctable = (0...2**@bpp).inject(){|a,v|
a<<greyscale(@file.read(4,"C4"))}
    end

    def calc_padding
            databits = @width*@bpp
            paddingbits = (32-(databits%32)) %32
            width, sparebytes = (databits+paddingbits)/8,paddingbits/8
    end

    def load_data
        puts "loading data..."
        pattern = {1=>"B8",4=>"H2",8=>"C1" ,16=>"L1",24=>"C3"}
        throw "#{@file} is not a Valid BMP file" if !pattern[@bpp]
        rowdata =
        width,sparebytes = calc_padding
        if @bpp < 24
            load_ctab
            @height.times do
                line = @file.read(width, pattern[@bpp]*width)
                line = line.map{|s| s.split(//)}.flatten if @bpp < 8
#separate all the values
                sparebytes.times { line.pop }
      #reject the padding
                rowdata << line.map {|s| @ctable[s.to_i]}
            end
        else
            @height.times do
                rowdata << (0...@width).inject(){|a,v|
                    a<< greyscale(@file.read(3, pattern[@bpp]))
                }
                sparebytes.times {@file.read(1,"C")} #slurp padding
            end
        end
        Matrix.rows(rowdata.reverse,false)
    end

    def resize data, screenwidth
        factor = (@width / screenwidth.to_f).ceil
        @width /= factor; @height /= factor
        newdata = Array.new(@height){ Array.new(@width) }
        puts "Resizing by #{factor} to #{@width}x#{@height}... "
        @height.times { |y|
            @width.times { |x| sum = 0;
                grid = data.minor(y*factor,factor,x*factor,factor)
                grid.to_a.flatten.each{|e|sum+=e} #take average over square
                newdata[y]=sum/factor
            }
        }
        Matrix.rows(newdata,false)
    end

    def edgefind data
        puts "Finding Edges..."
        @output = ""
        gx =Matrix.rows [[-1,0,1],[-2,0,2],[-1,0,1]] #sobel convolution kernels
        gy = Matrix.rows [[1,2,1],[0,0,0],[-1,-2,-1]]

        1.upto(@height-2) {|y|
            1.upto(@width-2) {|x|
                sumX,sumY = 0,0
                v = data.minor((y-1)..(y+1),(x-1)..(x+1)).row_vectors
                3.times do |i|
                    gx.row(i).each2(v[i]) {|a,b| sumX += a*b}
                    gy.row(i).each2(v[i]) {|a,b| sumY += a*b}
                end
                @output += ((sumX.abs+sumY.abs) > $threshold) ? 'x' : ' '
            }
            @output+="\n"
        }
        @output
    end

    def optimize
        8.times do #if it doesn't get better in 8 tries, give up...
            density = @show.count('x') / (@width*@height).to_f
            break if (0.12 .. 0.33) === density #rough heuristic
            puts show,density,$threshold if $DEBUG
            @show = edgefind @image
            $threshold *= density / 0.2
        end
    end
end

$threshold = (ARGV[2]|| 500).to_i
b = BmpView.new(ARGV[0]||"ducky.bmp", ARGV[1]||80)
b.optimize unless ARGV[3]
puts b.show

---
$ ruby iview.rb ducky.bmp
loading data...
Resizing by 7 to 71x78...
Finding Edges...
                 xxxxxxxxxxxxxxxxx
                xxxxxx xxxxx xxxxxx
               xxxxx xx xxxxx
              xxxx xxxxx
             xxxx xxx
             xxx xxxx
            xxxx xx xxx
            xxx x xxxx
           xxx xxx
           xxx xxx
           xxx xxx
          xxx xxx
         xxxx xxx
         xxx xxxx xxx
        xxxxxxxxx xxx
        xxxxxxxxxx xxx
       xxxxxxx xxx xxx xxx
       xxx xxxxxxx xxxxx xxx
       xxx xxxxxx xxxxxxx xxx
       xxx xxxxx xxxxxxxxx xxx
       xxx xxxxx x xx xxx xxx
        xx xxxxx xxxxxxxxx xxx
        xxx xx xxxxxxxx xxx
        xxx xxxxxxxxxx xxxxxxxx xxx
        xxxxxxxxxxxxxxxxx xxxxxxx xxx
         xxxxxxxxxxxxxxxxxxxxxxx xxx xxxxx
         xxxxx xxxxxxxx xxxx xxxxxxxx
          xxxx xxxxxx xxx xxxxxx xxxx
           xxx xx xxxxx xxxx xxxxxx xxx
           xxxx xxx xxx xxxx xxxxxxxx x xxx
            xxx xxxxx xxxx xxxxxxxxxxxxxxxxxxxx xxxxx
            xxx xxxx xxxx xxxxxxxxxxxxxxxxx x xxx
            xxx x xxxx xxxxxxxxxxxxxxx xxxx
          xxxxxx xxx xxxxxxxxx x xx
         xxxxxxxxx xxxx xxx xxx xx
        xxxxxxxxxxxxxxxxxx xxx xxxxxx x
       xxxx xxxxxxxxxxxx xxx xxxxxx x
      xxxx xxxxxx x x xx xxxxxxx x
     xxxx xxxxxx xxxxxxxxxx x
    xxxx xxxxx xxxxxxxxxx x
   xxxx xxxxxx xxxxxxxxxx x
  xxxx xxxxxx xxxxxxxxxxxxxxxx x
  xxx xxxxxxx xxxxxxxxxxxxxxx x
xxx xxxxxxxxxxxxxxxxxxxx x x xx
xxx xxxxxxxxxxxxxxxxxx xx x xx
xxx xxxxxxxxxxxxxxxxx x x xxx
xxx xxxxxxxxxxxxxx x xxx
xx xxxx x xxx x xx xxxx
xx xx x xxx
xx xxxx
x x xxx
x x xxxx
x xxxx
x xxx
x xxxx
x xxxx
x xxxx
x xxxx
xx xxxxx
xx x xxxxx
xx xxxxx
xxx xxxxx
xxx xxxxx
xxxx xxxxx
xxx xxxxx
xxxx xxxxxxx
  xxxx xxxxxx
  xxxxx xxxxxx
   xxxxx xxxxxxx
    xxxxxx xxxxxxx
     xxxxxxx xxxxxxxx
      xxxxxxxx xxxxxxxx
        xxxxxxxxx xxxxxxxx
         xxxxxxxxxxxx xx xxxxxxxxx
           xxxxxxxxxxx xxxxxxxxxx
             xxxxxxxxxxxxxxxxxxxxxxxxx

$ ruby iview.rb toumb.bmp
loading data...
Resizing by 7 to 77x108...
Finding Edges...
Finding Edges...
Finding Edges...
                                                      xx
                                                          xxx
                                                     xxx xx xx
                                                          xx xxx
                                                            xxxx
                                      x x xx xx
                                     xxxx xxxxx
                                     xxxx xx xx
                   xxxx xxxx xxxxx
                xxxxxxx xxxx x xxxx
               xx x xx xxxxxxxx xxxx
               x x xxxxxxxxx xx xx
               x xx xxxxxxxxxx xxxxx
               xx xx xx xxxxxxx xxxx
               xx xx xx xxxxxxx x xx x
               xxx xxxxxx xx xxx xxx xx x
               xxx xxxxxxx xxxxxxxxxxxx xxxx xx xx
               xxx xx xxxx xxxxxxxxxxxxxx xxxxxx xxxxx
               xxx xx xxx xxxxxxx xxxxx xxxxxxxxx xxxx
               xxx xx xxx xxxxx x xxxx xxx xxxx x xx
               xx xx xxx xxxxxxxxx xxxxxx xxx xxxx
               xx xx xxx xxxx xxx xxxxxx xxx xxxx
               xx xxx xxx xxx xx xxxxx xxx xxxx
               xx xxx xxx xxx xx xx xxxx xxxx
              xxx xxxxxxx xxxxxxx xxxxx xxxx
             x x xxxxxx xxxxxxx x xxx xxxx
               xxx xxxxxx xxxxxxx x xxxx xxx
              x xxxxxxxx xxxx x xxxx x x
         x xx xxxxxxxx xxxx x xxxxxx xxxx
         x xxxxxxxxxx xxx x x xxxxx xxxx
         x xxxxxxxxxx xx x x xxxxx xxxx
         xx x xxxxxxxxxxxx xxx x xx xxxxx xxxx
        xxxxxx xxxx xxxxxx xxx x xxxx xx x x
       xxxxxxxxxx xxxxxxxx xxxxx xxxx xx xxx
      xxxx xxxxxx xxxxxx xxxx xxx xx xxx xxxx
     xxxxx xxxxxx xxxxxx xxx xxxxxxxx xxx xxxx
     xxx xxxxx xxxxxx xxxxxxxxxxxx xxxx xxxx
   xxxxx x xx xxxxxx xxxxxxx xx x x x xx x x
  xxxxxx xx xxxxxxxxx x xxxx x x xxxx xx x
  xxxxxxxxx xx xxxxxxx xxx x xxxx x x
  xxxxxx xxx xxxxxxx xxxx xxxxxxxxxx x x
   xx xx xxx xxxxxxx xxxxxxxxxxxxxxxxx xxx
   xxxxx xx xxxxxxx x xxx xxxxxx xxxx x x
   x xxx x xxxxxxxxxx xxxxxxxxx x x
   x xxx xxxxxxxx xxxxxxx xxxx xxxx x xx
   x xxx xxxxxxx xxxxxx xxxxxxxxxx xxxxxxx
     xxx xxx x xxxxxx xxxxxxxxxxxx x x xxx
     xxx xxx x xxxxxxxxx xx xxxxxx
     xxx xxx xxxxxxxx xxx xxxx
      xx xx xxx xx x xx
      xxx xxxxxx xxx xxx xx
      xxxxxxxxxxxx x x xxx xx xx
       xxxxxxxxxxx xx x xxxx xx x xx
       xxxxxxx xx xxxxx x x xx
        x xxxx xxx xxxxxx x xx
             x xx x xxxxx xxx xx
           x xx xxx xxx xx xx x xx
             xxxxxx xx xxx xxxxx xx x xx
     x xxxxxxxxx xx xxx xxx x xxxxx xx
          xxxxxxxxxx x xx xxxxxx xxxx xx
         xxxxx xxx xx xxxxx xxx x xx
         xxxx xxx x xxx x xxx x xx
         xxxxx xxx x xxx x xxx x x
          xxxx xxx x xxx x xxxx x x
          xxxxx x xxx xxx xxxxx x xxx
          xxxxxx xxxxx xxx xxxxxx x x xx
          xxx xx xxxxx xxx xxxxxxx x xxxx
           xx xxx xxxxx xxx xxxxxx x xxxxx
           xxx x xxxxx xxx xxxxx x xxxxx
           xxxx x xxxxx xxx xxxxx xxx xxxx
           xxxx xx xxxxxx xxx xxxx x xxxx
            xxx x xxxxx xxx xxxx x xxxxxxx
            xxx x xxxxx xxx xxxx x xxxxxx
            xxx xxxx xxxx xxxxx xx xxxxxxxx
             xx xxxxxxxx xxxxx xxx x xxx xx
             xxx xx xxxxxx xxxxx xxxx xxx xx
             xxx x xxxxx xxxxx xxxxx xxxxxx
              xx x xx xx xxxxx xxxxx xxxxxx
              xxx x xxxxx xxxxx xxxxxx xxxxxx
               xx xxxx xxxx xxxxxxxxx xxxxxx
               xxx xxxxx xxxxxxxxx xxxxx
               xxx xxxxx xx xxxxxx xxxxx
                xxx xxxxxx x xxx xxx xxxxx
                xxx xxxxx xx xxxxxxx xxxxx
            x xx xxxxxx xxx xxxxx xx xxxx
                 xxx xxxxx xxxxxxx xxxx xx
                 xxx xxxxxx xx xxxxx x xxxx
                  xx xxxxxx xxx xxxx xxxxxx
                  xxx xxxxxxxxx xxxxxxx xxxxxx
                  xxx xxxxxxxxxxxxx xxxxxxx xx xxx
                   xxxxxxxxxx xxxxx xxxx xx xx x x
                   xxxxxxxx xxxxxx xxxxxx x xxxx x
                     xxx xx xxx xx xxxx xxxxxx
                             xx xxx xx xxx xxx xxx
                             xx xxx xx x x xxx
                             xxxxxx xxx xx xx xx
                            xxxxxxx xxxxx x xxx
                            xxxxxx xxxxx xx
                           x xxxxx xxx xx xx
                          xx xxxxx xxxxxxxxxx
                          x xxx xxx xx x
                          x xxx x xxxxx x
                          x x xxxx xxx xxxxxxx
                          xxxxxxxx xxxx xxxxxxx
                          xxxxx xx xx xxx xxxx
                          xxxxx x xxxxxxx

-Adam

Harold Hausman wrote:

  [...]
> Maybe we'll see a smaller fowl soon :slight_smile:

But what of the majesty of the whole thing?! (:

I can't really judge when just two eyes or the beak
fill the screen in 1280x1024 resolution :stuck_out_tongue:

Turning my monitor towards the window and viewing
from the end of my garden helps ;))

( Wilson's idea of using a small font was good. )

Certainly majestic !

daz

···

On 10/12/05, daz wrote:

Dominik Bathon wrote:

> Maybe we'll see a smaller fowl soon :slight_smile:

I am not sure if you meant golfing by "a smaller fowl", [...]

I'd just like to be able to see the whole image without needing
to project it onto the side of a tower block, first :wink: ...
.... but golfing's OK ...

[...]
GRADIENT[(file.read(3).unpack("CCC").inject { |a,b| a+b } / 3) >> 4]

I abandoned a similar construct after finding that String# is
quicker than short String#unpack sequences. Unpacking the whole
string is very quick but then Array# is needed later.
Mine is still messy, though.

[...]
end.reverse)

Yes, I should have had the courage to reverse instead of maintaining
a pointer.

And here are two different short version, they need ARGV[0] and
also write to stdout:
     ['snip']*2

Dominik

I won't try to compete :slight_smile:

Cheers,

daz

···

On Wed, 12 Oct 2005 14:07:08 +0200, daz wrote: