/**************************************************************************
 *{@C
 *      Copyright:      1988-2020 Paul Obermeier (obermeier@poSoft.de)
 *
 *      Module:         ImageProcessing
 *      Filename:       IPT_TclIfThreded.c
 *
 *      Author:         Paul Obermeier
 *
 *      Description:    The interface between the image
 *                      library and the Tcl interpreter.
 *			This file contains all thread-aware functions.
 *
 *      Additional documentation:
 *                      None.
 *
 *      Exported functions:
 *
 **************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#include "UT_Compat.h"

#include "UT_Macros.h"
#include "UT_Error.h"
#include "UT_Memory.h"
#include "FF_Image.h"
#include "IP_Image.h"

#include <tcl.h>
#include "UTT_TclIf.h"
#include "IPT_TclIf.h"
#include "IPT_ImagePrivate.h"

#if 0
    #define DEBUG_LOCAL
#endif

UT_Bool IPT_CompositeAlpha (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    IP_ImageId fgimg, bgimg, mtimg;
    double  fr, fg, fb;
    double  br, bg, bb;
    UT_Bool fast;

    IPT_Get_Fix_Image (1, fgimg);
    IPT_Get_Fix_Image (2, bgimg);
    UTT_GetOptFloat64 (3, fr, 1.0);
    UTT_GetOptFloat64 (4, fg, 1.0);
    UTT_GetOptFloat64 (5, fb, 1.0);
    UTT_GetOptFloat64 (6, br, 1.0);
    UTT_GetOptFloat64 (7, bg, 1.0);
    UTT_GetOptFloat64 (8, bb, 1.0);
    UTT_GetOptBool    (9, fast, UT_False);
    IPT_Get_Opt_Image (10, mtimg, NULL);

    return IP_CompositeAlpha (fgimg, bgimg, img,
			     fr, fg, fb, br, bg, bb,
			     mtimg, fast);
}

UT_Bool IPT_CompositeColorMatte (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    IP_ImageId fgimg, bgimg, mtimg;
    double  fr, fg, fb;
    double  br, bg, bb;
    UT_Bool fast;

    IPT_Get_Fix_Image (1, fgimg);
    IPT_Get_Fix_Image (2, bgimg);
    UTT_GetOptFloat64 (3, fr, 1.0);
    UTT_GetOptFloat64 (4, fg, 1.0);
    UTT_GetOptFloat64 (5, fb, 1.0);
    UTT_GetOptFloat64 (6, br, 1.0);
    UTT_GetOptFloat64 (7, bg, 1.0);
    UTT_GetOptFloat64 (8, bb, 1.0);
    UTT_GetOptBool    (9, fast, UT_False);
    IPT_Get_Opt_Image (10, mtimg, NULL);

    return IP_CompositeColorMatte (fgimg, bgimg, img,
			      fr, fg, fb, br, bg, bb,
			      mtimg, fast);
}

UT_Bool IPT_CompositeDepth (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    IP_ImageId fgimg, bgimg;

    IPT_Get_Fix_Image (1, fgimg);
    IPT_Get_Fix_Image (2, bgimg);
    return IP_CompositeDepth (fgimg, bgimg, img);
}

UT_Bool IPT_CrossDissolve (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    IP_ImageId fgimg, bgimg;
    double mix;

    IPT_Get_Fix_Image  (1, fgimg);
    IPT_Get_Fix_Image  (2, bgimg);
    UTT_GetFixFloat64 (3, mix);
    return IP_CrossDissolve (fgimg, bgimg, img, mix);
}

UT_Bool IPT_Interlace (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    IP_ImageId fld1, fld2;
    UT_Bool skip;

    IPT_Get_Fix_Image (1, fld1);
    IPT_Get_Fix_Image (2, fld2);
    UTT_GetFixBool    (3, skip);
    return IP_Interlace (fld1, fld2, img, skip);
}

UT_Bool IPT_Unlace (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    IP_ImageId frm;
    UT_Bool odd;
    Int32   mode;

    IPT_Get_Fix_Image (1, frm);
    UTT_GetFixBool    (2, odd);
    UTT_GetOptInt32   (3, mode, IP_UnlaceModeNone);
    return IP_Unlace (frm, img, odd, (IP_UnlaceModeType)mode);
}

UT_Bool IPT_ChangeGamma (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    Int32 chn;
    double gamma, scl, off;

    UTT_GetFixInt32    (1, chn);
    UTT_GetFixFloat64 (2, gamma);
    UTT_GetOptFloat64 (3, scl, 1.0);
    UTT_GetOptFloat64 (4, off, 0.0);
    return IP_ChangeGamma (img, chn, gamma, scl, off);
}

UT_Bool IPT_RemapValues (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    Int32 chn, lutsize;
    UT_Bool retVal;
    Float32 *lut;

    UTT_GetFixInt32       (1, chn);
    UTT_GetFixFloat32List (2, lut, lutsize, 2);

    retVal = IP_RemapValues (img, chn, lutsize, lut);
    UT_MemFree (lut);
    return retVal;
}

UT_Bool IPT_Blur (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    double f, g;

    UTT_GetFixFloat64 (1, f);
    UTT_GetOptFloat64 (2, g, f);
    return IP_Blur (img, f, g);
}

UT_Bool IPT_DepthBlur (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    double f, g, mindepth, maxdepth;

    UTT_GetFixFloat64   (1, f);
    UTT_GetOptFloat64   (2, g, f);
    UTT_GetOptFloat64   (3, mindepth, -1.0);
    UTT_GetOptFloat64   (4, maxdepth, -1.0);
    return IP_DepthBlur (img, f, g, mindepth, maxdepth);
}

UT_Bool IPT_Derivates (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    IP_ImageId srcimg;
    Int32   srcchn, hchn, vchn;
    UT_Bool wrap;

    IPT_Get_Fix_Image (1, srcimg);
    UTT_GetFixInt32   (2, srcchn);
    UTT_GetFixInt32   (3, hchn);
    UTT_GetFixInt32   (4, vchn);
    UTT_GetFixBool    (5, wrap);
    return IP_Derivates (srcimg, srcchn, img, hchn, vchn, wrap);
}

UT_Bool IPT_Median (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    return IP_Median (img);
}

UT_Bool IPT_MedianSequence (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    IP_ImageId srcimg1, srcimg2, srcimg3;

    IPT_Get_Fix_Image (1, srcimg1);
    IPT_Get_Fix_Image (2, srcimg2);
    IPT_Get_Fix_Image (3, srcimg3);
    return IP_MedianSequence (srcimg1, srcimg2, srcimg3, img);
}

UT_Bool IPT_Dilatation (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    Int32       n;

    UTT_GetOptInt32 (1, n, 1);
    return IP_Dilatation (img, n);
}

UT_Bool IPT_Erosion (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    Int32       n;

    UTT_GetOptInt32 (1, n, 1);
    return IP_Erosion (img, n);
}

UT_Bool IPT_CutOff (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    double    tmin, tmax;

    UTT_GetFixFloat64 (1, tmin);
    UTT_GetOptFloat64 (2, tmax, 1.0);
    if (tmin > tmax) {
        UT_SWAP (tmin, tmax, double);
    }
    return IP_CutOff (img, tmin, tmax);
}

UT_Bool IPT_Threshold (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    IP_ImageId src;
    double    t;
    Int32     overwrite;

    IPT_Get_Fix_Image  (1, src);
    UTT_GetFixFloat64 (2, t);
    UTT_GetOptInt32   (3, overwrite, 0);
    return IP_Threshold (src, img, t, overwrite);
}

UT_Bool IPT_MarkNonZeroPixels (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    IP_ImageId src;
    Int32      Threshold;
    Int32      numMarkedPixels;
    UT_Bool    success;

    IPT_Get_Fix_Image (1, src);
    UTT_GetFixInt32   (2, Threshold);
    success = IP_MarkNonZeroPixels (src, img, Threshold, &numMarkedPixels);
    UTT_SetFixInt32 (3, numMarkedPixels);
    return success;
}

UT_Bool IPT_DifferenceImage (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    IP_ImageId src1;
    IP_ImageId src2;
    UT_Bool    useAbsValue;

    IPT_Get_Fix_Image (1, src1);
    IPT_Get_Fix_Image (2, src2);
    UTT_GetOptBool    (3, useAbsValue, UT_True);
    return IP_DifferenceImage (src1, src2, img, useAbsValue);
}

UT_Bool IPT_Flicker (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    return IP_Flicker (img);
}

UT_Bool IPT_FlipDiagonal (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    IP_FlipDiagonal (img);
    return UT_True;
}

UT_Bool IPT_FlipHorizontal (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    IP_FlipHorizontal (img);
    return UT_True;
}

UT_Bool IPT_FlipVertical (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    IP_FlipVertical (img);
    return UT_True;
}

UT_Bool IPT_Rotate (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    IP_ImageId srcimg;
    Int32 angle;

    IPT_Get_Fix_Image (1, srcimg);
    UTT_GetFixInt32   (2, angle);
    return IP_Rotate (srcimg, img, angle);
}

UT_Bool IPT_ScaleRect (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    IP_ImageId srcimg;
    Int32 xs1, ys1, xs2, ys2, xd1, yd1, xd2, yd2;
    UT_Bool pyrfilter, gc;

    IPT_Get_Fix_Image (1, srcimg);
    UTT_GetFixInt32   (2, xs1);
    UTT_GetFixInt32   (3, ys1);
    UTT_GetFixInt32   (4, xs2);
    UTT_GetFixInt32   (5, ys2);
    UTT_GetFixInt32   (6, xd1);
    UTT_GetFixInt32   (7, yd1);
    UTT_GetFixInt32   (8, xd2);
    UTT_GetFixInt32   (9, yd2);
    UTT_GetOptBool   (10, pyrfilter, UT_False);
    UTT_GetOptBool   (11, gc, UT_False);
    return IP_ScaleRect
	(srcimg, img,
	xs1, ys1, xs2, ys2,
	xd1, yd1, xd2, yd2,
	pyrfilter, gc);
}

UT_Bool IPT_GenNoise (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    Int32 chn, seed, p, coh;
    double z;

    UTT_GetFixInt32    (1, chn);
    UTT_GetFixInt32    (2, seed);
    UTT_GetFixInt32    (3, p);
    UTT_GetFixInt32    (4, coh);
    UTT_GetFixFloat64 (5, z);
    return IP_GenNoise (img, chn, seed, p, coh, z);
}

UT_Bool IPT_GenJuliaSet (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    Int32 i, n, numit;
    UInt8 rmap[256], gmap[256], bmap[256];
    Int32   *rtmp, *gtmp, *btmp;
    double cr, ci, rcen, icen, rlen;

    UTT_GetFixFloat64   (1, cr);
    UTT_GetFixFloat64   (2, ci);
    UTT_GetFixFloat64   (3, rcen);
    UTT_GetFixFloat64   (4, icen);
    UTT_GetFixFloat64   (5, rlen);
    UTT_GetFixInt32      (6, numit);
    UTT_GetFixInt32List (7, rtmp, n, numit);
    UTT_GetFixInt32List (8, gtmp, n, numit);
    UTT_GetFixInt32List (9, btmp, n, numit);

    for (i=0; i<UT_MIN (n, 256); i++)
    {
	rmap[i] = (UInt8) rtmp[i];
	gmap[i] = (UInt8) gtmp[i];
	bmap[i] = (UInt8) btmp[i];
    }
    UT_MemFree (rtmp);
    UT_MemFree (gtmp);
    UT_MemFree (btmp);
    return 
	IP_GenJuliaSet (img, cr, ci, rcen, icen, rlen, numit, rmap, gmap, bmap);
}

UT_Bool IPT_GenMandelbrot (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    Int32 i, n, numit;
    UInt8 rmap[256], gmap[256], bmap[256];
    Int32   *rtmp, *gtmp, *btmp;
    double rcen, icen, rlen;

    UTT_GetFixFloat64   (1, rcen);
    UTT_GetFixFloat64   (2, icen);
    UTT_GetFixFloat64   (3, rlen);
    UTT_GetFixInt32      (4, numit);
    UTT_GetFixInt32List (5, rtmp, n, numit);
    UTT_GetFixInt32List (6, gtmp, n, numit);
    UTT_GetFixInt32List (7, btmp, n, numit);

    for (i=0; i<UT_MIN (n, 256); i++)
    {
	rmap[i] = (UInt8) rtmp[i];
	gmap[i] = (UInt8) gtmp[i];
	bmap[i] = (UInt8) btmp[i];
    }
    UT_MemFree (rtmp);
    UT_MemFree (gtmp);
    UT_MemFree (btmp);

    return 
	IP_GenMandelbrot (img, rcen, icen, rlen, numit, rmap, gmap, bmap);
}

UT_Bool IPT_Histogram (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    Int32 chn;
    Int32 buf[256];

    UTT_GetFixInt32 (1, chn);
    if (!IP_Histogram (img, chn, buf))
	return UT_False;
    UTT_SetFixInt32List (2, buf, 256);
    return UT_True;
}

UT_Bool IPT_GetChanStats (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    Float32 meanVal, stdDev;
    Int32   chn;
    UInt32  numPix;
    UT_Bool useMatte;

    UTT_GetFixInt32 (1, chn);
    UTT_GetOptBool  (5, useMatte, UT_False);

    if (!IP_GetChanStats (img, chn, &meanVal, &stdDev, &numPix, useMatte)) {
	return UT_False;
    }
    UTT_SetFixFloat64 (2, meanVal);
    UTT_SetFixFloat64 (3, stdDev);
    UTT_SetFixInt32   (4, numPix);
    return UT_True;
}

UT_Bool IPT_GetChanRange (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    Int32   chn;
    Float32 minVal, maxVal;

    UTT_GetFixInt32 (1, chn);
    if (!IP_GetChanRange (img, chn, &minVal, &maxVal)) {
	return UT_False;
    }
    UTT_SetFixFloat64 (2, minVal);
    UTT_SetFixFloat64 (3, maxVal);
    return UT_True;
}

UT_Bool IPT_GetDepthRange (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    Float32 minVal, maxVal;

    if (!IP_GetDepthRange (img, &minVal, &maxVal))
	return UT_False;
    UTT_SetFixFloat64 (1, minVal);
    UTT_SetFixFloat64 (2, maxVal);
    return UT_True;
}

UT_Bool IPT_GetTemperatureRange (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    Float32 minVal, maxVal;

    if (!IP_GetTemperatureRange (img, &minVal, &maxVal))
	return UT_False;
    UTT_SetFixFloat64 (1, minVal);
    UTT_SetFixFloat64 (2, maxVal);
    return UT_True;
}

UT_Bool IPT_GetRadianceRange (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    Float32 minVal, maxVal;

    if (!IP_GetRadianceRange (img, &minVal, &maxVal))
	return UT_False;
    UTT_SetFixFloat64 (1, minVal);
    UTT_SetFixFloat64 (2, maxVal);
    return UT_True;
}

UT_Bool IPT_DiffChannel (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    IP_ImageId img2;
    Int32 chn;
    Int32 less1[256], less2[256];

    IPT_Get_Fix_Image     (1, img2);
    UTT_GetFixInt32       (2, chn);
    if (!IP_DiffChannel (img, img2, chn, less1, less2))
	return UT_False;
    UTT_SetFixInt32List (3, less1, 256);
    UTT_SetFixInt32List (4, less2, 256);
    return UT_True;
}

UT_Bool IPT_Correlate (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    IP_ImageId	img2;
    Int32		chn, xs1, ys1, xs2, ys2, xd1, yd1;
    Float32	r;

    IPT_Get_Fix_Image (1, img2);
    UTT_GetFixInt32   (2, chn);
    UTT_GetFixInt32   (3, xs1);
    UTT_GetFixInt32   (4, ys1);
    UTT_GetFixInt32   (5, xs2);
    UTT_GetFixInt32   (6, ys2);
    UTT_GetFixInt32   (7, xd1);
    UTT_GetFixInt32   (8, yd1);
    if (!IP_Correlate (img, img2, chn, xs1, ys1,
			       xs2, ys2, xd1, yd1, &r))
	return UT_False;
    UTT_SetFixFloat64Result (r);
    return UT_True;
}

UT_Bool IPT_FindPattern (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    IP_ImageId	img2;
    Int32		chn, xs1, ys1, xs2, ys2, xd1, yd1, xd2, yd2;
    Float32	xp, yp, rp;

    IPT_Get_Fix_Image (1,  img2);
    UTT_GetFixInt32   (2,  chn);
    UTT_GetFixInt32   (3,  xs1);
    UTT_GetFixInt32   (4,  ys1);
    UTT_GetFixInt32   (5,  xs2);
    UTT_GetFixInt32   (6,  ys2);
    UTT_GetFixInt32   (7,  xd1);
    UTT_GetFixInt32   (8,  yd1);
    UTT_GetFixInt32   (9,  xd2);
    UTT_GetFixInt32  (10, yd2);
    if (!IP_FindPattern (img, img2, chn, xs1, ys1, xs2, ys2,
			   xd1, yd1, xd2, yd2, &xp, &yp, &rp))
	return UT_False;
    UTT_SetFixFloat64  (11, xp);
    UTT_SetFixFloat64  (12, yp);
    UTT_SetFixFloat64  (13, rp);
    return UT_True;
}

UT_Bool IPT_GetSample (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    Int32 chn;
    double x, y;

    UTT_GetFixInt32    (1, chn);
    UTT_GetFixFloat64 (2, x);
    UTT_GetFixFloat64 (3, y);
    UTT_SetFixFloat64Result (IP_GetSample (img, chn, x, y));
    return UT_True;
}

UT_Bool IPT_ShearVertical (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    double m, t;

    UTT_GetFixFloat64  (1, m);
    UTT_GetFixFloat64  (2, t);
    return IP_ShearVertical (img, m, t);
}

UT_Bool IPT_ShearHorizontal (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    double m, t;

    UTT_GetFixFloat64  (1, m);
    UTT_GetFixFloat64  (2, t);
    return IP_ShearHorizontal (img, m, t);
}

UT_Bool IPT_AsPhoto (ELEMPARAMLIST)
{
    Int32 i, n, *chan = NULL;
    Int32 defMap3[] = { FF_ImgChanTypeRed, FF_ImgChanTypeGreen, FF_ImgChanTypeBlue, FF_ImgChanTypeNone };
    Int32 defMap4[] = { FF_ImgChanTypeRed, FF_ImgChanTypeGreen, FF_ImgChanTypeBlue, FF_ImgChanTypeMatte };
    FF_ImgFmtType imgFmt[FF_NumImgChanTypes];
    FF_ImgChanType chanMap[4];
    char photoName[MAXPATH + 1];
    double gamma, minVal, maxVal;
    IP_ImageId img = (IP_ImageId) clientData;
    void *memstate;

    memstate = UT_MemRemember ();
    UTT_GetFixString   (1, photoName, MAXPATH + 1, UT_False);

    /* If no channel mapping is specified, use default mapping depending
       on whether the image has a transpareny channel.*/
    IP_ImageInfo (img, NULL, imgFmt);
    if (imgFmt[FF_ImgChanTypeMatte] != FF_ImgFmtTypeNone)
    {
	UTT_GetOptInt32List (2, chan, n, 1, defMap4);
	#if defined(DEBUG_LOCAL)
	    printf ("Transparency channel: YES (nchan=%d)\n", n);
	#endif
    }
    else
    {
	UTT_GetOptInt32List (2, chan, n, 1, defMap3);
	#if defined(DEBUG_LOCAL)
	    printf ("Transparency channel: NO (nchan=%d)\n", n);
	#endif
    }

    if (n == 0)
    {	/* UTT_GetInt32List does not support the minlen parameter. */
	chan = defMap3;
	n = 4;
    }
    for (i=0; i<n; i++)
	chanMap[i] = (FF_ImgChanType) chan[i];
    for (i=n; i<4; i++)
	chanMap[i] = FF_ImgChanTypeNone;

    UTT_GetOptFloat64 (3, gamma,  1.0);
    UTT_GetOptFloat64 (4, minVal, 0.0);
    UTT_GetOptFloat64 (5, maxVal, 1.0);

    UT_MemRestore (memstate);

    return IP_Img2Photo (img, photoName, chanMap, 
                         gamma, minVal, maxVal, interp);
}

UT_Bool IPT_NewImageFromPhoto (OBJPARAMLIST)
{
    char photoName[MAXPATH + 1];
    IP_ImageId img;

    UTT_GetFixString   (1, photoName, MAXPATH + 1, UT_False);
    img = IP_Photo2Img (photoName, interp);
    if (!img)
        return UT_False;
    *clientData = img;
    return UT_True;
}

UT_Bool IPT_ApplyLogo (ELEMPARAMLIST)
{
    IP_ImageId img = (IP_ImageId) clientData;
    IP_ImageId logo;
    Int32 x1, y1;
    double sr, sg, sb;

    IPT_Get_Fix_Image  (1, logo);
    UTT_GetFixInt32    (2, x1);
    UTT_GetFixInt32    (3, y1);
    UTT_GetOptFloat64 (4, sr, 1.0);
    UTT_GetOptFloat64 (5, sg, 1.0);
    UTT_GetOptFloat64 (6, sb, 1.0);

    return IP_ApplyLogo (img, logo, x1, y1, sr, sg, sb);
}
