#include "TIFF_reader.h"

namespace MobilePhotoTool{


	TIFF_reader::TIFF_reader(MPT_Exception *exception, const char *path)
	{
		this->ifd			= NULL;
		this->number_ifd	= 0;
		this->ifd_exif		= NULL;

		buffer = new MPT_Buffer(exception, path);
		MPT_EXCEPTION_TEST;
		if(buffer->get_size(exception) < 8){
			//throw new MPT_Exception("The file can not be a TIFF or DNG file",__FILE__, __LINE__);
			MPT_EXCEPTION("The file can not be a TIFF or DNG file");
		}
		MPT_EXCEPTION_TEST;
		this->ifd_preview	= NULL;
		this->raw_processor	= NULL;

		this->exception = exception;
		if(this->exception == NULL){
			this->exception = exception = new MPT_Exception();
		}

		read_Header(exception);
	}


	TIFF_reader::~TIFF_reader(void)
	{ 
		size_t pos;
		if(this->ifd != NULL){
			for(pos = 0; pos < this->number_ifd; pos += 1){
				if(this->ifd[pos] != NULL){
					//this->ifd[pos]->~IFD();
					delete this->ifd[pos];
				}
			}
			//delete []this->ifd;
			free(this->ifd);
		}

		if(this->ifd_exif != NULL){
			delete this->ifd_exif;
		}

		if(this->exception != NULL){
			delete exception;
			this->exception = NULL;
		}

		delete buffer;
		buffer = NULL;


		Raw_Processor_Creater::delete_Processor(this->raw_processor);
	}

	void TIFF_reader::read_Header(MPT_Exception *exception)
	{
		streamoff offset;
		bool readmore = true;
		IFD *ifd;

		switch(buffer->get_ushort(exception)){
		case 0x4949:
			buffer->set_order(exception, MPT_Buffer::LittleEndian);
			break;
		case 0x4D4D:
			buffer->set_order(exception, MPT_Buffer::BigEndian);
			break;
		}
		MPT_EXCEPTION_TEST;

		if(buffer->get_ushort(exception) == 42){
			offset = buffer->get_uint(exception);
			MPT_EXCEPTION_TEST;
			
			if(readmore){
				ifd = new IFD(exception, buffer, offset);
				if(ifd == NULL){
					MPT_EXCEPTION("No Memory");
				}
				MPT_EXCEPTION_TEST;

				offset = ifd->read(exception);
				MPT_EXCEPTION_TEST;
				this->set_IFD(exception, ifd);
				MPT_EXCEPTION_TEST;

				if(offset == 0){
					readmore = false;
				}
			}
		}else{
			MPT_EXCEPTION("The file can not be a TIFF or DNG file");
		}
	}

	void TIFF_reader::set_ifd_preview(MPT_Exception *exception)
	{
		if(ifd_preview == NULL){
			IFD *ifd;
			size_t pos;
			for(pos = 0; pos < this->number_ifd; pos++){
				ifd = this->ifd[pos];
				ifd = ifd->reduced_resolution_IFD(exception);
				MPT_EXCEPTION_TEST;
				if(ifd != NULL){
					ifd_preview = ifd;
				}
			}
		}
		if(ifd_preview == NULL){
			MPT_EXCEPTION("No preview image found.");
		}
	}

	unsigned int TIFF_reader::get_preview_width(MPT_Exception *exception)
	{
		unsigned int width = 0;
		set_ifd_preview(exception);
		MPT_EXCEPTION_TEST 0;

		width = ifd_preview->getImageWidth(exception);
		MPT_EXCEPTION_TEST 0;

		return width;
	}

	unsigned int TIFF_reader::get_preview_length(MPT_Exception *exception)
	{
		unsigned int length = 0;
		set_ifd_preview(exception);
		MPT_EXCEPTION_TEST 0;

		length = ifd_preview->getImageLength(exception);
		MPT_EXCEPTION_TEST 0;

		return length;
	}

	unsigned int TIFF_reader::getPreview_int_RGB(MPT_Exception *exception, unsigned int *data,  size_t size)
	{
		unsigned int	width, length, state, compression, *bitspersample, 
						photometricInterpretationtom, *stripoffsets, rowsperstrip;
		size_t			numberSamples, numberStrips, stripbytecount;
		IFD *ifd;
		state = 0;
		unsigned char in_data[3];

		bitspersample = stripoffsets = NULL;

		set_ifd_preview(exception);
		MPT_EXCEPTION_TEST 99;
		ifd = this->ifd_preview;
		width	= ifd->getImageWidth(exception);
		MPT_EXCEPTION_TEST 0;
		length	= ifd->getImageLength(exception);
		MPT_EXCEPTION_TEST 0;
		
		if(test_width_length(exception, width, length)){
			if(size >= width * length){
				compression 					= ifd->getCompression(exception);
				bitspersample 					= ifd->getBitsPerSample(exception, &numberSamples);
				photometricInterpretationtom	= ifd->getPhotometricInterpretation(exception);
				MPT_EXCEPTION_TEST 0;
				if(numberSamples == 3){
					if(	compression == 1 &&
						photometricInterpretationtom == 2 &&
						bitspersample[0] == 8 &&
						bitspersample[1] == 8 &&
						bitspersample[2] == 8 ){

							stripoffsets	= ifd->getStripOffsets(exception, &numberStrips);
							rowsperstrip	= ifd->getRowsPerStrip(exception);
							stripbytecount	= ifd->getStripByteCounts(exception);
							MPT_EXCEPTION_TEST 0;

							for(unsigned int strip = 0; strip < numberStrips; strip += 1){
								unsigned int startrow	= strip * rowsperstrip;
								unsigned int endrow		= startrow + rowsperstrip;
								unsigned int dest_row, pixel;
								if(endrow > length){
									endrow = length;
								}
								buffer->position(exception, stripoffsets[strip]);
								MPT_EXCEPTION_TEST 0;
								for(;startrow < endrow; startrow += 1){
									dest_row = startrow * width;
									for(unsigned int col = 0; col < width; col += 1){
										buffer->get_ubytes(exception, in_data, 3);
										MPT_EXCEPTION_TEST 0;
										pixel = in_data[0];
										pixel <<= 8;
										pixel |= in_data[1];
										pixel <<= 8;
										pixel |= in_data[2];
										data[dest_row + col] = pixel;
									}
								}
							}	

					}else{
						state = 4;
					}
				}else{
					state = 3;
				}
			}else{
				state = 2;
			}
		}else{
			state = 1;
		}

		if(bitspersample != NULL){
			delete []bitspersample;
		}
		
		if(stripoffsets != NULL){
			delete []stripoffsets;
		}
		return state;
	}

	unsigned int TIFF_reader::getPreview_int_RGB(MPT_Exception *exception, unsigned short *data,  size_t size)
	{
		unsigned int	width, length, state, compression, *bitspersample,
						photometricInterpretationtom, *stripoffsets, rowsperstrip;
		size_t			numberSamples, numberStrips, stripbytecount;
		IFD *ifd;
		state = 0;
		unsigned char in_data[3];

		bitspersample = stripoffsets = NULL;

		set_ifd_preview(exception);
		MPT_EXCEPTION_TEST 99;
		ifd = this->ifd_preview;
		width	= ifd->getImageWidth(exception);
		MPT_EXCEPTION_TEST 0;
		length	= ifd->getImageLength(exception);
		MPT_EXCEPTION_TEST 0;

		if(test_width_length(exception, width, length)){
			if(size >= width * length){
				compression 					= ifd->getCompression(exception);
				bitspersample 					= ifd->getBitsPerSample(exception, &numberSamples);
				photometricInterpretationtom	= ifd->getPhotometricInterpretation(exception);
				MPT_EXCEPTION_TEST 0;
				if(numberSamples == 3){
					if(	compression == 1 &&
						photometricInterpretationtom == 2 &&
						bitspersample[0] == 8 &&
						bitspersample[1] == 8 &&
						bitspersample[2] == 8 ){

							stripoffsets	= ifd->getStripOffsets(exception, &numberStrips);
							rowsperstrip	= ifd->getRowsPerStrip(exception);
							stripbytecount	= ifd->getStripByteCounts(exception);
							MPT_EXCEPTION_TEST 0;

							for(unsigned int strip = 0; strip < numberStrips; strip += 1){
								unsigned int startrow	= strip * rowsperstrip;
								unsigned int endrow		= startrow + rowsperstrip;
								unsigned int dest_row;
								unsigned short pixel;
								if(endrow > length){
									endrow = length;
								}
								buffer->position(exception, stripoffsets[strip]);
								MPT_EXCEPTION_TEST 0;
								for(;startrow < endrow; startrow += 1){
									dest_row = startrow * width;
									for(unsigned int col = 0; col < width; col += 1){
										buffer->get_ubytes(exception, in_data, 3);
										MPT_EXCEPTION_TEST 0;
										pixel = in_data[0] & 0xF8;
										pixel <<= 3;
										pixel |= in_data[1] >> 2;
										pixel <<= 5;
										pixel |= in_data[2] >> 3;
										data[dest_row + col] = pixel;
									}
								}
							}

					}else{
						state = 4;
					}
				}else{
					state = 3;
				}
			}else{
				state = 2;
			}
		}else{
			state = 1;
		}

		if(bitspersample != NULL){
			delete []bitspersample;
		}

		if(stripoffsets != NULL){
			delete []stripoffsets;
		}
		return state;
	}

	bool TIFF_reader::test_width_length(MPT_Exception *, unsigned int width, unsigned int length)
	{
		bool back = false;
		if((TIFF_reader::MAX_PIXEL / width) > length){
			back = true;
		}

		return back;
	}

	void TIFF_reader::load_Raw_Processor(MPT_Exception *exception)
	{
		IFD *raw_ifd = NULL;
		
		size_t pos;
		for(pos = 0; pos < this->number_ifd; pos++){
			raw_ifd = this->ifd[pos];
			raw_ifd = raw_ifd->raw_IFD(exception);
			MPT_EXCEPTION_TEST;
			if(raw_ifd != NULL){
				break;
			}
		}
		if(raw_ifd == NULL){
			MPT_EXCEPTION("No raw image found.");
		}

		this->raw_processor = Raw_Processor_Creater::create_Processor(exception, raw_ifd, this->ifd[0]);
		MPT_EXCEPTION_TEST;

	}

	Raw_Processor *TIFF_reader::get_Raw_Processor(MPT_Exception *exception)
	{
		if(this->raw_processor == NULL){
			this->load_Raw_Processor(exception);
			MPT_EXCEPTION_TEST NULL;
		}
		return this->raw_processor;
	}

	MPT_Exception *TIFF_reader::get_exception()
	{
		MPT_Exception *exception = this->exception;

		if(exception == NULL){
			this->exception = exception = new MPT_Exception();
		}
		return exception;
	}

	void TIFF_reader::set_IFD(MPT_Exception *exception, IFD *ifd)
	{
		size_t temp;
		if(this->ifd == NULL){
			this->ifd = (IFD**)malloc(sizeof(IFD *));
			if(this->ifd == NULL){
				MPT_EXCEPTION("Out of memory.");
			}
			this->number_ifd = 1;
			this->ifd[0] = ifd;
		}else{
			temp = this->number_ifd + 1;
			this->ifd = (IFD**)realloc(this->ifd, sizeof(IFD *) * temp);
			if(this->ifd == NULL){
				MPT_EXCEPTION("Out of memory.");
			}
			this->ifd[this->number_ifd] = ifd;
			this->number_ifd += 1;
		}
	}


	unsigned int TIFF_reader::set_Exif(MPT_Exception *exception){
		unsigned int back = MPT_NOSUCCESS ;
		unsigned int pos, pos_exif;
		IFD_ENTRY *entry	= NULL;
		IFD *exif_ifd 		= NULL;

		if(this->number_ifd > 0){
			for(pos = 0; pos < this->number_ifd && entry == NULL; pos++){
				entry = this->ifd[pos]->get_IFD_ENTRY(exception, IFD_TYPE::Exif_IFD);
				MPT_EXCEPTION_TEST back;
				if(entry->type->type_length(exception) == 4){
					pos_exif = entry->get_integer_as_uinterger(exception);
					MPT_EXCEPTION_TEST back;

					exif_ifd = new IFD(exception, buffer, pos_exif);
					MPT_EXCEPTION_TEST back;
					exif_ifd->read(exception);
					MPT_EXCEPTION_TEST back;
					this->ifd_exif = exif_ifd;
					back = MPT_SUCCESS;
				}
			}
		}
		return back;
	}

	unsigned int TIFF_reader::get_Exif_ExposureTime(MPT_Exception *exception, unsigned int return_value[2]){
		unsigned int back	= MPT_NOSUCCESS ;
		IFD_ENTRY *entry	= NULL;

		if(this->ifd_exif == NULL){
			if(set_Exif(exception) != MPT_SUCCESS){
				return back;
			}
		}
		entry = ifd_exif->get_IFD_ENTRY(exception, IFD_TYPE::Exif_ExposureTime);
		MPT_EXCEPTION_TEST back;
		if(entry == NULL){
			return back;
		}

		entry->get_as_rational(exception, return_value, 2);
		MPT_EXCEPTION_TEST back;
		back = MPT_SUCCESS;

		return back;
	}

	unsigned int TIFF_reader::get_Exif_FNumber(MPT_Exception *exception, unsigned int return_value[2]){
		unsigned int back	= MPT_NOSUCCESS ;
		IFD_ENTRY *entry	= NULL;

		if(this->ifd_exif == NULL){
			if(set_Exif(exception) != MPT_SUCCESS){
				return back;
			}
		}
		entry = ifd_exif->get_IFD_ENTRY(exception, IFD_TYPE::Exif_FNumber);
		MPT_EXCEPTION_TEST back;
		if(entry == NULL){
			return back;
		}

		entry->get_as_rational(exception, return_value, 2);
		MPT_EXCEPTION_TEST back;
		back = MPT_SUCCESS;

		return back;
	}

	unsigned int TIFF_reader::get_Exif_ExposureProgram(MPT_Exception *exception, unsigned int return_value[1]){
		unsigned int back	= MPT_NOSUCCESS ;
		IFD_ENTRY *entry	= NULL;

		if(this->ifd_exif == NULL){
			if(set_Exif(exception) != MPT_SUCCESS){
				return back;
			}
		}
		entry = ifd_exif->get_IFD_ENTRY(exception, IFD_TYPE::Exif_ExposureProgram);
		MPT_EXCEPTION_TEST back;
		if(entry == NULL){
			return back;
		}
		return_value[0] = entry->get_integer_as_uinterger(exception);
		MPT_EXCEPTION_TEST back;
		back = MPT_SUCCESS;

		return back;
	}

	unsigned int TIFF_reader::get_Exif_ISOSpeedRatings(MPT_Exception *exception, unsigned int return_value[1]){
		unsigned int back	= MPT_NOSUCCESS ;
		IFD_ENTRY *entry	= NULL;

		if(this->ifd_exif == NULL){
			if(set_Exif(exception) != MPT_SUCCESS){
				return back;
			}
		}
		entry = ifd_exif->get_IFD_ENTRY(exception, IFD_TYPE::Exif_ISOSpeedRatings);
		MPT_EXCEPTION_TEST back;
		if(entry == NULL){
			return back;
		}

		return_value[0] = entry->get_integer_as_uinterger(exception);
		MPT_EXCEPTION_TEST back;
		back = MPT_SUCCESS;

		return back;
	}

	unsigned int TIFF_reader::get_Exif_DateTimeOriginal(MPT_Exception *exception, char return_value[20]){
		unsigned int back	= MPT_NOSUCCESS ;
		IFD_ENTRY *entry	= NULL;

		if(this->ifd_exif == NULL){
			if(set_Exif(exception) != MPT_SUCCESS){
				return back;
			}
		}
		entry = ifd_exif->get_IFD_ENTRY(exception, IFD_TYPE::Exif_DateTimeOriginal);
		MPT_EXCEPTION_TEST back;
		if(entry == NULL){
			return back;
		}

		entry->get_as_char(exception, return_value, 20);
		MPT_EXCEPTION_TEST back;
		back = MPT_SUCCESS;

		return back;
	}

	unsigned int TIFF_reader::get_Exif_SubsecTimeOriginal(MPT_Exception *exception, char return_value[20]){
		unsigned int back	= MPT_NOSUCCESS ;
		IFD_ENTRY *entry	= NULL;

		if(this->ifd_exif == NULL){
			if(set_Exif(exception) != MPT_SUCCESS){
				return back;
			}
		}
		entry = ifd_exif->get_IFD_ENTRY(exception, IFD_TYPE::Exif_SubsecTimeOriginal);
		MPT_EXCEPTION_TEST back;
		if(entry == NULL){
			return back;
		}

		entry->get_as_char(exception, return_value, 20);
		MPT_EXCEPTION_TEST back;
		back = MPT_SUCCESS;

		return back;	}

	unsigned int TIFF_reader::get_Exif_DateTimeDigitized(MPT_Exception *exception, char return_value[20]){
		unsigned int back	= MPT_NOSUCCESS ;
		IFD_ENTRY *entry	= NULL;

		if(this->ifd_exif == NULL){
			if(set_Exif(exception) != MPT_SUCCESS){
				return back;
			}
		}
		entry = ifd_exif->get_IFD_ENTRY(exception, IFD_TYPE::Exif_DateTimeDigitized);
		MPT_EXCEPTION_TEST back;
		if(entry == NULL){
			return back;
		}

		entry->get_as_char(exception, return_value, 20);
		MPT_EXCEPTION_TEST back;
		back = MPT_SUCCESS;

		return back;
	}

	unsigned int TIFF_reader::get_Exif_SubsecTimeDigitized(MPT_Exception *exception, char return_value[20]){
		unsigned int back	= MPT_NOSUCCESS ;
		IFD_ENTRY *entry	= NULL;

		if(this->ifd_exif == NULL){
			if(set_Exif(exception) != MPT_SUCCESS){
				return back;
			}
		}
		entry = ifd_exif->get_IFD_ENTRY(exception, IFD_TYPE::Exif_SubsecTimeDigitized);
		MPT_EXCEPTION_TEST back;
		if(entry == NULL){
			return back;
		}

		entry->get_as_char(exception, return_value, 20);
		MPT_EXCEPTION_TEST back;
		back = MPT_SUCCESS;

		return back;
	}

	unsigned int TIFF_reader::get_Exif_ExposureBiasValue(MPT_Exception *exception, int return_value[2]){
		unsigned int back	= MPT_NOSUCCESS ;
		IFD_ENTRY *entry	= NULL;

		if(this->ifd_exif == NULL){
			if(set_Exif(exception) != MPT_SUCCESS){
				return back;
			}
		}
		entry = ifd_exif->get_IFD_ENTRY(exception, IFD_TYPE::Exif_ExposureBiasValue);
		MPT_EXCEPTION_TEST back;
		if(entry == NULL){
			return back;
		}

		entry->get_as_srational(exception, return_value, 1);
		MPT_EXCEPTION_TEST back;
		back = MPT_SUCCESS;

		return back;	}

	unsigned int TIFF_reader::get_Exif_MeteringMode(MPT_Exception *exception, unsigned int return_value[1]){
		unsigned int back	= MPT_NOSUCCESS ;
		IFD_ENTRY *entry	= NULL;

		if(this->ifd_exif == NULL){
			if(set_Exif(exception) != MPT_SUCCESS){
				return back;
			}
		}
		entry = ifd_exif->get_IFD_ENTRY(exception, IFD_TYPE::Exif_MeteringMode);
		MPT_EXCEPTION_TEST back;
		if(entry == NULL){
			return back;
		}

		return_value[0] = entry->get_integer_as_uinterger(exception);
		MPT_EXCEPTION_TEST back;
		back = MPT_SUCCESS;

		return back;
	}

	unsigned int TIFF_reader::get_Exif_Flash(MPT_Exception *exception, unsigned int return_value[1]){
		unsigned int back	= MPT_NOSUCCESS ;
		IFD_ENTRY *entry	= NULL;

		if(this->ifd_exif == NULL){
			if(set_Exif(exception) != MPT_SUCCESS){
				return back;
			}
		}
		entry = ifd_exif->get_IFD_ENTRY(exception, IFD_TYPE::Exif_Flash);
		MPT_EXCEPTION_TEST back;
		if(entry == NULL){
			return back;
		}

		return_value[0] = entry->get_integer_as_uinterger(exception);
		MPT_EXCEPTION_TEST back;
		back = MPT_SUCCESS;

		return back;
	}

	unsigned int TIFF_reader::get_Exif_FlashEnergy(MPT_Exception *exception, unsigned int return_value[2]){
		unsigned int back	= MPT_NOSUCCESS ;
		IFD_ENTRY *entry	= NULL;

		if(this->ifd_exif == NULL){
			if(set_Exif(exception) != MPT_SUCCESS){
				return back;
			}
		}
		entry = ifd_exif->get_IFD_ENTRY(exception, IFD_TYPE::Exif_FlashEnergy);
		MPT_EXCEPTION_TEST back;
		if(entry == NULL){
			return back;
		}

		entry->get_as_rational(exception, return_value, 2);
		MPT_EXCEPTION_TEST back;
		back = MPT_SUCCESS;

		return back;
	}

	unsigned int TIFF_reader::get_Exif_FocalLength(MPT_Exception *exception, unsigned int return_value[2]){
		unsigned int back	= MPT_NOSUCCESS ;
		IFD_ENTRY *entry	= NULL;

		if(this->ifd_exif == NULL){
			if(set_Exif(exception) != MPT_SUCCESS){
				return back;
			}
		}
		entry = ifd_exif->get_IFD_ENTRY(exception, IFD_TYPE::Exif_FocalLength);
		MPT_EXCEPTION_TEST back;
		if(entry == NULL){
			return back;
		}

		entry->get_as_rational(exception, return_value, 2);
		MPT_EXCEPTION_TEST back;
		back = MPT_SUCCESS;

		return back;
	}

	unsigned int TIFF_reader::get_Exif_FocalLengthIn35mmFilm(MPT_Exception *exception, unsigned int return_value[1]){
		unsigned int back	= MPT_NOSUCCESS ;
		IFD_ENTRY *entry	= NULL;

		if(this->ifd_exif == NULL){
			if(set_Exif(exception) != MPT_SUCCESS){
				return back;
			}
		}
		entry = ifd_exif->get_IFD_ENTRY(exception, IFD_TYPE::Exif_FocalLengthIn35mmFilm);
		MPT_EXCEPTION_TEST back;
		if(entry == NULL){
			return back;
		}

		return_value[0] = entry->get_integer_as_uinterger(exception);
		MPT_EXCEPTION_TEST back;
		back = MPT_SUCCESS;

		return back;
	}

	unsigned int TIFF_reader::get_Exif_SensingMethod(MPT_Exception *exception, unsigned int return_value[1]){
		unsigned int back	= MPT_NOSUCCESS ;
		IFD_ENTRY *entry	= NULL;

		if(this->ifd_exif == NULL){
			if(set_Exif(exception) != MPT_SUCCESS){
				return back;
			}
		}
		entry = ifd_exif->get_IFD_ENTRY(exception, IFD_TYPE::Exif_SensingMethod);
		MPT_EXCEPTION_TEST back;
		if(entry == NULL){
			return back;
		}

		return_value[0] = entry->get_integer_as_uinterger(exception);
		MPT_EXCEPTION_TEST back;
		back = MPT_SUCCESS;

		return back;
	}

	unsigned int TIFF_reader::get_Exif_CustomRendered(MPT_Exception *exception, unsigned int return_value[1]){
		unsigned int back	= MPT_NOSUCCESS ;
		IFD_ENTRY *entry	= NULL;

		if(this->ifd_exif == NULL){
			if(set_Exif(exception) != MPT_SUCCESS){
				return back;
			}
		}
		entry = ifd_exif->get_IFD_ENTRY(exception, IFD_TYPE::Exif_CustomRendered);
		MPT_EXCEPTION_TEST back;
		if(entry == NULL){
			return back;
		}

		return_value[0] = entry->get_integer_as_uinterger(exception);
		MPT_EXCEPTION_TEST back;
		back = MPT_SUCCESS;

		return back;
	}

	unsigned int TIFF_reader::get_Exif_ExposureMode(MPT_Exception *exception, unsigned int return_value[1]){
		unsigned int back	= MPT_NOSUCCESS ;
		IFD_ENTRY *entry	= NULL;

		if(this->ifd_exif == NULL){
			if(set_Exif(exception) != MPT_SUCCESS){
				return back;
			}
		}
		entry = ifd_exif->get_IFD_ENTRY(exception, IFD_TYPE::Exif_ExposureMode);
		MPT_EXCEPTION_TEST back;
		if(entry == NULL){
			return back;
		}

		return_value[0] = entry->get_integer_as_uinterger(exception);
		MPT_EXCEPTION_TEST back;
		back = MPT_SUCCESS;

		return back;
	}

	unsigned int TIFF_reader::get_Exif_WhiteBalance(MPT_Exception *exception, unsigned int return_value[1]){
		unsigned int back	= MPT_NOSUCCESS ;
		IFD_ENTRY *entry	= NULL;

		if(this->ifd_exif == NULL){
			if(set_Exif(exception) != MPT_SUCCESS){
				return back;
			}
		}
		entry = ifd_exif->get_IFD_ENTRY(exception, IFD_TYPE::Exif_WhiteBalance);
		MPT_EXCEPTION_TEST back;
		if(entry == NULL){
			return back;
		}

		return_value[0] = entry->get_integer_as_uinterger(exception);
		MPT_EXCEPTION_TEST back;
		back = MPT_SUCCESS;

		return back;
	}

	unsigned int TIFF_reader::get_Exif_SceneCaptureType(MPT_Exception *exception, unsigned int return_value[1]){
		unsigned int back	= MPT_NOSUCCESS ;
		IFD_ENTRY *entry	= NULL;

		if(this->ifd_exif == NULL){
			if(set_Exif(exception) != MPT_SUCCESS){
				return back;
			}
		}
		entry = ifd_exif->get_IFD_ENTRY(exception, IFD_TYPE::Exif_SceneCaptureType);
		MPT_EXCEPTION_TEST back;
		if(entry == NULL){
			return back;
		}

		return_value[0] = entry->get_integer_as_uinterger(exception);
		MPT_EXCEPTION_TEST back;
		back = MPT_SUCCESS;

		return back;
	}

	unsigned int TIFF_reader::get_Exif_Contrast(MPT_Exception *exception, unsigned int return_value[1]){
		unsigned int back	= MPT_NOSUCCESS ;
		IFD_ENTRY *entry	= NULL;

		if(this->ifd_exif == NULL){
			if(set_Exif(exception) != MPT_SUCCESS){
				return back;
			}
		}
		entry = ifd_exif->get_IFD_ENTRY(exception, IFD_TYPE::Exif_Contrast);
		MPT_EXCEPTION_TEST back;
		if(entry == NULL){
			return back;
		}

		return_value[0] = entry->get_integer_as_uinterger(exception);
		MPT_EXCEPTION_TEST back;
		back = MPT_SUCCESS;

		return back;
	}

	unsigned int TIFF_reader::get_Exif_Saturation(MPT_Exception *exception, unsigned int return_value[1]){
		unsigned int back	= MPT_NOSUCCESS ;
		IFD_ENTRY *entry	= NULL;

		if(this->ifd_exif == NULL){
			if(set_Exif(exception) != MPT_SUCCESS){
				return back;
			}
		}
		entry = ifd_exif->get_IFD_ENTRY(exception, IFD_TYPE::Exif_Saturation);
		MPT_EXCEPTION_TEST back;
		if(entry == NULL){
			return back;
		}

		return_value[0] = entry->get_integer_as_uinterger(exception);
		MPT_EXCEPTION_TEST back;
		back = MPT_SUCCESS;

		return back;
	}

	unsigned int TIFF_reader::get_Exif_Sharpness(MPT_Exception *exception, unsigned int return_value[1]){
		unsigned int back	= MPT_NOSUCCESS ;
		IFD_ENTRY *entry	= NULL;

		if(this->ifd_exif == NULL){
			if(set_Exif(exception) != MPT_SUCCESS){
				return back;
			}
		}
		entry = ifd_exif->get_IFD_ENTRY(exception, IFD_TYPE::Exif_Sharpness);
		MPT_EXCEPTION_TEST back;
		if(entry == NULL){
			return back;
		}

		return_value[0] = entry->get_integer_as_uinterger(exception);
		MPT_EXCEPTION_TEST back;
		back = MPT_SUCCESS;

		return back;
	}

	unsigned int TIFF_reader::get_Exif_BaselineSharpness(MPT_Exception *exception, unsigned int return_value[1]){
		unsigned int back	= MPT_NOSUCCESS ;
		IFD_ENTRY *entry	= NULL;

		if(this->ifd_exif == NULL){
			if(set_Exif(exception) != MPT_SUCCESS){
				return back;
			}
		}
		entry = ifd_exif->get_IFD_ENTRY(exception, IFD_TYPE::Exif_BaselineSharpness);
		MPT_EXCEPTION_TEST back;
		if(entry == NULL){
			return back;
		}

		return_value[0] = entry->get_integer_as_uinterger(exception);
		MPT_EXCEPTION_TEST back;
		back = MPT_SUCCESS;

		return back;
	}

	unsigned int TIFF_reader::get_Exif_SubjectDistanceRange(MPT_Exception *exception, unsigned int return_value[1]){
		unsigned int back	= MPT_NOSUCCESS ;
		IFD_ENTRY *entry	= NULL;

		if(this->ifd_exif == NULL){
			if(set_Exif(exception) != MPT_SUCCESS){
				return back;
			}
		}
		entry = ifd_exif->get_IFD_ENTRY(exception, IFD_TYPE::Exif_SubjectDistanceRange);
		MPT_EXCEPTION_TEST back;
		if(entry == NULL){
			return back;
		}

		return_value[0] = entry->get_integer_as_uinterger(exception);
		MPT_EXCEPTION_TEST back;
		back = MPT_SUCCESS;

		return back;
	}

}
