• Welcome to Vampyre Imaging Library Forum. Please login or sign up.
 

DDS loading and use in DelphiX

Started by dbots, 27 March 2010, 10:24:07

Previous topic - Next topic

dbots

Hi all,
I am using DelphiX in an application I wrote to display bitmaps and jpeg images.
Now, a client gave to me DDS files and asked to use these.
I tried to use Vampyre imaging library to load DDS with code :

InitImage(Img);
LoadImageFromFile('data51.dds', Img);


where Img is TImageData, but then cannot find out how to transfer this on TDirectDrawSurface of DelphiX, so that I finally display it on the application's DirectX Surface.

Any recommendations or help would be greatly appreciated.
Thank you in advance.

Galfar

One way is to load DDS file into TImagingGraphic (see ImagingComponents.pas unit). It's regular TGraphic descendant so you can then use TDirectDrawSurface.LoadFromGraphic method to load the surface. But I looked at the code of LoadFromGraphic and it won't preserve alpha channel.
Better way would be to create empty surface, lock it, and copy bits from image to the surface (and unlock).
Somewhat simpler may be to convert TImageData contents to DelphiX's TDIB. You can then create surface with preserved alpha from TDIB easily.




dbots

Quote from: Galfar on 31 March 2010, 16:12:23
One way is to load DDS file into TImagingGraphic (see ImagingComponents.pas unit). It's regular TGraphic descendant so you can then use TDirectDrawSurface.LoadFromGraphic method to load the surface. But I looked at the code of LoadFromGraphic and it won't preserve alpha channel.
Better way would be to create empty surface, lock it, and copy bits from image to the surface (and unlock).
Somewhat simpler may be to convert TImageData contents to DelphiX's TDIB. You can then create surface with preserved alpha from TDIB easily.


Thank you very much for replying.
It's necessary to keep the alpha channel and opacity so the first solution won't fit.
I will try other solutions and inform of any success.
About the third solution, how can I convert TImageData to DelphiX's TDIB ?
I would be grateful if you could post some sample code about 2nd and 3rd solution.
For example, how to convert TImageData to DelphiX's TDIB ? Does TDIB keep alpha channel ?
There is a tool called PNG2DIB that was developed by Jaro Benes, the person who updates unDelphiX, and says that keeps alpha channel. What I did was load DDS from Paint.NET, save it as PNG and kept all alpha channel and opacity but then I had problem to display PNG over DX surfaces using DelphiX - made things very slow because PNG draws on surface.canvas while all others draw on surface.
So I used PNG2DIB to transform to DIB and use directly from DelphiX but after the conversion I lost all alpha channel and opacity.

dbots

So I tried the second solution but won't work.

I load the DDS file like this :

var img : TImagingGraphic;
     dxsurf : TDirectDrawSurface;  //that's the DX surface I will use later

img := TImagingGraphic.Create;
img.LoadFromFile('mydds.dds');


but then trying to test if all OK until now, I do  :

img.SaveToFile('test.dds');

and the produced test.dds file has a bitmap header, it's not a dds file.

Anyway, I continue with :

dxsurf := TDirectDrawSurface.Create(form1.DXDraw1.DDraw);
dxsurf.SetSize(img.Width, img.Height);
dxsurf.Fill(0);


and then either of the following two :

dxsurf.Lock;
Move(img, dxsurf, SizeOf(img);
dxsurf.UnLock;


OR


mmm := TMemoryStream.Create;
img.SaveToStream(mmm);
dxsurf.Lock;
move(mmm, dxsurf, sizeof(mmm));
dxsurf.UnLock;


When "unlocking" the program hangs.
Also, if I use sizeof(img), it's always = 4, is that strange ?

and finally I start the DXTimer :


form1.dxtimer1.enabled := TRUE;


As usual, I try to draw the surface on the main DXDraw Surface, in the OnTimer event of DXTimer, using :

form1.DXDraw1.Surface.Fill(clSilver);
form1.DXDraw1.Surface.Draw(0,0,dxsurf);


I read somewhere that when I use Move, I must copy after the 5th byte of the DDS file that is in memory.
Does it make any sense to try that ?

Thank you.

Galfar

TImagingGraphic loads all file types supported by Imaging, but saves only bitmaps. Saving is not needed though - try dxsurf.LoadFromGraphic(img)
Move(img, dxsurf, SizeOf(img);
and the other one is totally wrong, you can't use it like this.
I'll post some code for you to try later today.

dbots


dbots

Hi, just to inform, I tried :

  img := TImagingGraphic.Create;
  img.LoadFromFile('mydds.dds');
  dxsurf := TDirectDrawSurface.Create(form1.DXDraw1.DDraw);
  dxsurf.SetSize(img.Width, img.Height);
  dxsurf.Fill(0);
  dxsurf.LoadFromGraphic(img);

and I get the DDS image displayed but alpha channel is completely lost and I see some transparent parts on it- it's like having converted it to BMP and displaying a surface loaded from BMP.

If I add :

Move(img, dxsurf, SizeOf(img);

after

dxsurf.LoadFromGraphic(img);

then program hangs on that line with "Move".

dbots

Hi Galfar,

did you have any time to make that sample code ?

Thank you.

Galfar

2 April 2010, 03:55:19 #8 Last Edit: 2 April 2010, 04:00:58 by Galfar
This should convert TImageData to TDIB, test it please.

var
  DIB: TDIB;
  Img: TImageData;

... load DDS to Img ...

DIB := TDIB.Create;
DIB.SetSize(Img.Width, Img.Height);
// make sure both are 32bit
DIB.BitCount := 32;
ConvertImage(Img, ifA8R8G8B8);
// copy bits
Move(Img.Bits, DIB.PBits, Img.Size);

... now make surface out of DIB32 ...


How do you display the surface afterwards?


EDIT: There's some info about drawing images with alpha channel in DelphiX: http://delphigamedev.com/forums/viewtopic.php?f=2&t=1185


dbots

Thank you for replying.

When I use

Move(img.Bits, DIB.PBits, img.Size);

I get error : Constant object cannot be passed as var paramater.
The syntax of Move (I use Delphi 7) is :
procedure  Move( const Source; var Dest; count : Integer );

Galfar

Looks like TDIB is bottom-top image, so try this instead of that single Move:


  LineBytes := DIB.WidthBytes;
  for I := 0 to Img.Height - 1 do
    Move(PByteArray(Img.Bits)[I * LineBytes], DIB.Scanline[I]^, LineBytes);

dbots

Hi, still no success. Currently with the code :


var
  Form1: TForm1;
  DIB : TDIB;
  img: TImageData;
  dxsurf : TDirectDrawSurface;

implementation

{$R *.dfm}

procedure TForm1.DXTimer1Timer(Sender: TObject; LagCount: Integer);
begin
  form1.DXDraw1.Surface.Fill(clSilver);
  form1.DXDraw1.Surface.Draw(1,1,dxsurf);
  form1.DXDraw1.Flip;
end;

procedure TForm1.DXDraw1Initialize(Sender: TObject);
var linebytes,i : integer;
begin
  InitImage(img);
  LoadImageFromFile('mydds.dds', img);

  DIB := TDIB.Create;
  DIB.SetSize(img.Width, img.Height, 32);

  // make sure both are 32bit
  //DIB.BitCount := 32;

  ConvertImage(img, ifA8R8G8B8);

  // copy bits
  LineBytes := DIB.WidthBytes;
  for I := 0 to Img.Height - 1 do
    begin
    Move(PByteArray(Img.Bits)[I * LineBytes], DIB.Scanline[I]^, LineBytes);
    end;

  dxsurf := TDirectDrawSurface.Create(form1.DXDraw1.DDraw);
  dxsurf.LoadFromDIB(dib);

  form1.DXTimer1.Enabled := TRUE;
end;



I see the picture but with no alpha channel. It's like I have saved it as bitmap.

I used dib.savetofile to see if dib is OK but the problem starts from there. When I open this saved dib, it's like what I see - image is fine but with no alpha channel - like bitmap.

Note that DIB unit that I use is from unDelphiX - don't know if that makes any difference.

dbots

Hi Galfar,
do you have any news about the problem with DDS ?
Please note that if it's possible to make it work even with PNG images for me it's fine, but keeping the alpha channel is the most important.
I tried and used pngimage in delphi but to make it work with DelphiX I have to use the dxdraw.surface.canvas.Draw and not the dxdraw.surface.Draw so this makes things much slower.
If you have any solution for PNG, please post.

dbots

Hi Galfar,

did you have any news please ?
(even on using PNG if DDS is a problem)

Thank you.

Galfar

Check out TDXImageList class mentioned in this forum thread http://delphigamedev.com/forums/viewtopic.php?f=2&t=1185.

I think you can't get any alpha blending simply by using Surface.Draw methods (http://www.gamedev.net/community/forums/topic.asp?topic_id=303701 - it would have to be hardware supported to work).

Quick Reply

With Quick-Reply you can write a post when viewing a topic without loading a new page. You can still use bulletin board code and smileys as you would in a normal post.

Name:
Email:

Shortcuts: ALT+S save/post or ALT+P preview

SMF spam blocked by CleanTalk