Author Topic: Using Direct3D to Load Images  (Read 27841 times)

0 Members and 1 Guest are viewing this topic.

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Using Direct3D to Load Images
« on: December 23, 2007 »
I knocked this code up today because I wanted to be able to load PNG images.  Since neither LoadImage nor OleLoadPicture can handle PNG, I had a go with Direct3D.  Here's the code
Code: [Select]
#include <windows.h>
#include "d3dx9tex.h"
#include <stdlib.h>
...
HRESULT err;
unsigned int *pix;
IDirect3D9 *d3d9;
IDirect3DDevice9 *d3ddev;
IDirect3DTexture9 *d3dtex;
D3DPRESENT_PARAMETERS d3dpp = {0};
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
d3dpp.SwapEffect = D3DSWAPEFFECT_FLIP;
d3dpp.Windowed = TRUE;
d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
err = d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &d3ddev);
assert(err == S_OK);
D3DXCreateTextureFromFileInMemory(d3ddev, img, size, &d3dtex);
D3DLOCKED_RECT lock;
D3DSURFACE_DESC d3ddesc;
d3dtex->GetLevelDesc(0, &d3ddesc);
pix = new unsigned int[d3ddesc.Width * d3ddesc.Height];
d3dtex->LockRect(0, &lock, NULL, D3DLOCK_READONLY);
unsigned int *dst, *src;
src = (unsigned int *)lock.pBits;
dst = pix;
for (unsigned int y = 0; y < d3ddesc.Height; y++)
{
memcpy(dst, src, d3ddesc.Width * sizeof(unsigned int));
dst += d3ddesc.Width;
src += lock.Pitch/sizeof(unsigned int);
}
d3dtex->UnlockRect(0);
d3dtex->Release();
d3ddev->Release();
d3d9->Release();
The inputs are
img - pointer to the PNG file in memory
size - size of the PNG file in memory
hWnd - handle to your window
The output is
pix - pointer to the RGB image in memory

You will need to add d3d9.lib and d3dx9.lib to the linker options.

As well as PNG, this routine will load bmp, .dds, .dib, .hdr, .jpg, .pfm, .ppm, and .tga

Jim
Challenge Trophies Won:

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: Using Direct3D to Load Images
« Reply #1 on: December 23, 2007 »
very very cool jim! k+

and is this compatible to use this in an ogl app or gdi app or is it d3d only.

-edit i can see it should be compatible with ogl, cool ill need to try it out.
« Last Edit: December 23, 2007 by ninogenio »
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Using Direct3D to Load Images
« Reply #2 on: December 23, 2007 »
Quote
and is this compatible to use this in an ogl app
I think so, and that is how I'm using it.  There are dire warnings in the paperwork about mixing OpenGL and Direct3D calls, but I think that's to do with trying to draw using both APIs at the same time.

Jim
Challenge Trophies Won:

Offline taj

  • Bytes hurt
  • DBF Aficionado
  • ******
  • Posts: 4810
  • Karma: 189
  • Scene there, done that.
    • View Profile
Re: Using Direct3D to Load Images
« Reply #3 on: December 25, 2007 »
Quote
and is this compatible to use this in an ogl app
I think so, and that is how I'm using it.  There are dire warnings in the paperwork about mixing OpenGL and Direct3D calls, but I think that's to do with trying to draw using both APIs at the same time.

Jim
Thats true. I've been mixing DX and OGL for quite a while. Maths, image loading, curve paths, host raytracing, model subdivision can all be done much smaller with DX. I then use OGL for rendering which is slightly larger (slightly) but I feel more comfortable with it.

Taj
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Using Direct3D to Load Images
« Reply #4 on: December 25, 2007 »
The way I figure it, the drivers MUST be able to handle multiple D3D and OpenGL contexts at the same time to work with a multithreaded OS, so there are some very basic minimum things it has to allow.  As long as it's not using thread/process id or window id as a unique identifier then it should be OK, though of course that's not rigourously defined anywhere.

Jim
Challenge Trophies Won:

Offline energy

  • Amiga 1200
  • ****
  • Posts: 280
  • Karma: 25
    • View Profile
Re: Using Direct3D to Load Images
« Reply #5 on: February 21, 2008 »
Dear Jim!

 :goodpost:

But theres something i dont understand! (trying to convert to Purebasic!)

Quote
pix = new unsigned int[d3ddesc.Width * d3ddesc.Height];

is  this right or

*pic= allocatememory(d3ddesc.Width * d3ddesc.Height)

Thank yu!
coding: jwasm,masm
hobby: www.scd2003.de

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: Using Direct3D to Load Images
« Reply #6 on: February 21, 2008 »
as long as you have declared your pic pointer as an unsigned int and allocatememory is as close as you can get to the new command in purebasic then that will be fine energy.

new is just a really good way in c++ of allocating memory.
« Last Edit: February 21, 2008 by ninogenio »
Challenge Trophies Won:

Offline energy

  • Amiga 1200
  • ****
  • Posts: 280
  • Karma: 25
    • View Profile
Re: Using Direct3D to Load Images
« Reply #7 on: February 21, 2008 »
ok that means that in c yu mustnt use the allocmem.... there yu can use NEW

then its ok when i use allocatememory in Purebasic!
coding: jwasm,masm
hobby: www.scd2003.de

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: Using Direct3D to Load Images
« Reply #8 on: February 21, 2008 »
yeah in c++ new is the best option. in purebasic if new is not allowed allocatememory should be fine.
Challenge Trophies Won:

Offline energy

  • Amiga 1200
  • ****
  • Posts: 280
  • Karma: 25
    • View Profile
Re: Using Direct3D to Load Images
« Reply #9 on: February 21, 2008 »
thank yu nino!
coding: jwasm,masm
hobby: www.scd2003.de

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Using Direct3D to Load Images
« Reply #10 on: February 21, 2008 »
*pic= allocatememory(d3ddesc.Width * d3ddesc.Height)

That would be too small, as each pixel is an integer (4 bytes) so you'd need to allocate 4x as much.
In C something like
Code: [Select]
unsigned int *pix = malloc(d3ddesc.Width * d3ddesc.Height * sizeof(unsigned int));or better
Code: [Select]
unsigned int *pix = malloc(d3ddesc.Width * d3ddesc.Height * sizeof *pix);
in C++
Code: [Select]
unsigned int *pix = new unsigned int [d3ddesc.Width * d3ddesc.Height];
Jim
Challenge Trophies Won:

Offline energy

  • Amiga 1200
  • ****
  • Posts: 280
  • Karma: 25
    • View Profile
Re: Using Direct3D to Load Images
« Reply #11 on: February 21, 2008 »
Hi Jim!

Small Error i cant find!
Hope yu can have an eye on it (Its Purebasic)
Result is in the exe!   (Displayed in OPENGL!)
Code: [Select]
Procedure.l DX_LoadTexture (*tex.Texture,*mem,PicSize.l)
  ;Texturloader orginally by Jim Shaw
 
  Protected *pix,*src, *dst, d3d9.IDirect3D9 , d3ddev.IDIRECT3DDEVICE9 , d3dtex.IDIRECT3DTEXTURE9, d3dpp.D3DPRESENT_PARAMETERS
  Protected lock.D3DLOCKED_RECT, d3ddesc.D3DSURFACE_DESC,i.l
  d3dpp\BackBufferFormat=#D3DFMT_UNKNOWN
  d3dpp\SwapEffect=#D3DSWAPEFFECT_FLIP
  d3dpp\Windowed=#True
  d3d9=Direct3DCreate9(#D3D_SDK_VERSION)
  d3d9\createdevice(#D3DADAPTER_DEFAULT,#D3DDEVTYPE_HAL,hwnd,#D3DCREATE_HARDWARE_VERTEXPROCESSING,@d3dpp,@d3ddev )
  D3DXCreateTextureFromFileInMemory(d3ddev,*mem,PicSize,@d3dtex)
  d3dtex\getleveldesc(0,@d3ddesc)
  *tex\Width= d3ddesc\Width
  *tex\Height= d3ddesc\Height
  *pix=AllocateMemory((d3ddesc\Width*d3ddesc\Height)*4)
  d3dtex\lockrect(0,@lock,#Null,#D3DLOCK_READONLY)
  *src=lock\pBits
  *dst=*pix
   For i=0 To (d3ddesc\Height-1)
    CopyMemory(*src,*dst,d3ddesc\Width*4 )
    *dst=*dst+d3ddesc\Width
    *src=*src+(lock\Pitch/4)
   Next
  d3dtex\unlockrect(0)
  d3dtex\release()
  d3ddev\release()
  d3d9\release()
  *tex\mem= *pix
EndProcedure

Thanx...  :-*
coding: jwasm,masm
hobby: www.scd2003.de

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Using Direct3D to Load Images
« Reply #12 on: February 21, 2008 »
It just crashes here and I can't see anything wrong with that code right now...doesn't mean it's right though :)
Jim
Challenge Trophies Won:

Offline energy

  • Amiga 1200
  • ****
  • Posts: 280
  • Karma: 25
    • View Profile
Re: Using Direct3D to Load Images
« Reply #13 on: February 21, 2008 »
Crashing???
ATI CArd?

Here is a screenshot!
coding: jwasm,masm
hobby: www.scd2003.de

Offline energy

  • Amiga 1200
  • ****
  • Posts: 280
  • Karma: 25
    • View Profile
Re: Using Direct3D to Load Images
« Reply #14 on: February 22, 2008 »
hi Jim!

Fixed all for Purebasic... runs very well with OPENGL!!!    THANX A LOT FOR THIS LOADER!!!!!     :cheers:

One resent fix i made for me:
Quote
For i=0 To (d3ddesc\Height-1)
    CopyMemory(*src,*dst,d3ddesc\Width*4 )
    *dst=*dst+d3ddesc\Width
    *src=*src+(lock\Pitch/4)

to
Quote
*src=lock\pBits
*dst=*pix+((d3ddesc\Width*(d3ddesc\Height-1))*4)
 For i=0 To (d3ddesc\Height-1)
   CopyMemory(*src,*dst,d3ddesc\Width*4 )
    *dst=*dst-(d3ddesc\Width*4)
    *src=*src+(lock\Pitch)
  Next

cause yu copy width*4 but calculating pointer for dest only for width

and for use in OPENGL i HAVE to turn the pic ... see *dst pointer!


Thanx
eNeRGy
coding: jwasm,masm
hobby: www.scd2003.de

Offline energy

  • Amiga 1200
  • ****
  • Posts: 280
  • Karma: 25
    • View Profile
Re: Using Direct3D to Load Images
« Reply #15 on: March 04, 2008 »
Hi Jim, Just one quick question:
Need to Have the Alpha-Value for the loaded Image!
Image is loaded in BGRA with this Routine...

But what value does this routine load for the Alpha-Value??

Thanx in Advance!
eNeRGy
coding: jwasm,masm
hobby: www.scd2003.de

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Using Direct3D to Load Images
« Reply #16 on: March 04, 2008 »
If there's an alpha channel in the image it'll use that.  The only formats I've seen work reliably for that are PNG, TGA and the DirectX specific ones.  BMP and JPG are no good.  If there's no alpha channel it'll be set to 0xff.

Jim
Challenge Trophies Won:

Offline energy

  • Amiga 1200
  • ****
  • Posts: 280
  • Karma: 25
    • View Profile
Re: Using Direct3D to Load Images
« Reply #17 on: March 05, 2008 »
Thanx Jim!
Is it possible to load directly in RGBA insted of BRGA?
Cant find anything in DirectX Help.

It was a Jpg i loaded with!
for the others with non Alpha valus ill change the routine and write manuell with a given Alpha-Value!

Cheers and best wishes....
eNeRGy
« Last Edit: March 05, 2008 by energy »
coding: jwasm,masm
hobby: www.scd2003.de

Offline energy

  • Amiga 1200
  • ****
  • Posts: 280
  • Karma: 25
    • View Profile
Re: Using Direct3D to Load Images
« Reply #18 on: March 05, 2008 »
all fixed now....
added transparency!!

coding: jwasm,masm
hobby: www.scd2003.de

Offline energy

  • Amiga 1200
  • ****
  • Posts: 280
  • Karma: 25
    • View Profile
Re: Using Direct3D to Load Images
« Reply #19 on: March 05, 2008 »
Added as Purbasic Userlib for download!
See:
http://dbfinteractive.com/index.php?topic=2946.msg40214#msg40214

Cheers eNeRGY
coding: jwasm,masm
hobby: www.scd2003.de