Solved

LoadPic program help

Posted on 2004-03-22
6
519 Views
Last Modified: 2007-12-19
Hi,
I am having a problem with LoadPic dealing with streaming images. Basically, I modified the code so that it would read jpeg image and then display the image insquence like a movie. But I'm having making it load faster or smoother. My goal to make it display 15 images per sec if possible. Plz take a look.

//---------------part of the code--------------------------------//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
      PAINTSTRUCT ps;
      HDC hdc;
      char buf[64];
      i = i%9;
      sprintf(buf,"frame%06d.jpg",i+1);                              LoadPictureFile(buf);
      hdc = BeginPaint(hWnd, &ps);
      if (gpPicture)
            {
            // get width and height of picture
            long hmWidth;
            long hmHeight;
            gpPicture->get_Width(&hmWidth);
            gpPicture->get_Height(&hmHeight);
            // convert himetric to pixels
            int nWidth      = MulDiv(hmWidth, GetDeviceCaps(hdc, LOGPIXELSX), HIMETRIC_INCH);
            int nHeight      = MulDiv(hmHeight, GetDeviceCaps(hdc, LOGPIXELSY), HIMETRIC_INCH);
            RECT rc;
            GetClientRect(hWnd, &rc);
            // display picture using IPicture::Render
            gpPicture->Render(hdc, 0, 0, nWidth, nHeight, 0, hmHeight, hmWidth, -hmHeight, &rc);
            }
            EndPaint(hWnd, &ps);
            i = i+1;
            return DefWindowProc(hWnd, message, wParam, lParam);
}
//----------------------part of the code end-----------------------------//


My loadpic program
// LoadPic.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "resource.h"
#include <fstream.h>
#include <string>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
int i = 1;

#define MAX_LOADSTRING      100
#define HIMETRIC_INCH      2540
#define MAP_LOGHIM_TO_PIX(x,ppli)   ( ((ppli)*(x) + HIMETRIC_INCH/2) / HIMETRIC_INCH )

// Global Variables:
HINSTANCE hInst;                                                // current instance
TCHAR szTitle[MAX_LOADSTRING];                              // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];                  // The title bar text
LPPICTURE gpPicture;
HWND ghWnd;

// Foward declarations of functions included in this code module:
ATOM                        MyRegisterClass(HINSTANCE hInstance);
BOOL                        InitInstance(HINSTANCE, int);
LRESULT CALLBACK      WndProc(HWND, UINT, WPARAM, LPARAM);

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
       // TODO: Place code here.
      MSG msg;

      // Initialize global strings
      LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
      LoadString(hInstance, IDC_LOADPIC, szWindowClass, MAX_LOADSTRING);
      MyRegisterClass(hInstance);

      // Perform application initialization:
      if (!InitInstance (hInstance, nCmdShow))
      {
            return FALSE;
      }

      // Main message loop:
      while (GetMessage(&msg, NULL, 0, 0))
      {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
      }

      if (gpPicture)
            gpPicture->Release();

      return msg.wParam;
}

ATOM MyRegisterClass(HINSTANCE hInstance)
{
      WNDCLASSEX wcex;

      wcex.cbSize = sizeof(WNDCLASSEX);

      wcex.style                  = CS_HREDRAW | CS_VREDRAW;
      wcex.lpfnWndProc      = (WNDPROC)WndProc;
      wcex.cbClsExtra            = 0;
      wcex.cbWndExtra            = 0;
      wcex.hInstance            = hInstance;
      wcex.hIcon                  = LoadIcon(hInstance, (LPCTSTR)IDI_LOADPIC);
      wcex.hCursor            = LoadCursor(NULL, IDC_ARROW);
      wcex.hbrBackground      = (HBRUSH)(COLOR_WINDOW+1);
      wcex.lpszMenuName      = (LPCSTR)IDC_LOADPIC;
      wcex.lpszClassName      = szWindowClass;
      wcex.hIconSm            = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);

      return RegisterClassEx(&wcex);
}

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;

   hInst = hInstance; // Store instance handle in our global variable
   gpPicture = NULL;

   ghWnd = hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

// This function loads a file into an IStream.
void LoadPictureFile(LPCTSTR szFile)
{
      // open file
      HANDLE hFile = CreateFile(szFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
      _ASSERTE(INVALID_HANDLE_VALUE != hFile);
      // get file size
      DWORD dwFileSize = GetFileSize(hFile, NULL);
      _ASSERTE(-1 != dwFileSize);
      LPVOID pvData = NULL;
      // alloc memory based on file size
      HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, dwFileSize);
      _ASSERTE(NULL != hGlobal);
      pvData = GlobalLock(hGlobal);
      _ASSERTE(NULL != pvData);
      DWORD dwBytesRead = 0;
      // read file and store in global memory
      BOOL bRead = ReadFile(hFile, pvData, dwFileSize, &dwBytesRead, NULL);
      _ASSERTE(FALSE != bRead);
      GlobalUnlock(hGlobal);
      CloseHandle(hFile);
      LPSTREAM pstm = NULL;
      // create IStream* from global memory
      HRESULT hr = CreateStreamOnHGlobal(hGlobal, TRUE, &pstm);
      _ASSERTE(SUCCEEDED(hr) && pstm);
      // Create IPicture from image file
      if (gpPicture)
            gpPicture->Release();
      hr = ::OleLoadPicture(pstm, dwFileSize, FALSE, IID_IPicture, (LPVOID *)&gpPicture);
      _ASSERTE(SUCCEEDED(hr) && gpPicture);      
      pstm->Release();
      InvalidateRect(ghWnd, NULL, TRUE);
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
      PAINTSTRUCT ps;
      HDC hdc;
      char buf[64];
                        i = i%9;
                        sprintf(buf,"frame%06d.jpg",i+1);                                    
                        LoadPictureFile(buf);
                        hdc = BeginPaint(hWnd, &ps);
                        if (gpPicture)
                        {
                        // get width and height of picture
                        long hmWidth;
                        long hmHeight;
                        gpPicture->get_Width(&hmWidth);
                        gpPicture->get_Height(&hmHeight);
                        // convert himetric to pixels
                        int nWidth      = MulDiv(hmWidth, GetDeviceCaps(hdc, LOGPIXELSX), HIMETRIC_INCH);
                        int nHeight      = MulDiv(hmHeight, GetDeviceCaps(hdc, LOGPIXELSY), HIMETRIC_INCH);
                        RECT rc;
                        GetClientRect(hWnd, &rc);
                        // display picture using IPicture::Render
                        gpPicture->Render(hdc, 0, 0, nWidth, nHeight, 0, hmHeight, hmWidth, -hmHeight, &rc);
                        }
                        EndPaint(hWnd, &ps);
                        i = i+1;
                        return DefWindowProc(hWnd, message, wParam, lParam);
}
0
Comment
Question by:musicc
  • 2
  • 2
  • 2
6 Comments
 
LVL 6

Expert Comment

by:joghurt
ID: 10652654
1. If you want a fast code then why are you drawing the image for every message? It would be enough to draw only for WM_PAINT messages.
2. I don't see any kind of timing. How do you want your frames (images) to be played with the same delay after each other?
3. For me using IPicture::Render doesn't seem to be the fastest way to draw an image.

All in all, why don't you convert your separate files into an AVI stream using the AviFile functions and play this stream?
0
 
LVL 6

Expert Comment

by:PlanetCpp
ID: 10652794
whoa,,, basically you are trying to show a picture every few milliseconds (which is faster then the pic can be rendered),, or not at all depending on what your program is doing,, move your mouse over the apps window and TONS of mouse messages will be sent and you are trying to draw the picture each time.. like joghurt said you do that in WM_PAINT only,, and then have a way outside such as a timer to tell the window when to repaint.. every 300 milliseconds or something.
but the avi idea would be cleaner
0
 

Author Comment

by:musicc
ID: 10657570
joghurt thank 4 reply,
1. If you want a fast code then why are you drawing the image for every message? It would be enough to draw only for WM_PAINT messages.
How? Could you help me started in this? I'll try to look on line for sample code. C++ is not my native programming language.

2. I don't see any kind of timing. How do you want your frames (images) to be played with the same delay after each other?
Same delay would be fine. I just to make the frames in motion for now.

3. For me using IPicture::Render doesn't seem to be the fastest way to draw an image.
The reason I use it is b/c what MS loadpic use. I didn't know any other render method there are in C++.

I have no experience of doing avi stream. I'll do that next after I get the motion images with the JPEG file.

PlanetCpp
I'm still a novice in C++. I would love to see some sample code how render images using WM_PAINT. Could you help me? As I explained to joghurt, I use the rendering method based on what loadpic has .
0
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 
LVL 6

Expert Comment

by:PlanetCpp
ID: 10660516
you can view my bitmap loading sample on my webiste www.PlanetCpp.com
if you are new to c++ i always suggest you learn the language well before you try to write gui's and if someone is new to writing gui's i always suggest they learn the basics before they get into graphic programming. you seemed to have jumped those two hurdles too soon.
graphics programming is VERY tricky at time expecially with GDI. your code may look lke it workes but still be riddled with memory leaks and potential crashes.
make sure you understand it first before you write it.
if you still want to get into it, lok at the bitmap loading example and also the timer example, you can time your frames then.
WM_PAINT is a message sent to your window when windows sees that it needs to be repainted, windows will take care of painting common classes and etc but you need to control the painting of anything else you wanted to add. you would add your code to load the image into the timer message or procedure,, then after its loaded you would tell window to repaint your window with updatewindow,, then wm_paint is where you paint the current frame
0
 

Author Comment

by:musicc
ID: 10671699
Thank, I'll try it out. I thought it would be easy to view jpeg in sequence.
0
 
LVL 6

Accepted Solution

by:
joghurt earned 450 total points
ID: 10672881
On how to write an AVI file:
- You can either check the WriteAvi.c example in MSDN (it's in C),
- or download CAviGenerator (C++ wrapper, written by Jonathan de Halleux).

All you need is a bitmap that I believe you can generate from your jpeg files (using IPicture::HANDLE and IPicture::CurDC). Now you can call GetDIBits to retrieve the bitmap bits you'll need to supply for AviAddFrame.
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

Often, when implementing a feature, you won't know how certain events should be handled at the point where they occur and you'd rather defer to the user of your function or class. For example, a XML parser will extract a tag from the source code, wh…
  Included as part of the C++ Standard Template Library (STL) is a collection of generic containers. Each of these containers serves a different purpose and has different pros and cons. It is often difficult to decide which container to use and …
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now