Avatar of musicc
musicc asked on

LoadPic program help

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);
}
C++

Avatar of undefined
Last Comment
joghurt

8/22/2022 - Mon
joghurt

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?
PlanetCpp

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
ASKER
musicc

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 .
I started with Experts Exchange in 2004 and it's been a mainstay of my professional computing life since. It helped me launch a career as a programmer / Oracle data analyst
William Peck
PlanetCpp

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
ASKER
musicc

Thank, I'll try it out. I thought it would be easy to view jpeg in sequence.
ASKER CERTIFIED SOLUTION
joghurt

Log in or sign up to see answer
Become an EE member today7-DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform
Sign up - Free for 7 days
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.
See how we're fighting big data
Not exactly the question you had in mind?
Sign up for an EE membership and get your own personalized solution. With an EE membership, you can ask unlimited troubleshooting, research, or opinion questions.
ask a question