File: pgm.c

package info (click to toggle)
zfp 1.0.1-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 4,744 kB
  • sloc: cpp: 20,656; ansic: 18,871; pascal: 1,231; f90: 907; python: 255; makefile: 183; sh: 79; fortran: 70
file content (112 lines) | stat: -rw-r--r-- 2,971 bytes parent folder | download | duplicates (2)
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;
}