#include <clib/alib_protos.h>
#include <pragma/datatypes_lib.h>
#include <pragma/exec_lib.h>
#include <pragma/graphics_lib.h>
#include <pragma/jpeg_lib.h>
#include <cybergraphx/cybergraphics.h>
#include <datatypes/pictureclass.h>
#include <tools/tools.h>
#include "class.h"

struct JPEGINFO
{
Object *obj;
RastPort *rp,*trp;
UBYTE *buffer,*pix,*col;
UWORD d;
UWORD gray;
ULONG h;
};

void ReadPrefs(Data *data);

static void _getline(UBYTE **scanline,ULONG y,ULONG w,JPEGINFO *info)
{
ULONG x;
register UBYTE *buf=info->buffer;
if(info->d<=8)
	{
	register UBYTE *pix=info->pix,*cp;
	ReadPixelLine8(info->rp,0,y,w,pix,info->trp);
	if(info->gray)
		{
		for(x=0;x<w;x++)
			{
			cp=&info->col[*(pix++)*3];
			*(buf++)=(UWORD(cp[0])+UWORD(cp[1])+UWORD(cp[2]))/3;
			}
		}
	else
		{
		for(x=0;x<w;x++)
			{
			cp=&info->col[*(pix++)*3];
			*(buf++)=cp[0];
			*(buf++)=cp[1];
			*(buf++)=cp[2];
			}
		}
	}
else
	{
	DoMethod(info->obj,PDTM_READPIXELARRAY,buf,RECTFMT_RGB,w*3,0,y,w,1);
	if(info->gray)
		{
		ULONG x1;
		for(x=x1=0;x<w;x++,x1+=3) buf[x]=(UWORD(buf[x1])+UWORD(buf[x1+1])+UWORD(buf[x1+2]))/3;
		}
	}
*scanline=info->buffer;
}

static ULONG getline(register __a0 UBYTE **scanline,register __d0 ULONG line,register __d1 ULONG w,register __a1 void *userdata)
{
_getline(scanline,line,w,(JPEGINFO *)userdata);
return 0;
}

ULONG SaveJPEG(IClass *cl,Object *obj,dtWrite *msg)
{
ULONG retval=0;
ULONG w,h,d;
UBYTE *buffer;
BitMapHeader *bh;
JPEGComHandle *jpc;
GetDTAttrs(obj,PDTA_BitMapHeader,&bh,TAG_END);
w=bh->bmh_Width;
h=bh->bmh_Height;
d=bh->bmh_Depth;
if(buffer=(UBYTE *)AllocVec(w*3,0))
	{
	Data *data=(Data *)INST_DATA(cl,obj);
	ReadPrefs(data);
	if(d<=8)
		{
		BitMap *tbm,*bm;
		GetDTAttrs(obj,PDTA_BitMap,&bm,TAG_END);
		if(tbm=AllocBitMap(w,1,d,BMF_MINPLANES,bm))
			{
			UBYTE *pix;
			if(pix=(UBYTE *)AllocVec(((w+16)>>4)<<4,0))
				{
				UBYTE *col;
				RastPort rp,trp;
				InitRastPort(&rp);
				InitRastPort(&trp);
				rp.BitMap=bm;
				trp.BitMap=tbm;
				GetDTAttrs(obj,PDTA_ColorRegisters,&col,TAG_END);
				if(!AllocJPEGCompress(&jpc,JPG_DestFile,msg->dtw_FileHandle,TAG_END))
					{
					JPEGINFO info={0,&rp,&trp,buffer,pix,col,d,data->gray,h};
					if(!CompressJPEG(jpc,JPG_CompressHook,getline,JPG_CompressUserData,&info,
					JPG_Width,w,JPG_Height,h,
					JPG_Quality,data->quality,
					JPG_Smoothing,data->smooth,
					JPG_ColourSpace,data->gray?JPCS_GRAYSCALE:JPCS_RGB,
					JPG_DCTMethod,data->dct,
					JPG_BytesPerPixel,data->gray?1:3,TAG_END)) retval=1;
					FreeJPEGCompress(jpc);
					}
				FreeVec(pix);
				}
			FreeBitMap(tbm);
			}
		}
	else
		{
		if(!AllocJPEGCompress(&jpc,JPG_DestFile,msg->dtw_FileHandle,TAG_END))
			{
			JPEGINFO info={obj,0,0,buffer,0,0,d,data->gray,h};
			if(!CompressJPEG(jpc,JPG_CompressHook,getline,JPG_CompressUserData,&info,
			JPG_Width,w,JPG_Height,h,
			JPG_Quality,data->quality,
			JPG_ColourSpace,data->gray?JPCS_GRAYSCALE:JPCS_RGB,
			JPG_Smoothing,data->smooth,
			JPG_DCTMethod,data->dct,
			JPG_BytesPerPixel,data->gray?1:3,TAG_END)) retval=1;
			FreeJPEGCompress(jpc);
			}
		}
	FreeVec(buffer);
	}
return retval;
}

