/* bitmap_24bitRGB.c
 * 
 * Värikuvien käsittelyyn 
 */ 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#include "def.h"
#include "bitmap_24bitRGB.h"

/*
 * LOCAL functions
 */

static int isValidCoords(Bitmap_24bitRGB *bitmap, int x, int y) {
  return ( (0 <= x && x < bitmap->width ) &&
	   (0 <= y && y < bitmap->height)    );
}
	  
/*
 * PUBLIC functions
 */

Bitmap_24bitRGB * create_bmp24bitRGB(int width, int height) {
  Bitmap_24bitRGB *bitmap;

  bitmap = malloc( sizeof(Bitmap_24bitRGB) );
  if(bitmap == NULL) {
    return NULL;
  }
  bitmap->width  = width;
  bitmap->height = height;
  
  bitmap->image = calloc(width*height, 3*sizeof(unsigned char) );
  if( bitmap->image == NULL ) {
    free(bitmap);
    return NULL;
  }

  return bitmap;
}

void setPixel_bmp24bitRGB(Bitmap_24bitRGB *bitmap, 
			  int x, int y, Pixel_24bitRGB pixel) {
  unsigned char *p;
  
  if( ! isValidCoords(bitmap, x, y) ) 
    return;

  p= bitmap->image + 
    3*(y * bitmap->width) + 3*x;

  p[0] = pixel.blue;
  p[1] = pixel.green;
  p[2] = pixel.red;

}

Pixel_24bitRGB getPixel_bmp24bitRGB(Bitmap_24bitRGB *bitmap,
				    int x, int y) {
  Pixel_24bitRGB pixel;
  unsigned char *p;
  
  assert( isValidCoords(bitmap,x,y) );

  p = bitmap->image + 
    3*(y * bitmap->width) + 3*x;
  
  pixel.blue  = p[0];
  pixel.green = p[1];
  pixel.red   = p[2];

  return pixel;
}

int writeToFile_bmp24bitRGB(Bitmap_24bitRGB *bitmap, char *filename) {
  FILE *file;
  int x,y;

  file = fopen(filename, "w");
  if(file == NULL) {
    perror( filename );
    return FALSE;
  }
    
  /* Header information */
  fprintf(file,"P6\n %d %d\n 255\n",bitmap->width,bitmap->height);
  
  for( y=0 ; y<bitmap->height ; y++ ) {
    for( x=0 ; x<bitmap->width ; x++ ){
      
      fwrite(bitmap->image + (y * bitmap->width + x)*3+2, 1, 1, file);
      fwrite(bitmap->image + (y * bitmap->width + x)*3+1, 1, 1, file);
      fwrite(bitmap->image + (y * bitmap->width + x)*3  , 1, 1, file);
    }
  }
  fclose(file);

  return TRUE;
}


/*
 * PENDING!
 * Korjaa nämä käyttämään libppm:ää ! Jossa on valmiit funkkarit headerin 
 * ja datan lukemiseen !                   Teemu Kurppa 22.2.2000
 */

static int isCorrectFileType(FILE *file) {
  char type[3];
  fscanf(file, "%s", type);
  return (type[0] == 'P' && type[1] == '6');
}


static int readDimensions(FILE *file, int *width, int *height, int *depth) {
  return fscanf(file, "%d %d %d", width, height, depth);
}



Bitmap_24bitRGB * readFromFile_bmp24bitRGB(char *filename) {
  FILE *file;
  int width, height, depth;
  int i;
  Bitmap_24bitRGB *bitmap;
  unsigned char pix[3];
  
  file = fopen(filename, "r");
  if(file == NULL) {
    perror( filename );
    return NULL;
  }
  
  if( ! isCorrectFileType(file) ) {
    fclose(file);
    return NULL;
  }
    
  if( readDimensions(file, &width, &height, &depth) != 3) {
    fclose(file);
    return NULL;
  }

  /* Jump over last newline */
  fseek(file, 1, SEEK_CUR);
  
  bitmap = create_bmp24bitRGB(width, height);
  if(bitmap == NULL) {
    fclose(file);
    return NULL;
  }

  i = 0;
  fread(pix, sizeof(unsigned char), 3, file);
  
  while( !feof(file) ) {
    bitmap->image[i+2] = (unsigned char) pix[0];
    bitmap->image[i+1] = (unsigned char) pix[1];
    bitmap->image[i+0] = (unsigned char) pix[2];
    i += 3;
    fread(pix, sizeof(unsigned char), 3, file);
  }
  
  
  fclose(file);
  
  return bitmap;
}  
  



