Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people, just like you, are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
Solved

LoadPic program help

Posted on 2004-03-22
6
548 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
Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
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

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.

860 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