/*
 Name        : mnist_image_parser.c
 Description : Parser for mnist image db file.
*/

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

int convertBigToLittleEndian(int i)
{
	unsigned char c1, c2, c3, c4;

	c1 = i & 255;
	c2 = (i >> 8) & 255;
	c3 = (i >> 16) & 255;
	c4 = (i >> 24) & 255;

	return ((int)c1 << 24) + ((int)c2 << 16) + ((int)c3 << 8) + c4;
}

int main() {
	FILE* images_file;
	// INSTRUCTIONS
	// download http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz to your own disk
	// (it is included as part of the MNOST DB story by Yann LeCunn, http://yann.lecun.com/exdb/mnist/) 
	// Ungzip the file, name the uncompressed file as you wish, e.g. "t10k-images-idx3-ubyte" 
	fopen_s(&images_file, "--- your path ---\t10k-images-idx3-ubyte", "rb");

	int magic_number;
	fread((int*)&magic_number, sizeof(int), 1, images_file);
	magic_number = convertBigToLittleEndian(magic_number);
	if (magic_number != 2051) {
		printf("Error reading magic number. Uncompress images file");
		exit(1);
	} 
	printf("Read magic number: %d\n", magic_number);

	// Read total number of images (train / test)
	int number_of_images;
	fread((int*)&number_of_images, sizeof(int), 1, images_file);
	number_of_images = convertBigToLittleEndian(number_of_images);
	printf("number of images: %d\n", number_of_images);

	// Read image dimension - verify parsing correctness
	int num_rows = 0, num_cols = 0;
	fread((int*)&num_rows, sizeof(int), 1, images_file);
	num_rows = convertBigToLittleEndian(num_rows);
	fread((int*)&num_cols, sizeof(int), 1, images_file);
	num_cols = convertBigToLittleEndian(num_cols);
	if (num_rows != 28 || num_cols != 28) {
		printf("read image dimensions %dx%d don't fit MNIST 28x28. Bad parsing?\n", num_rows, num_cols);
		exit(1);
	}
	
	//Read pixel values for each image
	int num_pixles_in_image = num_cols * num_rows;
	unsigned char* images_pixels_bytes = (unsigned char*)malloc(sizeof(unsigned char)*num_pixles_in_image);
	
	for (int images_done = 0; images_done < number_of_images; images_done++) {
		fread(images_pixels_bytes, sizeof(unsigned char), num_pixles_in_image, images_file);
		int idx = 0;
		for (idx = 0; idx < num_pixles_in_image; ++idx) {
			int image_pixel_value = hex_char_to_int(images_pixels_bytes[idx]);

			// A graphic of the number this represents.
			if (idx % num_cols == 0) printf("\n");
			if (images_pixels_bytes[idx] <= 200) {
				printf(".");
			} else {
				printf("*");
			}
		}
		printf("\n----------------------------------------------------------\n");
	}

	free(images_pixels_bytes);
	fclose(images_file);
}
