[Image-SIG] Help with AVI files

Riccardo Trocca rtrocca@libero.it
Fri, 22 Feb 2002 18:14:28 -0800


Hello,
	I'll describe my problem just saying that I'm getting crazy! Some time ago 
I wrote a Python extension that could read frames from an AVI file. 
Everything worked well until my HD crashed and I lost every bit of my work. 
Now I've got to do that again, therefore I'm writing a new extension. This 
time I decided to go through SWIG in order to learn it and then build a 
bigger package for Image Processing.
The problem that I've got now is that I can't see nothing else than noise 
in every image I try to grab with python.

The C program I wrote is simple, and I've already used it in other 
applications and it works:

struct  _AVIFile {
	PAVISTREAM ppavi;
	PGETFRAME pgframe;
	AVISTREAMINFO avis;
	LPBITMAPINFOHEADER bi;
	//IplImage* img;
	int width;
	int height;
	int frames;
	int bitcount;
	int current;
};

typedef struct _AVIFile AVIFile;

LONG AFOpenVideoStream(AVIFile* af,const char* path,bool flip=false);
LPBITMAPINFOHEADER AFGetFrame(AVIFile* af, int index);
void AFCloseVideoStream(AVIFile* af);


LONG AFOpenVideoStream(AVIFile* af,const char* path, bool flip){
	
	LONG hr;
	int channels;
	int origin;
	hr=AVIStreamOpenFromFile(
			&(af->ppavi),
			path,
			streamtypeVIDEO,
			0,
			OF_SHARE_DENY_WRITE,0L);


	if (hr!=0)
		return false;

	AVIStreamInfo(af->ppavi, &(af->avis), sizeof(af->avis));

	af->pgframe=AVIStreamGetFrameOpen(af->ppavi,0L);

	if (!af->pgframe)
		return false;

	af->bi = (LPBITMAPINFOHEADER) AVIStreamGetFrame(af->pgframe,0);

	af->frames=af->avis.dwLength;
	af->width=af->bi->biWidth;
	af->height=af->bi->biHeight;
	af->bitcount=af->bi->biBitCount;
	
	
	af->current=0;
	
	return true;
}


LPBITMAPINFOHEADER AFGetFrame(AVIFile* af, int index){
	static int temp;
	temp=(index>af->frames-1?af->frames-1:(index<0?0:index));
	if (af->current!=temp) {
		af->current=temp;
		af->bi=(LPBITMAPINFOHEADER) AVIStreamGetFrame(af->pgframe,af->current);
	}
	return af->bi;
}

Then I wrote a SWIG file like this:


%module _pyAVIFile
%{

#include <windows.h>
#include <vfw.h>
#include <Numeric/arrayobject.h>
#include "AVIFile.h"
#include <stdio.h>
	

%}

%include "typemaps.i"

typedef struct  {
	%readonly
	int width;
	int height;
	int frames;
	int bitcount;
	int current;
} AVIFile;



%addmethods  AVIFile{
	 AVIFile(char* path) {
		AVIFile* af=(AVIFile*)malloc(sizeof(AVIFile));
		if (!AFOpenVideoStream(af,path,false))
			return NULL;
		return af;
	}
	~AVIFile() {
		AFCloseVideoStream(self);
		 free(self);
	}


	PyObject* getNumeric(int frame) {
		int dims[3];
		dims[0]=self->width;
		dims[1]=self->height;
		dims[2]=3;
		AFGetFrame(self,frame);
		return PyArray_FromDimsAndData(3,dims,PyArray_UBYTE, 
(char*)self+(self->bi->biSize));
	}
	
	PyObject* getString(int frame) {
		int dims[3];
		dims[0]=self->width;
		dims[1]=self->height;
		dims[2]=3;
		AFGetFrame(self,frame);
		
		return 
PyString_FromStringAndSize((char*)self+(self->bi->biSize),dims[0]*dims[1]*dims[2]);
	}
	
}



void AVIFileInit();
void AVIFileExit();

%init %{
	import_array();
%}


Of course all of this will work with just 24bit images, but by now it is 
ok. Everything seems to work, and when I open the AVI file I can see the 
exact width and size being read. Ok. The problem is with the Numeric and 
string representation.
If I try to print the Numeric object, Python crashes. This just printing! 
if I use NumTut.view it will not crash, but it will show just noise!
The same result with:

im=Image.new('RGB',(352,288))
im.fromstring(af2.getString(100))
im.show()

the same "noise"

I remember problems with channels ordering, but in that case I should be 
able to see a false color image. Well, now I'm really lost. Can somebody 
give some help?

Riccardo