/*
  Copyright (C) 1999 E. H. Haley
  
  fixed the upside-downiness of GL's coo sys
  
  still to do: use stencil buffer to do it on the cheap(?)
*/

#include <GL/glut.h>
#include <X11/Xlib.h>
#include <stdlib.h>
#include <stdio.h>
#include <jpeglib.h>
#include <jerror.h>

JSAMPLE *arr;
JSAMPROW *rows;
JSAMPARRAY image;
int w,h;

void loadj(int *aardc, char **aardv)
{
  struct jpeg_decompress_struct cinfo;
  struct jpeg_error_mgr jerr;
  FILE * infile;
  int i;

  if ((infile = fopen(*(aardv+1), "rb")) == NULL)
    { fprintf(stderr, "can't open %s\n", *(aardv+1)); exit(1); }

  cinfo.err = jpeg_std_error(&jerr);
  jpeg_create_decompress(&cinfo);
  jpeg_stdio_src(&cinfo, infile);
  jpeg_read_header(&cinfo, TRUE);

  jpeg_calc_output_dimensions(&cinfo);
  w=cinfo.output_width;
  h=cinfo.output_height;

  arr=(JSAMPLE *) calloc(sizeof(JSAMPLE),w*h*3);
  rows=(JSAMPROW *) calloc(sizeof(JSAMPROW),h);

  for (i=0; i<h; i++)
    rows[h-i-1]=arr+i*w*3;
  //    rows[i]=arr+i*w*3; // I should let the GL deal, it's what's backwards--
  image=rows;

  jpeg_start_decompress(&cinfo);

  while (cinfo.output_scanline < cinfo.output_height)
    jpeg_read_scanlines(&cinfo, image+cinfo.output_scanline, h);
  
  jpeg_finish_decompress(&cinfo);
  fclose(infile);
  jpeg_destroy_decompress(&cinfo);
}

void cones(void)
{
  int i,j,k;

  for(j=-20; j<20; j++)
    for(i=-20; i<20; i++)
      {
	//k=3*((i+20)*6 + (19-j)*8*w); //19-j vs j+20 bcs GL is upside down
	k=3*((i+20)*6 + (j+20)*8*w);
	glColor3f
	  ((float)arr[k]/256.0,
	   (float)arr[k+1]/256.0,
	   (float)arr[k+2]/256.0);
	glLoadIdentity();
	glTranslatef(((float)i+(float)random()/(float)RAND_MAX)/20.0,
		     ((float)j+(float)random()/(float)RAND_MAX)/20.0,
		     0.0);
	glutSolidCone(0.1,-0.1,16,12);
      }
}

void display(void)
{
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glPushMatrix();
  cones();
  glPopMatrix();
  glFlush();
}

void mouse(int button, int state, int x, int y)
{
  free(arr);
  free(rows);
  exit(0);
}

void myinit(int *aardc, char **aardv)
{
  glClearColor(0.0,0.0,0.0,1.0);
  glClearDepth(1.0);
  loadj(aardc, aardv);
}

int main(int aardc, char **aardv)
{
  myinit(&aardc, aardv);
  glutInit(&aardc, aardv);

  glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);
  glutInitWindowSize(w,h);
  glutCreateWindow("DJT");
  glutDisplayFunc(display);
  glutMouseFunc(mouse);

  glEnable(GL_DEPTH_TEST);
  glShadeModel(GL_FLAT);

  
  glutMainLoop();
  exit(0);
}

