#include <endian.h>
#include <stdio.h>
#include <stdlib.h>
#include <zlib.h>

static int fix_pngheader (const char *filename, unsigned int height);

int
main (int argc, char **argv)
{
  if (argc == 3)
    fix_pngheader (argv[2], atoi (argv[1]));
  else
    printf ("Usage: pngfix height pngfile.png\n");
}

static int
fix_pngheader (const char *filename, unsigned int height)
{
  FILE *png = NULL;
  int ret = -1;

  png = fopen (filename, "r+");

  if (png) {
    char buf[17];
    uLong crc;
    char temp[4];

    /* change height field */
    fseek (png, 20, SEEK_SET);
    memcpy (temp, &height, 4);
#if __BYTE_ORDER == __LITTLE_ENDIAN
    fwrite (&temp[3], 1, 1, png);
    fwrite (&temp[2], 1, 1, png);
    fwrite (&temp[1], 1, 1, png);
    fwrite (&temp[0], 1, 1, png);
#else
    fwrite (&height, 1, 4, png);
#endif

    /* compute new crc */
    fseek (png, 12, SEEK_SET);
    fread (&buf, 17, 1, png);

    crc = crc32 (0L, Z_NULL, 0);
    crc = (int) crc32 (crc, (const Bytef *) buf, 17);

    /* write new crc */
    fseek (png, 29, SEEK_SET);
    memcpy (temp, &crc, 4);
#if __BYTE_ORDER == __LITTLE_ENDIAN
    fwrite (&temp[3], 1, 1, png);
    fwrite (&temp[2], 1, 1, png);
    fwrite (&temp[1], 1, 1, png);
    fwrite (&temp[0], 1, 1, png);
#else
    fwrite (&crc, 1, 4, png);
#endif

    fclose (png);

    ret = 0;
  }
  else {
    fprintf (stderr, "ERROR: unable to open %s", filename);
  }

  return ret;
}
