Format and link fix 2000/bmeyer, update .gitignore

This commit is contained in:
Cody Boone Ferguson committed 2023-04-19 12:43:05 -07:00
1 parent ea79092508
commit acdb26d5c4
4 files changed
+82 -93

No files matched your search

+1
View File
@@ -1 +1,2 @@
bmeyer bmeyer
lavabus.glic
+79 -91
View File
@@ -1,11 +1,11 @@
# Best Utility # Best Utility
Bernd Meyer Bernd Meyer
Monash University, Melbourne, Australia Monash University, Melbourne, Australia
1/832 Blackburn Rd 1/832 Blackburn Rd
Clayton, VIC 3168 Clayton, VIC 3168
Australia Australia
http://byron.csse.monash.edu.au/ <https://web.archive.org/web/20030212213342/http://byron.csse.monash.edu.au/realindex.html>
## To build: ## To build:
@@ -27,7 +27,7 @@ In a video window (white text on black background):
./bmeyer < michael.pgm > michael.glic ./bmeyer < michael.pgm > michael.glic
``` ```
Compare the michael.pgm to the screen output. Compare the `michael.pgm` to the screen output.
To test that you are compressing and decompressing the same way the To test that you are compressing and decompressing the same way the
author was, try: author was, try:
@@ -42,8 +42,8 @@ Also try in a reverse video window:
./bmeyer < michael.pgm 2>/dev/null | ./bmeyer > new.pgm ./bmeyer < michael.pgm 2>/dev/null | ./bmeyer > new.pgm
``` ```
Compare the michael.pgm to the screen output. Compare the new.pgm file Compare the [michael.pgm](michael.pgm) to the screen output. Compare the
to the michael.pgm file. `new.pgm` file to the [michael.pgm](michael.pgm) file.
Create a large reverse video xterm, say 200 columns wide and try: Create a large reverse video xterm, say 200 columns wide and try:
@@ -63,7 +63,8 @@ Decompress that smaller glic-file:
./bmeyer -2 200 < lavabus.glic2 > new.pgm ./bmeyer -2 200 < lavabus.glic2 > new.pgm
``` ```
Compare the new.pgm file to the lavabus.pgm file by viewing them. Compare the `new.pgm` file to the [lavabus.pgm](lavabus.pgm) file by viewing
them.
## Judges' remarks: ## Judges' remarks:
@@ -94,25 +95,23 @@ to set your FPU to use 64 bit mode. See the extra build lines
in the Makefile, and read the author's remarks below. in the Makefile, and read the author's remarks below.
If you cannot work out how to get into 64 bit mode, you can If you cannot work out how to get into 64 bit mode, you can
try using -ffloat-store if you compile with GCC (this may have try using `-ffloat-store` if you compile with GCC (this may have
a performance penalty). The resulting binary will have a good a performance penalty). The resulting binary will have a good
chance to produce portable files, but due to the resulting chance to produce portable files, but due to the resulting
double-rounding (first internally to 80 bit, then to 64 bit double-rounding (first internally to 80 bit, then to 64 bit
on writing the value to memory), there is a small but very real on writing the value to memory), there is a small but very real
chance any given file produced might not be portable. chance any given file produced might not be portable.
The makefile defaults to -O3 and no `asm()` call. The [Makefile](Makefile) defaults to `-O3` and no `asm()` call.
## Author's remarks: ## Author's remarks:
GLICBAWLS This program is called `GLICBAWLS`
A) Function #### Function
===========
"GLICBAWLS" stands for: `GLICBAWLS` stands for "Grey Level Image Compression By Adaptive Weighted Least
Squares".
"Grey Level Image Compression By Adaptive Weighted Least Squares".
And that's exactly what this program does --- feed it a .PGM file And that's exactly what this program does --- feed it a .PGM file
(either raw [i.e. P5] or ascii [i.e. P2]) on stdin, and it will (either raw [i.e. P5] or ascii [i.e. P2]) on stdin, and it will
@@ -131,7 +130,7 @@ and then
./bmeyer < michael.glic > michael.decoded.pgm ./bmeyer < michael.glic > michael.decoded.pgm
``` ```
As it turns out, glicbawls compresses greyscale images (or, more As it turns out, `glicbawls` compresses greyscale images (or, more
precisely, "natural" greyscale images) better than any other precisely, "natural" greyscale images) better than any other
program I am aware of (with the exception of the not-yet-published program I am aware of (with the exception of the not-yet-published
program developed for my PhD thesis). Of course, this might take program developed for my PhD thesis). Of course, this might take
@@ -142,25 +141,25 @@ output to stderr (assuming white text on black background). If you
have trouble recognizing the image, try squinting at it ;-). have trouble recognizing the image, try squinting at it ;-).
If you still have trouble, simply use a terminal or xterm with If you still have trouble, simply use a terminal or xterm with
more than 80 columns, and tell glicbawls about it by giving the more than 80 columns, and tell `glicbawls` about it by giving the
number of columns as an argument. For example number of columns as an argument. For example
```sh ```sh
./bmeyer 260 <lavabus.pgm >lavabus.glic ./bmeyer 260 <lavabus.pgm >lavabus.glic
``` ```
will allow glicbawls to use up to 260 columns, which makes things will allow `glicbawls` to use up to 260 columns, which makes things
much more recognizable. much more recognizable.
Still running out of space? Need to compress those images just a Still running out of space? Need to compress those images just a
tad more? And maybe you can handle some loss due to the tad more? And maybe you can handle some loss due to the
compression? If so, you can use glicbawls' "near lossless" compression? If so, you can use `glicbawls`' "near lossless"
compression mode. In that mode, the decoded pixel values are compression mode. In that mode, the decoded pixel values are
allowed to differ from tbe originals, but there is an upper limit allowed to differ from the originals, but there is an upper limit
on the magnitude of the difference. For example, if a maximum on the magnitude of the difference. For example, if a maximum
error of 2 is allowed, an original pixel value of 37 could be error of 2 is allowed, an original pixel value of 37 could be
decoded as 35,36,37, 38 or 39. In order to use this mode, simply decoded as 35,36,37, 38 or 39. In order to use this mode, simply
give the maximum allowed error as an argument, with a dash ('-') give the maximum allowed error as an argument, with a dash (`-`)
before it. For example before it. For example
```sh ```sh
@@ -183,8 +182,8 @@ terminal for the progress display, and
will decompress the result on such a terminal. will decompress the result on such a terminal.
But wait, there is more --- you can also feed glicbawls .PPM files But wait, there is more --- you can also feed `glicbawls` .PPM files
(i.e. colour images), raw or ascii, your choice. Glicbawls will (i.e. colour images), raw or ascii, your choice. `Glicbawls` will
compress and decompress them just fine. However, it only does compress and decompress them just fine. However, it only does
"reasonably well" on them; It beats PNG easily, but there are "reasonably well" on them; It beats PNG easily, but there are
certainly programs out there that can compress colour images certainly programs out there that can compress colour images
@@ -192,61 +191,54 @@ considerably better. And don't even *think* about using it for
so-called "artistic" images (i.e. anything that wasn't scanned so-called "artistic" images (i.e. anything that wasn't scanned
from a photo or camera).... from a photo or camera)....
***************************************************************** ### WARNING
* *
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING *
* * `Glicball` is rather CPU and FPU intensive. Don't run it on anything slow.
* * Things start to be usable around 300+MHz, with 600+ being highly desirable.
* Glicball is rather CPU and FPU intensive. Don't *
* run it on anything slow. Things start to be *
* usable around 300+MHz, with 600+ being highly *
* desirable. *
* *
*****************************************************************
B) Compile Instructions
=======================
Unlike most compression program, glicbawls makes heavy use of ### Compile Instructions
Unlike most compression program, `glicbawls` makes heavy use of
floating point maths --- and not all FPUs are created equal. Most floating point maths --- and not all FPUs are created equal. Most
importantly, the x86 and 68k FPUs use 80 bit floating point importantly, the x86 and 68k FPUs use 80 bit floating point
formats internally, while most other processors use IEEE 64 bit formats internally, while most other processors use IEEE 64 bit
formats by default. If not taken care of, this means that a formats by default. If not taken care of, this means that a
glicbawls file compressed on one CPU cannot generally be `glicbawls` file compressed on one CPU cannot generally be
decompressed on another. decompressed on another.
Fortunately, just about all current FPUs can be put into IEEE 64 Fortunately, just about all current FPUs can be put into IEEE 64
bit mode (or at least something close enough for bit mode (or at least something close enough for
glicbawls). Unfortunately, there is no standard way of doing `glicbawls`). Unfortunately, there is no standard way of doing
so. For this reason, the build file contains *three* compile so. For this reason, the build file contains *three* compile
lines; One for machines that already use 64 bit mode by default lines; One for machines that already use 64 bit mode by default
(most RISC processors), one for linux/x86 machines using libc4, (most RISC processors), one for linux/x86 machines using libc4,
libc5 or glibc2.0, and one for linux/x86 machines using glibc2.1 libc5 or glibc2.0, and one for linux/x86 machines using glibc2.1
(glibc2.1 no longer exports the __setfpucw function, necessitating (glibc2.1 no longer exports the `__setfpucw()` function, necessitating
the use of gcc inline assembly. *Grumble*). the use of gcc inline assembly. \*Grumble\*).
So, if you are building on a machine that does not, by default, So, if you are building on a machine that does not, by default,
use IEEE 64 bit floating point doubles, you'll have to define Y to use IEEE 64 bit floating point doubles, you'll have to define `Y` to
be a command that switches it into that mode. If you fail to do be a command that switches it into that mode. If you fail to do
so, your glicbawls executable will still be able to decompress its so, your `glicbawls` executable will still be able to decompress its
own compressed files, but you may be unable to exchange files with own compressed files, but you may be unable to exchange files with
glicbawls on other machines. `glicbawls` on other machines.
C) Obfuscation ### Obfuscation
==============
Most of the obfuscation of this program was driven by the Most of the obfuscation of this program was driven by the
desperate struggle to fit all of glicbawls' features into code desperate struggle to fit all of `glicbawls`' features into code
that fits the IOCCC's size limits. All identifiers names are that fits the IOCCC's size limits. All identifiers names are
single-character, which was only possible by ruthless exploitation single-character, which was only possible by ruthless exploitation
of scope. There is a function M() that handles nearly all input of scope. There is a function `M()` that handles nearly all input
from stdin, handles all output to stdout, and also recursively from stdin, handles all output to stdout, and also recursively
calculates one of the mathematical expressions needed for error calculates one of the mathematical expressions needed for error
modelling. There is a function that calculates (A^(-1)*b)*x with A modelling. There is a function that calculates `(A^(-1)*b)*x` with `A`
a matrix and b and x being vectors, and does so in a very being a matrix and `b` and `x` being vectors, and does so in a very
efficient way --- but one would be hard pressed to find it. There efficient way --- but one would be hard pressed to find it. There
is an arithmetic coder that is even less recognizable. A lot of is an arithmetic coder that is even less recognizable. A lot of
loop variables don't get initialized, but instead the code is loop variables don't get initialized, but instead the code is
@@ -257,7 +249,7 @@ meaning all the time, and the differences between compressing and
decompressing are handled in rather subtle ways all over the decompressing are handled in rather subtle ways all over the
program. The string that holds the ascii values for displaying the program. The string that holds the ascii values for displaying the
progress image doubles as a description on how to find a pixel's progress image doubles as a description on how to find a pixel's
causal neighbours. And then there are a few #define's that really causal neighbours. And then there are a few `#define`s that really
are just in there to save a few characters, but as an added are just in there to save a few characters, but as an added
"benefit" make the source ever more unreadable. "benefit" make the source ever more unreadable.
@@ -265,31 +257,30 @@ In short --- running it through the preprocessor and the
pretty-printer will give you something that looks slightly less pretty-printer will give you something that looks slightly less
like line noise and slightly more like a C program, but unless you like line noise and slightly more like a C program, but unless you
are a true wizard, it is unlikely to gain you any insights into are a true wizard, it is unlikely to gain you any insights into
what is actually going on....[0] what is actually going on....\[0\]
D) Bugs, Assumptions and TODOs ### Bugs, Assumptions and TODOs
==============================
Glicbawls assumes that characters are 8 bit wide, and that the `Glicbawls` assumes that characters are 8 bit wide, and that the
character set used is ASCII. If one of these isn't true, all hell character set used is ASCII. If one of these isn't true, all hell
will break loose. will break loose.
The .PGM headers are not checked very thoroughly --- glicbawls The .PGM headers are not checked very thoroughly --- `glicbawls`
will happily try to encode lots of files that it shouldn't will happily try to encode lots of files that it shouldn't
touch. The old adage of "garbage in, garbage out" holds in that touch. The old adage of "garbage in, garbage out" holds in that
case. Furthermore, even if glicbawls detects an incorrect input, case. Furthermore, even if `glicbawls` detects an incorrect input,
it fails to provide a meaningful error message, and instead it fails to provide a meaningful error message, and instead
simply aborts. simply aborts.
When decompressing a near-losslessy encoded image, the maximum When decompressing a near-lossless encoded image, the maximum
allowed error is required as a command line parameter. This should allowed error is required as a command line parameter. This should
really be saved in the compressed file! really be saved in the compressed file!
Glicbawls relies on the decimal representation of all integers `Glicbawls` relies on the decimal representation of all integers
having less than 255 digits. While ANSI C does not guarantee this, having less than 255 digits. While ANSI C does not guarantee this,
it seems rather unlikely that anyone in the foreseeable future it seems rather unlikely that anyone in the foreseeable future
would use images with 10^255 rows, columns or different levels of would use images with `10^255` rows, columns or different levels of
grey. Also, it is assumed that any integer used can be cast to a grey. Also, it is assumed that any integer used can be cast to a
double and back without loss of precision. This limits the number double and back without loss of precision. This limits the number
of rows, columns and grey levels to 9 quintillion, which should of rows, columns and grey levels to 9 quintillion, which should
@@ -302,14 +293,13 @@ million in a lottery. But if it happens to you, don't say I
didn't warn you! Instead, go out and buy a lightning rod and a didn't warn you! Instead, go out and buy a lightning rod and a
lottery ticket ;-) lottery ticket ;-)
At one point, a pointer to int is used as the target of a "%1[#]" At one point, a pointer to int is used as the target of a `"%1[#]"`
conversion in a scanf, which makes gcc rather unhappy, but conversion in a scanf, which makes gcc rather unhappy, but
shouldn't really cause anyone any trouble. The same goes for a shouldn't really cause anyone any trouble. The same goes for a
couple of assignments which are used as truth values. couple of assignments which are used as truth values.
E) Algorithm ### Algorithm
============
An exhaustive explanation of the algorithm used would go beyond An exhaustive explanation of the algorithm used would go beyond
the scope of an info file, and would also be quite difficult in the scope of an info file, and would also be quite difficult in
@@ -321,11 +311,11 @@ expected value is calculated by creating a least squares predictor
of order 12 based on all of the previously encoded/decoded of order 12 based on all of the previously encoded/decoded
pixels. However, the contribution of each pixel is weighted pixels. However, the contribution of each pixel is weighted
according to its Manhattan-distance from the current pixel, according to its Manhattan-distance from the current pixel,
D. That weight used is pow(0.8,D). [1][2][3] D. That weight used is `pow(0.8,D)`. \[1\] \[2\] \[3\]
In a similar way, the prediction *errors* for all previous pixels In a similar way, the prediction *errors* for all previous pixels
are combined --- a weighted average (with weight pow(0.7,D)) of are combined --- a weighted average (with weight `pow(0.7,D)`) of
the squares of all previous prediction errors is taken, and the the squares of all previous prediction errors is taken, and the
square root of the (appropriately scaled) result is called sigma. square root of the (appropriately scaled) result is called sigma.
@@ -343,22 +333,22 @@ arithmetic decoder provides the information which half the actual
value is in. In both cases, the interval borders are adjusted value is in. In both cases, the interval borders are adjusted
accordingly, the arithmetic coder/decoder updated, and the accordingly, the arithmetic coder/decoder updated, and the
interval halving repeated until the precise value has been interval halving repeated until the precise value has been
en/decoded[4]. en/decoded\[4\].
[0] Yes, this could be seen as a challenge.... [0] Yes, this could be seen as a challenge....
[1] Actually, the weight is pow(0.8,D)/s, where s is the sigma [1] Actually, the weight is `pow(0.8,D)/s`, where `s` is the sigma
used for en/decoding the particular previous pixel. Dividing used for en/decoding the particular previous pixel. Dividing
by s is a rather arbitrary action justified only by the by `s` is a rather arbitrary action justified only by the
improvement in results. Mathematically, I can only justify improvement in results. Mathematically, I can only justify
dividing by s^2, or not dividing at all.... dividing by `s^2`, or not dividing at all....
[2] Obviously, these least squares predictors are not calculated [2] Obviously, these least squares predictors are not calculated
from scratch for each pixel. Some clever reuse of earlier from scratch for each pixel. Some clever reuse of earlier
results allows O(1) calculation, rather than the results allows O(1) calculation, rather than the
O(previous_rows*columns) this description would suggest. `O(previous_rows*columns)` this description would suggest.
[3] As anyone who has ever tried local least squares knows from [3] As anyone who has ever tried local least squares knows from
bitter experience, there is a lot of numerical instability bitter experience, there is a lot of numerical instability
associated with them. So glicbawls adds a bias towards an associated with them. So `glicbawls` adds a bias towards an
averaging predictor to the equation system the least squares averaging predictor to the equation system the least squares
predictor is calculated from. The weight that is given to predictor is calculated from. The weight that is given to
this bias is constantly adjusted throughout coding/decoding, this bias is constantly adjusted throughout coding/decoding,
@@ -370,31 +360,29 @@ en/decoded[4].
iteration ends as soon as the interval is small enough to iteration ends as soon as the interval is small enough to
guarantee decoding within the requested maximum error. guarantee decoding within the requested maximum error.
####################################################################
Photo Credit: ### Photo Credit:
Lavabus was taken by the judge, Landon Curt Noll. Michael was [Lavabus](lavabus.pgm) was taken by the judge, Landon Curt Noll.
provided by the author. Lenna is a 1972 Playboy centerfold. [Michael](michael.pgm) was provided by the author. [Lenna](lenna.glic) is a
1972 Playboy centerfold.
michael.pgm - [michael.pgm](michael.pgm)
The author's Godchild and nephew. The author's Godchild and nephew.
lavabus.pgm - [lavabus.pgm](lavabus.pgm)
A bus that was trapped by lava from Kilauea volcano in A bus that was trapped by lava from Kilauea volcano in Hawaii, USA. Nobody
Hawaii, USA. Nobody was in the bus at the time, BTW. was in the bus at the time, BTW. Photo date: 1981.
Photo date: 1981.
lenna.glic - [lenna.glic](lenna.glic)
A November 1972 Playboy centerfold was scanned in long ago and A November 1972 Playboy centerfold was scanned in long ago and has been used
has been used for image compression research since then. Playboy for image compression research since then. Playboy originally threatened to
originally threatened to prosecute unauthorized use, but prosecute unauthorized use, but eventually granted that, having been in use
eventually granted that, having been in use for image compression for image compression testing for so long, it was now a useful benchmark.
testing for so long, it was now a useful benchmark. (Note: This (Note: This picture doesn't show very much.)
picture doesn't show very much.)
## Copyright and CC BY-SA 4.0 License: ## Copyright and CC BY-SA 4.0 License:
+1 -1
View File
@@ -24,7 +24,7 @@ Arne "Timwi" Heizmann,Arne_"Timwi"_Heizmann,null,null,timwi@gmx.net,Germany,null
Baruch Nissenbaum,Baruch_Nissenbaum,null,null,baruch@eng.tau.ac.il,null,null); Baruch Nissenbaum,Baruch_Nissenbaum,null,null,baruch@eng.tau.ac.il,null,null);
Bas de Bakker,Bas_de_Bakker,null,null,bas@bbwt.demon.nl,null,null); Bas de Bakker,Bas_de_Bakker,null,null,bas@bbwt.demon.nl,null,null);
Ben Lynn,Ben_Lynn,https://crypto.stanford.edu/~blynn/,null,benlynn@gmail.com,null,@bmxlynn); Ben Lynn,Ben_Lynn,https://crypto.stanford.edu/~blynn/,null,benlynn@gmail.com,null,@bmxlynn);
Bernd Meyer,Bernd_Meyer,http://byron.csse.monash.edu.au/,null,bmeyer@cs.monash.edu.au,null,null); Bernd Meyer,Bernd_Meyer,https://web.archive.org/web/20030212213342/http://byron.csse.monash.edu.au/realindex.html,null,bmeyer@cs.monash.edu.au,null,null);
Brent Burley,Brent_Burley,null,null,brent.burley@disney.com,null,null); Brent Burley,Brent_Burley,null,null,brent.burley@disney.com,null,null);
Brian Westley,Brian_Westley,http://www.westley.org,null,brian@westley.org,null,null); Brian Westley,Brian_Westley,http://www.westley.org,null,brian@westley.org,null,null);
Bruce Holloway,Bruce_Holloway,null,null,null,null,null); Bruce Holloway,Bruce_Holloway,null,null,null,null,null);
Can't render this file because it contains an unexpected character in line 23 and column 6.
+1 -1
View File
@@ -837,7 +837,7 @@ Contest </I></FONT></CENTER><BR>
<LI TYPE=square>Best RFC Obfuscation (<A HREF="years.html#1996_rcm">1996 rcm</A>) <LI TYPE=square>Best RFC Obfuscation (<A HREF="years.html#1996_rcm">1996 rcm</A>)
</UL><BR> </UL><BR>
<LI TYPE=none><A NAME="Bernd_Meyer"></A><B><a href="&#x6D;&#x61;&#105;&#108;&#x74;o&#58;&#x62;&#109;&#101;&#121;&#x65;&#x72;&#x40;&#x63;&#x73;.&#109;&#x6F;&#x6E;&#x61;&#x73;&#104;&#46;&#101;&#x64;&#x75;&#x2E;&#x61;&#x75;">Bernd Meyer</a></B> -- <A HREF="http://byron.csse.monash.edu.au/">http://byron.csse.monash.edu.au/</a> <LI TYPE=none><A NAME="Bernd_Meyer"></A><B><a href="&#x6D;&#x61;&#105;&#108;&#x74;o&#58;&#x62;&#109;&#101;&#121;&#x65;&#x72;&#x40;&#x63;&#x73;.&#109;&#x6F;&#x6E;&#x61;&#x73;&#104;&#46;&#101;&#x64;&#x75;&#x2E;&#x61;&#x75;">Bernd Meyer</a></B> -- <A HREF="https://web.archive.org/web/20030212213342/http://byron.csse.monash.edu.au/realindex.html">https://web.archive.org/web/20030212213342/http://byron.csse.monash.edu.au/realindex.html</a>
<UL> <UL>
<LI TYPE=square>Best Utility (<A HREF="years.html#2000_bmeyer">2000 bmeyer</A>) <LI TYPE=square>Best Utility (<A HREF="years.html#2000_bmeyer">2000 bmeyer</A>)
</UL><BR> </UL><BR>