1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
|
/* simple example that shows how zfp can be used to compress pgm images */
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "zfp.h"
int main(int argc, char* argv[])
{
double rate = 0;
uint nx, ny;
uint x, y;
char line[0x100];
uchar* image;
zfp_field* field;
zfp_stream* zfp;
bitstream* stream;
void* buffer;
size_t bytes;
size_t size;
switch (argc) {
case 2:
if (sscanf(argv[1], "%lf", &rate) != 1)
goto usage;
break;
default:
usage:
fprintf(stderr, "Usage: pgm <rate|-precision> <input.pgm >output.pgm\n");
return EXIT_FAILURE;
}
/* read pgm header */
if (!fgets(line, sizeof(line), stdin) || strcmp(line, "P5\n") ||
!fgets(line, sizeof(line), stdin) || sscanf(line, "%u%u", &nx, &ny) != 2 ||
!fgets(line, sizeof(line), stdin) || strcmp(line, "255\n")) {
fprintf(stderr, "error opening image\n");
return EXIT_FAILURE;
}
if ((nx & 3u) || (ny & 3u)) {
fprintf(stderr, "image dimensions must be multiples of four\n");
return EXIT_FAILURE;
}
/* read image data */
image = malloc(nx * ny);
if (fread(image, sizeof(*image), nx * ny, stdin) != nx * ny) {
fprintf(stderr, "error reading image\n");
return EXIT_FAILURE;
}
/* create input array */
field = zfp_field_2d(image, zfp_type_int32, nx, ny);
/* initialize compressed stream */
zfp = zfp_stream_open(NULL);
if (rate < 0)
zfp_stream_set_precision(zfp, (uint)floor(0.5 - rate));
else
zfp_stream_set_rate(zfp, rate, zfp_type_int32, 2, zfp_false);
bytes = zfp_stream_maximum_size(zfp, field);
buffer = malloc(bytes);
stream = stream_open(buffer, bytes);
zfp_stream_set_bit_stream(zfp, stream);
zfp_field_free(field);
/* compress */
for (y = 0; y < ny; y += 4)
for (x = 0; x < nx; x += 4) {
uchar ublock[16];
int32 iblock[16];
uint i, j;
for (j = 0; j < 4; j++)
for (i = 0; i < 4; i++)
ublock[i + 4 * j] = image[x + i + nx * (y + j)];
zfp_promote_uint8_to_int32(iblock, ublock, 2);
zfp_encode_block_int32_2(zfp, iblock);
}
zfp_stream_flush(zfp);
size = zfp_stream_compressed_size(zfp);
fprintf(stderr, "%u compressed bytes (%.2f bps)\n", (uint)size, (double)size * CHAR_BIT / (nx * ny));
/* decompress */
zfp_stream_rewind(zfp);
for (y = 0; y < ny; y += 4)
for (x = 0; x < nx; x += 4) {
int32 iblock[16];
uchar ublock[16];
uint i, j;
zfp_decode_block_int32_2(zfp, iblock);
zfp_demote_int32_to_uint8(ublock, iblock, 2);
for (j = 0; j < 4; j++)
for (i = 0; i < 4; i++)
image[x + i + nx * (y + j)] = ublock[i + 4 * j];
}
zfp_stream_close(zfp);
stream_close(stream);
free(buffer);
/* output reconstructed image */
printf("P5\n");
printf("%u %u\n", nx, ny);
printf("255\n");
fwrite(image, sizeof(*image), nx * ny, stdout);
free(image);
return 0;
}
|