Thread loading images faster until they disapear in Studio - c++

I am pretty new to visual studio. I am trying to load images and display it on a UI with two buttons start and stop. Every time I complete my count of total frames the next time I press start my images load more faster than before and in the end images the speed is so fast that they just disappear or appear as black. The thread speed or loading of images time increases as with each cycle. How can I limit this.. or put a time interval between showing two images. Thank you.
there code is as follows :
void CmirrorImageDlg::OnBnClickedStart()
{
m_play = TRUE;
CString num = NULL;
num.Format(_T("Pause"));
m_start.EnableWindow(false);
m_stop.EnableWindow(true);
m_stop.SetWindowTextW(num);
m_pThread = AfxBeginThread(Operate, (LPVOID)this, THREAD_PRIORITY_NORMAL);
}
void CmirrorImageDlg::OnBnClickedStop()
{
m_play = FALSE;
CString num = NULL;
num.Format(_T("Resume"));
m_start.EnableWindow(true);
m_stop.EnableWindow(false);
m_start.SetWindowTextW(num);
m_count = 0;
//m_pThread = AfxBeginThread(Operate, (LPVOID)this, THREAD_PRIORITY_ABOVE_NORMAL);
// TODO: Add your control notification handler code here
}
UINT CmirrorImageDlg::Operate(LPVOID param)
{
CmirrorImageDlg* pDlg = (CmirrorImageDlg*) param;
CString test;
while ( pDlg->m_play && pDlg->m_count < TOTAL_FRAME_NUMBER)
{
test.Format(_T("images/%.4d.BMP"),pDlg->m_count);
pDlg->hbitmap = (HBITMAP)LoadImage(NULL,test,IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
pDlg->inv_hbitmap = pDlg->GetInvertedBitmap(pDlg->hbitmap, TRUE);
pDlg->inv_hbitmap_1 = pDlg->GetInvertedBitmap(pDlg->hbitmap , FALSE);
//CBitmap map = LoadBitmapW(test);
//filePath = IDB_BITMAP1;
//filePath++;
//IDB_PICTURE2.LoadBitmapW(filePath);
pDlg->m_picture.SetBitmap(pDlg->hbitmap);
pDlg->m_picture_2.SetBitmap(pDlg->inv_hbitmap);
pDlg->m_picture_3.SetBitmap(pDlg->inv_hbitmap_1);
CString num = NULL;
num.Format(_T("%d"),pDlg->m_count);
pDlg->m_label.SetWindowTextW(num);
// TODO: Add your control notification handler code here
pDlg->m_count++;
}
if(pDlg->m_count >= TOTAL_FRAME_NUMBER)
{
CString num = NULL;
num.Format(_T("%d"),0);
pDlg->m_count = 0;
pDlg->m_play= false;
pDlg->m_label.SetWindowTextW(num);
pDlg->m_picture.SetBitmap(NULL);
pDlg->m_picture_2.SetBitmap(NULL);
pDlg->m_picture_3.SetBitmap(NULL);
CString num1 = NULL;
num.Format(_T("Stop"));
pDlg->m_start.EnableWindow(true);
pDlg->m_stop.EnableWindow(false);
pDlg->m_stop.SetWindowTextW(num);
num.Format(_T("Start"));
pDlg->m_start.SetWindowTextW(num);
//pDlg->m_pThread->SuspendThread();
}
return 0;
}

A reasonably simple option:
Set a WM_TIMER for your dialog to fire every 40 milliseconds (if you want 25 frames per second). If not playing, the timer handler will do nothing.
When the user hits play, you'll load the first image, and then set the 'playing' flag. Inside the timer handler, it will take the currently loaded image and blit it to the screen, then load the next image and return. When there are no more images in the sequence you clear your 'playing' flag.
Because you always display the current image when the timer fires, it doesn't matter how long it takes to load the next image (as long as you can do it faster than the playback).

Related

MFC Open big document

I have an Single-document Interface(SDI) Microsoft Foundation Class(MFC) app that has to load a big document file (takes about 2 minutes). For that reason, my app stays unresponsive while I am opening the document.
However, I would like my app to be responsive while opening the document. The problem is that, if I try to load my document on a thread, my OnopenDocument function (in my doc) will return before I actually open the document:
BOOL CmodguiDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
if (!CDocument::OnOpenDocument(lpszPathName))
return FALSE;
start_tread(_open_doc); // just an example
return TRUE; // Will return before the document will actually be open
}
How can I do this to be non-locking but only returning after the document is actually open? Or how can I at least make my app responsive while I am loading the document?
Thanks
Returning after the thread has been created is OK. You should define a state for the document such as loading and loaded. When you start the thread the state should be loading. The view(s) should look at the state and display accordingly. When the thread has finished loading the document it should post a message to the document. In the handler, set the state to loaded and call UpdateAllViews() to give the views the chance to update with the new document data.
Example: This will print "loading" while the doc is loading and "loaded" and loaded after it finished in the view.
In resource.h:
#define IDD_NotifyDocumentFinished 101
In the document header:
public:
enum DocState
{
None,
Failed,
Loading,
Loaded
};
DocState GetDocState() const {return m_state;}
private:
DocState m_state;
void StartLoading();
In the document implementation:
BOOL CMFCDocViewAsyncDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
if(!CDocument::OnOpenDocument(lpszPathName))
return FALSE;
m_state = Loading;
StartLoading();
return TRUE;
}
UINT LongRunningFunction(LPVOID param)
{
Sleep(3000);
HWND hWnd = AfxGetApp()->m_pMainWnd->GetSafeHwnd();
NMHDR hdr = {hWnd, IDD_NotifyDocumentFinished, 0};
::SendMessage(hWnd, WM_NOTIFY, 0, reinterpret_cast<LPARAM>(&hdr));
return 0;
}
void CMFCDocViewAsyncDoc::StartLoading()
{
AfxBeginThread(&LongRunningFunction, nullptr);
}
BOOL CMFCDocViewAsyncDoc::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
{
if(HIWORD(nCode) == WM_NOTIFY)
{
WORD wCode = LOWORD(nCode);
AFX_NOTIFY * notify = reinterpret_cast<AFX_NOTIFY*>(pExtra);
if(notify->pNMHDR->idFrom == IDD_NotifyDocumentFinished)
{
m_state = Loaded;
UpdateAllViews(nullptr);
}
}
return TRUE;
}
In the view:
void CMFCDocViewAsyncView::OnDraw(CDC* pDC)
{
CMFCDocViewAsyncDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
CMFCDocViewAsyncDoc::DocState state = pDoc->GetDocState();
CString sstate;
switch(state)
{
case CMFCDocViewAsyncDoc::None:
sstate = "None";
break;
case CMFCDocViewAsyncDoc::Failed:
sstate = "Failed";
break;
case CMFCDocViewAsyncDoc::Loading:
sstate = "Loading";
break;
case CMFCDocViewAsyncDoc::Loaded:
sstate = "Loaded";
break;
}
pDC->TextOut(50, 50, sstate);
}
Update: Also look here for a similar, more detailed example http://www.codeproject.com/Articles/14706/Notifying-the-Document.
When it takes two minutes to just load something, then there are two reasons for that:
You are doing something stupid while loading, like e.g. running expensive algorithms on the data like indexing or graphical rendering. If you store the data in containers, the overhead of allocations could also become significant. If that is the case, only perform them on demand or perform these operations asynchronously in the background. You can notify the main thread (the one running the UI) when done in order to display the rendered graphics, for example.
The data is incredibly large. In that case, you will have to rethink how to access this data anyway, because any operation might be expensive. Your best bet will be to use an asynchronous model, like sending a request to the model to perform some operation. The model then sends a response to the UI to display the data. In that case, you need to think about how to make this transparent to the user though. One approach is to darken the display area after a change request and only brighten it up after the response or a progress bar.

QProgressDialog bar resets to zero when completes

I am using QProgressDialog which obviously just shows progress and it increments along the way. When it reaches 100%, the progress bar on it resets to zero instead of showing 100% there after.
progress is member variable of the class.
QSharedPointer<QProgressDialog> progress;
It is used in on_clicked event. Note I am using Sleep() for simulation, I know it doesn't belong there. The problem is when it reaches 100%, the progress bar shows zero progress and I want to stick to 100%.
void MainWindow::on_pushButtonConvert_clicked()
{
int numFiles = 10;
progress = (QSharedPointer<QProgressDialog>) new QProgressDialog("Copying files...", "Abort Copy", 0, numFiles, this);
progress->setWindowModality(Qt::WindowModal);
progress->setAutoClose( false );
for (int i = 0; i < numFiles; i++) {
progress->setValue(i);
if (progress->wasCanceled())
break;
//... copy one file
Sleep(500);
}
progress->setValue(numFiles);
}
I figured it out, I had to call:
progress->setAutoReset( false );

Animation using .png files cocos2dx

I have 34 .png image files for 9 different scenarios. Each time the user picks 1 of those 9 scenarios and according to that I generate animation using the following
std::string name;
MixingScreen::animation = CCAnimation::create();
// load image file from local file system to CCSpriteFrame, then add into CCAnimation
for (int i = 0; i < 34; i++)
{
std::stringstream st,ii;
st << Constants::flav;
if (i<10)
{
ii<<i;
name="screen/screen02/fx/sugar/0" + st.str()+"/a_0000"+ii.str()+".png";
}
else
{
ii<<i;
name="screen/screen02/fx/sugar/0" + st.str()+"/a_000"+ii.str()+".png";
}
//sprintf(szImageFileName, "Images/grossini_dance_%02d.png", i);
MixingScreen::animation->addSpriteFrameWithFileName(name.c_str());
}
MixingScreen::animation->setDelayPerUnit(5.0f / 34.0f);
action = CCAnimate::create(MixingScreen::animation);
CCCallFunc *done = CCCallFunc::create(this, callfunc_selector(MixingScreen::doneMixing));
CCSequence *readySequence = CCSequence::create(action,done,NULL);
particles->runAction(readySequence);
The problem I am facing is that when this animation runs, there is a time lag(everything stops for few seconds) and then the animation starts. Any solution?
Every time you call animation->addSpriteFrameWithFileName() a new "CCSpriteFrame" is created.
Instead you should first add the sprite frames to CCSpriteFrameCache and use
animation->addSpriteFrame(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameWithName(""))
Ps: these function names might be a little different but i hope you get the idea.

Invoke a method only once from a class

I have a shape class in which there is a method (hitTest(int,int)) that continuously checks if the mouse is inside its bounds or not. In another method, I keep on checking if the mouse has stayed there for more than 1 sec.
If it has, trigger a function (by notification/event) that runs animation
It it has not, then don't trigger the animation
If it has already triggered the animation and the animation is running but the mouse leaves the area during this, trigger an interrupt function (by notification/event)
//OnLoad _initHover = false;
void update() //called continously in the application per frame
{
if(hitTest(getMouseX(), getMouseY())){
if(!_initHover){
_initHover = true;
_hoverStartTime = getCurrentTime(); //start hover time
cout<<"Start hist test\n";
}
//If it has hovered over the video for 1.0 sec
if((ofGetElapsedTimef() - _hoverStartTime) > 1.0){
cout<<"Hitting continously for 1 sec\n";
notificationCenter->postNotification(new AnimationStartNotification);
}
}
else{
_initHover = false;
notificationCenter->postNotification(new AnimationInterruptNotification);
}
}
The above code runs fine but there's a logical issue I am facing while trying to use. There are multiple instances of the above Shape class and each class consequently has their update() method as well. The mouse cursor has which has animationStarthandler and animationStophandlers is a single class in the whole application.
Issue 1: So, even when one of the shape just notifies the animationStarthandler to fire, the other shape classes on which hit test is false set the animation to interrupt and the animation does not run.
Issue 2: When the hit test succeeds and the cursor has been in the area for more than 1 sec, the hit test will keep on sending the notification to start the animation (anim's duration 1.5 sec approx.) How do I restrict the hit test to fire the animation only once and keep on firing the same animation again and again?
If in the main method of my application, I directly try to fire the animation by calling the method playAnimation in the pointer class, I get the required result. But I want to give this hover timing and animation functionality to the ShapeClass itself. Any suggestions?
I think that you should consider adding a new boolean, which holds the information of the triggering of the animation (called in the code sample _animationTriggered). This prevents shapes that have not triggered the animation to stop it and the animation that triggered it to make it several times.
if(hitTest(getMouseX(), getMouseY()))
{
if(!_initHover)
{
_initHover = true;
_hoverStartTime = getCurrentTime();
cout<<"Start hist test\n";
}
if((ofGetElapsedTimef() - _hoverStartTime) > 1.0)
{
if (!_animationTriggered)
{
cout<<"Hitting continously for 1 sec\n";
notificationCenter->postNotification(new AnimationStartNotification);
_animationTriggered = true;
}
}
}
else
{
if ( _animationTriggered )
{
_initHover = false;
notificationCenter->postNotification(new AnimationInterruptNotification);
_animationTriggered = false;
}
}
Don't forget to initialie this new boolean in the same place as _initHover

ID3D10Device::RSSetState to be called every frame?

I am trying to create a ID3D10RasterizerState with direct3D10, and then call
ID3D10Device::RSSetState()
with the proper information. However, whenever the window get rescaled, or when the app goes fullscreen, the rasterizerstate seems to reset to the default state.
I have tried to set the state with WM_SIZE messages, but awkwardly, nothing seems to happen...
It works properly when I call RSSetState() every frame, but that seems highly inefficient.
Does anyone know a solution to this?
It seems to be poorly documented on msdn.
Code:
bool TestGameApp::InitGame()
{
D3D10_RASTERIZER_DESC desc;
desc.AntialiasedLineEnable = TRUE;
desc.CullMode = D3D10_CULL_NONE;
desc.DepthBias = 0;
desc.DepthBiasClamp = 0.0f;
desc.FillMode = D3D10_FILL_SOLID;
desc.FrontCounterClockwise = false;
desc.MultisampleEnable = true;
desc.ScissorEnable = FALSE;
desc.SlopeScaledDepthBias = 0.0f;
m_pD3DDevice->CreateRasterizerState(&desc,m_pRSState);
m_pD3DDevice->RSSetState(m_pRSState);
//...more code
}
WndProc:
switch( message )
{
case WM_SIZE:
{
m_pD3DDevice->RSSetState(m_pRSState);
break;
}
}
Just set it every frame. In general you want to minimize the number of render state changes in a frame but you don't need to worry about the performance impact of setting the rasterizer state once a frame. Setting it every frame also lets you do things like enable and disable wireframe rendering for debugging.