#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include "mcgill.h"
#define eq(a, b) (!strcmp((a), (b)))
#define FALSE 0
#define TRUE 1
#define EC_MODE 1
#define NN_MODE 2
#if !defined(__MWERKS__)
typedef int boolean;
#endif
boolean msb_first = TRUE;
boolean partial_last_scanline;
int compression_mode = NN_MODE;
FILE *fp_out;
int bits;
int max;
double exponent;
double mult = 1.0;
double offset;
double sine_mult;
void
put_pixel(pixel)
unsigned pixel;
{
int ch;
if (pixel > max)
{
fprintf(stderr, "ERROR: pixel value too large: %02x\n", pixel);
exit(1);
}
if (bits > 16)
if (msb_first)
{
ch = (pixel >> 24) & 0xff;
putc(ch, fp_out);
ch = (pixel >> 16) & 0xff;
putc(ch, fp_out);
ch = (pixel >> 8) & 0xff;
putc(ch, fp_out);
ch = pixel & 0xff;
putc(ch, fp_out);
}
else
{
ch = pixel & 0xff;
putc(ch, fp_out);
ch = (pixel >> 8) & 0xff;
putc(ch, fp_out);
ch = (pixel >> 16) & 0xff;
putc(ch, fp_out);
ch = (pixel >> 24) & 0xff;
putc(ch, fp_out);
}
else if (bits > 8)
if (msb_first)
{
ch = pixel >> 8;
putc(ch, fp_out);
ch = pixel & 0xff;
putc(ch, fp_out);
}
else
{
ch = pixel & 0xff;
putc(ch, fp_out);
ch = pixel >> 8;
putc(ch, fp_out);
}
else
putc(pixel, fp_out);
}
void
map_nn(sigma, end)
unsigned *sigma;
unsigned *end;
{
int del;
int x;
int xp;
unsigned *s;
xp = *sigma;
s = sigma + 1;
while (s < end)
{
x = *s;
del = x-xp;
if (del >= 0)
{
if (del <= xp)
*s++ = del << 1;
else
*s++ = x;
}
else
{
if (del >= (xp-max))
*s++ = ((-del)<<1) - 1;
else
*s++ = max-x;
}
xp = x;
}
}
void
random_scanline(pixels_per_block, width)
int pixels_per_block;
int width;
{
unsigned *end;
unsigned *s;
unsigned scanline[8*1024];
int blocks;
int delta;
int high;
int i;
int low;
int pixel;
int x;
if (width > sizeof(scanline)/sizeof(unsigned))
{
fprintf(stderr, "Maximum scanline width exceeded.\n");
exit(1);
}
end = scanline + width;
s = scanline;
while (s < end)
{
x = uni() * 6;
switch (x)
{
case 0:
/*** Random block ***/
for (i = 0; i < pixels_per_block; i++)
{
if (s >= end)
continue;
pixel = uni() * (max+1);
*s++ = pixel;
}
break;
case 1:
/*** block where low <= pixel[i] <= high ***/
pixel = uni() * (max+1);
delta = uni() * 32;
low = pixel - delta;
if (low < 0)
low = 0;
high = low + delta;
if (high > max)
high = max;
delta = high - low + 1;
for (i = 0; i < pixels_per_block; i++)
{
if (s >= end)
continue;
pixel = low + uni() * delta;
*s++ = pixel;
}
break;
case 2:
/*** block where | pixel[i] - pixel[i+1] | <= delta ***/
pixel = uni() * (max+1);
delta = uni() * 128 + 1;
low = pixel - delta;
if (low < 0)
low = 0;
high = low + delta;
if (high > max)
high = max;
delta = high - low + 1;
for (i = 0; i < pixels_per_block; i++)
{
if (s >= end)
continue;
x = uni() * delta;
pixel += x - delta/2;
if (pixel > max)
pixel = max;
else if (pixel < 0)
pixel = 0;
*s++ = pixel;
}
break;
case 3:
/*** Same till end of line ***/
pixel = uni() * (max+1);
while (s < end)
*s++ = pixel;
break;
case 4:
/*** Same till end of line ***/
blocks = ((end - s) + pixels_per_block - 1)/pixels_per_block;
blocks = uni() * blocks + 1;
pixel = uni() * (max+1);
for (i = 0; i < blocks * pixels_per_block; i++)
if (s < end)
*s++ = pixel;
break;
case 5:
/*** low entropy block ***/
/*** where | pixel[i] - pixel[i+1] | <= delta ***/
pixel = uni() * (max+1);
delta = uni() * 8 + 1;
low = pixel - delta;
if (low < 0)
low = 0;
high = low + delta;
if (high > max)
high = max;
delta = high - low + 1;
for (i = 0; i < pixels_per_block; i++)
{
if (s >= end)
continue;
x = uni() * delta;
pixel += x - delta/2;
if (pixel > max)
pixel = max;
else if (pixel < 0)
pixel = 0;
*s++ = pixel;
}
break;
}
}
if (compression_mode == EC_MODE)
map_nn(scanline, scanline + width);
s = scanline;
while (s < end)
put_pixel(*s++);
}
void
random_float_scanline(pixels_per_block, width)
int pixels_per_block;
int width;
{
float scanline[8*1024];
double start;
double step;
double x;
double y;
int i;
if (width > sizeof(scanline)/sizeof(float))
{
fprintf(stderr, "Maximum scanline width exceeded.\n");
exit(1);
}
start = uni();
step = uni()/width;
#if 0
printf("start= %10.7lf\n", start);
printf("step = %10.7lf\n", step);
#endif
x = start;
for (i = 0; i < width; i++)
{
y = sin(x) * sine_mult + offset;
scanline[i] = y;
x += step;
}
fwrite(scanline, width, sizeof(float), fp_out);
}
void
random_double_scanline(pixels_per_block, width)
int pixels_per_block;
int width;
{
double scanline[8*1024];
double start;
double step;
double x;
double y;
int i;
if (width > sizeof(scanline)/sizeof(float))
{
fprintf(stderr, "Maximum scanline width exceeded.\n");
exit(1);
}
for (i = 0; i < 10; i++)
uni();
start = uni();
step = uni()/width;
#if 0
printf("start= %10.7lf\n", start);
printf("step = %10.7lf\n", step);
#endif
x = start;
for (i = 0; i < width; i++)
{
y = sin(x) * sine_mult + offset;
scanline[i] = y;
x += step;
#if 0
printf("%16.13lf\n", y);
#endif
}
fwrite(scanline, width, sizeof(double), fp_out);
}
void
usage(name)
char *name;
{
fprintf(stderr, "Usage: %s [options] bits j lines width output-file\n", name);
exit(1);
}
int
main(argc, argv)
int argc;
char **argv;
{
char *output_file;
int i;
int l;
int lines;
int pixels_per_block;
int width;
for (i = 1; i < argc; i++)
{
if (*argv[i] == '-')
{
if (eq(argv[i], "-chip"))
;
else if (eq(argv[i], "-ec"))
compression_mode = EC_MODE;
else if (eq(argv[i], "-exp"))
{
i++;
exponent = atoi(argv[i]);
}
else if (eq(argv[i], "-ki"))
;
else if (eq(argv[i], "-kz"))
;
else if (eq(argv[i], "-lsb"))
msb_first = FALSE;
else if (eq(argv[i], "-msb"))
msb_first = TRUE;
else if (eq(argv[i], "-mult"))
{
i++;
mult = atoi(argv[i]);
}
else if (eq(argv[i], "-nn"))
compression_mode = NN_MODE;
else if (eq(argv[i], "-p"))
partial_last_scanline = TRUE;
else if (eq(argv[i], "-raw"))
;
else if (eq(argv[i], "-v"))
;
else if (eq(argv[i], "-V"))
;
else
{
usage(argv[0]);
exit(1);
}
}
else
break;
}
if (argc - i != 5)
{
usage(argv[0]);
exit(1);
}
printf("bits=%s\n", argv[i]);
bits = atoi(argv[i+0]);
pixels_per_block = atoi(argv[i+1]);
lines = atoi(argv[i+2]);
width = atoi(argv[i+3]);
output_file = argv[i+4];
if ((fp_out = fopen(output_file, "wb")) == 0)
{
fprintf(stderr, "Could not open output file: %s\n", output_file);
exit(1);
}
if (bits == 32 || bits == 64)
{
sine_mult = pow(2.0, exponent+mult);
offset = pow(2.0, exponent);
printf("offset=%g sine_mult=%g\n", offset, sine_mult);
}
rstart(-time(0), time(0));
max = (1 << bits) - 1;
for (l = 0; l < lines; l++)
{
if (partial_last_scanline && l == lines-1)
width = uni() * (width-1) + 1;
if (bits == 32)
random_float_scanline(pixels_per_block, width);
else if (bits == 64)
random_double_scanline(pixels_per_block, width);
else
random_scanline(pixels_per_block, width);
}
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1