//
// vector.cpp : angle entre deux vecteurs
//
// link : vfw32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib  kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib 
//
// "$Id: $"
//
//                   Copyright (c) 2004, O'ksi'D
//                      All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//      Redistributions of source code must retain the above copyright
//      notice, this list of conditions and the following disclaimer.
//
//      Redistributions in binary form must reproduce the above copyright
//      notice, this list of conditions and the following disclaimer in the
//      documentation and/or other materials provided with the distribution.
//
//      Neither the name of O'ksi'D nor the names of its contributors
//      may be used to endorse or promote products derived from this software
//      without specific prior written permission.
//
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//

#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <windows.h>
#include <windowsx.h>
#include <vfw.h>

#define FACTOR 30.0 // facteur de mutliplication de l'angle

// v1 . v2
int produit_scalaire(unsigned char *v1, unsigned char *v2, int r)
{
	int ret = 0;
	while (--r >= 0) {
		ret += v1[r] * v2[r];
	}
	return ret;
}

// ||v1|| * ||v2||
double produit_normes(unsigned char *v1, unsigned char *v2, int r)
{
	double nv1 = 0;
	double nv2 = 0;

	while (--r >= 0) {
		nv1 += v1[r] * v1[r];
		nv2 += v2[r] * v2[r];
	}
	nv1 = sqrt(nv1);
	nv2 = sqrt(nv2);
	return nv1 * nv2; 
}

// angle en degrés entre deux vecteurs 
// (v1 . v2) / (||v1|| * ||v2||) = cos(AOB)
double angle_entre_vecteur(unsigned char *v1, unsigned char *v2, int r)
{
	double s;
	double n;
	static double pi = 0.0;
	if (pi == 0.0) pi = 4 * atan(1.0);
	s = produit_scalaire(v1, v2, r);
	n = produit_normes(v1, v2, r);
	if (s == n) return 0.0;
	if (n == 0.0) return 90.0;
	return acos(s / n) / pi * 180.0;
}

unsigned char bouge(unsigned char *src1, unsigned char *src2, int line_size, int carre)
{
	int x;
	int y;
	static int size = 0;
	static unsigned char *v1 = NULL;
	static unsigned char *v2 = NULL;
	double ret;	
	if (carre > size) {
		size = carre;
		v1 = (unsigned char *)realloc(v1, size * size);
		v2 = (unsigned char *)realloc(v2, size * size);
	}

	for (y = 0; y < carre; y++) {
		for (x = 0; x < carre; x++) {
			int sx, dx;
			unsigned char v;;
			sx = y * line_size + x;
			dx = carre * y + x;
			v = v1[dx] = (src1[sx] + src1[sx+1] + src1[sx+2]) / 3;
			v2[dx] = (src2[sx] + src2[sx+1] + src2[sx+2]) / 3;
		}
	}
	
	ret = angle_entre_vecteur(v1, v2, carre * carre);
	ret = ret / FACTOR * 255;
	if (ret > 255.0) ret = 255;

	return (unsigned char) ret;	
}

// SaveSmall - copies a stream of data from one file, compresses 
// the stream, and writes the compressed stream to a new file. 
// 
// ps stream interface pointer 
// lpFilename - new AVI file to build 
// 
 
void process_avi(LPSTR inFile, LPSTR lpFilename) 
{ 
    PAVISTREAM ps;
    PAVIFILE         pf; 
    PAVISTREAM       psSmall; 
    HRESULT          hr; 
    AVISTREAMINFO    strhdr; 
    BITMAPINFOHEADER bi; 
    BITMAPINFOHEADER biNew; 
    LONG             lStreamSize; 
    LPVOID           lpOld; 
    LPVOID           lpOld1; 
    LPVOID           lpOld2; 
    LPVOID           lpNew; 
    PAVIFILE pfile; 
    int i;
 
    AVIFileInit();          // opens AVIFile library 
 
    hr = AVIFileOpen(&pfile, inFile, OF_SHARE_DENY_WRITE, 0L); 
    if (hr != 0){ 
        // Handle failure.
        return; 
    }
    ps = 0; 
    for (i=0; i < 200 ;i++) {
	if (AVIFileGetStream(pfile, &ps, streamtypeVIDEO, i) == AVIERR_OK) break;
    }
    if (!ps) return;

    // Determine the size of the format data using 
    // AVIStreamFormatSize. 
    AVIStreamFormatSize(ps, 0, &lStreamSize); 
    if (lStreamSize > sizeof(bi)) // Format too large? 
        return; 
 
    lStreamSize = sizeof(bi); 
    hr = AVIStreamReadFormat(ps, 0, &bi, &lStreamSize); // Read format 
    if (bi.biCompression != BI_RGB) // Wrong compression format? 
        return; 

    if (bi.biBitCount != 24) return; // not RGB ? 
 
    hr = AVIStreamInfo(ps, &strhdr, sizeof(strhdr)); 
 
    // Create new AVI file using AVIFileOpen. 
    hr = AVIFileOpen(&pf, lpFilename, OF_WRITE | OF_CREATE, NULL); 
    if (hr != 0) 
        return; 
 
    // Set parameters for the new stream. 
    biNew = bi; 
    biNew.biWidth /= 1; 
    biNew.biHeight /= 1; 
    biNew.biSizeImage = ((((UINT)biNew.biBitCount * biNew.biWidth 
                        + 31)&~31) / 8) * biNew.biHeight; 

    SetRect(&strhdr.rcFrame, 0, 0, (int) biNew.biWidth, 
            (int) biNew.biHeight); 
 
    // Create a stream using AVIFileCreateStream. 
    hr = AVIFileCreateStream(pf, &psSmall, &strhdr); 
    if (hr != 0) {            //Stream created OK? If not, close file. 
        AVIFileRelease(pf); 
        return; 
    } 
 
    // Set format of new stream using AVIStreamSetFormat. 
    hr = AVIStreamSetFormat(psSmall, 0, &biNew, sizeof(biNew)); 
    if (hr != 0) { 
        AVIStreamRelease(psSmall); 
        AVIFileRelease(pf); 
        return; 
    } 
 
    // Allocate memory for the bitmaps. 
    lpOld = lpOld1 = GlobalAllocPtr(GMEM_MOVEABLE, bi.biSizeImage);
    lpOld2 = GlobalAllocPtr(GMEM_MOVEABLE, bi.biSizeImage);  
    lpNew = GlobalAllocPtr(GMEM_MOVEABLE, biNew.biSizeImage); 
 
    // Read the stream data using AVIStreamRead. 
    for (lStreamSize = AVIStreamStart(ps); lStreamSize <
        AVIStreamEnd(ps); lStreamSize++) {
	int x, y; 
	int line_size;
	int carre = 3;
	
	lpOld = (lpOld == lpOld1) ? lpOld2 : lpOld1;
        hr = AVIStreamRead(ps, lStreamSize, 1, lpOld, bi.biSizeImage,
            NULL, NULL); 
        // 
        // Place error check here. 
        // 
	line_size = ((((UINT)biNew.biBitCount * biNew.biWidth + 31)&~31) / 8);

        // Do something with the data and write it to lpNew buffer. 
	for (y = carre - 1; y < bi.biHeight - carre; y++) {
		unsigned char *src = (unsigned char*)lpOld + line_size * y;
		unsigned char *src1 = (unsigned char*)lpOld1 + line_size * y;
		unsigned char *src2 = (unsigned char*)lpOld2 + line_size * y;
		unsigned char *dst = (unsigned char*)lpNew + line_size * y;
		for (x = carre - 1; x < bi.biWidth - carre; x++) {
			int lum;
			lum = src[x * 3] + src[x * 3 + 1] + src[x * 3 + 2];
			lum /= 3;
			
			if (lum > 255) lum = 255;
			lum = bouge(src1 + 3 * x, src2 + 3 * x, line_size, carre);
			dst[x * 3 ] = (unsigned char)lum;
			dst[x * 3 + 1] = (unsigned char)lum;
			dst[x * 3 + 2] = (unsigned char)lum;
		}
	}			
 
        // Save the compressed data using AVIStreamWrite. 
        hr = AVIStreamWrite(psSmall, lStreamSize, 1, lpNew,
            biNew.biSizeImage, AVIIF_KEYFRAME, NULL, NULL); 
    } 
 
     // Close the stream and file. 
    AVIStreamRelease(psSmall); 
    AVIFileRelease(pf); 
    AVIFileRelease(pfile);  // closes the file 
    AVIFileExit();          // releases AVIFile library 

} 

int main(int argc, char* argv[])
{
	unsigned char v1[] = {1,1,0};
	unsigned char v2[] = {1,1,1};
	int r = 3;
 
	printf("Angle : %lf deg.\n", angle_entre_vecteur(v1, v2, r));
	process_avi("c:\\temp\\test.avi", "c:\\temp\\test1.avi");

//	getch();
	return 0;
}

