Exemple #1
0
// This must be called before any frame-saving is attempted.
void CAnimationExporter::CreateGif()
{
    if(!g_canvas || !g_canvas->model || !g_canvas->model->animManager)
    {
        wxMessageBox(_T("Unable to create animated GIF!"), _T("Error") );
        wxLogMessage(_T(
            "Error: Unable to created animated GIF.  A required objects pointer was null!") );
        Show(false);
        return ;
    }

    CxImage **gifImages = NULL; // Our pointer array of images

    // Reset the state of our GUI objects
    btnStart->Enable(false);
    btnCancel->Enable(false);
    cbGrey->Enable(false);
    cbTrans->Enable(false);
    cbDither->Enable(false);
    cbShrink->Enable(false);
    txtFrames->Enable(false);
    txtSizeX->Enable(false);
    txtSizeY->Enable(false);
    txtDelay->Enable(false);

    // Pause our rendering to screen so we can focus on making the animated image
    g_videoSetting.render = false;

    m_fAnimSpeed = g_canvas->model->animManager->GetSpeed(); 
        // Save the old animation speed
    g_canvas->model->animManager->SetSpeed(1.0f); // Set it to the normal speed.

    m_iTotalAnimFrames = g_canvas->model->animManager->GetFrameCount();
    wxString(txtFrames->GetValue() ).ToLong( (long*) &m_iTotalFrames);
    wxString(txtDelay->GetValue() ).ToLong( (long*) &m_iDelay);

    // will crash program - prevent this from happening
    if(m_iTotalFrames > m_iTotalAnimFrames)
    {
        wxMessageBox(_T(
            "Impossible to make a gif with more frames than the model animation.\nClosing gif exporter."), _T("Error") );
        wxLogMessage(_T(
            "Error: Unable to make a gif with more frames than the model animation.") );
        this->Show(false);
        return ;
    }

    if(m_iDelay < 1)
    {
        m_iDelay = 1;
    }
    if(m_iDelay > 100)
    {
        m_iDelay = 100;
    }

    m_iTimeStep = int(m_iTotalAnimFrames / m_iTotalFrames); 
        // Total number of frames in the animation / total frames going into our exported animation image

    if(m_bShrink)
    {
        wxString(txtSizeX->GetValue() ).ToLong( (long*) &m_iNewWidth);
        wxString(txtSizeY->GetValue() ).ToLong( (long*) &m_iNewHeight);

        // Just a minor check,  final image size can not be smaller than 32x32 pixels.
        if(m_iNewWidth < 32 || m_iNewHeight < 32)
        {
            m_iNewWidth = 32;
            m_iNewHeight = 32;
        }
    }

    // CREATE OUR RENDERTOTEXTURE OBJECT
    // -------------------------------------------
    // if either are supported use our 'RenderTexture' object.
    if(g_videoSetting.supportPBO || g_videoSetting.supportVBO)
    {
        g_canvas->rt = new RenderTexture();

        if(!g_canvas->rt)
        {
            wxLogMessage(_T("Error: RenderToTexture object is null!") );
            this->Show(false);
            return ;
        }

        g_canvas->rt->Init( (HWND)g_canvas->GetHandle(), 0, 0, g_videoSetting.supportFBO)
            ;

        m_iWidth = g_canvas->rt->nWidth;
        m_iHeight = g_canvas->rt->nHeight;
        g_canvas->rt->BeginRender();
    }
    else
    {
        glReadBuffer(GL_BACK);
        int screenSize[4];
        glGetIntegerv(GL_VIEWPORT, screenSize); 
            // get the width/height of the canvas
        m_iWidth = screenSize[2];
        m_iHeight = screenSize[3];
        return ;
    }

    // Stop our animation
    g_canvas->model->animManager->Pause(true);
    g_canvas->model->animManager->Stop();
    g_canvas->model->animManager->AnimateParticles();

    // Size of our buffer to hold the pixel data
    m_iSize = m_iWidth * m_iHeight * 4; // (width*height*bytesPerPixel)	

    // Create one frame to make our optimal colour palette from.
    unsigned char *buffer = new unsigned char[m_iSize];
    gifImages = new CxImage *[m_iTotalFrames];

    for(unsigned int i = 0; i < m_iTotalFrames; i++)
    {
        lblCurFrame->SetLabel(wxString::Format(_T("Current Frame: %i"), i) );

        this->Refresh();
        this->Update();

        CxImage *newImage = new CxImage(0);

        g_canvas->RenderToBuffer();

        glReadPixels(0, 0, m_iWidth, m_iHeight, GL_BGRA_EXT, GL_UNSIGNED_BYTE,
            buffer);
        newImage->CreateFromArray(buffer, m_iWidth, m_iHeight, 32, (m_iWidth *4)
            , false);

        // not needed due to the code just below, which fixes the issue with particles
        //g_canvas->model->animManager->SetTimeDiff(m_iTimeStep);
        //g_canvas->model->animManager->Tick(m_iTimeStep);

        if(g_canvas->root)
        {
            g_canvas->root->tick( (float)m_iTimeStep);
        }
        if(g_canvas->sky)
        {
            g_canvas->sky->tick( (float)m_iTimeStep);
        }


#ifdef _WIN32
        if(m_bGreyscale)
        {
            newImage->GrayScale();
        }
#endif //_WIN32

        if(m_bShrink && m_iNewWidth != m_iWidth && m_iNewHeight != m_iHeight)
        {
            newImage->Resample(m_iNewWidth, m_iNewHeight, 2);
        }

        // if (Optimise) {
        if(!m_pPal)
        {
            CQuantizer q(256, 8);
            q.ProcessImage( (HANDLE)newImage->GetDIB() );
            m_pPal = (RGBQUAD*)calloc(256 *sizeof(RGBQUAD), 1); 
                //This creates our gifs optimised global colour palette
            q.SetColorTable(m_pPal);
        }

        newImage->DecreaseBpp(8, m_bDiffuse, m_pPal, 256);
        newImage->SetCodecOption(2); // for LZW compression

        if(m_bTransparent)
        {
            newImage->SetTransIndex(newImage->GetPixelIndex(0, 0) );
        }

        newImage->SetFrameDelay(m_iDelay);

        gifImages[i] = newImage;

        // All the memory that we allocate for newImage gets cleared at the end
    }

    wxDELETEA(buffer);

    if(g_videoSetting.supportPBO || g_videoSetting.supportVBO)
    {
        g_canvas->rt->EndRender();

        // Clear RenderTexture object.
        g_canvas->rt->Shutdown();
        wxDELETE(g_canvas->rt);
    }

    // CREATE THE ACTUAL MULTI-IMAGE GIF ANIMATION
    // ------------------------------------------------------
    // Create the file and write all the data
    // Open/Create the file that were going to save to
    FILE *hFile = NULL;
    hFile = fopen(m_strFilename.fn_str(), "wb");

    // Set gif options
    CxImageGIF multiImage;
    multiImage.SetComment("Exported from WoW Model Viewer");
    if(m_bTransparent)
    {
        multiImage.SetDisposalMethod(2);
    }
    else
    {
        multiImage.SetDisposalMethod(0);
    }

    multiImage.SetFrameDelay(m_iDelay);
    multiImage.SetCodecOption(2); // LZW
    multiImage.SetLoops(0); // Set the animation to loop indefinately.

    // Create/Compose the animated gif
    multiImage.Encode(hFile, gifImages, m_iTotalFrames, false);

    // ALL DONE, START THE CLEAN UP
    // --------------------------------------------------------
    // Close file
    fclose(hFile);

    // Free the memory used by all the images to create the GIF
    for(unsigned int i = 0; i < m_iTotalFrames; i++)
    {
        gifImages[i]->Destroy();
        wxDELETE(gifImages[i]);
    }
    wxDELETEA(gifImages);

    // Free memory used by the colour palette
    if(m_pPal)
    {
        free(m_pPal);
        m_pPal = NULL;
    }

    wxLogMessage(_T("Info: GIF Animation successfully created.") );

    g_canvas->model->animManager->SetSpeed(m_fAnimSpeed); 
        // Return the animation speed back to whatever it was previously set as
    g_canvas->model->animManager->Play();

    Show(false);

    g_videoSetting.render = true;
    g_canvas->InitView();
}
UINT CFrameGrabThread::GrabFrames(){
	#define TIMEBETWEENFRAMES	50.0 // could be a param later, if needed
	for (int i = 0; i!= nFramesToGrab; i++)
		imgResults[i] = NULL;
	try{
		HRESULT hr;
		CComPtr<IMediaDet> pDet;
		hr = pDet.CoCreateInstance(__uuidof(MediaDet));
		if (!SUCCEEDED(hr))
			return 0;

		// Convert the file name to a BSTR.
		CComBSTR bstrFilename(strFileName);
		hr = pDet->put_Filename(bstrFilename);

		long lStreams;
		bool bFound = false;
		hr = pDet->get_OutputStreams(&lStreams);
		for (long i = 0; i < lStreams; i++)
		{
			GUID major_type;
			hr = pDet->put_CurrentStream(i);
			hr = pDet->get_StreamType(&major_type);
			if (major_type == MEDIATYPE_Video)
			{
				bFound = true;
				break;
			}
		}
		
		if (!bFound)
			return 0;
		
		double dLength = 0;
		pDet->get_StreamLength(&dLength);
		if (dStartTime > dLength)
			dStartTime = 0;

		long width = 0, height = 0; 
		AM_MEDIA_TYPE mt;
		hr = pDet->get_StreamMediaType(&mt);
		if (mt.formattype == FORMAT_VideoInfo) 
		{
			VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)(mt.pbFormat);
			width = pVih->bmiHeader.biWidth;
			height = pVih->bmiHeader.biHeight;
			
	        
			// We want the absolute height, don't care about orientation.
			if (height < 0) height *= -1;
		}
		else {
			return 0; // Should not happen, in theory.
		}

		/*FreeMediaType(mt); = */	
		if (mt.cbFormat != 0){
			CoTaskMemFree((PVOID)mt.pbFormat);
			mt.cbFormat = 0;
			mt.pbFormat = NULL;
		}
		if (mt.pUnk != NULL){
			mt.pUnk->Release();
			mt.pUnk = NULL;
		}
		/**/

	    
		long size;
		uint32 nFramesGrabbed;
		for (nFramesGrabbed = 0; nFramesGrabbed != nFramesToGrab; nFramesGrabbed++){
			hr = pDet->GetBitmapBits(dStartTime + (nFramesGrabbed*TIMEBETWEENFRAMES), &size, NULL, width, height);
			if (SUCCEEDED(hr)) 
			{
				// we could also directly create a Bitmap in memory, however this caused problems/failed with *some* movie files
				// when I tried it for the MMPreview, while this method works always - so I'll continue to use this one
				long nFullBufferLen = sizeof( BITMAPFILEHEADER ) + size;
				char* buffer = new char[nFullBufferLen];
				
				BITMAPFILEHEADER bfh;
				memset( &bfh, 0, sizeof( bfh ) );
				bfh.bfType = 'MB';
				bfh.bfSize = nFullBufferLen;
				bfh.bfOffBits = sizeof( BITMAPINFOHEADER ) + sizeof( BITMAPFILEHEADER );
				memcpy(buffer,&bfh,sizeof( bfh ) );

				try {
					hr = pDet->GetBitmapBits(dStartTime+ (nFramesGrabbed*TIMEBETWEENFRAMES), NULL, buffer + sizeof( bfh ), width, height);
				}
				catch (...) {
					ASSERT(0);
					hr = E_FAIL;
				}
				if (SUCCEEDED(hr))
				{
					// decode
					CxImage* imgResult = new CxImage();
					imgResult->Decode((BYTE*)buffer, nFullBufferLen, CXIMAGE_FORMAT_BMP);
					delete[] buffer;
					if (!imgResult->IsValid()){
						delete imgResult;
						break;
					}

					// resize if needed
					if (nMaxWidth > 0 && nMaxWidth < width){
						float scale = (float)nMaxWidth / imgResult->GetWidth();
						int nMaxHeigth = (int)(imgResult->GetHeight() * scale);
						imgResult->Resample(nMaxWidth, nMaxHeigth, 0);
					}
					
					// decrease bpp if needed
					if (bReduceColor){
						RGBQUAD* ppal=(RGBQUAD*)malloc(256*sizeof(RGBQUAD));
						if (ppal) {
							CQuantizer q(256,8);
							q.ProcessImage(imgResult->GetDIB());
							q.SetColorTable(ppal);
							imgResult->DecreaseBpp(8, true, ppal);
							free(ppal);
						}
					}
					
					//CString TestName;
					//TestName.Format("G:\\testframe%i.png",nFramesGrabbed);
					//imgResult->Save(TestName,CXIMAGE_FORMAT_PNG);
					// done
					imgResults[nFramesGrabbed] = imgResult;
				}
				else{
					delete[] buffer;
					break;
				}
			}
		}
		return nFramesGrabbed;
	}
	catch(...){
		ASSERT(0);
		return 0;
	}
}
Exemple #3
0
//////////////////////////////////////////////////////////////////////////////
// CMainFrame message handlers
void CMainFrame::OnEditPaste() 
{
	CDemoDoc *NewDoc=(CDemoDoc*)((CDemoApp*)AfxGetApp())->demoTemplate->OpenDocumentFile(NULL); 

	if (NewDoc)
	{
		if (OpenClipboard())
		{
			HANDLE hData=NULL;
			
			if (hData = GetClipboardData(((CDemoApp*)AfxGetApp())->GetCF())){ //custom CxImage object
				CxImage *newima = new CxImage();
				DWORD dwSize = GlobalSize(hData);
				if (dwSize) {
					BYTE *lpVoid = (BYTE *)GlobalLock(hData);
					newima->UnDump(lpVoid);
					GlobalUnlock(lpVoid);
				}
				NewDoc->image = newima;
			} else if (hData = GetClipboardData(CF_DIB)){ // check if bitmap
				CxImage *newima = new CxImage();
				newima->CreateFromHANDLE(hData);
				NewDoc->image = newima;
			} else  {		
#if CXIMAGE_SUPPORT_WMF
				if (hData = GetClipboardData(CF_ENHMETAFILE)) //check if metafile
				{
					HENHMETAFILE hMeta = (HENHMETAFILE)hData;
					ENHMETAHEADER emh;
					GetEnhMetaFileHeader(hMeta, sizeof(emh), &emh); 

					int	cx,cy;
					cx = (int)((emh.rclBounds.right - emh.rclBounds.left)/2.54);
					cy = (int)((emh.rclBounds.bottom - emh.rclBounds.top)/2.54);

					HDC hDC0 = ::GetDC(0); // screen dc
					HBITMAP hBitmap = CreateCompatibleBitmap(hDC0, cx, cy);
					HDC	hDC = CreateCompatibleDC(hDC0);	// memory dc compatible with screen
					::ReleaseDC(0, hDC0);	// don't need anymore. get rid of it.

					if (hDC && hBitmap){

						RECT rc = {0,0,cx,cy};
						int bpp = ::GetDeviceCaps(hDC, BITSPIXEL);

						HBITMAP hBitmapOld = (HBITMAP)SelectObject(hDC, hBitmap);

						// paint the background
						DWORD	dwBack = RGB(255, 255, 255); //GetSysColor(COLOR_WINDOW);
						DWORD OldColor = SetBkColor(hDC, dwBack);
						ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
						SetBkColor(hDC, OldColor);

						// Play the Metafile into Memory DC
						BOOL bRet = PlayEnhMetaFile(hDC, hMeta,	&rc);

						SelectObject(hDC, hBitmapOld);

						CxImage *newima = new CxImage();
						if(bRet && newima->Create(cx, cy, bpp, CXIMAGE_FORMAT_WMF)){
							
							bRet = GetDIBits(hDC, hBitmap, 0,	(UINT)cy, newima->GetBits(),
								             (LPBITMAPINFO)newima->GetDIB(), DIB_RGB_COLORS);

							NewDoc->image = newima;
						}
						else
						{
							delete newima;
						}
					}
					if (hBitmap) DeleteObject(hBitmap);
					if (hDC) DeleteDC(hDC);
				}
#endif
			}
		}

		CloseClipboard();

		CString s;
		s.Format(_T("Clipboard Image %d"),((CDemoApp*)AfxGetApp())->m_nDocCount++);
		NewDoc->SetTitle(s);
		NewDoc->UpdateAllViews(0,WM_USER_NEWIMAGE);
		NewDoc->UpdateStatusBar();
	}
}
// return number of faces and score
void detectFaces(const CxImage& img, std::list <Face>& lFaces, int nRot)
{
	if (cascade_el == NULL || cascade_er == NULL || cascade_f == NULL || cascade_m == NULL || cascade_n == NULL)
		init();
	CxImage imgRotated (img);
	imgRotated.Rotate180();
	IplImage *pIplImage = cvCreateImageHeader (cvSize (img.GetWidth(), img.GetHeight()), 8, img.GetBpp() / 8);
	pIplImage->imageDataOrigin = (char*)imgRotated.GetDIB();
	pIplImage->imageData = (char*)imgRotated.GetBits();

	CvMemStorage			*storage;

	/* setup memory storage, needed by the object detector */
	storage = cvCreateMemStorage(0);

	assert(cascade_f && cascade_el && cascade_er && cascade_m && cascade_n && storage);

	/* haar detection for faces */
	CvSeq *pFaces = cvHaarDetectObjects(
		pIplImage, cascade_f, storage,
		1.2, 2, CV_HAAR_DO_CANNY_PRUNING, cvSize( 40, 40 ) );
	if (pFaces->total == 0)
		return;

	CvSeq seqFaces (*pFaces);
	list <CvRect> lrFaces;
	for(int idxFace = 0; idxFace < seqFaces.total; idxFace++ ) {
		CvRect *r = (CvRect*)cvGetSeqElem(&seqFaces, idxFace);
		if (r)
			lrFaces.push_back (*r);
	}

	/* haar detection for eyes */
	list<pair <RECT, RECT>> lpairEyes;
	detect_eyes (storage, pIplImage, lpairEyes);
	
	/* haar detection for mouths */
	list<RECT> lMouths;
	detect_mouths (storage, pIplImage, lMouths);
	
	/* haar detection for noses */
	list<RECT> lNoses;
	detect_noses (storage, pIplImage, lNoses);
	
	for(list <CvRect>::iterator itFace = lrFaces.begin(); itFace != lrFaces.end(); ++itFace) {
		CvRect r (*itFace);
		CvRect rFace (*itFace);
		rFace.x = img.GetWidth() - r.x - r.width;
		rFace.y = img.GetHeight() - r.y - r.height;
		RECT rcFace; 
		rcFace.left = img.GetWidth() - r.x - r.width - 10; rcFace.right = img.GetWidth() - r.x + 10;
		rcFace.top = img.GetHeight() - r.y - r.height - 10; rcFace.bottom = img.GetHeight() - r.y + 10;

		/* detect current eyes */
		pair <RECT, RECT> pairEyes;
		match_eyes_with_face (lpairEyes, rFace, pairEyes);

		/* detect current mouth */
		RECT rcMouth;
		match_mouths_with_face (lMouths, rFace, pairEyes, rcMouth);

		/* detect current nose */
		RECT rcNose;
		match_noses_with_face (lNoses, rFace, pairEyes, rcMouth, rcNose);

		lFaces.push_back (Face (rcFace, pairEyes, rcMouth, rcNose, nRot));
	}
	Face::adjustRectFaces(lFaces);

	cvReleaseMemStorage (&storage);

	cvReleaseImageHeader (&pIplImage);
}