/*
 * Project Name JPEG API for HW JPEG IP IN WINCE
 * Copyright  2007 Samsung Electronics Co, Ltd. All Rights Reserved. 
 *
 * This software is the confidential and proprietary information
 * of Samsung Electronics  ("Confidential Information").   
 * you shall not disclose such Confidential Information and shall use
 * it only in accordance with the terms of the license agreement
 * you entered into with Samsung Electronics 
 *
 * This file implements JPEG driver.
 *
 * @name JPEG DRIVER MODULE Module (JPGApi.c)
 * @author Jiyoung Shin (idon.shin@samsung.com)
 * @date 28-05-07
 */
#include <windows.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
//#include <bsp.h>
#include "JPGApi.h"
#include "JPGDriver.h"
#include "JPGMem.h"
#include "JPGOpr.h"
#include "SVEDriverAPI.h"
#include "CMMAPI.h"


//////////////////////////////////////////////////////////////////////////////////////
// Definition																		//
//////////////////////////////////////////////////////////////////////////////////////
#define JPG_DRIVER_NAME		L"JPG1:"
#define CMM_DRIVER_NAME     L"CMM1:"

#define TRUE	1
#define FALSE	0

typedef struct tag_JPGLIB {
    HANDLE  hJPG;
    HANDLE  hCMM;
    JPG_ARGS  args;
	UINT8	thumbnailFlag;
	ExifFileInfo *ExifInfo;
} _JPGLIB;


UCHAR ExifHeader[6]=
{
	0x45,0x78,0x69,0x66,0x00,0x00
};

UCHAR TIFFHeader[8]=
{
	0x49,0x49,0x2A,0x00,0x08,0x00,0x00,0x00
};

//////////////////////////////////////////////////////////////////////////////////////
// function declair																	//
//////////////////////////////////////////////////////////////////////////////////////
static JPEG_ERRORTYPE initEncodeParam(void * openHandle);
static JPEG_ERRORTYPE makeThumbImage(void *openHandle);
static JPEG_ERRORTYPE MCUCheck(IN_MODE_T format, UINT32 width, UINT32 height);
static JPEG_ERRORTYPE makeExifFile(_JPGLIB *pCTX, char *ExifOut, UINT *totalLen);
static void scalDownYUV422(char *srcBuf, INT32 srcWidth, INT32 srcHeight, 
							char *dstBuf, INT32 dstWidth, INT32 dstHeight);
static void scalDownRGB565(char *srcBuf, INT32 srcWidth, INT32 srcHeight, 
				char *dstBuf, INT32 dstWidth, INT32 dstHeight);

/*----------------------------------------------------------------------------
*Function: SsbSipJPEGDecodeInit

*Parameters:
*Return Value:		Decoder Init handle
*Implementation Notes: Initialize JPEG Decoder Deivce Driver
-----------------------------------------------------------------------------*/
void *SsbSipJPEGDecodeInit(void)
{
	_JPGLIB    *pCTX = NULL;
	CMM_ALLOC_PRAM_T	CMMParam;
	JPEG_ERRORTYPE ret;
	int         phyIMGDataAddr, virIMGDataAddr;

	// DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s++\r\n"), _T(__FUNCTION__)));
	pCTX = (_JPGLIB *) malloc(sizeof(_JPGLIB));
	if (pCTX == NULL)
	{
        // ERRMSG((_T("[JPGAPI] SsbSipJPEGDecodeInit :: malloc failed.\r\n")));
		return NULL;
	}
	memset(pCTX, 0x00, sizeof(_JPGLIB));

	pCTX->hJPG = CreateFile(JPG_DRIVER_NAME,
	                        GENERIC_READ|GENERIC_WRITE,
	                        0,
	                        NULL,
	                        OPEN_EXISTING,
	                        FILE_ATTRIBUTE_NORMAL,NULL);
	
	if(pCTX->hJPG == INVALID_HANDLE_VALUE)
	{
        // ERRMSG((_T("[JPGAPI] SsbSipJPEGDecodeInit :: JPG Open failure.\r\n")));
		free(pCTX);
		return NULL;
	}

	pCTX->hCMM = CreateFile(CMM_DRIVER_NAME,
                            GENERIC_READ|GENERIC_WRITE,
                            0,
                            NULL,
                            OPEN_EXISTING,
                            FILE_ATTRIBUTE_NORMAL,
                            NULL);
	if (pCTX->hCMM == INVALID_HANDLE_VALUE)
	{
        // ERRMSG((_T("[JPGAPI] SsbSipJPEGDecodeInit :: CMM Open failure.\r\n")));
	        free(pCTX);
	        return NULL;
	}

	pCTX->args.decParam = (JPG_DEC_PROC_PARAM *)malloc(sizeof(JPG_DEC_PROC_PARAM));
	
	if(pCTX->args.decParam == NULL)
	{
        // ERRMSG((_T("[JPGAPI] SsbSipJPEGDecodeInit :: Out of Memory\r\n")));
		free(pCTX);
		return NULL;
	}
	
	memset(pCTX->args.decParam, 0x00, sizeof(JPG_DEC_PROC_PARAM));

	pCTX->args.decParam->decType = JPG_MAIN;

	///////////////////////////////////////
	// make JPEG decode output buffer
	///////////////////////////////////////
	// CMM alloc
	CMMParam.size = (unsigned int)MAX_YUV_SIZE;
	CMMParam.cacheFlag = 0;
	CMMParam.dramLocation = DRAM_1;

	ret = DeviceIoControl(pCTX->hCMM, IOCTL_CODEC_MEM_ALLOC, (PBYTE)&CMMParam, 
		                        sizeof(CMM_ALLOC_PRAM_T *), &(virIMGDataAddr), sizeof(virIMGDataAddr), NULL, NULL);
	
	if(ret == FALSE)
	{
        // ERRMSG((_T("[JPGAPI] SsbSipJPEGDecodeInit :: IOCTL_CODEC_MEM_ALLOC failed\r\n")));
		free(pCTX);
		return NULL;
	}

	ret = DeviceIoControl(pCTX->hCMM, IOCTL_CODEC_GET_PHY_ADDR, (PBYTE)virIMGDataAddr, 
	                        sizeof(virIMGDataAddr), &(phyIMGDataAddr), sizeof(phyIMGDataAddr), 
	                        NULL, NULL);
	
	if(ret == FALSE)
	{
        // ERRMSG((_T("[JPGAPI] SsbSipJPEGDecodeInit :: IOCTL_CODEC_GET_PHY_ADDR failed\r\n")));
		free(pCTX);
		return NULL;
	}

	pCTX->args.OutBuf = (char *)virIMGDataAddr;
	pCTX->args.phyOutBuf = (char *)phyIMGDataAddr;

    // DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s--\r\n"), _T(__FUNCTION__)));
	return (void *)pCTX;
}


/*----------------------------------------------------------------------------
*Function: SsbSipJPEGEncodeInit

*Parameters:
*Return Value:		Encoder Init handle
*Implementation Notes: Initialize JPEG Encoder Deivce Driver
-----------------------------------------------------------------------------*/
void *SsbSipJPEGEncodeInit(void)
{
    _JPGLIB    *pCTX = NULL;
	CMM_ALLOC_PRAM_T	CMMParam;
	JPEG_ERRORTYPE ret;
    int         phyJPGDataAddr, virJPGDataAddr;

    // DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s++\r\n"), _T(__FUNCTION__)));
	pCTX = (_JPGLIB *) malloc(sizeof(_JPGLIB));
	if (pCTX == NULL)
	{
        // ERRMSG((_T("[JPGAPI] SsbSipJPEGEncodeInit :: malloc failed.\r\n")));
		return NULL;
	}
	memset(pCTX, 0x00, sizeof(_JPGLIB));

    pCTX->hJPG = CreateFile(JPG_DRIVER_NAME,
							GENERIC_READ|GENERIC_WRITE,
							0,
							NULL,
							OPEN_EXISTING,
							FILE_ATTRIBUTE_NORMAL,NULL);
	if(pCTX->hJPG == INVALID_HANDLE_VALUE){
        // ERRMSG((_T("[JPGAPI] SsbSipJPEGEncodeInit :: JPG Open failure.\r\n")));
		free(pCTX);
		return NULL;
	}

	pCTX->hCMM = CreateFile(CMM_DRIVER_NAME,
					   GENERIC_READ|GENERIC_WRITE,
					   0,
					   NULL,
					   OPEN_EXISTING,
					   FILE_ATTRIBUTE_NORMAL,
					   NULL);
	if (pCTX->hCMM == INVALID_HANDLE_VALUE)
	{
        // ERRMSG((_T("[JPGAPI] SsbSipJPEGEncodeInit :: CMM Open failure.\r\n")));
		free(pCTX);
		return NULL;
	}

	pCTX->args.encParam = (JPG_ENC_PROC_PARAM *)malloc(sizeof(JPG_ENC_PROC_PARAM));
	if(pCTX->args.encParam == NULL){
        // ERRMSG((_T("[JPGAPI] SsbSipJPEGEncodeInit :: Out of Memory\r\n")));
		free(pCTX);
		return NULL;
	}
	memset(pCTX->args.encParam, 0x00, sizeof(JPG_ENC_PROC_PARAM));

	pCTX->args.thumbEncParam = (JPG_ENC_PROC_PARAM *)malloc(sizeof(JPG_ENC_PROC_PARAM));
	if(pCTX->args.thumbEncParam == NULL){
        // ERRMSG((_T("[JPGAPI] SsbSipJPEGEncodeInit :: Out of Memory\r\n")));
	    free(pCTX);
		return NULL;
	}
	memset(pCTX->args.thumbEncParam, 0x00, sizeof(JPG_ENC_PROC_PARAM));

	pCTX->args.encParam->sampleMode = JPG_420;
	pCTX->args.encParam->encType = JPG_MAIN;
	pCTX->args.thumbEncParam->sampleMode = JPG_420;
	pCTX->args.thumbEncParam->encType = JPG_THUMBNAIL;
	pCTX->thumbnailFlag = FALSE;


    ///////////////////////////////////////
    // make JPEG encode output buffer
    ///////////////////////////////////////
	// CMM main buffer alloc
	CMMParam.size = (unsigned int)MAX_FILE_SIZE;
	CMMParam.cacheFlag = 0;
    CMMParam.dramLocation = DRAM_1;

	ret = DeviceIoControl(pCTX->hCMM, IOCTL_CODEC_MEM_ALLOC, (PBYTE)&CMMParam, 
					sizeof(CMM_ALLOC_PRAM_T *), &(virJPGDataAddr), sizeof(virJPGDataAddr), NULL, NULL);
	if(ret == FALSE){
        // ERRMSG((_T("[JPGAPI] SsbSipJPEGDecodeInit :: IOCTL_CODEC_MEM_ALLOC failed\r\n")));
		free(pCTX);
		return NULL;
	}

	ret = DeviceIoControl(pCTX->hCMM, IOCTL_CODEC_GET_PHY_ADDR, (PBYTE)virJPGDataAddr, 
							sizeof(virJPGDataAddr), &(phyJPGDataAddr), sizeof(phyJPGDataAddr), 
							NULL, NULL);
	if(ret == FALSE)
	{
        // ERRMSG((_T("[JPGAPI] SsbSipJPEGDecodeInit :: IOCTL_CODEC_GET_PHY_ADDR failed\r\n")));
		free(pCTX);
		return NULL;
	}
    pCTX->args.OutBuf = (char *)virJPGDataAddr;
    pCTX->args.phyOutBuf = (char *)phyJPGDataAddr;

    // CMM Thumbnail buffer alloc
	CMMParam.size = (unsigned int)MAX_FILE_THUMB_SIZE;
	CMMParam.cacheFlag = 0;
    CMMParam.dramLocation = DRAM_1;

	ret = DeviceIoControl(pCTX->hCMM, IOCTL_CODEC_MEM_ALLOC, (PBYTE)&CMMParam, 
					sizeof(CMM_ALLOC_PRAM_T *), &(virJPGDataAddr), sizeof(virJPGDataAddr), NULL, NULL);
	if(ret == FALSE){
        // ERRMSG((_T("[JPGAPI] SsbSipJPEGDecodeInit :: IOCTL_CODEC_MEM_ALLOC failed\r\n")));
		free(pCTX);
		return NULL;
	}

	ret = DeviceIoControl(pCTX->hCMM, IOCTL_CODEC_GET_PHY_ADDR, (PBYTE)virJPGDataAddr, 
							sizeof(virJPGDataAddr), &(phyJPGDataAddr), sizeof(phyJPGDataAddr), 
							NULL, NULL);
	if(ret == FALSE)
	{
        // ERRMSG((_T("[JPGAPI] SsbSipJPEGDecodeInit :: IOCTL_CODEC_GET_PHY_ADDR failed\r\n")));
		free(pCTX);
		return NULL;
	}
    pCTX->args.OutThumbBuf = (char *)virJPGDataAddr;
    pCTX->args.phyOutThumbBuf = (char *)phyJPGDataAddr;

    // DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s--\r\n"), _T(__FUNCTION__)));
	return pCTX;
}


/*----------------------------------------------------------------------------
*Function: SsbSipJPEGDecodeExe

*Parameters: 		*openHandle	: openhandle from SsbSipJPEGDecodeInit
*Return Value:		JPEG_ERRORTYPE
*Implementation Notes: Decode JPEG file 
-----------------------------------------------------------------------------*/
JPEG_ERRORTYPE SsbSipJPEGDecodeExe(void *openHandle)
{
    _JPGLIB *pCTX;
    JPG_ARGS *pArgs;
	int	    ret;

	// DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s++\r\n"), _T(__FUNCTION__)));

	if (openHandle == NULL) 
	{
		// ERRMSG((_T("[JPGAPI] SsbSipJPEGDecodeExe :: openHandle is NULL\r\n")));
		return JPEG_FAIL;
	}

	pCTX  = (_JPGLIB *) openHandle;
    pArgs = &(pCTX->args);

	// DBGMSG(JPG_DBG,(_T("[JPGAPI] pCTX->args.decParam->fileSize : %d\r\n"), pCTX->args.decParam->fileSize));
	if(pCTX->args.decParam->decType == JPG_MAIN)
	{
		ret = DeviceIoControl(pCTX->hJPG, IOCTL_JPG_DECODE, pArgs, sizeof(JPG_ARGS),NULL, 0, (PDWORD)(pCTX->args.decParam), NULL);

		if(ret == 0)
		{
	            // ERRMSG((_T("[JPGAPI] SsbSipJPEGDecodeExe :: IOCTL_JPG_DECODE failed\r\n")));
            return JPEG_FAIL;
		}

	    // DBGMSG(JPG_DBG,(_T("[JPGAPI] decParam->width : %d decParam->height : %d\r\n"), pCTX->args.decParam->width, pCTX->args.decParam->height));
	    // DBGMSG(JPG_DBG,(_T("[JPGAPI] streamSize : %d\r\n"), pCTX->args.decParam->dataSize));
    }
	else
	{
		// thumbnail decode, for the future work.
	}
	// DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s--\r\n"), _T(__FUNCTION__)));
	return JPEG_OK;
}

/*----------------------------------------------------------------------------
*Function: makeThumbImage

*Parameters: 		*openHandle	: openhandle from SsbSipJPEGEncodeInit
*Return Value:		JPEG_ERRORTYPE	
*Implementation Notes: make thumbnail image
-----------------------------------------------------------------------------*/
static JPEG_ERRORTYPE makeThumbImage(void *openHandle)
{
    _JPGLIB *pCTX;
    JPG_ARGS *pArgs = NULL;
	int	    ret;
	int	    result;

    // DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s++\r\n"), _T(__FUNCTION__)));
	if (openHandle == NULL)
	{
        // ERRMSG((_T("[JPGAPI] makeThumbImage :: openHandle is NULL\r\n")));
		return JPEG_FAIL;
	}

	pCTX  = (_JPGLIB *) openHandle;
    pArgs = &(pCTX->args);

    if((result = MCUCheck(pCTX->args.thumbEncParam->inFormat, pCTX->args.thumbEncParam->width, pCTX->args.thumbEncParam->height)) != JPEG_OK){
        // ERRMSG((_T("[JPGAPI] makeThumbImage :: thumbnail width/height doesn't match with MCU\r\n")));
		return JPEG_FAIL;
	}

	// encode thumbnail image
	ret = DeviceIoControl(pCTX->hJPG, IOCTL_JPG_ENCODE, 
	                    pArgs, sizeof(JPG_ARGS),
	                    NULL, 0, 
	                    (LPDWORD)pCTX->args.thumbEncParam, NULL);
	if(ret == 0){
            // ERRMSG((_T("[JPGAPI] makeThumbImage :: IOCTL_JPG_ENCODE failed\r\n")));
			return JPEG_FAIL;
	}

	if(pCTX->args.thumbEncParam->fileSize > MAX_FILE_THUMB_SIZE){
        // ERRMSG((_T("[JPGAPI] makeThumbImage :: thumbnail data is too big\r\n")));
		return JPEG_FAIL;
	}

    // DBGMSG(JPG_DBG,(_T("[JPGAPI] thumbFilesize : %d\r\n"), pCTX->args.thumbEncParam->fileSize));
    // DBGMSG(JPG_DBG,(_T("[JPGAPI] pCTX->args.OutThumbBuf(addr : 0x%08x callerProcessID : 0x%x)\r\n"), pCTX->args.OutThumbBuf, (HANDLE)GetCurrentProcessId()));

    // DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s--\r\n"), _T(__FUNCTION__)));	
	return JPEG_OK;
}


/*----------------------------------------------------------------------------
*Function: MCUCheck

*Parameters: 		*openHandle	: openhandle from SsbSipJPEGEncodeInit
*Return Value:		JPEG_ERRORTYPE	
*Implementation Notes: check MCU
-----------------------------------------------------------------------------*/
static JPEG_ERRORTYPE MCUCheck(IN_MODE_T format, UINT32 width, UINT32 height)
{

    // DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s++\r\n"), _T(__FUNCTION__)));
    switch (format) {
        case JPG_MODESEL_YCBCR: 
        	if(width%16 == 0 && height%8 == 0)
        		return JPEG_OK;
        case JPG_MODESEL_RGB: 
        	return JPEG_OK;
        default: return JPEG_FAIL;
    }

    // DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s--\r\n"), _T(__FUNCTION__)));
	return JPEG_FAIL;
}


/*----------------------------------------------------------------------------
*Function: scalDownYUV422

*Parameters: 		*srcBuf: input yuv buffer
					srcWidth: width of input yuv
					srcHeight: height of input yuv
					*dstBuf: output yuv buffer
					dstWidth: width of output yuv
					dstHeight: height of output yuv
*Return Value:		None	
*Implementation Notes: scaling down YCBYCR format
-----------------------------------------------------------------------------*/
static void scalDownYUV422(char *srcBuf, INT32 srcWidth, INT32 srcHeight, 
				char *dstBuf, INT32 dstWidth, INT32 dstHeight)
{
	INT32	scaleX, scaleY;
	INT32	iXsrc, iXdst;
	INT32	iYsrc;

    // DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s++\r\n"), _T(__FUNCTION__)));
	scaleX = srcWidth/dstWidth;
	scaleY = srcHeight/dstHeight;

	iXdst = 0;
	for(iYsrc=0; iYsrc < srcHeight; iYsrc++){
		if(iYsrc % scaleY == 0){
			for(iXsrc = iYsrc*srcWidth*2; iXsrc < iYsrc*srcWidth*2+srcWidth*2;){
				if((iXsrc % (4*scaleX)) == 0){
					dstBuf[iXdst++] = srcBuf[iXsrc++];
					dstBuf[iXdst++] = srcBuf[iXsrc++];
					dstBuf[iXdst++] = srcBuf[iXsrc++];
					dstBuf[iXdst++] = srcBuf[iXsrc++];
				}else iXsrc++;
			}
		}
	}

    // DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s--\r\n"), _T(__FUNCTION__)));
}


/*----------------------------------------------------------------------------
*Function: scalDownRGB565

*Parameters: 		*srcBuf: input rgb buffer
					srcWidth: width of input rgb
					srcHeight: height of input rgb
					*dstBuf: output rgb buffer
					dstWidth: width of output rgb
					dstHeight: height of output rgb
*Return Value:		None	
*Implementation Notes: scaling down RGB565 format
-----------------------------------------------------------------------------*/
static void scalDownRGB565(char *srcBuf, INT32 srcWidth, INT32 srcHeight, 
				char *dstBuf, INT32 dstWidth, INT32 dstHeight)
{
	INT32	scaleX, scaleY;
	INT32	iXsrc, iXdst;
	INT32	iYsrc;

    // DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s++\r\n"), _T(__FUNCTION__)));
	scaleX = srcWidth/dstWidth;
	scaleY = srcHeight/dstHeight;

	iXdst = 0;
	for(iYsrc=0; iYsrc < srcHeight; iYsrc++){
		if(iYsrc % scaleY == 0){
			for(iXsrc = iYsrc*srcWidth*2; iXsrc < iYsrc*srcWidth*2+srcWidth*2;){
				if((iXsrc % (2*scaleX)) == 0){
					dstBuf[iXdst++] = srcBuf[iXsrc++];
					dstBuf[iXdst++] = srcBuf[iXsrc++];
				}else iXsrc++;
			}
		}
	}
    // DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s--\r\n"), _T(__FUNCTION__)));
}


/*----------------------------------------------------------------------------
*Function: SsbSipJPEGEncodeExe

*Parameters: 		*openHandle : openhandle from SsbSipJPEGEncodeInit
					*Exif : Exif file parameter
*Return Value:		JPEG_ERRORTYPE
*Implementation Notes: Encode JPEG file 
-----------------------------------------------------------------------------*/
JPEG_ERRORTYPE SsbSipJPEGEncodeExe(void *openHandle, ExifFileInfo *Exif)
{
    _JPGLIB *pCTX;
    JPG_ARGS *pArgs = NULL;
	char *outBuf = NULL;
	char *ExifBuf;
	UINT ExifLen;
	UINT bufSize;
	CMM_ALLOC_PRAM_T	CMMParam;
	JPEG_ERRORTYPE result;
	int ret;

    // DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s++\r\n"), _T(__FUNCTION__)));
	if (openHandle == NULL)
	{
        // ERRMSG((_T("[JPGAPI] SsbSipJPEGEncodeExe :: openHandle is NULL\r\n")));
		return JPEG_FAIL;
	}

	pCTX  = (_JPGLIB *) openHandle;
    pArgs = &(pCTX->args);


	// check MUC validation with width & hegiht & sampling mode
	if((result = MCUCheck(pCTX->args.encParam->inFormat, pCTX->args.encParam->width, pCTX->args.encParam->height)) != JPEG_OK){
        // ERRMSG((_T("[JPGAPI] SsbSipJPEGEncodeExe :: width/height doesn't match with MCU\r\n")));
		return JPEG_FAIL;
	}

	// check validation of input datasize
	if((pCTX->args.encParam->width)*(pCTX->args.encParam->height)*2 != pCTX->args.encParam->dataSize){
        // ERRMSG((_T("[JPGAPI] SsbSipJPEGEncodeExe :: data size and width/height doesn't match\r\n")));
		return JPEG_FAIL;
	}

	// scale down data for thumbnail encoding
	if((Exif != NULL) && (pCTX->thumbnailFlag == TRUE)){
		if((pCTX->args.encParam->width % pCTX->args.thumbEncParam->width != 0) 
			|| (pCTX->args.encParam->height % pCTX->args.thumbEncParam->height != 0)){
            // ERRMSG((_T("[JPGAPI] SsbSipJPEGEncodeExe ::Main JPEG  have to be multiple of Thumbnail resolution \r\n")));
			return JPEG_FAIL;
		}

		pCTX->args.thumbEncParam->dataSize = (pCTX->args.thumbEncParam->width)*(pCTX->args.thumbEncParam->height)*2;

        // CMM Thumbnail input buffer alloc
    	CMMParam.size = pCTX->args.thumbEncParam->dataSize;
    	CMMParam.cacheFlag = 0;
        CMMParam.dramLocation = DRAM_1;

    	ret = DeviceIoControl(pCTX->hCMM, IOCTL_CODEC_MEM_ALLOC, (PBYTE)&CMMParam, 
    					sizeof(CMM_ALLOC_PRAM_T *), &(pCTX->args.InThumbBuf), sizeof(pCTX->args.InThumbBuf), NULL, NULL);
    	if(ret == FALSE){
            // ERRMSG((_T("[JPGAPI] SsbSipJPEGEncodeExe :: IOCTL_CODEC_MEM_ALLOC failed\r\n")));
    		return JPEG_FAIL;
    	}

    	ret = DeviceIoControl(pCTX->hCMM, IOCTL_CODEC_GET_PHY_ADDR, (PBYTE)pCTX->args.InThumbBuf, 
    							sizeof(pCTX->args.InThumbBuf), &(pCTX->args.phyInThumbBuf), sizeof(pCTX->args.phyInThumbBuf), 
    							NULL, NULL);
    	if(ret == FALSE)
    	{
            // ERRMSG((_T("[JPGAPI] SsbSipJPEGEncodeExe :: IOCTL_CODEC_GET_PHY_ADDR failed\r\n")));
    		return JPEG_FAIL;
    	}
        // DBGMSG(JPG_DBG,(_T("[JPGAPI] pCTX->args.InThumbBuf(addr : 0x%08x callerProcessID : 0x%x)\r\n"), pCTX->args.InThumbBuf, (HANDLE)GetCurrentProcessId()));

        // scale down intput image to make thumbnail image
        switch (pCTX->args.encParam->inFormat) {
            case JPG_MODESEL_YCBCR: 
                scalDownYUV422(pCTX->args.InBuf, pCTX->args.encParam->width, pCTX->args.encParam->height, 
    						pCTX->args.InThumbBuf, pCTX->args.thumbEncParam->width, pCTX->args.thumbEncParam->height);
                break;
            case JPG_MODESEL_RGB:
                scalDownRGB565(pCTX->args.InBuf, pCTX->args.encParam->width, pCTX->args.encParam->height, 
    						pCTX->args.InThumbBuf, pCTX->args.thumbEncParam->width, pCTX->args.thumbEncParam->height);
                break;
            default: 
                return JPEG_FAIL;
        }

	}

	// encode main image
	ret = DeviceIoControl(pCTX->hJPG, IOCTL_JPG_ENCODE, 
	                    pArgs, sizeof(JPG_ARGS),
	                    NULL, 0, 
	                    (LPDWORD)pCTX->args.encParam, NULL);
	if(ret == 0){
            // ERRMSG((_T("[JPGAPI] SsbSipJPEGEncodeExe :: IOCTL_JPG_ENCODE failed\r\n")));
			return JPEG_FAIL;
	}

	// if user want to make Exif file
	if(Exif){
		pCTX->ExifInfo = Exif;

		// encode thumbnail image
		if(pCTX->thumbnailFlag){			
			if((ret = makeThumbImage(openHandle)) != JPEG_OK)
				return JPEG_FAIL;

			bufSize = EXIF_FILE_SIZE + pCTX->args.thumbEncParam->fileSize;
		}else 
			bufSize = EXIF_FILE_SIZE;

		if(pCTX->args.encParam->fileSize + bufSize > MAX_FILE_SIZE){
            // ERRMSG((_T("[JPGAPI] SsbSipJPEGEncodeExe :: Exif Error - out of JPEG output buffer\r\n")));
			return JPEG_FAIL;
		}

		ExifBuf = (char *)malloc(bufSize);
		if(ExifBuf == NULL){
            // ERRMSG((_T("[JPGAPI] SsbSipJPEGEncodeExe :: Out of Memory\r\n")));
			return JPEG_OUT_OF_MEMORY;
		}
        // DBGMSG(JPG_DBG,(_T("[JPGAPI] ExifBuf (addr : 0x%08x)\r\n"), ExifBuf));
		memset(ExifBuf, 0x20, bufSize);

		// make Exif file including thumbnail image
		if((result = makeExifFile(pCTX, ExifBuf, &ExifLen)) != JPEG_OK){
			free(ExifBuf);
			return JPEG_FAIL;
		}

	    // DBGMSG(JPG_DBG,(_T("[JPGAPI] ExifLen : %d pCTX->args.encParam->fileSize : %d\r\n"), ExifLen, pCTX->args.encParam->fileSize));
		// merge Exif file with encoded JPEG file header
		memmove(&pCTX->args.OutBuf[ExifLen+2], &pCTX->args.OutBuf[2], pCTX->args.encParam->fileSize - 2); 
		memcpy(&pCTX->args.OutBuf[2], ExifBuf, ExifLen);
		pCTX->args.encParam->fileSize += ExifLen;
		free(ExifBuf);
	}

    // DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s--\r\n"), _T(__FUNCTION__)));
	return JPEG_OK;
}


/*----------------------------------------------------------------------------
*Function: SsbSipJPEGGetDecodeInBuf

*Parameters: 		*openHandle : openhandle from SsbSipJPEGDecodeInit
					size : input stream(YUV/RGB) size
*Return Value:		virtual address of Decoder input buffer
*Implementation Notes: allocate decoder input buffer 
-----------------------------------------------------------------------------*/
void *SsbSipJPEGGetDecodeInBuf(void *openHandle, long size)
{
    _JPGLIB *pCTX;
	CMM_ALLOC_PRAM_T	CMMParam;
	int     ret;


    // DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s++\r\n"), _T(__FUNCTION__)));
	if(size < 0 || size > MAX_FILE_SIZE){
        // ERRMSG((_T("[JPGAPI] SsbSipJPEGGetDecodeInBuf :: Invalid Decoder input buffer size\r\n")));
		return NULL;
	}

	if (openHandle == NULL)
	{
        // ERRMSG((_T("[JPGAPI] SsbSipJPEGGetDecodeInBuf :: openHandle is NULL\r\n")));
		return NULL;
	}

	pCTX  = (_JPGLIB *) openHandle;

	// CMM alloc
	CMMParam.size = (unsigned int)size;
	CMMParam.cacheFlag = 0;
    CMMParam.dramLocation = DRAM_1;

	pCTX->args.decParam->fileSize = size;
	
	ret = DeviceIoControl(pCTX->hCMM, IOCTL_CODEC_MEM_ALLOC, (PBYTE)&CMMParam, 
					sizeof(CMM_ALLOC_PRAM_T *), &(pCTX->args.InBuf), sizeof(pCTX->args.InBuf), NULL, NULL);
	if(ret == FALSE){
        // ERRMSG((_T("[JPGAPI] SsbSipJPEGGetDecodeInBuf :: IOCTL_CODEC_MEM_ALLOC failed\r\n")));
		return NULL;
	}

	ret = DeviceIoControl(pCTX->hCMM, IOCTL_CODEC_GET_PHY_ADDR, (PBYTE)pCTX->args.InBuf, 
							sizeof(pCTX->args.InBuf), &(pCTX->args.phyInBuf), sizeof(pCTX->args.phyInBuf), 
							NULL, NULL);
	if(ret == FALSE)
	{
        // ERRMSG((_T("[JPGAPI] SsbSipJPEGGetDecodeInBuf :: IOCTL_CODEC_GET_PHY_ADDR failed\r\n")));
		return NULL;
	}

    // DBGMSG(JPG_DBG,(_T("[JPGAPI] pCTX->InBuf(addr : 0x%08x size: %d callerProcessID : 0x%x)\r\n"), pCTX->args.InBuf, size, (HANDLE)GetCurrentProcessId()));
    // DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s--\r\n"), _T(__FUNCTION__)));
	return (void *)(pCTX->args.InBuf);
}


/*----------------------------------------------------------------------------
*Function: SsbSipJPEGGetDecodeOutBuf

*Parameters: 		*openHandle : openhandle from SsbSipJPEGDecodeInit
					size : output JPEG file size
*Return Value:		virtual address of Decoder output buffer
*Implementation Notes: return decoder output buffer 
-----------------------------------------------------------------------------*/
void *SsbSipJPEGGetDecodeOutBuf (void *openHandle, long *size)
{
    _JPGLIB *pCTX;

    // DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s++\r\n"), _T(__FUNCTION__)));
	if (openHandle == NULL)
	{
        // ERRMSG((_T("[JPGAPI] SsbSipJPEGGetDecodeOutBuf :: openHandle is NULL\r\n")));
		return NULL;
	}

	pCTX  = (_JPGLIB *) openHandle;

	*size = pCTX->args.decParam->dataSize;
    // DBGMSG(JPG_DBG,(_T("[JPGAPI] DecodeOutBuf : 0x%08x size : %d\r\n"), pCTX->args.OutBuf, pCTX->args.decParam->dataSize));
    // DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s--\r\n"), _T(__FUNCTION__)));
	return (pCTX->args.OutBuf);
}


/*----------------------------------------------------------------------------
*Function: SsbSipJPEGGetEncodeInBuf

*Parameters: 		*openHandle : openhandle from SsbSipJPEGEncodeInit
					size : input JPEG file size
*Return Value:		virtual address of Encoder input buffer
*Implementation Notes: allocate encoder input buffer 
-----------------------------------------------------------------------------*/
void *SsbSipJPEGGetEncodeInBuf(void *openHandle, long size)
{	
    _JPGLIB *pCTX;
	CMM_ALLOC_PRAM_T	CMMParam;
	int     ret;

    // DBGMSG(JPG_FUNC,(_T("[JPGAPI]  %s++\r\n"), _T(__FUNCTION__)));
	if(size < 0 || size > MAX_YUV_SIZE){
        // ERRMSG((_T("[JPGAPI] SsbSipJPEGGetEncodeInBuf :: Invalid Encoder input buffer size(%d)\r\n"), size));
		return NULL;
	}

	if (openHandle == NULL)
	{
        // ERRMSG((_T("[JPGAPI] SsbSipJPEGGetEncodeInBuf :: openHandle is NULL\r\n")));
		return NULL;
	}

	pCTX  = (_JPGLIB *) openHandle;

	// CMM alloc
	CMMParam.size = (unsigned int)size;
	CMMParam.cacheFlag = 0;
    CMMParam.dramLocation = DRAM_1;
    
	pCTX->args.encParam->dataSize = size;

	ret = DeviceIoControl(pCTX->hCMM, IOCTL_CODEC_MEM_ALLOC, (PBYTE)&CMMParam, 
					sizeof(CMM_ALLOC_PRAM_T *), &(pCTX->args.InBuf), sizeof(pCTX->args.InBuf), NULL, NULL);
	if(ret == FALSE){
        // ERRMSG((_T("[JPGAPI] SsbSipJPEGGetEncodeInBuf :: IOCTL_CODEC_MEM_ALLOC failed\r\n")));
		return NULL;
	}

	ret = DeviceIoControl(pCTX->hCMM, IOCTL_CODEC_GET_PHY_ADDR, (PBYTE)pCTX->args.InBuf, 
							sizeof(pCTX->args.InBuf), &(pCTX->args.phyInBuf), sizeof(pCTX->args.phyInBuf), 
							NULL, NULL);
	if(ret == FALSE)
	{
        // ERRMSG((_T("[JPGAPI] SsbSipJPEGGetEncodeInBuf :: IOCTL_CODEC_GET_PHY_ADDR failed\r\n")));
		return NULL;
	}

    // DBGMSG(JPG_DBG,(_T("[JPGAPI] pCTX->args.InBuf(addr : 0x%08x size: %d callerProcessID : 0x%x)\r\n"), pCTX->args.InBuf, size, (HANDLE)GetCurrentProcessId()));

    // DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s--\r\n"), _T(__FUNCTION__)));
	return (pCTX->args.InBuf);
}


/*----------------------------------------------------------------------------
*Function: SsbSipJPEGGetEncodeOutBuf

*Parameters: 		*openHandle : openhandle from SsbSipJPEGEncodeInit
					*size : output stream(YUV/RGB) size
*Return Value:		virtual address of Encoder output buffer
*Implementation Notes: return encoder output buffer 
-----------------------------------------------------------------------------*/
void *SsbSipJPEGGetEncodeOutBuf (void *openHandle, long *size)
{
    _JPGLIB *pCTX;

    // DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s++\r\n"), _T(__FUNCTION__)));
	if (openHandle == NULL)
	{
        // ERRMSG((_T("[JPGAPI] SsbSipJPEGGetEncodeOutBuf :: openHandle is NULL\r\n")));
		return NULL;
	}

	pCTX  = (_JPGLIB *) openHandle;
    
	*size = pCTX->args.encParam->fileSize;

    // DBGMSG(JPG_DBG,(_T("[JPGAPI] EncodeOutBuf : 0x%08x size : %d\r\n"), pCTX->args.OutBuf, pCTX->args.encParam->fileSize));
    // DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s--\r\n"), _T(__FUNCTION__)));
	return (pCTX->args.OutBuf);

}


/*----------------------------------------------------------------------------
*Function: SsbSipJPEGGetConfig

*Parameters: 		type : config type to get
					*value : config value to get
*Return Value:		JPEG_ERRORTYPE
*Implementation Notes: return JPEG config value to user 
-----------------------------------------------------------------------------*/
JPEG_ERRORTYPE SsbSipJPEGGetConfig (void *openHandle, JPEGConf type, INT32 *value)
{
    _JPGLIB *pCTX;
	JPEG_ERRORTYPE result = JPEG_OK;

    // DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s++\r\n"), _T(__FUNCTION__)));
	if (openHandle == NULL)
	{
        // ERRMSG((_T("[JPGAPI] SsbSipJPEGGetConfig :: openHandle is NULL\r\n")));
		return JPEG_FAIL;
	}

	pCTX  = (_JPGLIB *) openHandle;
    
	switch(type){
		case JPEG_GET_DECODE_WIDTH: *value = (INT32)pCTX->args.decParam->width; break;
		case JPEG_GET_DECODE_HEIGHT: *value = (INT32)pCTX->args.decParam->height; break;
		case JPEG_GET_DECODE_YUV_WIDTH: *value = (INT32)pCTX->args.decParam->yuvwidth; break;
		case JPEG_GET_DECODE_YUV_HEIGHT: *value = (INT32)pCTX->args.decParam->yuvheight; break;
		case JPEG_GET_SAMPING_MODE: *value = (INT32)pCTX->args.decParam->sampleMode; break;
		default : 
            // ERRMSG((_T("[JPGAPI] SsbSipJPEGGetConfig :: Invalid Config type\r\n")));
			result = JPEG_FAIL;
	}

    // DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s--\r\n"), _T(__FUNCTION__)));
	return result;
}


/*----------------------------------------------------------------------------
*Function: SsbSipJPEGSetConfig

*Parameters: 		type : config type to set
					*value : config value to set
*Return Value:		JPEG_ERRORTYPE
*Implementation Notes: set JPEG config value from user 
-----------------------------------------------------------------------------*/
JPEG_ERRORTYPE SsbSipJPEGSetConfig (void *openHandle, JPEGConf type, INT32 value)
{
    _JPGLIB *pCTX;
	JPEG_ERRORTYPE result = JPEG_OK;

    // DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s++\r\n"), _T(__FUNCTION__)));
    // DBGMSG(JPG_DBG,(_T("[JPGAPI] SsbSipJPEGSetConfig(%d : %d)\r\n"), type, value));

	if (openHandle == NULL)
	{
        // ERRMSG((_T("[JPGAPI] SsbSipJPEGSetConfig :: openHandle is NULL\r\n")));
		return JPEG_FAIL;
	}

	pCTX  = (_JPGLIB *) openHandle;

	switch(type){
        case JPEG_SET_DECODE_OUT_FORMAT: 
			{
				if(value != YCBCR_420 && value != YCBCR_422)
				{
                    // ERRMSG((_T("[JPGAPI] SsbSipJPEGSetConfig :: Invalid decode output format\r\n")));
					result = JPEG_FAIL;
				}
				else
				{
					pCTX->args.decParam->outFormat = value;
				}
				break;
			}
        case JPEG_SET_ENCODE_WIDTH: 
			{
				if(value < 0 || value > MAX_JPG_WIDTH){
                    // ERRMSG((_T("[JPGAPI] SsbSipJPEGSetConfig :: Invalid width\r\n")));
					result = JPEG_FAIL;
				}else
					pCTX->args.encParam->width = value; 
				break;
			}
		case JPEG_SET_ENCODE_HEIGHT: 
			{
				if(value < 0 || value > MAX_JPG_HEIGHT){
                    // ERRMSG((_T("[JPGAPI] SsbSipJPEGSetConfig :: Invalid height\r\n")));
					result = JPEG_FAIL;
				}else
					pCTX->args.encParam->height = value;
				break;
			}	
		case JPEG_SET_ENCODE_QUALITY:
			{
				if(value < JPG_QUALITY_LEVEL_1 || value > JPG_QUALITY_LEVEL_4){
                    // ERRMSG((_T("[JPGAPI] SsbSipJPEGSetConfig :: Invalid Quality value\r\n")));
					result = JPEG_FAIL;
				}else
					pCTX->args.encParam->quality = value;
					pCTX->args.thumbEncParam->quality = value;
				break;
			}
		case JPEG_SET_ENCODE_THUMBNAIL: 
			{
				if((value != TRUE) && (value != FALSE)){
                    // ERRMSG((_T("[JPGAPI] SsbSipJPEGSetConfig :: Invalid thumbnailFlag\r\n")));
					result = JPEG_FAIL;
				}else
					pCTX->thumbnailFlag = value;
				break;
			}
        case JPEG_SET_ENCODE_IN_FORMAT: 
			{
				if(value != JPG_MODESEL_YCBCR && value != JPG_MODESEL_RGB){
                    // ERRMSG((_T("[JPGAPI] SsbSipJPEGSetConfig :: Invalid sampleMode\r\n")));
					result = JPEG_FAIL;
				}
				else{
					pCTX->args.encParam->inFormat = value;
					pCTX->args.thumbEncParam->inFormat = value;
				}
				break;
			}
        case JPEG_SET_ENCODE_Y16: 
			{
				if(value != JPG_MODE_Y16_0 && value != JPG_MODE_Y16_16){
                    // ERRMSG((_T("[JPGAPI] SsbSipJPEGSetConfig :: Invalid sampleMode\r\n")));
					result = JPEG_FAIL;
				}
				else{
					pCTX->args.encParam->mode_Y16 = value;
					pCTX->args.thumbEncParam->mode_Y16 = value;
				}
				break;
			}
        case JPEG_SET_SAMPING_MODE: 
			{
				if(value != JPG_420 && value != JPG_422){
                    // ERRMSG((_T("[JPGAPI] SsbSipJPEGSetConfig :: Invalid sampleMode\r\n")));
					result = JPEG_FAIL;
				}
				else{
					pCTX->args.encParam->sampleMode = value;
					pCTX->args.thumbEncParam->sampleMode = value;
				}
				break;
			}
		case JPEG_SET_THUMBNAIL_WIDTH: 
			{
				if(value < 0 || value > MAX_JPG_THUMBNAIL_WIDTH){
                    // ERRMSG((_T("[JPGAPI] SsbSipJPEGSetConfig :: Invalid thumbWidth\r\n")));
					result = JPEG_FAIL;
				}else
					pCTX->args.thumbEncParam->width = value;
				break;
			}
		case JPEG_SET_THUMBNAIL_HEIGHT: 
			{
				if(value < 0 || value > MAX_JPG_THUMBNAIL_HEIGHT){
                    // ERRMSG((_T("[JPGAPI] SsbSipJPEGSetConfig :: Invalid thumbHeight\r\n")));
                    result = JPEG_FAIL;
				}else
					pCTX->args.thumbEncParam->height = value;
				break;
			}
		default : 
            // ERRMSG((_T("[JPGAPI] SsbSipJPEGSetConfig :: Invalid Config type\r\n")));
			result = JPEG_FAIL;
	}

    // DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s--\r\n"), _T(__FUNCTION__)));
	return result;
}


/*----------------------------------------------------------------------------
*Function: SsbSipJPEGDecodeDeInit

*Parameters: 		*openHandle : openhandle from SsbSipJPEGDecodeInit
*Return Value:		JPEG_ERRORTYPE
*Implementation Notes: Deinitialize JPEG Decoder Device Driver 
-----------------------------------------------------------------------------*/
JPEG_ERRORTYPE SsbSipJPEGDecodeDeInit (void *openHandle)
{
	_JPGLIB  *pCTX;

    // DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s++\r\n"), _T(__FUNCTION__)));
	if (openHandle == NULL)
	{
        // ERRMSG((_T("[JPGAPI] SsbSipJPEGDecodeDeInit :: openHandle is NULL\r\n")));
		return JPEG_FAIL;
	}
    
    pCTX=(_JPGLIB *)openHandle;
    

	if(pCTX->args.decParam != NULL)
		free(pCTX->args.decParam);

	CloseHandle(pCTX->hJPG);
	CloseHandle(pCTX->hCMM);
	free(pCTX);

    // DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s--\r\n"), _T(__FUNCTION__)));
	return JPEG_OK;
}

/*----------------------------------------------------------------------------
*Function: SsbSipJPEGEncodeDeInit

*Parameters: 		*openHandle : openhandle from SsbSipJPEGEncodeInit
*Return Value:		True/False
*Implementation Notes: Deinitialize JPEG Encoder Device Driver 
-----------------------------------------------------------------------------*/
JPEG_ERRORTYPE SsbSipJPEGEncodeDeInit (void *openHandle)
{
	_JPGLIB  *pCTX;

    
    // DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s++\r\n"), _T(__FUNCTION__)));
	if (openHandle == NULL)
	{
        // ERRMSG((_T("[JPGAPI] SsbSipJPEGEncodeDeInit :: openHandle is NULL\r\n")));
		return JPEG_FAIL;
	}
    pCTX=(_JPGLIB *)openHandle;
    

	if(pCTX->args.encParam != NULL)
		free(pCTX->args.encParam);

	if(pCTX->args.thumbEncParam != NULL)
		free(pCTX->args.thumbEncParam);

	if(pCTX->ExifInfo != NULL)
		free(pCTX->ExifInfo);

	CloseHandle(pCTX->hJPG);
	CloseHandle(pCTX->hCMM);
	free(pCTX);
    
    // DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s--\r\n"), _T(__FUNCTION__)));
	return JPEG_OK;
}


/*----------------------------------------------------------------------------
*Function: SsbSipJPEGDisplay

*Parameters: 		*openHandle : openhandle from SsbSipJPEGEncodeInit
*Return Value:		True/False
*Implementation Notes: Deinitialize JPEG Encoder Device Driver 
-----------------------------------------------------------------------------*/
void *SsbSipJPEGGetDecodeOutPhyBuf(void *openHandle)
{
    _JPGLIB *pCTX;

    // DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s++\r\n"), _T(__FUNCTION__)));
	if (openHandle == NULL)
	{
        // ERRMSG((_T("[JPGAPI] SsbSipJPEGGetDecodeOutPhyBuf :: openHandle is NULL\r\n")));
		return NULL;
	}
    pCTX=(_JPGLIB *)openHandle;

    // DBGMSG(JPG_DBG,(_T("[JPGAPI] phy_addr_frame : 0x%08x\r\n"), pCTX->args.phyOutBuf));
    // DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s--\r\n"), _T(__FUNCTION__)));
	return pCTX->args.phyOutBuf;
}


/*----------------------------------------------------------------------------
*Function: makeExifFile

*Parameters: 		*jCtx : Exif file information & thumbnail data
					*ExifOut : result buffer of Exif file
					*totalLen : the length of Exif file
*Return Value:
*Implementation Notes: make Exif file
-----------------------------------------------------------------------------*/

// julie.kwon@samsung.com
// WinCE 5.0, enable optimize option does excessive optimization.
// It causes Exif data broken.
//
#pragma optimize("", off)   
//
//
static JPEG_ERRORTYPE makeExifFile(_JPGLIB *pCTX, char *ExifOut, UINT *totalLen)
{
    UCHAR *ExifInitialCount = NULL;
	UCHAR *tempExif = (UCHAR *)ExifOut;
	UINT ExifSize;
	UINT santemp;
	UCHAR * startoftiff = NULL;
	UCHAR * IFD1OffsetAddress = NULL;
	UCHAR APP1Marker[2]=	{0xff,0xe1};
	UCHAR ExifLen[4]={0};
	UCHAR Nentries[2]={8,0};
	UCHAR SubIFDNentries[2]={18,0};
	UCHAR IFD1Nentries[2]={6,0};
	UCHAR EndOfEntry[4]={0};

	//VARIABLES FOR THE MAKE OF THE CAMERA
	UCHAR  maketag[2]={0xf,0x1};	
	UCHAR  makeformat[2]={0x2,0x0};
	UCHAR  Ncomponent[4]={32,0x0,0x0,0x0};
	char  make[32];
	UCHAR makeoffchar[4];
	UCHAR * offset;

	//VARIABLES FOR THE MODEL OF THE CAMERA
	UCHAR  modeltag[2]={0x10,0x1};	
	UCHAR  modelformat[2]={0x2,0x0};
	UCHAR  NcomponentModel[4]={32,0x0,0x0,0x0};		
	char  model[32];
	UCHAR modeloffchar[4];
	
	//VARIABLES FOR THE ORIENTATION OF THE CAMERA
	UCHAR  orientationtag[2]={0x12,0x1};	
	UCHAR  orientationformat[2]={0x3,0x0};
	UCHAR  NcomponentOrientation[4]={0x1,0x0,0x0,0x0};	
	UINT  Orientation[1];
	UCHAR  Orient[4] = {0};

		
	//VARIABLES FOR THE JPEG PROCESS
	UCHAR  Processtag[2]={0x00,0x02};	
	UCHAR  Processformat[2]={0x3,0x0};
	UCHAR  NcomponentProcess[4]={0x1,0x0,0x0,0x0};	
	UINT  Process[1];
	UCHAR  Proc[4] = {0};

	//VARIABLES FOR THE X-RESOLUTION OF THE IMAGE	
	UCHAR  XResolutiontag[2]={0x1A,0x1};	
	UCHAR  XResolutionformat[2]={0x5,0x0};
	UCHAR  NcomponentXResolution[4]={0x1,0x0,0x0,0x0};	
	UINT  XResolutionNum[1];//={0x00000048};
	UINT  XResolutionDen[1];//={0x00000001};
	
	UCHAR XResolutionoffchar[4];
	UCHAR XResolutionNumChar[4];
	UCHAR XResolutionDenChar[4];

	//VARIABLES FOR THE Y-RESOLUTION OF THE IMAGE
	UCHAR  YResolutiontag[2]={0x1B,0x1};	
	UCHAR  YResolutionformat[2]={0x5,0x0};
	UCHAR  NcomponentYResolution[4]={0x1,0x0,0x0,0x0};	
	UINT  YResolutionNum[1];//={0x00000048};
	UINT  YResolutionDen[1];//={0x00000001};
	
	UCHAR YResolutionoffchar[4];
	UCHAR YResolutionNumChar[4];
	UCHAR YResolutionDenChar[4];

	//VARIABLES FOR THE RESOLUTION UNIT OF THE CAMERA
	UCHAR  RUnittag[2]={0x28,0x1};	
	UCHAR  RUnitformat[2]={0x3,0x0};
	UCHAR  NcomponentRUnit[4]={0x1,0x0,0x0,0x0};	
	UINT  RUnit[1];
	UCHAR  RUnitChar[4] = {0};

	
	//VARIABLES FOR THE VERSION NO OF THE SOFTWARE
	UCHAR  Versiontag[2]={0x31,0x1};	
	UCHAR  Versionformat[2]={0x2,0x0};
	UCHAR  NcomponentVersion[4]={32,0x0,0x0,0x0};	
	char  Version[32];//="version 1.2";
	UCHAR Versionoffchar[4];

	//VARIABLES FOR THE DATE/TIME 
	UCHAR  DateTimetag[2]={0x32,0x1};	
	UCHAR  DateTimeformat[2]={0x2,0x0};
	UCHAR  NcomponentDateTime[4]={20,0,0,0};		
	UCHAR  DateTime[32];//="2006:6:09 15:17:32";
	char  DateTimeClose[1]={0};
	UCHAR DateTimeoffchar[4];

	//VARIABLES FOR THE COPYRIGHT
	UCHAR  CopyRighttag[2]={0x98,0x82};	
	UCHAR  CopyRightformat[2]={0x2,0x0};
	UCHAR  NcomponentCopyRight[4]={32,0x0,0x0,0x0};		
	char  CopyRight[32];
	UCHAR CopyRightoffchar[4];

	//VARIABLES FOR THE OFFSET TO SUBIFD 
	UCHAR  SubIFDOffsettag[2]={0x69,0x87};	
	UCHAR  SubIFDOffsetformat[2]={0x4,0x0};
	UCHAR  NcomponentSubIFDOffset[4]={0x1,0x0,0x0,0x0};		
	UCHAR  SubIFDOffsetChar[4] = {0};


	//VARIABLES FOR THE EXPOSURE TIME 	
	UCHAR  ExposureTimetag[2]={0x9A,0x82};	
	UCHAR  ExposureTimeformat[2]={0x5,0x0};
	UCHAR  NcomponentExposureTime[4]={0x1,0x0,0x0,0x0};	
	UINT  ExposureTimeNum[1];
	UINT  ExposureTimeDen[1];
	
	UCHAR ExposureTimeoffchar[4];
	UCHAR ExposureTimeNumChar[4];
	UCHAR ExposureTimeDenChar[4];

	//VARIABLES FOR THE FNUMBER	
	UCHAR  FNumbertag[2]={0x9D,0x82};	
	UCHAR  FNumberformat[2]={0x5,0x0};
	UCHAR  NcomponentFNumber[4]={0x1,0x0,0x0,0x0};	
	UINT  FNumberNum[1];
	UINT  FNumberDen[1];
	
	UCHAR FNumberoffchar[4];
	UCHAR FNumberNumChar[4];
	UCHAR FNumberDenChar[4];

	//VARIABLES FOR THE EXPOSURE PROGRAM OF THE CAMERA
	UCHAR  ExposureProgramtag[2]={0x22,0x88};	
	UCHAR  ExposureProgramformat[2]={0x3,0x0};
	UCHAR  NcomponentExposureProgram[4]={0x1,0x0,0x0,0x0};	
	UINT  ExposureProgram[1];
	UCHAR  ExposureProgramChar[4] = {0};

	//VARIABLES FOR THE ISO SPEED RATINGS OF THE CAMERA
	UCHAR  ISOSpeedRatingstag[2]={0x27,0x88};	
	UCHAR  ISOSpeedRatingsformat[2]={0x3,0x0};
	UCHAR  NcomponentISOSpeedRatings[4]={0x2,0x0,0x0,0x0};	
	unsigned short   ISOSpeedRatings[2];	
	UCHAR  ISOSpeedRatingsChar[4] = {0};

	//VARIABLES FOR THE BRIGHTNESS OF THE IMAGE	
	UCHAR  Brightnesstag[2]={0x03,0x92};	
	UCHAR  Brightnessformat[2]={0xA,0x0};
	UCHAR  NcomponentBrightness[4]={0x1,0x0,0x0,0x0};	
	int BrightnessNum[1];
	int BrightnessDen[1];
	
	UCHAR Brightnessoffchar[4];
	UCHAR BrightnessNumChar[4];
	UCHAR BrightnessDenChar[4];

	//VARIABLES FOR THE EXPOSURE Bias	
	UCHAR  ExposureBiastag[2]={0x04,0x92};	
	UCHAR  ExposureBiasformat[2]={0xA,0x0};
	UCHAR  NcomponentExposureBias[4]={0x1,0x0,0x0,0x0};	
	int ExposureBiasNum[1];//={-8};
	int ExposureBiasDen[1];//={1};
	
	UCHAR ExposureBiasoffchar[4];
	UCHAR ExposureBiasNumChar[4];
	UCHAR ExposureBiasDenChar[4];

	//VARIABLES FOR THE SUBJECT DISTANCE OF THE IMAGE	
	UCHAR  SubjectDistancetag[2]={0x06,0x92};	
	UCHAR  SubjectDistanceformat[2]={0xA,0x0};
	UCHAR  NcomponentSubjectDistance[4]={0x1,0x0,0x0,0x0};	
	int SubjectDistanceNum[1];
	int SubjectDistanceDen[1];
	
	UCHAR SubjectDistanceoffchar[4];
	UCHAR SubjectDistanceNumChar[4];
	UCHAR SubjectDistanceDenChar[4];

	//VARIABLES FOR THE METERING MODE
	UCHAR  MeteringModetag[2]={0x07,0x92};	
	UCHAR  MeteringModeformat[2]={0x3,0x0};
	UCHAR  NcomponentMeteringMode[4]={0x1,0x0,0x0,0x0};	
	UINT   MeteringMode[1];
	UCHAR  MeteringModeChar[4] = {0};

	//VARIABLES FOR THE FLASH
	UCHAR  Flashtag[2]={0x09,0x92};	
	UCHAR  Flashformat[2]={0x3,0x0};
	UCHAR  NcomponentFlash[4]={0x1,0x0,0x0,0x0};	
	UINT   Flash[1]={1};
	UCHAR  FlashChar[4] = {0};

	//VARIABLES FOR THE FOCAL LENGTH	
	UCHAR  FocalLengthtag[2]={0x0A,0x92};	
	UCHAR  FocalLengthformat[2]={0x5,0x0};
	UCHAR  NcomponentFocalLength[4]={0x1,0x0,0x0,0x0};	
	UINT FocalLengthNum[1];
	UINT FocalLengthDen[1];
	
	UCHAR FocalLengthoffchar[4];
	UCHAR FocalLengthNumChar[4];
	UCHAR FocalLengthDenChar[4];

    //VARIABLES FOR THE ISO WIDTH OF THE MAIN IMAGE			
	UCHAR  Widthtag[2]={0x02,0xA0};	
	UCHAR  Widthformat[2]={0x3,0x0};
	UCHAR  NcomponentWidth[4]={0x1,0x0,0x0,0x0};	
	UINT   Width[1];
	UCHAR  WidthChar[4] = {0};

	//VARIABLES FOR THE ISO HEIGHT OF THE MAIN IMAGE		
	UCHAR  Heighttag[2]={0x03,0xA0};	
	UCHAR  Heightformat[2]={0x3,0x0};
	UCHAR  NcomponentHeight[4]={0x1,0x0,0x0,0x0};	
	UINT   Height[1];
	UCHAR  HeightChar[4] = {0};

	//VARIABLES FOR THE COLORSPACE
	UCHAR  ColorSpacetag[2]={0x01,0xA0};	
	//char  ColorSpacetag[2]={0x54,0x56};
	UCHAR  ColorSpaceformat[2]={0x3,0x0};
	UCHAR  NcomponentColorSpace[4]={0x1,0x0,0x0,0x0};	
	UINT   ColorSpace[1];//={1};
	UCHAR  ColorSpaceChar[4] = {0};

	//VARIABLES FOR THE FocalPlaneXResolution	
	UCHAR  FocalPlaneXResolutiontag[2]={0x0E,0xA2};	
	UCHAR  FocalPlaneXResolutionformat[2]={0x5,0x0};
	UCHAR  NcomponentFocalPlaneXResolution[4]={0x1,0x0,0x0,0x0};	
	UINT FocalPlaneXResolutionNum[1];
	UINT FocalPlaneXResolutionDen[1];
	
	UCHAR FocalPlaneXResolutionoffchar[4];
	UCHAR FocalPlaneXResolutionNumChar[4];
	UCHAR FocalPlaneXResolutionDenChar[4];

	//VARIABLES FOR THE FocalPlaneYResolution 	
	UCHAR  FocalPlaneYResolutiontag[2]={0x0F,0xA2};	
	UCHAR  FocalPlaneYResolutionformat[2]={0x5,0x0};
	UCHAR  NcomponentFocalPlaneYResolution[4]={0x1,0x0,0x0,0x0};	
	UINT FocalPlaneYResolutionNum[1];
	UINT FocalPlaneYResolutionDen[1];
	
	UCHAR FocalPlaneYResolutionoffchar[4];
	UCHAR FocalPlaneYResolutionNumChar[4];
	UCHAR FocalPlaneYResolutionDenChar[4];

	//VARIABLES FOR THE FocalPlaneResolutionUnit
	UCHAR  FocalPlaneResolutionUnittag[2]={0x10,0xA2};	
	UCHAR  FocalPlaneResolutionUnitformat[2]={0x3,0x0};
	UCHAR  NcomponentFocalPlaneResolutionUnit[4]={0x1,0x0,0x0,0x0};	
	UINT   FocalPlaneResolutionUnit[1];
	UCHAR  FocalPlaneResolutionUnitChar[4] = {0};

	
	//VARIABLES FOR THE WHITE BALANCE PROGRAM OF THE CAMERA
	UCHAR  WhiteBalancetag[2]={0x07,0x00};	
	UCHAR  WhiteBalanceformat[2]={0x3,0x0};
	UCHAR  NcomponentWhiteBalance[4]={0x1,0x0,0x0,0x0};	
	UINT WhiteBalance[1];
	UCHAR  WhiteBalanceChar[4] = {0};

	//VARIABLES FOR THE USER COMMENTS
	UCHAR  UserCommentstag[2]={0x86,0x92};	
	UCHAR  UserCommentsformat[2]={0x7,0x0};
	UCHAR  NcomponentUserComments[4]={150,0x0,0x0,0x0};		
	UCHAR  UserComments[150];
	UCHAR UserCommentsoffchar[4];

	//VARIABLES FOR THE COMPRESSION TYPE
	UCHAR  Compressiontag[2]={0x03,0x01};	
	UCHAR  Compressionformat[2]={0x3,0x0};
	UCHAR  NcomponentCompression[4]={0x1,0x0,0x0,0x0};	
	UINT   Compression[1]={6};
	UCHAR  CompressionChar[4] = {0};

	//VARIABLES FOR THE JpegIFOffset 
	UCHAR  JpegIFOffsettag[2]={0x01,0x02};	
	UCHAR  JpegIFOffsetformat[2]={0x4,0x0};
	UCHAR  NcomponentJpegIFOffset[4]={0x1,0x0,0x0,0x0};		
	UCHAR  JpegIFOffsetChar[4] = {0};

	//VARIABLES FOR THE JpegIFByteCount 
	UCHAR  JpegIFByteCounttag[2]={0x02,0x02};	
	UCHAR  JpegIFByteCountformat[2]={0x4,0x0};
	UCHAR  NcomponentJpegIFByteCount[4]={0x1,0x0,0x0,0x0};		
	UCHAR  JpegIFByteCountChar[4] = {0};
	//END OF THE VARIABLES

    // DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s++\r\n"), _T(__FUNCTION__)));

	ExifInitialCount = tempExif;
    
	//for APP1 Marker(2 byte) and length(2 byte)
	tempExif += 4; 
	//write an exif header
	memcpy (tempExif, ExifHeader, 6);
	tempExif += 6 ;

	//write a tiff header
	memcpy (tempExif, TIFFHeader, 8);
	startoftiff=tempExif;
	tempExif += 8 ;
	//write no of entries in 1d0
	memcpy (tempExif, Nentries, 2);
	tempExif += 2 ;
	///////////////ENTRY NO 1 :MAKE OF CAMERA////////////////////////
	//write make tag
	memcpy (tempExif, maketag, 2);
	tempExif += 2 ;
	//write format
	memcpy (tempExif, makeformat, 2);
	tempExif += 2 ;
	//write no of component
	memcpy (tempExif, Ncomponent, 4);
	tempExif += 4 ;
	//write make
	//strcpy(make,tpJEInfo->Make);
	memcpy(make, pCTX->ExifInfo->Make,32);
	offset =(char*) 0x200;
	santemp=(int)(offset);
	makeoffchar[0]=(unsigned char)santemp;
	makeoffchar[1]=(unsigned char)(santemp>>8);
    makeoffchar[2]=(unsigned char)(santemp>>16);
	makeoffchar[3]=(unsigned char)(santemp>>24);
	//write the make offset into the bitstream
	memcpy (tempExif, makeoffchar, 4);
	tempExif += 4 ;
	memcpy (startoftiff+santemp, make, 32);
	offset+=32;
	
	///////////////ENTRY NO 2 :MODEL OF CAMERA////////////////////////
	//write model tag
	memcpy (tempExif, modeltag, 2);
	tempExif += 2 ;
	//write format
	memcpy (tempExif, modelformat, 2);
	tempExif += 2 ;
	//write no of component
	memcpy (tempExif, NcomponentModel, 4); //sanjeev
	tempExif += 4 ;
	//write model
//	strcpy(model,tpJEInfo->Model);
	memcpy(model,pCTX->ExifInfo->Model,32);
	santemp=(int)(offset);
	modeloffchar[0]=(unsigned char)santemp;
	modeloffchar[1]=(unsigned char)(santemp>>8);
    modeloffchar[2]=(unsigned char)(santemp>>16);
	modeloffchar[3]=(unsigned char)(santemp>>24);
	//write the model offset into the bitstream
	memcpy (tempExif, modeloffchar, 4);
	tempExif += 4 ;
	memcpy (startoftiff+santemp, model, 32);
	offset+=32;	


	///////////////ENTRY NO 3 :ORIENTATION OF CAMERA////////////////////////
	//write orientation tag
	memcpy (tempExif, orientationtag, 2);
	tempExif += 2 ;
	//write format
	memcpy (tempExif, orientationformat, 2);
	tempExif += 2 ;
	//write no of component
	memcpy (tempExif, NcomponentOrientation, 4);
	tempExif += 4 ;
	//write orientation mode
	Orientation[0] =pCTX->ExifInfo->Orientation;
	Orient[0] = (unsigned char)(Orientation[0]);
	Orient[1] = (unsigned char)(Orientation[0]>>8);
	Orient[2] = (unsigned char)(Orientation[0]>>16);
	Orient[3] = (unsigned char)(Orientation[0]>>24);

	memcpy (tempExif, Orient, 4);
	tempExif += 4 ;

		///////////////ENTRY NO 4 :JPEG PROCESS////////////////////////
	//write orientation tag
	memcpy (tempExif, Processtag, 2);
	tempExif += 2 ;
	//write format
	memcpy (tempExif, Processformat, 2);
	tempExif += 2 ;
	//write no of component
	memcpy (tempExif, NcomponentProcess, 4);
	tempExif += 4 ;
	//write orientation mode
	Process[0] =pCTX->ExifInfo->Process;
	Proc[0] = (unsigned char)(Process[0]);
	Proc[1] = (unsigned char)(Process[0]>>8);
	Proc[2] = (unsigned char)(Process[0]>>16);
	Proc[3] = (unsigned char)(Process[0]>>24);

	memcpy (tempExif, Proc, 4);
	tempExif += 4 ;
	
		///////////////ENTRY NO 5 :VERSION OF software////////////////////////
	//write VERSION tag
	memcpy (tempExif, Versiontag, 2);
	tempExif += 2 ;
	//write format
	memcpy (tempExif, Versionformat, 2);
	tempExif += 2 ;
	//write no of component
	memcpy (tempExif, NcomponentVersion, 4); //sanjeev
	tempExif += 4 ;
	
	
	santemp=(int)(offset);
	Versionoffchar[0]=(unsigned char)santemp;
	Versionoffchar[1]=(unsigned char)(santemp>>8);
    Versionoffchar[2]=(unsigned char)(santemp>>16);
	Versionoffchar[3]=(unsigned char)(santemp>>24);
	//write the VERSION offset into the bitstream
	memcpy (tempExif, Versionoffchar, 4);
	tempExif += 4 ;
//	strcpy(Version,pCTX->ExifInfo->Version);
	memcpy(Version,pCTX->ExifInfo->Version,32);
	memcpy (startoftiff+santemp, Version, 32);
	offset+=32;	
			///////////////ENTRY NO 6 :Date/Time////////////////////////
	//write model tag
	memcpy (tempExif, DateTimetag, 2);
	tempExif += 2 ;
	//write format
	memcpy (tempExif, DateTimeformat, 2);
	tempExif += 2 ;
	//write no of component
	memcpy (tempExif, NcomponentDateTime, 4); //sanjeev
	tempExif += 4 ;
	//write Date/Time
	//strcpy(DateTime,pCTX->ExifInfo->DateTime);
	memcpy(DateTime,pCTX->ExifInfo->DateTime,20);
	
	santemp=(int)(offset);
	DateTimeoffchar[0]=(unsigned char)santemp;
	DateTimeoffchar[1]=(unsigned char)(santemp>>8);
    DateTimeoffchar[2]=(unsigned char)(santemp>>16);
	DateTimeoffchar[3]=(unsigned char)(santemp>>24);
	//write the model offset into the bitstream
	memcpy (tempExif, DateTimeoffchar, 4);
	tempExif += 4 ;
	memcpy (startoftiff+santemp, DateTime, 19);
	memcpy (startoftiff+santemp+19, DateTimeClose, 1);

	offset+=32;	
			///////////////ENTRY NO 7 :COPYRIGHT INFO////////////////////////
	//write model tag
	memcpy (tempExif, CopyRighttag, 2);
	tempExif += 2 ;
	//write format
	memcpy (tempExif, CopyRightformat, 2);
	tempExif += 2 ;
	//write no of component
	memcpy (tempExif, NcomponentCopyRight, 4); //sanjeev
	tempExif += 4 ;

//	strcpy(CopyRight,pCTX->ExifInfo->CopyRight);////="copyright 2006";);
	memcpy(CopyRight,pCTX->ExifInfo->CopyRight,32);
	
	santemp=(int)(offset);
	CopyRightoffchar[0]=(unsigned char)santemp;
	CopyRightoffchar[1]=(unsigned char)(santemp>>8);
    CopyRightoffchar[2]=(unsigned char)(santemp>>16);
	CopyRightoffchar[3]=(unsigned char)(santemp>>24);
	//write the model offset into the bitstream
	memcpy (tempExif, CopyRightoffchar, 4);
	tempExif += 4 ;
	memcpy (startoftiff+santemp, CopyRight, 32);	

	offset+=32;	
	///////////////ENTRY NO 8 :OFFSET TO THE SubIFD ////////////////////////
	//write SubIFD tag
	memcpy (tempExif, SubIFDOffsettag, 2);
	tempExif += 2 ;
	//write format
	memcpy (tempExif, SubIFDOffsetformat, 2);
	tempExif += 2 ;
	//write no of component
	memcpy (tempExif, NcomponentSubIFDOffset, 4);
	tempExif += 4 ;
	//write the  offset to the SubIFD
	santemp=(int)(tempExif-startoftiff+8);
	SubIFDOffsetChar[0] = (unsigned char)(santemp);
	SubIFDOffsetChar[1] = (unsigned char)(santemp>>8);
	SubIFDOffsetChar[2] = (unsigned char)(santemp>>16);
	SubIFDOffsetChar[3] = (unsigned char)(santemp>>24);

	memcpy (tempExif, SubIFDOffsetChar, 4);
	tempExif += 4 ;


    // since it was the last directory entry, so next 4 bytes contains an offset to the IFD1.

    //since we dont know the offset lets put 0x0000 as an offset, later when get to know the
	//actual offset we will revisit here and put the actual offset.
	santemp=0x0000;
	SubIFDOffsetChar[0] = (unsigned char)(santemp);
	SubIFDOffsetChar[1] = (unsigned char)(santemp>>8);
	SubIFDOffsetChar[2] = (unsigned char)(santemp>>16);
	SubIFDOffsetChar[3] = (unsigned char)(santemp>>24);
	IFD1OffsetAddress = tempExif;
	memcpy (tempExif, SubIFDOffsetChar, 4);
	tempExif += 4 ;
/////////////EXIF SUBIFD STARTS HERE//////////////////////////////////
	//write no of entries in SubIFD
	memcpy (tempExif, SubIFDNentries, 2);
	tempExif += 2 ;
///////////////ENTRY NO 1 : EXPOSURE TIME////////////////////////
	//write EXPOSURE TIME tag
	memcpy (tempExif, ExposureTimetag, 2);
	tempExif += 2 ;
	//write format
	memcpy (tempExif, ExposureTimeformat, 2);
	tempExif += 2 ;
	//write no of component
	memcpy (tempExif, NcomponentExposureTime, 4); 
	tempExif += 4 ;
	//write EXPOSURE TIME
	
	santemp=(int)(offset);
	ExposureTimeoffchar[0]=(unsigned char)santemp;
	ExposureTimeoffchar[1]=(unsigned char)(santemp>>8);
    ExposureTimeoffchar[2]=(unsigned char)(santemp>>16);
	ExposureTimeoffchar[3]=(unsigned char)(santemp>>24);
	//write the X-Resolution offset into the bitstream
	memcpy (tempExif, ExposureTimeoffchar, 4);
	tempExif += 4 ;

	ExposureTimeNum[0]=pCTX->ExifInfo->ExposureTimeNum;
	ExposureTimeDen[0]=pCTX->ExifInfo->ExposureTimeDen;
	ExposureTimeNumChar[0]=(unsigned char)ExposureTimeNum[0];
	ExposureTimeNumChar[1]=(unsigned char)(ExposureTimeNum[0]>>8);
	ExposureTimeNumChar[2]=(unsigned char)(ExposureTimeNum[0]>>16);
	ExposureTimeNumChar[3]=(unsigned char)(ExposureTimeNum[0]>>24);

	ExposureTimeDenChar[0]=(unsigned char)ExposureTimeDen[0];
	ExposureTimeDenChar[1]=(unsigned char)(ExposureTimeDen[0]>>8);
	ExposureTimeDenChar[2]=(unsigned char)(ExposureTimeDen[0]>>16);
	ExposureTimeDenChar[3]=(unsigned char)(ExposureTimeDen[0]>>24);

	//WRITE THE EXPOSURE TIME NUMERATOR
	memcpy (startoftiff+santemp, ExposureTimeNumChar, 4);

	memcpy (startoftiff+santemp+4, ExposureTimeDenChar, 4);
	
	offset+=32;
	///////////////ENTRY NO 2 : F NUMBER////////////////////////
	//write FNumber tag
	memcpy (tempExif, FNumbertag, 2);
	tempExif += 2 ;
	//write format
	memcpy (tempExif, FNumberformat, 2);
	tempExif += 2 ;
	//write no of component
	memcpy (tempExif, NcomponentFNumber, 4); //sanjeev
	tempExif += 4 ;
	//write F NUMBER
	
	santemp=(int)(offset);
	FNumberoffchar[0]=(unsigned char)santemp;
	FNumberoffchar[1]=(unsigned char)(santemp>>8);
    FNumberoffchar[2]=(unsigned char)(santemp>>16);
	FNumberoffchar[3]=(unsigned char)(santemp>>24);
	//write the F NUMBER into the bitstream
	memcpy (tempExif, FNumberoffchar, 4);
	tempExif += 4 ;

	FNumberNum[0]=pCTX->ExifInfo->FNumberNum;
	FNumberDen[0]=pCTX->ExifInfo->FNumberDen;

	FNumberNumChar[0]=(unsigned char)FNumberNum[0];
	FNumberNumChar[1]=(unsigned char)(FNumberNum[0]>>8);
	FNumberNumChar[2]=(unsigned char)(FNumberNum[0]>>16);
	FNumberNumChar[3]=(unsigned char)(FNumberNum[0]>>24);

	FNumberDenChar[0]=(unsigned char)FNumberDen[0];
	FNumberDenChar[1]=(unsigned char)(FNumberDen[0]>>8);
	FNumberDenChar[2]=(unsigned char)(FNumberDen[0]>>16);
	FNumberDenChar[3]=(unsigned char)(FNumberDen[0]>>24);

	//WRITE THE FNumber NUMERATOR
	memcpy (startoftiff+santemp, FNumberNumChar, 4);

	memcpy (startoftiff+santemp+4, FNumberDenChar, 4);
	
	offset+=32;
	///////////////ENTRY NO 3 :EXPOSURE PROGRAM////////////////////////
	//write ExposureProgram tag
	memcpy (tempExif, ExposureProgramtag, 2);
	tempExif += 2 ;
	//write format
	memcpy (tempExif, ExposureProgramformat, 2);
	tempExif += 2 ;
	//write no of component
	memcpy (tempExif, NcomponentExposureProgram, 4);
	tempExif += 4 ;
	//write orientation mode
	ExposureProgram[0] =pCTX->ExifInfo->ExposureProgram;

	ExposureProgramChar[0] = (unsigned char)(ExposureProgram[0]);
	ExposureProgramChar[1] = (unsigned char)(ExposureProgram[0]>>8);
	ExposureProgramChar[2] = (unsigned char)(ExposureProgram[0]>>16);
	ExposureProgramChar[3] = (unsigned char)(ExposureProgram[0]>>24);

	memcpy (tempExif, ExposureProgramChar, 4);
	tempExif += 4 ;

///////////////ENTRY NO 4 :ISOSpeedRatings ////////////////////////
	//write ISOSpeedRatings  tag
	memcpy (tempExif, ISOSpeedRatingstag, 2);
	tempExif += 2 ;
	//write format
	memcpy (tempExif, ISOSpeedRatingsformat, 2);
	tempExif += 2 ;
	//write no of component
	memcpy (tempExif, NcomponentISOSpeedRatings, 4);
	tempExif += 4 ;
	//write orientation mode
	ISOSpeedRatings[0] = 1;
	ISOSpeedRatings[1] = 2;

	ISOSpeedRatingsChar[0] = (unsigned char)(ISOSpeedRatings[0]);
	ISOSpeedRatingsChar[1] = (unsigned char)(ISOSpeedRatings[0]>>8);
	ISOSpeedRatingsChar[2] = (unsigned char)(ISOSpeedRatings[1]);
	ISOSpeedRatingsChar[3] = (unsigned char)(ISOSpeedRatings[1]>>8);

	memcpy (tempExif, ISOSpeedRatingsChar, 4);
	tempExif += 4 ;

	
		///////////////ENTRY NO 5 : BRIGHTNESS OF THE IMAGE////////////////////////
	//write BRIGHTNESS tag
	memcpy (tempExif, Brightnesstag, 2);
	tempExif += 2 ;
	//write format
	memcpy (tempExif, Brightnessformat, 2);
	tempExif += 2 ;
	//write no of component
	memcpy (tempExif, NcomponentBrightness, 4); //sanjeev
	tempExif += 4 ;
	//write X - Resolution
	
	santemp=(int)(offset);
	Brightnessoffchar[0]=(unsigned char)santemp;
	Brightnessoffchar[1]=(unsigned char)(santemp>>8);
    Brightnessoffchar[2]=(unsigned char)(santemp>>16);
	Brightnessoffchar[3]=(unsigned char)(santemp>>24);
	//write the X-Resolution offset into the bitstream
	memcpy (tempExif, Brightnessoffchar, 4);
	tempExif += 4 ;

	BrightnessNum[0] = pCTX->ExifInfo->BrightnessNum;
	BrightnessDen[0] = pCTX->ExifInfo->BrightnessDen;

	BrightnessNumChar[0]=(unsigned char)BrightnessNum[0];
	BrightnessNumChar[1]=(unsigned char)(BrightnessNum[0]>>8);
	BrightnessNumChar[2]=(unsigned char)(BrightnessNum[0]>>16);
	BrightnessNumChar[3]=(unsigned char)(BrightnessNum[0]>>24);

	BrightnessDenChar[0]=(unsigned char)BrightnessDen[0];
	BrightnessDenChar[1]=(unsigned char)(BrightnessDen[0]>>8);
	BrightnessDenChar[2]=(unsigned char)(BrightnessDen[0]>>16);
	BrightnessDenChar[3]=(unsigned char)(BrightnessDen[0]>>24);

	//WRITE THE X - RESOLUTION NUMERATOR
	memcpy (startoftiff+santemp, BrightnessNumChar, 4);

	memcpy (startoftiff+santemp+4, BrightnessDenChar, 4);
	
	offset+=48;

	///////////////ENTRY NO 6 : EXPOSURE BIAS OF THE IMAGE////////////////////////
	//write BRIGHTNESS tag
	memcpy (tempExif, ExposureBiastag, 2);
	tempExif += 2 ;
	//write format
	memcpy (tempExif, ExposureBiasformat, 2);
	tempExif += 2 ;
	//write no of component
	memcpy (tempExif, NcomponentExposureBias, 4); //sanjeev
	tempExif += 4 ;
	//write EXPOSURE BIAS

	
	santemp=(int)(offset);
	ExposureBiasoffchar[0]=(unsigned char)santemp;
	ExposureBiasoffchar[1]=(unsigned char)(santemp>>8);
    ExposureBiasoffchar[2]=(unsigned char)(santemp>>16);
	ExposureBiasoffchar[3]=(unsigned char)(santemp>>24);
	//write the EXPOSURE BIAS offset into the bitstream
	memcpy (tempExif, ExposureBiasoffchar, 4);
	tempExif += 4 ;
	ExposureBiasNum[0]=pCTX->ExifInfo->ExposureBiasNum;
	ExposureBiasDen[0]=pCTX->ExifInfo->ExposureBiasDen;
	ExposureBiasNumChar[0]=(unsigned char)ExposureBiasNum[0];
	ExposureBiasNumChar[1]=(unsigned char)(ExposureBiasNum[0]>>8);
	ExposureBiasNumChar[2]=(unsigned char)(ExposureBiasNum[0]>>16);
	ExposureBiasNumChar[3]=(unsigned char)(ExposureBiasNum[0]>>24);

	ExposureBiasDenChar[0]=(unsigned char)ExposureBiasDen[0];
	ExposureBiasDenChar[1]=(unsigned char)(ExposureBiasDen[0]>>8);
	ExposureBiasDenChar[2]=(unsigned char)(ExposureBiasDen[0]>>16);
	ExposureBiasDenChar[3]=(unsigned char)(ExposureBiasDen[0]>>24);

	//WRITE THE EXPOSURE BIAS NUMERATOR
	memcpy (startoftiff+santemp, ExposureBiasNumChar, 4);

	memcpy (startoftiff+santemp+4, ExposureBiasDenChar, 4);
	
	offset+=48;
///////////////ENTRY NO 7 : SUBJECT DISTANCE////////////////////////
	//write SUBJECT DISTANCE tag
	memcpy (tempExif, SubjectDistancetag, 2);
	tempExif += 2 ;
	//write format
	memcpy (tempExif, SubjectDistanceformat, 2);
	tempExif += 2 ;
	//write no of component
	memcpy (tempExif, NcomponentSubjectDistance, 4); //sanjeev
	tempExif += 4 ;
	//write SUBJECT DISTANCE

	
	santemp=(int)(offset);
	SubjectDistanceoffchar[0]=(unsigned char)santemp;
	SubjectDistanceoffchar[1]=(unsigned char)(santemp>>8);
    SubjectDistanceoffchar[2]=(unsigned char)(santemp>>16);
	SubjectDistanceoffchar[3]=(unsigned char)(santemp>>24);
	//write the SUBJECT DISTANCE offset into the bitstream
	memcpy (tempExif, SubjectDistanceoffchar, 4);
	tempExif += 4 ;
	SubjectDistanceNum[0]=pCTX->ExifInfo->SubjectDistanceNum;
	SubjectDistanceDen[0]=pCTX->ExifInfo->SubjectDistanceDen;
	SubjectDistanceNumChar[0]=(unsigned char)SubjectDistanceNum[0];
	SubjectDistanceNumChar[1]=(unsigned char)(SubjectDistanceNum[0]>>8);
	SubjectDistanceNumChar[2]=(unsigned char)(SubjectDistanceNum[0]>>16);
	SubjectDistanceNumChar[3]=(unsigned char)(SubjectDistanceNum[0]>>24);

	SubjectDistanceDenChar[0]=(unsigned char)SubjectDistanceDen[0];
	SubjectDistanceDenChar[1]=(unsigned char)(SubjectDistanceDen[0]>>8);
	SubjectDistanceDenChar[2]=(unsigned char)(SubjectDistanceDen[0]>>16);
	SubjectDistanceDenChar[3]=(unsigned char)(SubjectDistanceDen[0]>>24);

	//WRITE THE SUBJECT DISTANCE NUMERATOR
	memcpy (startoftiff+santemp, SubjectDistanceNumChar, 4);

	memcpy (startoftiff+santemp+4, SubjectDistanceDenChar, 4);
	
	offset+=48;

	///////////////ENTRY NO 8 :METERING MODE////////////////////////
	//write METERING tag
	memcpy (tempExif, MeteringModetag, 2);
	tempExif += 2 ;
	//write format
	memcpy (tempExif, MeteringModeformat, 2);
	tempExif += 2 ;
	//write no of component
	memcpy (tempExif, NcomponentMeteringMode, 4);
	tempExif += 4 ;
	//write METERING mode
	MeteringMode[0] = pCTX->ExifInfo->MeteringMode;
	MeteringModeChar[0] = (unsigned char)(MeteringMode[0]);
	MeteringModeChar[1] = (unsigned char)(MeteringMode[0]>>8);
	MeteringModeChar[2] = (unsigned char)(MeteringMode[0]>>16);
	MeteringModeChar[3] = (unsigned char)(MeteringMode[0]>>24);

	memcpy (tempExif, MeteringModeChar, 4);
	tempExif += 4 ;

	///////////////ENTRY NO 9 :FLASH////////////////////////
	//write FLASH tag
	memcpy (tempExif, Flashtag, 2);
	tempExif += 2 ;
	//write format
	memcpy (tempExif, Flashformat, 2);
	tempExif += 2 ;
	//write no of component
	memcpy (tempExif, NcomponentFlash, 4);
	tempExif += 4 ;
	//write FLASH mode
	Flash[0]= pCTX->ExifInfo->Flash;
	FlashChar[0] = (unsigned char)(Flash[0]);
	FlashChar[1] = (unsigned char)(Flash[0]>>8);
	FlashChar[2] = (unsigned char)(Flash[0]>>16);
	FlashChar[3] = (unsigned char)(Flash[0]>>24);

	memcpy (tempExif, FlashChar, 4);
	tempExif += 4 ;

	///////////////ENTRY NO 10 : FOCAL LENGTH////////////////////////
	//write FOCAL LENGTH tag
	memcpy (tempExif, FocalLengthtag, 2);
	tempExif += 2 ;
	//write format
	memcpy (tempExif, FocalLengthformat, 2);
	tempExif += 2 ;
	//write no of component
	memcpy (tempExif, NcomponentFocalLength, 4); //sanjeev
	tempExif += 4 ;
	//write FOCAL LENGTH
	
	santemp=(int)(offset);
	FocalLengthoffchar[0]=(unsigned char)santemp;
	FocalLengthoffchar[1]=(unsigned char)(santemp>>8);
    FocalLengthoffchar[2]=(unsigned char)(santemp>>16);
	FocalLengthoffchar[3]=(unsigned char)(santemp>>24);
	//write the FOCAL LENGTH offset into the bitstream
	memcpy (tempExif, FocalLengthoffchar, 4);
	tempExif += 4 ;
	FocalLengthNum[0]=pCTX->ExifInfo->FocalLengthNum;
	FocalLengthDen[0]=pCTX->ExifInfo->FocalLengthDen;
	FocalLengthNumChar[0]=(unsigned char)FocalLengthNum[0];
	FocalLengthNumChar[1]=(unsigned char)(FocalLengthNum[0]>>8);
	FocalLengthNumChar[2]=(unsigned char)(FocalLengthNum[0]>>16);
	FocalLengthNumChar[3]=(unsigned char)(FocalLengthNum[0]>>24);

	FocalLengthDenChar[0]=(unsigned char)FocalLengthDen[0];
	FocalLengthDenChar[1]=(unsigned char)(FocalLengthDen[0]>>8);
	FocalLengthDenChar[2]=(unsigned char)(FocalLengthDen[0]>>16);
	FocalLengthDenChar[3]=(unsigned char)(FocalLengthDen[0]>>24);

	//WRITE THE FOCAL LENGTH NUMERATOR
	memcpy (startoftiff+santemp, FocalLengthNumChar, 4);

	memcpy (startoftiff+santemp+4, FocalLengthDenChar, 4);
	
	offset+=48;

	///////////////ENTRY NO 11 :Width////////////////////////
	//write Width tag
	memcpy (tempExif, Widthtag, 2);
	tempExif += 2 ;
	//write format
	memcpy (tempExif, Widthformat, 2);
	tempExif += 2 ;
	//write no of component
	memcpy (tempExif, NcomponentWidth, 4);
	tempExif += 4 ;
	//write Width
	Width[0]=pCTX->ExifInfo->Width;
	WidthChar[0] = (unsigned char)(Width[0]);
	WidthChar[1] = (unsigned char)(Width[0]>>8);
	WidthChar[2] = (unsigned char)(Width[0]>>16);
	WidthChar[3] = (unsigned char)(Width[0]>>24);

	memcpy (tempExif, WidthChar, 4);
	tempExif += 4 ;

	///////////////ENTRY NO 12 :Height////////////////////////
	//write Height tag
	memcpy (tempExif, Heighttag, 2);
	tempExif += 2 ;
	//write format
	memcpy (tempExif, Heightformat, 2);
	tempExif += 2 ;
	//write no of component
	memcpy (tempExif, NcomponentHeight, 4);
	tempExif += 4 ;
	//write Height 
	Height[0]=pCTX->ExifInfo->Height;
	HeightChar[0] = (unsigned char)(Height[0]);
	HeightChar[1] = (unsigned char)(Height[0]>>8);
	HeightChar[2] = (unsigned char)(Height[0]>>16);
	HeightChar[3] = (unsigned char)(Height[0]>>24);

	memcpy (tempExif, HeightChar, 4);
	tempExif += 4 ;

	///////////////ENTRY NO 13 :COLORSPACE////////////////////////
	//write ExposureProgram tag
	memcpy (tempExif, ColorSpacetag, 2);
	tempExif += 2 ;
	//write format
	memcpy (tempExif, ColorSpaceformat, 2);
	tempExif += 2 ;
	//write no of component
	memcpy (tempExif, NcomponentColorSpace, 4);
	tempExif += 4 ;
	//write orientation mode
	ColorSpace [0]= pCTX->ExifInfo->ColorSpace;
	ColorSpaceChar[0] = (unsigned char)(ColorSpace[0]);
	ColorSpaceChar[1] = (unsigned char)(ColorSpace[0]>>8);
	ColorSpaceChar[2] = (unsigned char)(ColorSpace[0]>>16);
	ColorSpaceChar[3] = (unsigned char)(ColorSpace[0]>>24);

	memcpy (tempExif, ColorSpaceChar, 4);
	tempExif += 4 ;
///////////////ENTRY NO 14 : FocalPlaneXResolution////////////////////////
	//write EXPOSURE TIME tag
	memcpy (tempExif, FocalPlaneXResolutiontag, 2);
	tempExif += 2 ;
	//write format
	memcpy (tempExif, FocalPlaneXResolutionformat, 2);
	tempExif += 2 ;
	//write no of component
	memcpy (tempExif, NcomponentFocalPlaneXResolution, 4); 
	tempExif += 4 ;
	//write EXPOSURE TIME
	
	santemp=(int)(offset);
	FocalPlaneXResolutionoffchar[0]=(unsigned char)santemp;
	FocalPlaneXResolutionoffchar[1]=(unsigned char)(santemp>>8);
    FocalPlaneXResolutionoffchar[2]=(unsigned char)(santemp>>16);
	FocalPlaneXResolutionoffchar[3]=(unsigned char)(santemp>>24);
	//write the X-Resolution offset into the bitstream
	memcpy (tempExif, FocalPlaneXResolutionoffchar, 4);
	tempExif += 4 ;
	FocalPlaneXResolutionNum[0] = pCTX->ExifInfo->FocalPlaneXResolutionNum;
	FocalPlaneXResolutionDen[0] = pCTX->ExifInfo->FocalPlaneXResolutionDen;

	FocalPlaneXResolutionNumChar[0]=(unsigned char)FocalPlaneXResolutionNum[0];
	FocalPlaneXResolutionNumChar[1]=(unsigned char)(FocalPlaneXResolutionNum[0]>>8);
	FocalPlaneXResolutionNumChar[2]=(unsigned char)(FocalPlaneXResolutionNum[0]>>16);
	FocalPlaneXResolutionNumChar[3]=(unsigned char)(FocalPlaneXResolutionNum[0]>>24);

	FocalPlaneXResolutionDenChar[0]=(unsigned char)FocalPlaneXResolutionDen[0];
	FocalPlaneXResolutionDenChar[1]=(unsigned char)(FocalPlaneXResolutionDen[0]>>8);
	FocalPlaneXResolutionDenChar[2]=(unsigned char)(FocalPlaneXResolutionDen[0]>>16);
	FocalPlaneXResolutionDenChar[3]=(unsigned char)(FocalPlaneXResolutionDen[0]>>24);

	//WRITE THE EXPOSURE TIME NUMERATOR
	memcpy (startoftiff+santemp, FocalPlaneXResolutionNumChar, 4);

	memcpy (startoftiff+santemp+4, FocalPlaneXResolutionDenChar, 4);
	
	offset+=48;

	///////////////ENTRY NO 15 : FocalPlaneYResolution////////////////////////
	//write EXPOSURE TIME tag
	memcpy (tempExif, FocalPlaneYResolutiontag, 2);
	tempExif += 2 ;
	//write format
	memcpy (tempExif, FocalPlaneYResolutionformat, 2);
	tempExif += 2 ;
	//write no of component
	memcpy (tempExif, NcomponentFocalPlaneYResolution, 4); //sanjeev
	tempExif += 4 ;
	//write EXPOSURE TIME
	
	santemp=(int)(offset);
	FocalPlaneYResolutionoffchar[0]=(unsigned char)santemp;
	FocalPlaneYResolutionoffchar[1]=(unsigned char)(santemp>>8);
    FocalPlaneYResolutionoffchar[2]=(unsigned char)(santemp>>16);
	FocalPlaneYResolutionoffchar[3]=(unsigned char)(santemp>>24);
	//write the X-Resolution offset into the bitstream
	memcpy (tempExif, FocalPlaneYResolutionoffchar, 4);
	tempExif += 4 ;
	FocalPlaneYResolutionNum[0] = pCTX->ExifInfo->FocalPlaneYResolutionNum;
	FocalPlaneYResolutionDen[0] = pCTX->ExifInfo->FocalPlaneYResolutionDen;

	FocalPlaneYResolutionNumChar[0]=(unsigned char)FocalPlaneYResolutionNum[0];
	FocalPlaneYResolutionNumChar[1]=(unsigned char)(FocalPlaneYResolutionNum[0]>>8);
	FocalPlaneYResolutionNumChar[2]=(unsigned char)(FocalPlaneYResolutionNum[0]>>16);
	FocalPlaneYResolutionNumChar[3]=(unsigned char)(FocalPlaneYResolutionNum[0]>>24);

	FocalPlaneYResolutionDenChar[0]=(unsigned char)FocalPlaneYResolutionDen[0];
	FocalPlaneYResolutionDenChar[1]=(unsigned char)(FocalPlaneYResolutionDen[0]>>8);
	FocalPlaneYResolutionDenChar[2]=(unsigned char)(FocalPlaneYResolutionDen[0]>>16);
	FocalPlaneYResolutionDenChar[3]=(unsigned char)(FocalPlaneYResolutionDen[0]>>24);

	//WRITE THE EXPOSURE TIME NUMERATOR
	memcpy (startoftiff+santemp, FocalPlaneYResolutionNumChar, 4);

	memcpy (startoftiff+santemp+4, FocalPlaneYResolutionDenChar, 4);
	
	offset+=48;

///////////////ENTRY NO 16 :FocalPlaneResolutionUnit////////////////////////
	//write ExposureProgram tag
	memcpy (tempExif, FocalPlaneResolutionUnittag, 2);
	tempExif += 2 ;
	//write format
	memcpy (tempExif, FocalPlaneResolutionUnitformat, 2);
	tempExif += 2 ;
	//write no of component
	memcpy (tempExif, NcomponentFocalPlaneResolutionUnit, 4);
	tempExif += 4 ;
	//write FocalPlaneResolutionUnit
	FocalPlaneResolutionUnit[0] = pCTX->ExifInfo->FocalPlaneResolutionUnit;
	FocalPlaneResolutionUnitChar[0] = (unsigned char)(FocalPlaneResolutionUnit[0]);
	FocalPlaneResolutionUnitChar[1] = (unsigned char)(FocalPlaneResolutionUnit[0]>>8);
	FocalPlaneResolutionUnitChar[2] = (unsigned char)(FocalPlaneResolutionUnit[0]>>16);
	FocalPlaneResolutionUnitChar[3] = (unsigned char)(FocalPlaneResolutionUnit[0]>>24);

	memcpy (tempExif, FocalPlaneResolutionUnitChar, 4);
	tempExif += 4 ;
		///////////////ENTRY NO 17 :UserComments////////////////////////
		//write model tag
	memcpy (tempExif, UserCommentstag, 2);
	tempExif += 2 ;
	//write format
	memcpy (tempExif, UserCommentsformat, 2);
	tempExif += 2 ;
	//write no of component
	memcpy (tempExif, NcomponentUserComments, 4); //sanjeev
	tempExif += 4 ;
	//write model
//	strcpy(model,tpJEInfo->Model);
	memcpy(UserComments,pCTX->ExifInfo->UserComments,150);
	santemp=(int)(offset);
	UserCommentsoffchar[0]=(unsigned char)santemp;
	UserCommentsoffchar[1]=(unsigned char)(santemp>>8);
    UserCommentsoffchar[2]=(unsigned char)(santemp>>16);
	UserCommentsoffchar[3]=(unsigned char)(santemp>>24);
	//write the User Comments offset into the bitstream
	memcpy (tempExif, UserCommentsoffchar, 4);
	tempExif += 4 ;
	memcpy (startoftiff+santemp, UserComments, 128);
	offset+=128;
///////////////ENTRY NO 18 :WHITE BALANCE////////////////////////
	//write WhiteBalance tag
	memcpy (tempExif, WhiteBalancetag, 2);
	tempExif += 2 ;
	//write format
	memcpy (tempExif, WhiteBalanceformat, 2);
	tempExif += 2 ;
	//write no of component
	memcpy (tempExif, NcomponentWhiteBalance, 4);
	tempExif += 4 ;
	//write orientation mode
	WhiteBalance[0] = pCTX->ExifInfo->WhiteBalance;
	WhiteBalanceChar[0] = (unsigned char)(WhiteBalance[0]);
	WhiteBalanceChar[1] = (unsigned char)(WhiteBalance[0]>>8);
	WhiteBalanceChar[2] = (unsigned char)(WhiteBalance[0]>>16);
	WhiteBalanceChar[3] = (unsigned char)(WhiteBalance[0]>>24);

	memcpy (tempExif, WhiteBalanceChar, 4);
	tempExif += 4 ;
	if(pCTX->thumbnailFlag)
	{
//Go back where IFD1 Offset is stored and store there the actual offset of IFD1
	santemp=(int)(tempExif - startoftiff);
	SubIFDOffsetChar[0] = (unsigned char)(santemp);
	SubIFDOffsetChar[1] = (unsigned char)(santemp>>8);
	SubIFDOffsetChar[2] = (unsigned char)(santemp>>16);
	SubIFDOffsetChar[3] = (unsigned char)(santemp>>24);	
	memcpy (IFD1OffsetAddress, SubIFDOffsetChar, 4);
	

/////////////EXIF IFD1 STARTS HERE//////////////////////////////////
	//write no of entries in SubIFD
	memcpy (tempExif, IFD1Nentries, 2);
	tempExif += 2 ;

	///////////////ENTRY NO 1 :Compression Type////////////////////////
	//write Compression tag
	memcpy (tempExif, Compressiontag, 2);
	tempExif += 2 ;
	//write format
	memcpy (tempExif, Compressionformat, 2);
	tempExif += 2 ;
	//write no of component
	memcpy (tempExif, NcomponentCompression, 4);
	tempExif += 4 ;
	//write orientation mode
	CompressionChar[0] = (unsigned char)(Compression[0]);
	CompressionChar[1] = (unsigned char)(Compression[0]>>8);
	CompressionChar[2] = (unsigned char)(Compression[0]>>16);
	CompressionChar[3] = (unsigned char)(Compression[0]>>24);

	memcpy (tempExif, CompressionChar, 4);
	tempExif += 4 ;

	
///////////////ENTRY NO 2 : X - RESOLUTION OF THE IMAGE////////////////////////
	//write model tag
	memcpy (tempExif, XResolutiontag, 2);
	tempExif += 2 ;
	//write format
	memcpy (tempExif, XResolutionformat, 2);
	tempExif += 2 ;
	//write no of component
	memcpy (tempExif, NcomponentXResolution, 4); //sanjeev
	tempExif += 4 ;
	//write X - Resolution

	
	santemp=(int)(offset);
	XResolutionoffchar[0]=(unsigned char)santemp;
	XResolutionoffchar[1]=(unsigned char)(santemp>>8);
    XResolutionoffchar[2]=(unsigned char)(santemp>>16);
	XResolutionoffchar[3]=(unsigned char)(santemp>>24);
	//write the X-Resolution offset into the bitstream
	memcpy (tempExif, XResolutionoffchar, 4);
	tempExif += 4 ;
	XResolutionNum[0] = pCTX->ExifInfo->XResolutionNum;
	XResolutionDen[0] = pCTX->ExifInfo->XResolutionDen;
	XResolutionNumChar[0]=(unsigned char)XResolutionNum[0];
	XResolutionNumChar[1]=(unsigned char)(XResolutionNum[0]>>8);
	XResolutionNumChar[2]=(unsigned char)(XResolutionNum[0]>>16);
	XResolutionNumChar[3]=(unsigned char)(XResolutionNum[0]>>24);

	XResolutionDenChar[0]=(unsigned char)XResolutionDen[0];
	XResolutionDenChar[1]=(unsigned char)(XResolutionDen[0]>>8);
	XResolutionDenChar[2]=(unsigned char)(XResolutionDen[0]>>16);
	XResolutionDenChar[3]=(unsigned char)(XResolutionDen[0]>>24);

	//WRITE THE X - RESOLUTION NUMERATOR
	memcpy (startoftiff+santemp, XResolutionNumChar, 4);

	memcpy (startoftiff+santemp+4, XResolutionDenChar, 4);
	
	offset+=48;
	///////////////ENTRY NO 3 : Y - RESOLUTION OF THE IMAGE////////////////////////
	//write model tag
	memcpy (tempExif, YResolutiontag, 2);
	tempExif += 2 ;
	//write format
	memcpy (tempExif, YResolutionformat, 2);
	tempExif += 2 ;
	//write no of component
	memcpy (tempExif, NcomponentYResolution, 4); //sanjeev
	tempExif += 4 ;
	//write Y - Resolution


	santemp=(int)(offset);
	YResolutionoffchar[0]=(unsigned char)santemp;
	YResolutionoffchar[1]=(unsigned char)(santemp>>8);
    YResolutionoffchar[2]=(unsigned char)(santemp>>16);
	YResolutionoffchar[3]=(unsigned char)(santemp>>24);
	//write the X-Resolution offset into the bitstream
	memcpy (tempExif, YResolutionoffchar, 4);
	tempExif += 4 ;
	YResolutionNum[0] = pCTX->ExifInfo->YResolutionNum;
	YResolutionDen[0] = pCTX->ExifInfo->YResolutionDen;
	YResolutionNumChar[0]=(unsigned char)YResolutionNum[0];
	YResolutionNumChar[1]=(unsigned char)(YResolutionNum[0]>>8);
	YResolutionNumChar[2]=(unsigned char)(YResolutionNum[0]>>8);
	YResolutionNumChar[3]=(unsigned char)(YResolutionNum[0]>>8);

	YResolutionDenChar[0]=(unsigned char)YResolutionDen[0];
	YResolutionDenChar[1]=(unsigned char)(YResolutionDen[0]>>8);
	YResolutionDenChar[2]=(unsigned char)(YResolutionDen[0]>>8);
	YResolutionDenChar[3]=(unsigned char)(YResolutionDen[0]>>8);

	//WRITE THE Y - RESOLUTION NUMERATOR
	memcpy (startoftiff+santemp, YResolutionNumChar, 4);

	memcpy (startoftiff+santemp+4, YResolutionDenChar, 4);
	
	offset+=48;
		///////////////ENTRY NO 4 :RESOLUTION UNIT ////////////////////////
	//write orientation tag
	memcpy (tempExif, RUnittag, 2);
	tempExif += 2 ;
	//write format
	memcpy (tempExif, RUnitformat, 2);
	tempExif += 2 ;
	//write no of component
	memcpy (tempExif, NcomponentRUnit, 4);
	tempExif += 4 ;
	//write orientation mode
	RUnit[0] = pCTX->ExifInfo->RUnit;
	RUnitChar[0] = (unsigned char)(RUnit[0]);
	RUnitChar[1] = (unsigned char)(RUnit[0]>>8);
	RUnitChar[2] = (unsigned char)(RUnit[0]>>16);
	RUnitChar[3] = (unsigned char)(RUnit[0]>>24);

	memcpy (tempExif, RUnitChar, 4);
	tempExif += 4 ;

		///////////////ENTRY NO 5 :JpegIFByteCount ////////////////////////
	//write SubIFD tag
	memcpy (tempExif, JpegIFByteCounttag, 2);
	tempExif += 2 ;
	//write format
	memcpy (tempExif, JpegIFByteCountformat, 2);
	tempExif += 2 ;
	//write no of component
	memcpy (tempExif, NcomponentJpegIFByteCount, 4);
	tempExif += 4 ;
	//write the  offset to the SubIFD
	santemp=pCTX->args.thumbEncParam->fileSize;
	JpegIFByteCountChar[0] = (unsigned char)(santemp);
	JpegIFByteCountChar[1] = (unsigned char)(santemp>>8);
	JpegIFByteCountChar[2] = (unsigned char)(santemp>>16);
	JpegIFByteCountChar[3] = (unsigned char)(santemp>>24);

	memcpy (tempExif, JpegIFByteCountChar, 4);
	tempExif += 4 ;
	///////////////ENTRY NO 6 :JpegIFOffset ////////////////////////
	//write JpegIFOffset tag
	memcpy (tempExif, JpegIFOffsettag, 2);
	tempExif += 2 ;
	//write format
	memcpy (tempExif, JpegIFOffsetformat, 2);
	tempExif += 2 ;
	//write no of component
	memcpy (tempExif, NcomponentJpegIFOffset, 4);
	tempExif += 4 ;
	//write the  offset to the SubIFD
	santemp=(int)(offset);
	JpegIFOffsetChar[0] = (unsigned char)(santemp);
	JpegIFOffsetChar[1] = (unsigned char)(santemp>>8);
	JpegIFOffsetChar[2] = (unsigned char)(santemp>>16);
	JpegIFOffsetChar[3] = (unsigned char)(santemp>>24);

	memcpy (tempExif, JpegIFOffsetChar, 4);
	tempExif += 4 ;
	//COPY  THE THUMBNAIL DATA
	memcpy (startoftiff+santemp, pCTX->args.OutThumbBuf, pCTX->args.thumbEncParam->fileSize);
}

	//////////////WRITE END OF ENTRY FLAG//////////////////
	memcpy (tempExif, EndOfEntry, 4);
	tempExif += 4 ;
	if(pCTX->thumbnailFlag)
	{
		offset+=pCTX->args.thumbEncParam->fileSize;
	}

	santemp=(unsigned int)(offset);

	//////////////////////ENTRIES ARE OVER/////////////////////////////////
	ExifSize = (santemp)+8;
	ExifLen[1] = (unsigned char)(ExifSize);
	ExifLen[0] = (unsigned char)(ExifSize>>8);


	if(ExifSize > EXIF_FILE_SIZE + MAX_FILE_THUMB_SIZE - 2){
        // ERRMSG((_T("[JPGAPI] makeExifFile :: Invalid Exif size\r\n")));
		tempExif = NULL;
		*totalLen = 0;
		return JPEG_FAIL;
	}

    tempExif = ExifInitialCount;
    memcpy (tempExif, APP1Marker, 2);
    tempExif += 2 ;
    memcpy (tempExif, ExifLen, 2);
    *totalLen = ExifSize + 2;
    // DBGMSG(JPG_DBG,(_T("[JPGAPI] totalLen : %d\\r\n"), *totalLen));

    // DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s--\r\n"), _T(__FUNCTION__)));
	return JPEG_OK;
}

void *SsbSipJPEGGetRGBPhyBuf(void *openHandle, int Width, int Height)
{
	_JPGLIB    *pCTX = NULL;
	CMM_ALLOC_PRAM_T	CMMParam;
	JPEG_ERRORTYPE ret;
	int         phyIMGDataAddr, virIMGDataAddr;

	RETAILMSG(1,(TEXT("[JPGAPI] %s++\r\n"), _T(__FUNCTION__)));
	
	pCTX = openHandle;
	
	if (pCTX->hCMM == INVALID_HANDLE_VALUE)
	{
	        RETAILMSG(1,(_T("[JPGAPI] SsbSipJPEGGetRGBPhyBuf :: CMM Open failure.\r\n")));
	        free(pCTX);
	        return NULL;
	}

	///////////////////////////////////////
	// make JPEG decode output buffer
	///////////////////////////////////////
	// CMM alloc
	CMMParam.size = (unsigned int)Width*Height*4;
	CMMParam.cacheFlag = 0;
	CMMParam.dramLocation = DRAM_1;

	ret = DeviceIoControl(pCTX->hCMM, IOCTL_CODEC_MEM_ALLOC, (PBYTE)&CMMParam, 
		                        sizeof(CMM_ALLOC_PRAM_T *), &(virIMGDataAddr), sizeof(virIMGDataAddr), NULL, NULL);
	
	if(ret == FALSE)
	{
		RETAILMSG(1,(_T("[JPGAPI] SsbSipJPEGGetRGBPhyBuf :: IOCTL_CODEC_MEM_ALLOC failed\r\n")));
		free(pCTX);
		return NULL;
	}

	ret = DeviceIoControl(pCTX->hCMM, IOCTL_CODEC_GET_PHY_ADDR, (PBYTE)virIMGDataAddr, 
	                        sizeof(virIMGDataAddr), &(phyIMGDataAddr), sizeof(phyIMGDataAddr), 
	                        NULL, NULL);
	
	if(ret == FALSE)
	{
		RETAILMSG(1,(_T("[JPGAPI] SsbSipJPEGGetRGBPhyBuf :: IOCTL_CODEC_GET_PHY_ADDR failed\r\n")));
		free(pCTX);
		return NULL;
	}

	RETAILMSG(1,(_T("[JPGAPI] %s--\r\n"), _T(__FUNCTION__)));
	
	return  (char *)phyIMGDataAddr;
}
	
//
//
#pragma optimize("", on)
//
//
