Draw an Image on my Form

  • Thread starter Thread starter DraguVaso
  • Start date Start date
D

DraguVaso

Hi,

I have an inherited DataGrid, that does lots of extra stuff. For exemple
drawing a backgroundimage in every cell. The problem is that it's taking too
much time (using gdi+), so I want to do it using DirectX. I downloaded
already the DSK etc, but I can't find how I need to draw an image on a given
position. I don't need stuff to write advanced 3D-games, just painting that
image. Can anybody help me with this? I'm already looking for this the whole
afternoon :-/

I learned already that I shouldn't use DirectDraw (not supported anymore)
but Direct3D? But that's really all I know yet.

Basicly I jsut need to be able to draw an imahe (jpg, bitmap) on a Form in
VB.NET: as simple and as fast as possible.. :-)

Thanks a lot in advance,

Pieter
 
Have you timed to find out what the problem is ? DirectX would more likely
help if you repeateadly draw the whole (updated) thing. Here you just have
to draw this one time before there is some other kind of interaction.

Before switching to a whole new method I would investigate (in particular I
would time) the current code to find out where is spent the time budget...

(and next time thanks for trying to narrow down the groups to which you
posts).
 
Well that's exactly what made me decide which to use DirectX: for every cell
it has to paint an image, and this has to happen on every paint of my
datagrid. So everytilme somebody scrolls, clicks in it, etc. I timed it, and
it takes the most time of my whole application (after using my application
for some seconds it has painted the same hing already more tahn 4000
times...) ! I'm trying to make it faster tha past days, and imrpoved it
already a lot, but I saw the only improvement i can make now is using
DirectX...
 
If you switch to DX, you will need to re-implement your datagrid in DX and
paint all the data, etc. DX and GDI are very, very different.
 
You wont be able to do this with the standard datagrid, I think you will
need to find a third party grid that supports drawing an image in each cell
and then keeps that on its backbuffer and doesnt render the image with each
paint, or find an open source grid and modify for you needs.

James
 
I meant not as a whole but broken into steps. How much time does it take to
render how many cells ? What if you try to render a bitmap the same number
of times ? Especially keep ind mind that there are some subtles things that
could slow down the process such as stretching or doing some operations each
time you draw a cell rather than once etc...

You could also see if alternate approaches may help such as drawing the
datagrid as a bitmap with a transparent color on a backgrround bitmap.

DirectX is a low level API to discuss with graphics hardware and doesn't
provide any GDI integration. IMO would be much more complex and I still
suspect you have room left for improvments...
 
What method are you using ? Using a brush seems quite quick...
(narrowed down to
microsoft.public.dotnet.framework,microsoft.public.dotnet.framework.drawing,
microsoft.public.dotnet.general)
 
Yes I am able to do it with the standard grid: I'm actually doing it
already. But I just want to be able to do it with DirectX....

So my question is still: how do I paint an image using directX? does nobody
knows this? :-S
 
I prerender my images: that speeded up things a lot.
I put al my images into the Format32bppPArgb-Pixelformat
I use double buffering
I also use
g.InterpolationMode = Drawing2D.InterpolationMode.NearestNeighbor
g.CompositingQuality = Drawing2D.CompositingQuality.HighSpeed
g.SmoothingMode = Drawing2D.SmoothingMode.HighSpeed
I don't paint a BackGround to gain time.

I used a code profiler to determine the bottlenecks and speed up several
things. the only thing that still takes much time is the method which is
actually paintng every time the image: "g.DrawImage(fe.BackgroundImage,
rectB)". I know i could get faster using DrawimageUnscaled, but because ot
he cell's width etc changes I can't use it here.

So I really think there isn't any more room left to make other improvements.
So that's why i really would like to know how I have to paint an image with
DirectX. Is this really such a hard question? Just painting an image with
DirectX?
 
I don't get it really: How can I use a Brush it I want to paint an image? I
thought a Brush is jsut one color, not an image? Or am I wrong?
 
What I meant is that you can use directx onto a standard control and that
you need to fundamentally change the way you are doing things.

Good luck though!

J

#
 
See the TexturedBrush class. A brush is used to "fill in" something. It can
be a "solid" color but also an image. See it as a kind of wallpaper (sorry
for my poor English).
So you want to render in each cell a different bitmap ? Each bitmap is
stretched to fit in the cell ?

I'm not sure what is the graphics aspect you want but you could also see if
a new strategy could help such as grabbing the datagrid as a bitmap and
combining it as a whole with perhaps a transparent color.

Using DirectX is IMO a bit risky for such an application as it will
introduce a new dependency (for example if the target platform doesn't have
DX9 installed it won't work) plus the result will depend on the hardware
support and finally you'll have likely some problems as you'll likely have
to combine GDI/DirectX.

As a whole it doesn't seem to me that such a requirement should trigger the
use of DirectX. If you really want to go this route, you could perhaps try
to render a stretched bitmap "cells" time at an arbitrary location. It
should already give you the maximum improvment you could get over using
GDI+.

Good luck.
 
As a side note if you have several cells with the same width/height you
could perhaps create a stretched version and use it to perform an
unstretched copy ?

--
 
I'm pretty sure the answer is "you can't do it". GDI+ uses Graphics
objects, rectangles, polygons, lines, and Fill routines designed for 2D
drawing. DirectX uses Surface objects, vertexes, polygons (though not the
same as a GDI+ polygon), shaders, and renderers designed for 3D drawing.

GDI+ and DirectX are completely different models, built for completely
different tasks, and I don't believe there is any bridge mechanism between
them. Even if there were, it's likely all to be through Interop, which
could eat up all the speed gains you might get by drawing your image with
DirectX. Or, you'd have to do all the translation by hand in code -
essentially re-creating your DataGrid visual representation completely
within the DirectX environment. That's simply not practical.

This is what the folks have been trying to tell you with their posts: you
either need to go 100% DirectX (which means you're dropping the DataGrid
inheritance and writing your own completely from scratch), or 100% GDI+ -
you can't mix the two. Given that the DataGrid uses GDI+, the logical thing
to do is work to get acceptable performance from GDI+. Of course, you've
already said that you're not getting acceptable performance from GDI+, so
you're back to creating your own grid from scratch (using either drawing
library), purchasing one, or trying to get what you've got working.

If your problem is that your cells are not the same size as your background
image, and that they can be resized, you can approach it one of two ways:
allow your background image to be tiled (which can be done quite quickly
with a TextureBrush, and should perform well); or maintain a cache of all
distinct cell sizes, along with appropriately-sized background images, and
draw them into the cell (which may not help much, if the user does a lot of
resizing.) I am assuming that you're only drawing the background image on
visible DataGrid cells, but if not, that's another optimization that will
likely pay off quite well.

You could also consider going directly to the GDI BitBlt API call - I've
heard that the speed gains in doing that outweigh the cost of the Interop
call, but I haven't tested that.

- Scott
 
I'm trying to use the TextureBrush, but it doesn't give the effect Iwant it
to have: it doesn't put in every cell 1 image, but puts the image x times
next to each other, independent of the cell-sizes... What I need is: one
image for each cell, and the image should be adapted to the cell-size... I
tried with the Wrapmode.Clamp, but that just draws the image only one time:
in the left upper corner of my DataGrid... :-/
 
Your description below is not quite consistent:
I prerender my images: that speeded up things a lot.
I know i could get faster using DrawimageUnscaled, but because
the cell's width etc changes I can't use it here.

You are missing a big optimization if your "prerendering" code does not also
prerender to the ultimate size you're going to display. Stretching
operations are very expensive--far more so that bpp changes--you must arrange
your code to minimize the number of calls to DrawImage() over the course of
scrolling, otherwise you haven't optimized fully. (Technically, calling
DrawImage() with the width/height of the bitmap will be the same performance
as DrawImageUnscaled(), so the whole idea is to avoid stretching (or
shrinking) the image during critical performance times.)

My other concern is with your statement:
1. Format32bppPArgb pixel format is not the correct choice for optimum
performance;
As this will only increase performance if the user is running at 32bpp (and
not, say, 16bpp). Also, leaving Alpha information in the format seems
suspicious to me--it seems that would means DrawImage() has more work to do.
In any case, I believe the correct way to optimize this is to use:
bmp = new Bitmap(width, height, graphics)
Where graphics was created as a "screen compatible" graphics (e.g. the one
you get during a paint event). This will ensure the pixel format matches
what eventually will go on the screen. Note that this can get complicated
for multi-monitor support (as each monitor can run at a different pixel
depth), so sticking with PixelFormat.Format32bppRgb might be warranted to
avoid these issues.

A final note: Never use the ImageAttribute parameter to DrawImage() (unless,
of course, you absolutely must), as this will massively slow things down.

I have done this quite successfully for a grid of picture thumbnails, and it
scrolls lightning fast. In my case, images that were not yet pre-rendered
got a place-holder image until a worker thread generated a thumbnail. This
entirely removes the slow stretch operation from the painting code, which is
always a good thing to do.

--Chris Fraley
 
Hi,

Thanks a lot for the great explication and nice hints!
For the moment I'm using an event for each Cell to define the parameters of
it (background image, forgroundimage etc). But I guess that I will gain the
most in speed when using 1 default image for each column, that I resize on
every column-resize?

Just one question: How did you do the stuff with the place-holder image and
the worker thread-stuff?? It seems quit interesting to me. Is there a
possiblity to knwo which image is not yet prerendered? And how does the
prerendering principe acutally works?

Thanks,

Pieter
 
What is the layout ? "One image for each cell" would means you have really a
distinct image in each cell ? Or do you meant this is the same image or
several images based on some kind of criteria.

In case your design is to use the same picture in several cells, you could
see if you could create a scaled version of the image and use it for all
cells that have the same width/height (which is likely if you paint the same
images in all columns).

Before doing something as radical as an API change, you could for example
try to write a test application that really draws those bitmaps in a fully
optimized way (ie. scaled, no format change when blitting etc...). It should
give you an idea of how fast you can go. You'll then sacrifice a bit of time
to create those optimal conditions...

Good luck.
 
I meant fully optimized even if not applicable in the real app. The goal is
to have an idea about the highest level of performance and to see if the
real app is close.

--
 
Hello:

I have taken three images of type gif. i am not able to get the transparency
as well as rotation. and also i need the grouping of the images. I need some
sample code to solve this problem as i am new to this field.

i am using the following code for transparency.

Color col = bm.GetPixel( 1, 1 );
picRT.Region = BitmapToRegion.Convert( bm, col,
TransparencyMode.ColorKeyTransparent);

But if i use this code i am not getting rotation. i will be thankful if u
help in regards
Dhanunjay
 
Back
Top