Skip to main content
gamedev.net
🔒 Locked

Jpeg loader

Started by Axel 2 replies 1.1k views
Original Post
Axel
Axel
I am having an very hard time finding a jpeg loader that makes sense to me. Can somebody help me out. Remember that I am new to this type of programming so I may need some guidance here. Thanks. Axel
Axel
Otis
Otis
If you have Visual Studio and the MSDN library, check out the help that comes with the function OleLoadPicture(). This is a win32 API call that loads jpeg, png, gif, tga, bmp and many other formats. It's a bit of a pain to get the buffer out of it, because it can render to a DeviceContext (which you normally use in Direct3D) but it doesn't supply a normal RGBA buffer. There is an example provided, loadpic, which shows how this function can be used. The only disadvantage is that you need Windows95 or higher and internet explorer 3 or higher. Windows95 OSR2 and higher comes with IE3.

I did a test with this code and it works ok. I've added a piece of code that will render the loaded image on a memoryDeviceContext which is then usable to grab the buffer from using GetDIBits. The code I've added is in WM_PAINT (pardon me for the horrible code, most of it is not mine, it's just testcode )

NOTE:The buffer, pBuf, is freed just below the buffer is filled. I just checked it with the debugger. So it doesn't do anything with the received pixels.

enjoy. Oh and before you think you need a jpeg library... no, all is done using win32 api calls. no extra library needed.

LoadPic.cpp:
  
// LoadPic.cpp : Defines the entry point for the application.

//


#include "stdafx.h"
#include "resource.h"

#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;
}



//

// FUNCTION: MyRegisterClass()

//

// PURPOSE: Registers the window class.

//

// COMMENTS:

//

// This function and its usage is only necessary if you want this code

// to be compatible with Win32 systems prior to the 'RegisterClassEx'

// function that was added to Windows 95. It is important to call this function

// so that the application will get 'well formed' small icons associated

// with it.

//

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

//

// FUNCTION: InitInstance(HANDLE, int)

//

// PURPOSE: Saves instance handle and creates main window

//

// COMMENTS:

//

// In this function, we save the instance handle in a global variable and

// create and display the main program window.

//

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

//

// FUNCTION: WndProc(HWND, unsigned, WORD, LONG)

//

// PURPOSE: Processes messages for the main window.

//

// WM_COMMAND - process the application menu

// WM_PAINT - Paint the main window

// WM_DESTROY - post a quit message and return

//

//

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc, hPic;
BITMAPINFO bmpI;
OLE_HANDLE pOLE;
HBITMAP hBMP;


switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:

switch (wmId)
{
case IDM_OPEN:
{
// get file name to open

TCHAR szFile[MAX_PATH];
ZeroMemory(szFile, MAX_PATH);
OPENFILENAME ofn;
ZeroMemory(&ofn, sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
ofn.hwndOwner = hWnd;
ofn.lpstrFilter = _T("Supported Files Types(*.bmp;*.gif;*.jpg;*.ico;*.emf;*.wmf)\0*.bmp;*.gif;*.jpg;*.ico;*.emf;*.wmf\0Bitmaps (*.bmp)\0*.bmp\0GIF Files (*.gif)\0*.gif\0JPEG Files (*.jpg)\0*.jpg\0Icons (*.ico)\0*.ico\0Enhanced Metafiles (*.emf)\0*.emf\0Windows Metafiles (*.wmf)\0*.wmf\0\0");
ofn.lpstrTitle = _T("Open Picture File");
ofn.lpstrFile = szFile;
ofn.nMaxFile = MAX_PATH;
if (IDOK == GetOpenFileName(&ofn))
// load the file

LoadPictureFile(szFile);
}
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
int nWidth,nHeight, iResult;
DWORD dwError;
HRESULT hr;
unsigned char *pBuf;
if (gpPicture)
{
// get width and height of picture

long hmWidth;
long hmHeight;
gpPicture->get_Width(&hmWidth);
gpPicture->get_Height(&hmHeight);
// convert himetric to pixels

nWidth = MulDiv(hmWidth, GetDeviceCaps(hdc, LOGPIXELSX), HIMETRIC_INCH);
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);

HDC memDC = CreateCompatibleDC ( hdc );
HBITMAP memBM = CreateCompatibleBitmap ( hdc, nWidth, nHeight);
SelectObject ( memDC, memBM );

pBuf=(unsigned char *)malloc(nWidth*nHeight*3);
memset(pBuf,0,(nWidth*nHeight*3));

hr=gpPicture->Render(memDC,0,0,nWidth,nHeight, 0, hmHeight, hmWidth, -hmHeight, &rc);
if(SUCCEEDED(hr))
{
bmpI.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
bmpI.bmiHeader.biBitCount=24;
bmpI.bmiHeader.biHeight=nHeight;
bmpI.bmiHeader.biWidth=nWidth;
bmpI.bmiHeader.biPlanes=1;
bmpI.bmiHeader.biCompression=BI_RGB;
bmpI.bmiHeader.biClrImportant=0;
bmpI.bmiHeader.biClrUsed=0;
bmpI.bmiHeader.biSizeImage=0;
bmpI.bmiHeader.biXPelsPerMeter=0;
bmpI.bmiHeader.biYPelsPerMeter=0;
iResult=GetDIBits(memDC,memBM,0,nHeight,pBuf,&bmpI,DIB_RGB_COLORS);
dwError=GetLastError();
}
free(pBuf);
}
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
[/source]

LoadPic.h:

[source]

#if !defined(AFX_LOADPIC_H__5EB6AF99_E13D_11D2_90C6_00C04F9403C2__INCLUDED_)
#define AFX_LOADPIC_H__5EB6AF99_E13D_11D2_90C6_00C04F9403C2__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000


#include "resource.h"


#endif // !defined(AFX_LOADPIC_H__5EB6AF99_E13D_11D2_90C6_00C04F9403C2__INCLUDED_)



It has a menu and some icons. These are stored in a resource file. I can't paste that here, so you have to hack that out of the sourcecode.

Link with the normal .lib stuff.



Edited by - Otis on November 17, 2000 4:30:42 AM
--
Get productive, Get DemoGL: http://www.demogl.com
loki555
loki555
i''ve been looking for a way to implement gifs for a long time. using the oleloadimage method looks like an efficient way to do this. i''m trying to use gifs as textures in opengl.
now, my problem is: how do i get the data out of a LPPICTURE object? i orientate myself on the opengl tutorials by nehe. he uses a structure called ''AUX_RGBImageRec''. its data is contained in ''AUX_RGBImageRec->data''. how should i do this with this LPPICTURE-stuff?

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.