/*
 *  psychlops_g_JPEG_bridge.cpp
 *  Psychlops Standard Library (Universal)
 *
 *  Last Modified 2009/04/22 by Kenchi HOSOKAWA
 *  (C) 2006- Kenchi HOSOKAWA, Kazushi MARUYA and Takao SATO
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern "C" {
#include "jpeglib.h"
}


#include "../../../core/ApplicationInterfaces/psychlops_code_exception.h"
#include "../../../core/graphic/psychlops_g_image.h"
#include "psychlops_g_JPEG_bridge.h"


namespace Psychlops {
namespace IMAGE_FORMATS {


	JPEG_BRIDGE::JPEG_BRIDGE() {
		is_opened_ = false;
	}
	JPEG_BRIDGE::~JPEG_BRIDGE() {
		close();
	}


	void JPEG_BRIDGE::load(const char *file_name, Image * target) {
		open(file_name, "rb");

		check_before_read();
		read(target);
	}
	void JPEG_BRIDGE::save(const char *file_name, Image * target) {
/*
		open(file_name, "wb");

		prepare_before_write();
		write(target);
*/
	}
	void JPEG_BRIDGE::open(const char *file_name, const char *mode) {
		if(!is_opened_)
			if ((fp = fopen(file_name, mode)) == NULL)
					throw Exception(typeid(*this), "FILE ACCESS ERROR", "Failed to open the requested file.");
		is_opened_ = true;
	}
	void JPEG_BRIDGE::close() {
		if(is_opened_) fclose(fp);
		is_opened_ = false;
	}


	void JPEG_BRIDGE::check_before_read() {
		cinfo.err = jpeg_std_error(&jerr);

		jpeg_create_decompress(&cinfo);
		jpeg_stdio_src(&cinfo, fp);
		jpeg_read_header(&cinfo, TRUE);

		cinfo.dct_method = JDCT_ISLOW;
		cinfo.quantize_colors = FALSE;
		cinfo.dither_mode = JDITHER_NONE;
		cinfo.do_fancy_upsampling = TRUE;

		jpeg_calc_output_dimensions(&cinfo);
}

	void JPEG_BRIDGE::read(Image * target) {
		size_t width  = cinfo.output_width;
		size_t height = cinfo.output_height;
		Image::PixelComponentsCnt pix_component;
		switch (cinfo.output_components) {
			case 1:
				pix_component = Image::GRAY;
				break;
			case 3:
				pix_component = Image::RGB;
				break;
			case 4:
				pix_component = Image::RGBA;
				break;
			default:
				pix_component = Image::RGB;
				break;
		}
		//int rec_outbuf_height;

		target->set(width, height, pix_component);
		readTargetMemoryAlignment(target);
//		for(unsigned int i=0; i<height; i++) row_pointers[i] = target_bitmap_ub_ + (height-i-1)*(target_bytes_per_line_);
		size_t buf_w  = sizeof(char)*width*cinfo.out_color_components;
		char *iobuffer = (char *)  (*cinfo.mem->alloc_small)((j_common_ptr)&cinfo, JPOOL_IMAGE, buf_w);
		JSAMPROW pixrow = (JSAMPROW) iobuffer;
		JSAMPARRAY samp_buf = &pixrow;


		jpeg_start_decompress(&cinfo);
		int l = 0;
		JDIMENSION l_num;
		while (cinfo.output_scanline < cinfo.output_height) {
			l_num = jpeg_read_scanlines(&cinfo, samp_buf, 1);
			memcpy(target_bitmap_ub_+(height-l-1)*(target_bytes_per_line_), iobuffer, target_bytes_per_line_);
			l++;
		}
		jpeg_finish_decompress(&cinfo);
		jpeg_destroy_decompress(&cinfo);
	}




	void JPEG_BRIDGE::prepare_before_write() {
	}

	void JPEG_BRIDGE::write(Image * target) {
		unsigned int width = (unsigned int)target->getWidth();
		unsigned int height = (unsigned int)target->getHeight();

		switch (pix_components_) {
			case Image::GRAY:
				break;
			case Image::RGB:
				break;
			case Image::RGBA:
				break;
			default:
				break;
		}

		unsigned int bit_depth;
		switch(pix_precision_) {
			case Image::FLOAT:
				throw Exception(typeid(*this), "FILE FORMAT ERROR", "The requested data is not able to be put as a PNG file.");
				break;
			case Image::BYTE:
				bit_depth = 8;
				break;
			default:
				bit_depth = 8;
				break;
		}
	}


}
}
