/* 
   Copyright (C) 1999 E. H. Haley
   
   derh, loads a jpeg: rjf loads any jpeg (RGB/G), wjf writes one.
   Only for symmetry are wjf's integer arguments pointers.  A JSAMPLE
   is almost certainly an unsigned byte.

   Unfortunately, I'm doing the row-reversing here instead of in the
   GL code.  GL wants its images upside down.  I _should_ do it clean
   here and then draw them with glPixelZoom(1,-1) or whatever.

*/

#include <stdlib.h>
#include <stdio.h>
#include <jpeglib.h>
#include <jerror.h>
#include "loadj.h"

JSAMPLE *rjf(char *filename, int *w, int *h, int *c)
{
  JSAMPLE *arr;
  JSAMPROW *rows;
  JSAMPARRAY image;
  struct jpeg_decompress_struct cinfo;
  struct jpeg_error_mgr jerr;
  FILE * infile;
  int i,ww,hh,cc;

  cinfo.err = jpeg_std_error(&jerr);
  jpeg_create_decompress(&cinfo);
  
  if ((infile = fopen(filename, "rb")) == NULL)
    { fprintf(stderr, "loadj: rjf()can't open %s\n", filename);
    return (JSAMPLE *)NULL; }

  jpeg_stdio_src(&cinfo, infile);
  jpeg_read_header(&cinfo, TRUE);
  
  jpeg_calc_output_dimensions(&cinfo);
  *w=ww=cinfo.output_width;
  *h=hh=cinfo.output_height;
  *c=cc=cinfo.out_color_components;
      
  arr=(JSAMPLE *) calloc(ww*hh*cc,sizeof(JSAMPLE));
  rows=(JSAMPROW *) calloc(hh,sizeof(JSAMPROW));
  
  for (i=0; i<hh; i++)
    rows[i]=arr + (hh-1-i)*ww*cc; //for GL, we're reversing the rows.
  image=rows;
      
  jpeg_start_decompress(&cinfo);
  
  while (cinfo.output_scanline < hh)
    jpeg_read_scanlines (&cinfo, image+cinfo.output_scanline, hh);
  
  jpeg_finish_decompress(&cinfo);
  fclose(infile);
  jpeg_destroy_decompress(&cinfo);
  free(rows);
  return arr;
}


void wjf(JSAMPLE *arr, char *filename, int *w, int *h, int *c)
{
  JSAMPROW row[1];
  struct jpeg_compress_struct cinfo;
  struct jpeg_error_mgr jerr;
  FILE * outfile;
  int ww,hh,cc;

  cinfo.err = jpeg_std_error(&jerr);
  jpeg_create_compress(&cinfo);
  
  if ((outfile = fopen(filename, "wb")) == NULL)
    { fprintf(stderr, "can't open %s\n", filename); exit(1); }
  jpeg_stdio_dest(&cinfo, outfile);
  
  cinfo.image_width=ww=*w;
  cinfo.image_height=hh=*h;
  cinfo.input_components=cc=*c;
  cinfo.in_color_space=(cc>2?JCS_RGB:JCS_GRAYSCALE);
  jpeg_set_defaults(&cinfo);
    
  jpeg_start_compress(&cinfo, TRUE);

  while (cinfo.next_scanline < cinfo.image_height)
    {
      row[0] = &arr[(hh-1-cinfo.next_scanline) * ww*cc]; //reverse order for GL
      jpeg_write_scanlines(&cinfo, row, 1);
    }
    
  jpeg_finish_compress(&cinfo);
  fclose(outfile);
  jpeg_destroy_compress(&cinfo);

  return;
}
