#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern "C" {
#ifdef boolean
#define HAVE_BOOLEAN
#endif
#include <jpeglib.h>
#undef boolean
}

#include <vdr/tools.h>

#include "tools.h"


int ImageResizeRGB(unsigned char *iSourceImage, unsigned int iSourceImageWidth, unsigned int iSourceImageHeight,
			unsigned char *oDestImage, unsigned int iDestImageWidth, unsigned int iDestImageHeight)
{
	if ((iSourceImageWidth == 0) || (iSourceImageHeight == 0) || (iDestImageWidth == 0) || (iDestImageHeight == 0))
		return -1;

	double wScaleX = (float)iDestImageWidth / (float)iSourceImageWidth;
	double wScaleY = (float)iDestImageHeight / (float)iSourceImageHeight;

	unsigned int wSourceX, wSourceY;

	for (unsigned int row = 0; row < iDestImageHeight; row++)
	{
		for (unsigned int col = 0; col < iDestImageWidth; col++)
		{
			wSourceX = (unsigned int)(col * (1.0/wScaleX));
			wSourceY = (unsigned int)(row * (1.0/wScaleY));
			//if (wSourceX >= iSourceImageWidth))
			//	wSourceX = iSourceImageWidth - 1;
			//if (wSourceY >= iSourceImageHeight))
			//	wSourceY = iSourceImageHeight - 1;
			memcpy(&oDestImage[((row*iDestImageWidth)+col)*3],&iSourceImage[((wSourceY*iSourceImageWidth)+wSourceX)*3],3);
		}
	}

	return 0;
}

#define EM84JPEGCOMPRESSMEM 500000

struct tEm84JpegCompressData {
  int size;
  uchar *mem;
  };

static void Em84JpegCompressInitDestination(j_compress_ptr cinfo)
{
  tEm84JpegCompressData *jcd = (tEm84JpegCompressData *)cinfo->client_data;
  if (jcd) {
     cinfo->dest->free_in_buffer = jcd->size = EM84JPEGCOMPRESSMEM;
     cinfo->dest->next_output_byte = jcd->mem = MALLOC(uchar, jcd->size);
     }
}

static boolean Em84JpegCompressEmptyOutputBuffer(j_compress_ptr cinfo)
{
  tEm84JpegCompressData *jcd = (tEm84JpegCompressData *)cinfo->client_data;
  if (jcd) {
     int Used = jcd->size;
     jcd->size += EM84JPEGCOMPRESSMEM;
     jcd->mem = (uchar *)realloc(jcd->mem, jcd->size);
     if (jcd->mem) {
        cinfo->dest->next_output_byte = jcd->mem + Used;
        cinfo->dest->free_in_buffer = jcd->size - Used;
        return TRUE;
        }
     }
  return FALSE;
}

static void Em84JpegCompressTermDestination(j_compress_ptr cinfo)
{
  tEm84JpegCompressData *jcd = (tEm84JpegCompressData *)cinfo->client_data;
  if (jcd) {
     int Used = cinfo->dest->next_output_byte - jcd->mem;
     if (Used < jcd->size) {
        jcd->size = Used;
        jcd->mem = (uchar *)realloc(jcd->mem, jcd->size);
        }
     }
}

uchar * Em84RgbToJpeg(uchar *Mem, int Width, int Height, int &Size, int Quality)
{
  if (Quality < 0)
     Quality = 0;
  else if (Quality > 100)
     Quality = 100;

  jpeg_destination_mgr jdm;

  jdm.init_destination = Em84JpegCompressInitDestination;
  jdm.empty_output_buffer = Em84JpegCompressEmptyOutputBuffer;
  jdm.term_destination = Em84JpegCompressTermDestination;

  struct jpeg_compress_struct cinfo;
  struct jpeg_error_mgr jerr;
  cinfo.err = jpeg_std_error(&jerr);
  jpeg_create_compress(&cinfo);
  cinfo.dest = &jdm;
  tEm84JpegCompressData jcd;
  cinfo.client_data = &jcd;
  cinfo.image_width = Width;
  cinfo.image_height = Height;
  cinfo.input_components = 3;
  cinfo.in_color_space = JCS_RGB;

  jpeg_set_defaults(&cinfo);
  jpeg_set_quality(&cinfo, Quality, true);
  jpeg_start_compress(&cinfo, true);

  int rs = Width * 3;
  JSAMPROW rp[Height];
  for (int k = 0; k < Height; k++)
      rp[k] = &Mem[rs * k];
  jpeg_write_scanlines(&cinfo, rp, Height);
  jpeg_finish_compress(&cinfo);
  jpeg_destroy_compress(&cinfo);

  Size = jcd.size;
  return jcd.mem;
}