Very simple. It works fine but fails
on certain images. The one picture
I have that fails is 2500 x 1700 pixels
(approx.), from a digital camera. And
other pics saved from the same camera
seem to fail, even though they open
fine in IrfanView or PaintShopPro.
Is the picture just too big? Should I do it
a different way?
(I've never quite grokked what autoredraw
actually does.)
--
Randy Birch
MS MVP Visual Basic
http://vbnet.mvps.org/
Please reply to the newsgroups so all can participate.
"mayayana" <mayaXX...@mindXXspring.com> wrote in message
news:J6LIg.2643$bM....@newsread4.news.pas.earthlink.net...
VB's back-buffer implementation uses a Device Dependant Bitmap (DDB) to store the image data, which is quite limited in
how large it can be made. On older OS' this used to be ~16mb uncompressed data size, on later OS this has been expended
but is still quite restrictive.
The image you describe would take just over 16mb uncompressed space at 32-bit so this looks like it's hitting that
boundary.
A workaround for this is to use a Device Dependant Bitmap (DIB) and manage the GDI resources yourself, have a look at
the DIB article on my site for an example of how to work with them.
Hope this helps,
Mike
- Microsoft Visual Basic MVP -
E-Mail: ED...@mvps.org
WWW: Http://EDais.mvps.org/
Thanks.
The memory problem makes sense. I assume that
as Randy describes autoredraw I was putting double
data into memory with that. But it also failed with
autoredraw set to false. Even then, I guess, I was
actually trying to store two 14MB+ bitmaps by painting
one to the other.
I actually downloaded your DIB article
and part of the DC article tonight. I haven't worked
with this stuff for a long time, and never did very
much, but I've found a sample image editor project
in my pile of saved code that doesn't choke on the
big image. So I guess I probably have the basics
of what I need somewhere in there.
Search your code for CreateDIBSection(), that's the key to creating your DIB back-buffer.
Here's an old post with some pretty bare-bones DIB buffer creation:
http://groups.google.co.uk/group/microsoft.public.vb.winapi.graphics/msg/4f941fe33eef7264
Ignore the middle bit (messing around with VarPtrArray(), RtlMoveMemory() and such,) you only need the GDI calls at the
top and bottom of the example code.
--
>
> Search your code for CreateDIBSection(), that's the key to creating your
DIB back-buffer.
> Here's an old post with some pretty bare-bones DIB buffer creation:
>
http://groups.google.co.uk/group/microsoft.public.vb.winapi.graphics/msg/4f9
41fe33eef7264
> Ignore the middle bit (messing around with VarPtrArray(), RtlMoveMemory()
and such,) you only need the GDI calls at the
> top and bottom of the example code.
> Hope this helps,
>
Thanks. I've also been reading your DIB article.
It's nice -clear and informative, so I already know where
you're going with the array ops.
Ok, good good. In your case though, unless you're doing any image manipulation you should need to do anything with the
data itself.
Now I also want to do resizing. From my research
it appears that setting HALFTONE mode for
StretchBlt is the highest quality, but that it doesn't
work properly on Win9x even when the extra Win9x
steps are carried out? (According to the docs, only
SetBrushOrgEx is required on NT but 9x requires
further calls. I've found sample code for that, but I've
also found old posts that imply it doesn't work.)
I'm trying to figure out the very best way to do a resize
on both 9x and NT. Perhaps there's some kind of
HALFTONE algorithm if it won't work on 9x via API?
---------
An interesting sign of the times:
I entered this in Google:
"SetBrushOrgEx bitmap vb nt"
It returned this:
"Did you mean: SetBrushOrgEx bitmap vb net"
HALFTONE interpolation is not supported under Win9x or Me, If you want high-quality image resampling which is constant
over various OS' then I'd suggest you look into a 3'rd party graphics library, FreeImage for example is a pretty popular
one (http://freeimage.sourceforge.net/)
Hope this helps,
> I'm trying to figure out the very best way to do
> a resize on both 9x and NT. Perhaps there's
> some kind of HALFTONE algorithm if it won't
> work on 9x via API?
As Mike Sutton has already said, halftone is not available under Win9x and
you might be better off using a third party graphics library, or perhaps
GDI+, which I believe is possible under Win 9x although I'm not sre about
that). Before you do that though (or perhaps in addition to doing it) you
might like to check out the LoadImage API. It won't load jpegs of course,
but there are ways of getting around that problem by first converting the
jpeg to a bitmap and then loading the bitmap with LoadImage. No point in
going to all that trouble without checking it out in a simple way first
though to see if the quality is sufficient for your needs. The LoadImage
API, whch will work under Win9x as well as WinXP, can load and stretch a
bitmap into a device and it appears to use its own stretch algorithm which
to my eyes appears to be at least as good as halftone. To test it in the
simplest possible way just make sure your own system is set to 32 bit full
colour, load a jpg into a full size picture box and save it out as a bitmap.
Then pull the bitmap in using the LoadImage API, using suitable parameters
that cause it to stretch the picture to whatever size you require. Check
that against loading the same jpeg in the standard way and using StretchBlt
mode 3 to stretch it (by the way, you are using stretch mode 3 in Win9x are
you?). If you think the LoadImage stretch quality is no better than Mode 3
then you haven't wasted a lot of time, and if you think it is better then
you might think it worth going to the extra bit of trouble required to
overcome the limitations on machines running at 16 bit colour depth.
Mike
> An interesting sign of the times:
> I entered this in Google:
>
>"SetBrushOrgEx bitmap vb nt"
>
>It returned this:
>
>"Did you mean: SetBrushOrgEx bitmap vb net"
Sad. It really looks like that's where the market is headed, following the
Microsoft monopoly.
_______________________
Michael B. Johnson
> As Mike Sutton has already said, halftone is not available under Win9x and you might be better off using a third party
> graphics library, or perhaps GDI+, which I believe is possible under Win 9x although I'm not sre about that).
The minimum requirement for the .NET runtime is Win98/ME or NT4, it won't run under Win95 AFAIK.
> Before you do that though (or perhaps in addition to doing it) you might like to check out the LoadImage API. It won't
> load jpegs of course, but there are ways of getting around that problem by first converting the jpeg to a bitmap and
> then loading the bitmap with LoadImage. No point in
> going to all that trouble without checking it out in a simple way first
> though to see if the quality is sufficient for your needs.
How is loading the JPEG, saving it to disk then reloading it simpler than just loading the JPEG? ;)
Also, is the problem really in loading the JPEG off disk or displaying it in the picture box? At least when VB returns
the image in a StdPicture object it appears to be a DIB, which should mean it has no problems loading the image, just
displaying it. I've loaded a 6000*6000*24 bitmap in WinME directly into a StdPicture object, but loading the same image
into an AutoRedraw picture box simply hung the app so I couldn't say for sure. Also, WinME may not have the old 16mb
limitation it's been a long time since I worked with any of this stuff.
> The LoadImage API, whch will work under Win9x as well as WinXP, can
> load and stretch a bitmap into a device and it appears to use its own stretch
> algorithm which to my eyes appears to be at least as good as halftone.
LoadImage()'s scaling uses StretchDIBits() internally and sets COLORONCOLOR stretch mode which is natively available
under Win9x anyway.
If you're running on a Win9x/Me machine then setting the stretch mode to HALFTONE actually uses COLORONCOLOR internally,
so although it appears the call has succeeded it actually did something else.
It doesn't imply that at all. That's just Google's algorithm for
matching your search query to something it's familiar with.
---
Stefan Berglund
Adding to Stefan's reply... that search returns nothing, even if you let
Google convert the "nt" to "net".
This'n does though <g> (dropped the quotes and the reference to NT)... and,
they're mostly VB6 related.... and, since there are at least 2 in the list
from vbaccelerator.com, that's where I'd head for sample code.
Results 1 - 50 of about 83 English pages for SetBrushOrgEx VB
http://www.google.com/search?num=100&hl=en&lr=lang_en&as_qdr=all&q=SetBrushOrgEx+VB&lr=lang_en
--
Ken Halter - MS-MVP-VB - Please keep all discussions in the groups..
In Loving Memory - http://www.vbsight.com/Remembrance.htm
>>> An interesting sign of the times:
>>> I entered this in Google:
>>>
>>>"SetBrushOrgEx bitmap vb nt"
>
>Adding to Stefan's reply... that search returns nothing, even if you let
>Google convert the "nt" to "net".
>
>This'n does though <g> (dropped the quotes and the reference to NT)... and,
>they're mostly VB6 related.... and, since there are at least 2 in the list
>from vbaccelerator.com, that's where I'd head for sample code.
>
>Results 1 - 50 of about 83 English pages for SetBrushOrgEx VB
>http://www.google.com/search?num=100&hl=en&lr=lang_en&as_qdr=all&q=SetBrushOrgEx+VB&lr=lang_en
Very interesting.
Thank you for sharing your thoughts, Ken and Stefan.
_______________________
Michael B. Johnson
> How is loading the JPEG, saving it to disk then reloading
> it simpler than just loading the JPEG? ;)
I didn't mean it was a simple way of loading the picture, Mike. What I said
is that for a test system set to full colour it is a simple way of testing
the LoadImage API to see what quality it gives when stretching (load a jpg
into a VB autoredraw picture box and use SavePicture to save the Image as a
bmp file and then load and stretch the bmp file in one go using the
LoadImage API). That is only a test bed method which can be knocked up very
quickly for simply checking the quality of the stretch produced by LoadImage
on bitmaps, on the grounds that it would be pointless spending time writing
more complex code to perform the task on all colour depth systems if the
quality was not up to scratch anyway. My own personal opinion is that the
LoadImage stretch quality is fine, but of course this stuff is subjective
and others might disagree.
> At least when VB returns the image in a StdPicture object
> it appears to be a DIB, which should mean it has no problems
> loading the image, just . . .
Actually I'm not so sure about that Mike. If that is the case then shouldn't
the following code return the value 24 on a system running at 16 bit colour
depth? In fact it doesn't. It returns the value 16.
Dim p1 As StdPicture
Dim myBmp As BITMAP
Dim retval As Long
Set p1 = LoadPicture("c:\tulips.jpg")
retval = GetObject(p1.Handle, Len(myBmp), myBmp)
MsgBox myBmp.bmBitsPixel
> LoadImage()'s scaling uses StretchDIBits() internally
> and sets COLORONCOLOR stretch mode which is
> natively available
I don't think so Mike. Try drawing some text and a few circles on top of a
1024 x 768 full color bitmap and then stretch it to 800 x 600 using both
COLORONCOLOR (Stretch mode 3) and the LoadImage API. You'll find there is a
big difference in quality, with LoadImage performing much better than
COLORONCOLOR.
Mike Williams
Calling SetBrushOrgEx() isn't suddenly going to make halftone interpolation magically work on older OS.. The problem is
that StretchBlt() sometimes modifies the brush origin on the target DC during the call, so if you've previously set the
brush origin it may have been modified after the call. Since from what the OP has described has nothing to do with
using brushes on the same DC it doesn't really matter one way or the other.
FWIW,
I actually downloaded an image manipulation program
from VBAccelerator when I was trying to work out the
code for cropping, but that code also choked on very
large images. It certainly wasn't using any custom
resizing algorithm. It sounds like there just isn't anything
advanced in the Win9x API. Unfortunately the GDI+ is
1.6 MB and FreeImage is 1 MB. That's an awfully lot
of baggage just to get high quality resizing.
Oh, well. I guess I'll have to switch to .Net after all. :)
(Note: I'll be doing all cropping first, so no
resizing will be to different width/height ratio,
and resizing will probably only be to smaller, in
case that matters.)
----------------
Private Function ResampleDib(ByRef cDibTo As cDIBSection) As Boolean
Dim bDibFrom() As Byte
Dim bDibTo() As Byte
Dim tSAFrom As SAFEARRAY2D
Dim tSATo As SAFEARRAY2D
' Get the bits in the from DIB section:
With tSAFrom
.cbElements = 1
.cDims = 2
.Bounds(0).lLbound = 0
.Bounds(0).cElements = m_tBI.bmiHeader.biHeight
.Bounds(1).lLbound = 0
.Bounds(1).cElements = BytesPerScanLine()
.pvData = m_lPtr
End With
CopyMemory ByVal VarPtrArray(bDibFrom()), VarPtr(tSAFrom), 4
' Get the bits in the to DIB section:
With tSATo
.cbElements = 1
.cDims = 2
.Bounds(0).lLbound = 0
.Bounds(0).cElements = cDibTo.Height
.Bounds(1).lLbound = 0
.Bounds(1).cElements = cDibTo.BytesPerScanLine()
.pvData = cDibTo.DIBSectionBitsPtr
End With
CopyMemory ByVal VarPtrArray(bDibTo()), VarPtr(tSATo), 4
Dim xScale As Single
Dim yScale As Single
Dim x As Long, y As Long, xEnd As Long, xOut As Long
Dim fX As Single, fY As Single
Dim ifY As Long, ifX As Long
Dim dX As Single, dy As Single
Dim r As Long, r1 As Single, r2 As Single, r3 As Single, r4 As Single
Dim g As Long, g1 As Single, g2 As Single, g3 As Single, g4 As Single
Dim b As Long, b1 As Single, b2 As Single, b3 As Single, b4 As Single
Dim ir1 As Long, ig1 As Long, ib1 As Long
Dim ir2 As Long, ig2 As Long, ib2 As Long
xScale = (Width - 1) / cDibTo.Width
yScale = (Height - 1) / cDibTo.Height
xEnd = cDibTo.Width - 1
For y = 0 To cDibTo.Height - 1
fY = y * yScale
ifY = Int(fY)
dy = fY - ifY
For x = 0 To xEnd
fX = x * xScale
ifX = Int(fX)
dX = fX - ifX
ifX = ifX * 3
' Interpolate using the four nearest pixels in the source
b1 = bDibFrom(ifX, ifY): g1 = bDibFrom(ifX + 1, ifY): r1 =
bDibFrom(ifX + 2, ifY)
b2 = bDibFrom(ifX + 3, ifY): g2 = bDibFrom(ifX + 4, ifY): r2 =
bDibFrom(ifX + 5, ifY)
b3 = bDibFrom(ifX, ifY + 1): g3 = bDibFrom(ifX + 1, ifY + 1): r3
= bDibFrom(ifX + 2, ifY + 1)
b4 = bDibFrom(ifX + 3, ifY + 1): g4 = bDibFrom(ifX + 4, ifY +
1): r4 = bDibFrom(ifX + 5, ifY + 1)
' Interplate in x direction:
ir1 = r1 * (1 - dy) + r3 * dy: ig1 = g1 * (1 - dy) + g3 * dy:
ib1 = b1 * (1 - dy) + b3 * dy
ir2 = r2 * (1 - dy) + r4 * dy: ig2 = g2 * (1 - dy) + g4 * dy:
ib2 = b2 * (1 - dy) + b4 * dy
' Interpolate in y:
r = ir1 * (1 - dX) + ir2 * dX: g = ig1 * (1 - dX) + ig2 * dX: b
= ib1 * (1 - dX) + ib2 * dX
' Set output:
If (r < 0) Then r = 0
If (r > 255) Then r = 255
If (g < 0) Then g = 0
If (g > 255) Then g = 255
If (b < 0) Then b = 0
If (b > 255) Then
b = 255
End If
xOut = x * 3
bDibTo(xOut, y) = b
bDibTo(xOut + 1, y) = g
bDibTo(xOut + 2, y) = r
Next x
Next y
' Clear the temporary array descriptor
' (This does not appear to be necessary, but
' for safety do it anyway)
CopyMemory ByVal VarPtrArray(bDibFrom), 0&, 4
CopyMemory ByVal VarPtrArray(bDibTo), 0&, 4
End Function
The difficulty to my mind is that I'm not sure I'm capable
of really judging the quality difference if StretchBlt is
reasonably good. There might be shades of quality that
wouldn't show up onscreen but would show up in a print.
I can try StretchBlt, LoadImage, and Steve McMahon's
routine to see how they all compare, but I suspect I'm
probably going to just end up bug-eyed and confused.
Under XP I'm getting a 24-bit DIB regardless of the display depth, WinME is capping it at the display depth however it's
still returning a DIB so the size restrictions of a DDB do not apply which is the point I was making. Whether this
means it's going through a DDB to get there, or the display driver simply decides to down-sample from DIB to DIB I
couldn't say for sure.
> I don't think so Mike. Try drawing some text and a few circles on top of a 1024 x 768 full color bitmap and then
> stretch it to 800 x 600 using both COLORONCOLOR (Stretch mode 3) and the LoadImage API. You'll find there is a big
> difference in quality, with LoadImage performing much better than COLORONCOLOR.
I'm getting pixel-for-pixel exactly the same image using LoadImage as with COLORONCOLOR stretch mode, here's a demo app
to demo that:
'***
Private Declare Function CreateCompatibleDC Lib "GDI32.dll" (ByVal hDC As Long) As Long
Private Declare Function CreateDIBSection Lib "GDI32.dll" (ByVal hDC As Long, ByRef pBitmapInfo As BitmapInfoHeader,
ByVal un As Long, ByRef lplpVoid As Long, ByVal handle As Long, ByVal dw As Long) As Long
Private Declare Function GetDIBits Lib "GDI32.dll" (ByVal aHDC As Long, ByVal hBitmap As Long, ByVal nStartScan As Long,
ByVal nNumScans As Long, ByRef lpBits As Any, ByRef lpBI As BitmapInfoHeader, ByVal wUsage As Long) As Long
Private Declare Function TextOut Lib "GDI32.dll" Alias "TextOutA" (ByVal hDC As Long, ByVal X As Long, ByVal Y As Long,
ByVal lpString As String, ByVal nCount As Long) As Long
Private Declare Function Ellipse Lib "GDI32.dll" (ByVal hDC As Long, ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As
Long, ByVal Y2 As Long) As Long
Private Declare Function CreatePen Lib "GDI32.dll" (ByVal nPenStyle As Long, ByVal nWidth As Long, ByVal crColor As
Long) As Long
Private Declare Function SelectObject Lib "GDI32.dll" (ByVal hDC As Long, ByVal hObject As Long) As Long
Private Declare Function DeleteDC Lib "GDI32.dll" (ByVal hDC As Long) As Long
Private Declare Function DeleteObject Lib "GDI32.dll" (ByVal hObject As Long) As Long
Private Declare Function CreateFont Lib "GDI32.dll" Alias "CreateFontA" (ByVal nHeight As Long, ByVal nWidth As Long,
ByVal nEscapement As Long, ByVal nOrientation As Long, ByVal fnWeight As Long, ByVal fdwItalic As Long, ByVal
fdwUnderline As Long, ByVal fdwStrikeOut As Long, ByVal fdwCharSet As Long, ByVal fdwOutputPrecision As Long, ByVal
fdwClipPrecision As Long, ByVal fdwQuality As Long, ByVal fdwPitchAndFamily As Long, ByVal lpszFace As String) As Long
Private Declare Function LoadImage Lib "User32.dll" Alias "LoadImageA" (ByVal hInst As Long, ByVal lpszName As String,
ByVal uType As Long, ByVal cxDesirded As Long, ByVal cyDesired As Long, ByVal fuLoad As Long) As Long
Private Declare Function SetStretchBltMode Lib "GDI32.dll" (ByVal hDC As Long, ByVal nStretchMode As Long) As Long
Private Declare Function StretchBlt Lib "GDI32.dll" (ByVal hDC As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth
As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal nSrcWidth As Long,
ByVal nSrcHeight As Long, ByVal dwRop As Long) As Long
Private Declare Function BitBlt Lib "GDI32.dll" (ByVal hDestDC As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth
As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As
Long
Private Type BitmapInfoHeader ' 40 bytes
biSize As Long
biWidth As Long
biHeight As Long
biPlanes As Integer
biBitCount As Integer
biCompression As Long
biSizeImage As Long
biXPelsPerMeter As Long
biYPelsPerMeter As Long
biClrUsed As Long
biClrImportant As Long
End Type
Private Sub Form_Load()
Dim BMInfo As BitmapInfoHeader
Dim hDC As Long, hBMP As Long, hOldBMP As Long
Dim DataPtr As Long
Dim hFont As Long, hOldFont As Long
Dim hPen As Long, hOldPen As Long
Dim TempPic As StdPicture
Const BI_RGB As Long = &H0
Const DIB_RGB_COLORS As Long = &H0
Const DemoText As String = "Hello, world!"
Const PS_SOLID As Long = &H0
Const PicPath As String = "C:\temp.bmp"
Const IMAGE_BITMAP As Long = &H0
Const LR_LOADFROMFILE As Long = &H10
Const COLORONCOLOR As Long = &H3
Const HALFTONE As Long = &H4
Const FW_BOLD As Long = 700
With BMInfo
.biSize = Len(BMInfo)
.biWidth = 800
.biHeight = 600
.biPlanes = 1
.biBitCount = 24
.biCompression = BI_RGB
End With
hDC = CreateCompatibleDC(0&)
hBMP = CreateDIBSection(hDC, BMInfo, DIB_RGB_COLORS, DataPtr, 0, 0)
hOldBMP = SelectObject(hDC, hBMP)
hPen = CreatePen(PS_SOLID, 40, vbRed)
hOldPen = SelectObject(hDC, hPen)
Call Ellipse(hDC, 100, 100, 700, 500)
Call SelectObject(hDC, hOldPen)
Call DeleteObject(hPen)
hFont = CreateFont(50, 0, 0, 0, FW_BOLD, 0, 0, 0, 0, 0, 0, 0, 0, "Arial")
hOldFont = SelectObject(hDC, hFont)
Call TextOut(hDC, 50, 50, DemoText, Len(DemoText))
Call SelectObject(hDC, hOldFont)
Call DeleteObject(hFont)
Set TempPic = GDIToPicture(hBMP, False)
Call SavePicture(TempPic, PicPath)
Set TempPic = Nothing
Me.AutoRedraw = True ' Eugh..
Call SetStretchBltMode(Me.hDC, COLORONCOLOR)
Call StretchBlt(Me.hDC, 0, 0, 100, 100, hDC, 0, 0, BMInfo.biWidth, BMInfo.biHeight, vbSrcCopy)
Call StretchBlt(Me.hDC, 0, 100, 100, 100, hDC, 0, 0, BMInfo.biWidth, BMInfo.biHeight, vbSrcCopy)
Call SetStretchBltMode(Me.hDC, HALFTONE)
Call StretchBlt(Me.hDC, 100, 0, 100, 100, hDC, 0, 0, BMInfo.biWidth, BMInfo.biHeight, vbSrcCopy)
Call StretchBlt(Me.hDC, 100, 100, 100, 100, hDC, 0, 0, BMInfo.biWidth, BMInfo.biHeight, vbSrcCopy)
Call SelectObject(hDC, hOldBMP)
Call DeleteObject(hBMP)
hBMP = LoadImage(App.hInstance, PicPath, IMAGE_BITMAP, 100, 100, LR_LOADFROMFILE)
hOldBMP = SelectObject(hDC, hBMP)
Call BitBlt(Me.hDC, 200, 0, 100, 100, hDC, 0, 0, vbSrcCopy)
Call BitBlt(Me.hDC, 0, 100, 100, 100, hDC, 0, 0, vbSrcInvert)
Call BitBlt(Me.hDC, 100, 100, 100, 100, hDC, 0, 0, vbSrcInvert)
Call SelectObject(hDC, hOldBMP)
Call DeleteObject(hBMP)
Call DeleteDC(hDC)
Call Kill(PicPath)
End Sub
'***
This draws 5 images to the form; the top line is the COLORONCOLOR stretch, HALFTONE stretch and LoadImage() stretch.
The second line is the two stretch modes with the LoadImage() version overlaid on invert mode so that any pixels that
are different will show up. As expected the HALFTONE version has a lot of difference around the edges of the text and
circle where the filtering is taking place, however the COLORONCOLOR one is _exactly_ the same.
Here are screenshots from the application, WinME on the left, WinXP on the right:
Http://EDais.mvps.org/Tempfiles/StretchMEXP.png
It's using a lossless compression technique so you can't claim that compression is removing any details. Additionally,
here's the same image with a threshold operation applied which shows black pixels in black and anything else in white:
Http://EDais.mvps.org/Tempfiles/StretchMEXP_Thresh.gif
As you can clearly see the left overlay is exactly the same on both OS'.
I've tested this on 4 machines running under WinXP, 2K and ME with various combinations of graphics cards and drivers
and all have the same result (of course with the exception that HALFTONE doesn't work under ME.)
http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=46515&ln
gWId=1
It has VB code for several types of resampling
and a very nice sample project to display them.
> Under XP I'm getting a 24-bit DIB regardless of the display depth.
Are you using the exact code I posted, which loads a jpg file (not a bmp
file) into a StdPicture object using the VB LoadPicture function? At this
end if I do that I get a 24 bit bitmap in the StdPicture on an XP machine
running at full colour depth but I get a 16 bit bitmap on the same XP
machine running at 16 bit colour depth. If I first run the code with the
machine set to full colour and I then switch to 16 bit colour in Control
Panel without closing the VB test program I do still get a 24 bit bitmap,
but as soon as I close the VB program and reopen it (or restart the machine)
I get the 16 bit result. Can you check it again for me Mike? Perhaps others
here might like to check it as well? The code I'm using is shown below. In
the meantime, do you have any code that will reliably load a jpg into a
StdPicture obect while retaining its full 24 bit colour depth even on 16 bit
machines. If you do then I'd welcome a copy.
Mike Williams
Option Explicit
Private Declare Function GetObject Lib "gdi32" _
Alias "GetObjectA" (ByVal hObject As Long, _
ByVal nCount As Long, lpObject As Any) As Long
Private Type BITMAP
bmType As Long
bmWidth As Long
bmHeight As Long
bmWidthBytes As Long
bmPlanes As Integer
bmBitsPixel As Integer
bmBits As Long
End Type
Private Sub Command1_Click()
Dim p1 As StdPicture
Dim myBmp As BITMAP
Dim retval As Long
Set p1 = LoadPicture("c:\tulips.jpg")
retval = GetObject(p1.Handle, Len(myBmp), myBmp)
MsgBox myBmp.bmBitsPixel
LoadPicture
End Sub
> I just found a very interesting sample project:
http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=46515&lngWId=1
Now that is very interesting. And it is producing some excellent results.
Mike
Mike
Yes, and it's very simple code. The FreeImage
help file (a 2MB PDF download) has a sample
showing the effect of greatly enlarging a small
image with different filters. From looking at that
and trying the Reconstructor demo it seems that a
"bicubic" resample is probably the best way to get
very good quality reasonably quick, and bilinear is
moderately good very quickly. I wonder how that
compares to whatever method is used in StretchBlt.
Bicubic is pretty good for scaling images up, however Lanczos3 will generally give you a slightly sharper result but at
the cost of speed.
For your requirements though, I'd say Bicubic should be more than satisfactory. Indeed since your input is a JPEG
image, bicubic may be a better algorithm to go for anyway since Lanczos3 will often produce 'ringing' round JPEG
compression artefacts on badly compressed source images due to its edge enhancing properties.
Hope this helps,
I was loading a 24-bit bitmap running at 16-bit without a reboot, so those results may not have been entirely accurate,
however the bit depth of the image is not the point I've been trying to make - As long as it's loaded into a DIB the
memory limitation the OP was running into shouldn't be a factor. I wouldn't be surprised if the PictureBox uses a DDB
for its back buffer since it's primary purpose is for on-screen rendering, which would be where the "Cannot create
AutoRedraw image" error comes from. This makes far more sense since simply loading the picture has absolutely nothing
to do with AutoRedraw (it's not touched any controls at that point.) I cannot verify this assumption for the time being
though since I don't have a Win9x machine to hand.
I found this sampling page last night:
http://www.americaswonderlands.com/digital_photo_interpolation.htm
It seems like the bilinear is noticeably faster
and noticeably lower quality. Of the other methods,
I'm hard-pressed to see a significant difference
at any reasonable enlargement.
Unfortunately, the person who made the sample page
used a sharpen filter after resizing, so the samples
are a bit deceptive. But they all stil look remarkably
clear enlarged by a factor of about 6.
So then what about StretchBlt? Is that just dumb pixel
addition in the case of interpolation? And how would that
apply to shrinking? Do the different methods change
in their efficiency in that case?
> I was loading a 24-bit bitmap running at 16-bit without a reboot
> so those results may not have been entirely accurate
Yep. That's the point I was making. If you're running some code in the VB
IDE to check the depth of the bitmap after loading a jpg into a StdPicture
object using the VB LoadPicture function you need to at least close down and
restart the VB IDE after any change in screen depth, otherwise the result
will not be reliable.
> however the bit depth of the image is not the point I've been trying to
> make
I think it was, unless of course I misundertood you when you said, "Also, is
the problem really in loading the JPEG off disk or displaying it in the
picture box? At least when VB returns the image in a StdPicture object it
appears to be a DIB" ;-)
Mike
Yes, you did.. Unless your system is (again) operating differently to all mine, the bmBits member should be filled
indicating that the image is a DIB, not a DDB (a DDB's image data is managed by the graphics driver and as such you
don't get direct access to it.) Bit-depth is irrelevant, which is what I've been trying to explain..
Yeah, I found the same page while trying to find examples for my prior post, however due to the post-processing this
page's results are next to useless. One of the features of Lanczos3 interpolation is that it performs sharpening as
part of the interpolation process, which makes it very good at preserving detail, where as bicubic tents to smooth these
details out. This is more apparent when scaling down, however also plays a part when scaling up also.
> So then what about StretchBlt? Is that just dumb pixel
> addition in the case of interpolation? And how would that
> apply to shrinking? Do the different methods change
> in their efficiency in that case?
For COLORONCOLOR mode, it uses 'nearest neighbour' interpolation, which simply means no interpolation (in the page you
cited you'll see this right up at the top under the original image thumbnail.) For HALFTONE mode, you're looking at
Lanczos3 interpolation (although I'm not sure whether the one on the previous page uses Lanczos2 or Lanczos3 - The
latter being slower but higher quality due to it's larger sample kernel.)
> the bmBits member should be filled indicating that the image is a DIB
The original post was about picture quality, and one of the points raised in
the thread concerned the current colour depth of the system. You said, "Is
the problem really in loading the JPEG off disk or displaying it in the
picture box?". You went on to say, "At least when VB returns the image in a
StdPicture object it appears to be a DIB, which should mean it has no
problems loading the image".
Although you didn't specifically say so, the clear implication (as
reinforced below) was that you were saying the VB method of loading the jpeg
into a StdPicture object would not degrade the colour quality on a system
running at 16 bit colour depth, whereas of course displaying it in a Picture
Box on such a system would. But, contrary to what you clearly implied, that
does not in fact appear to be the case. The main point of my own response
was to in a way "defend" VB Picture Boxes (which I know you are not keen on,
at least in their Autoredraw state!) and to tell you that, contrary to what
you implied, it is the act of VB loading the jpeg into the StdPicture Object
on such a system that reduces the quality, whether you eventually place the
image in a Picture Box or not.
I think I was quite right in making the assumption above regarding the
implications of what you said because I notice that in some of your own
projects provided on http://edais.mvps.org/ you use the VB method of loading
a picture into a StdPicture object in a program whose specific task is to
perform some operation on an image without degrading its colour quality, and
I wanted to point out to you the problems of doing that on a system running
at 16 bit colour depth.
If I use the VB LoadPicture method to load a jpg (or a 24 bit bmp file) into
a StdPicture object (which is something you do yourself in your own
programs) when my system is running at 16 bit colour depth I end up with
only 16 bits per pixel in the StdPicture object instead of 24. Whether it is
in the form of a DIB or not effectively makes no difference to the fact that
the colour of the original jpg (or 24 bit bmp) file has been degraded to 16
bits by the act of "VB returning the object in a StdPicture object". So your
implied statement that it is the picture box that would degrade the image
and not the act of VB loading into the StdPicture object is not actually
true. That is the point I was trying to make, particularly as you have used
that method in some of your own programs and I make no apologies whatsoever
for pointing out my observations so that you can if necessary amend your
projects.
Here is some test code I used. You need to set your system to 16 bit colour
depth (and possibly also perform a restart just to make sure) before running
it. Obviously you will need to change the hard coded picture path to a 24
bit bmp file on your own system. The code gets both the BITMAP and the
DIBSection information (just to make sure) from the StdPicture object after
using the VB method to load a 24 bit full colour bitmap from file and it
displays the resultant bit depth in both cases in two message boxes. In both
cases the returned result is 16 bits per pixel on such a system, even though
the bitmap file itself has 24 bit colour depth . Since you use that method
yourself in your own code and also since you made the rather sarcastic
remark that "my system (again) appears to be operating differently to your
own" perhaps you might like to try the code for yourself on your own system.
Perhaps Mayayana (the original poster) might also like to try it on his
system.
Mike Williams
MVP Visual Basic
Option Explicit
Private Declare Function GetObject Lib "gdi32" _
Alias "GetObjectA" (ByVal hObject As Long, _
ByVal nCount As Long, lpObject As Any) As Long
Private Type Bitmap
bmType As Long
bmWidth As Long
bmHeight As Long
bmWidthBytes As Long
bmPlanes As Integer
bmBitsPixel As Integer
bmBits As Long
End Type
Private Type BitmapInfoHeader
biSize As Long
biWidth As Long
biHeight As Long
biPlanes As Integer
biBitCount As Integer
biCompression As Long
biSizeImage As Long
biXPelsPerMeter As Long
biYPelsPerMeter As Long
biClrUsed As Long
biClrImportant As Long
End Type
Private Type DIBSection
dsBm As Bitmap
dsBmih As BitmapInfoHeader
dsBitfields(0 To 2) As Long
dshSection As Long
dsOffset As Long
End Type
Private Sub Command1_Click()
Dim myDib As DIBSection
Dim p1 As StdPicture
Dim myBmp As Bitmap
Dim retval As Long
Set p1 = LoadPicture("c:\tulips.bmp")
retval = GetObject(p1.Handle, Len(myBmp), myBmp)
MsgBox myBmp.bmBitsPixel & " bits per pixel"
retval = GetObject(p1.Handle, Len(myDib), myDib)
MsgBox myDib.dsBmih.biBitCount & " bits per pixel"
End Sub
>
> > So then what about StretchBlt? Is that just dumb pixel
> > addition in the case of interpolation? And how would that
> > apply to shrinking? Do the different methods change
> > in their efficiency in that case?
>
> For COLORONCOLOR mode, it uses 'nearest neighbour' interpolation, which
simply means no interpolation (in the page you
> cited you'll see this right up at the top under the original image
thumbnail.) For HALFTONE mode, you're looking at
> Lanczos3 interpolation (although I'm not sure whether the one on the
previous page uses Lanczos2 or Lanczos3 -
I see. Thanks. It's helpful to get an idea
of the landscape - where Windows API
fits in.
> I must admit, I very nearly lost the will to
> live half way through your post . . .
Only nearly? That's sad Michael. Was it too much for you to read all in one
sitting? I hope you're feeling better now. Remember that if you ever feel
like that again you can always go to:
> In the original question the OP mentioned nothing
> about image quality, only that large files wouldn't load
If you were really concerned ONLY with the OP's ORIGINAL question then you
would have restricted yourself to answering just that one question. But you
didn't. You also answered a lot of other questions the OP posted in the same
thread, including the one in which he said, "Now I also want to do resizing.
From my research it appears that setting HALFTONE mode for StretchBlt is the
highest quality, but that it doesn't work properly". Isn't that about image
quality Michael?
> you may have made some good points in it
I did. I'm glad you agree.
> Indeed, his only concern was drawing to the screen
You know that's not true Michael. You've just made that up in an attempt to
crawl out of the hole you've dug for yourself. In fact the OP specifically
said, "There might be shades of quality that wouldn't show up onscreen but
would show up in a print". So your own statement of, "it's_completely
pointless_ arguing about the bit-depth of the image in memory since higher
depths won't be used" is . . . erm . . . how can I put this . . . erm . . .
completely pointless!
> I never made any claims of LoadPicture() and
> the depth it returns the image
Yes you did. Have you forgotten already Michael? I posted some LoadPicture
code for you to try on a system set to 16 bit colour depth and you said,
"Under XP I'm getting a 24-bit DIB regardless of the display depth". That's
exactly what you said Michael. I remember responding to that statement of
yours and telling you about the mistake you had made when running that code.
The statement you made makes it quite clear that you believe that
LoadPicture returns a 24 bit DIB regardless of the display depth. That's
exactly what you said. And you are wrong!
> If my own examples use it [LoadPicture into a StdPicture object]
There's no "if" about it Michael. It's a certainty. That's exactly what your
own example does!
> . . . it's only for the convenience
> of supporting GIF and JPEG
Well that's very convenient Michael. So what you're saying is your code
doesn't work properly, but it's convenient! I've got no problems with that.
I often write such code myself in various specific circumstances. But in
your case you went to a lot of trouble in your code and you used a lot of
API routines to draw the resized image in such a way as to avoid the loss of
colour depth that you would otherwise get if you instead used the native VB
methods and you effectively totally negated the effects of that by using the
LoadPicture function to load the image into a StdPicture object, thereby
destroying the bit depth of the image before the rest of your code even got
a look at it! That in itself wouldn't bother me of course. We all make
mistakes, including you. But I would prefer it if you would admit your
mistakes when you make them.
Why don't you just face facts Michael. You thought that using LoadPicture to
load a jpeg or a 24 bit bitmap file into a StdPicture object returned a 24
bit DIB whether your machine was running at 24 bit colour depth or not. In
fact you specifically said so in one of your responses. And you are wrong
Michael. It does not. On a system running at 16 bit colour depth it returns
a 16 bit DIB. Just admit it Michael. There's nothing wrong with being wrong
Michael. It comes to us all sometimes. Just admit it Michael. You'll feel a
lot better.
> I make no claims about the call's device independence
> (without knowing how the call's implemented internally
Yes you do Michael. Just admit it. You specifically told me that on your
system you get full colour depth even when it is running at 16 bit. But you
are wrong Michael. It does not. Not even on your system, not unless you
"fiddle" it. You made a mistake Michael.
You even went on to make the rather nasty and sarcastic remark, "unless your
system is (again) operating differently to all mine". I remember that thread
Michael. It was quite some time ago and as I recall it was something to do
with graphic output. I remember posting some code for people to try and
quite a number of people responded. In the end it turned out that most
systems were behaving in a similar manner to my own and your own system was
just about the only one producing a different result! How convenient.
> how could I, or you for that matter, [check the
> device independence of using LoadPicture to
> load an image into a StdPicture object]?
Very simple Michael. Just write some code (as I have done) to test the
premise and run that code on various systems set to various different colour
depths. You'll see that it is NOT device independent, as I have said and as
you have argued with. Over on this side of "the big pond" it's called "suck
it and see". Why don't you suck it Michael! You really seem totally unable
to admit it when you have made an error. In one of your posts, after you had
made a mistake and posted incorrect results, and after I had pulled you up
about it, you said . . .
"so those results may not have been entirely accurate"
Seems a bit verbose that, Michael, "may not have been entirely accurate".
Any chance you can condense that a little?
By the way, I'll be going on holiday tomorrow to the English Lake District
(really beautiful place, at all times of the year and something special in
September). I'll be away for about a week so I won't see your response to
this post until I get back. In the meantime, if you again "lose the will to
live" on reading this post please remember my advice. The Samaritans are
really nice people Michael. They'll look after you. Here's the link again:
Have a nice day.
Mike
(I wasn't sure about whether an 8-bit image
could be copied directly to a 24-bit DIB without
extra steps, but I'm having no trouble processing
GIFs and then saving them as 24-bit BMPs
to be turned into JPGs.)
I've then written a BitBlt routine into the class
for cropping and adapted the bilinear and
bicubic routines from the "Reconstructor"
sample project for resizing. It's complex code
but also very compact.
Each routine returns a new copy of the class,
which is really little more than a "gift wrapped"
DIB.
It's slightly slow with the resizing on large
images, but the quality seems to be very
good.
I also found straight VB code for writing JPGs,
but it has 2 drawbacks: 1) It's notably slow and
2) the author is rather obnoxious about getting
credit and specifies that commercial use
requires direct permission...so it's probably
not worth dealing with.
--------
The mystery to me now is that so many people
seem to be using FreeImage or GDI+ and don't
know about the "Reconstructor" code.
> I think I've got this worked out now.
> I'm loading images as StdPicture with
> LoadImage, then copying them into a
> 24-bit DIB in a class loosely based . .
As you appear to have discovered, LoadImage is a very useful function.
Capable of loading and if necessary stretching bitmaps into memory. In fact
if you set the LR_CREATEDIBSECTION flag in its fuLoad (un2) parameter it'll
load a bitmap from file straight into a DIBSection for you. It won't load
Jpegs of course, so you'll need to use a different method of loading them
(the VB LoadPicture function that Mike Sutton uses to load Jpegs into
StdPicture objects degrades the colour depth when run on 16 bit colour depth
systems). I seem to remember there being some nice code on the VBAccelerator
site though that will load a jpeg into a DIBSection for you. Check it out.
Mike
Actually I did mean LoadPicture. I still haven't
tried LoadImage. I gather that you mean a 24-bit
BMP or JPG on 16-bit display will get loaded by
LoadPicture as 16-bit and get distorted? (Is that
what the debate was about? I didn't catch that.)
That's an interesting distinction. So I guess the
tradeoff is between having the convenience of
LoadPicture, with the idea that nearly everyone
now uses 24- or 32-bit display, or doing the extra
work with LoadImage. Now I'm curious about
exactly what LoadPicture is wrapping, and whether
plain GDI might have the ability to load JPGs and
GIFs somehow, with reasonable ease. ...And there's
also the OLE version, which I haven't tried but have
seen used in code samples. It's hard to figure out
exactly what the differences are between all of those.
Yes. That was it. By the way, I'm sorry I haven't got time to answer your
other points (just about to leave for a little holiday) but I think you'll
find some good Jpeg to DIBSection code on the vbAccelerator site. As you
say, most systems these days run at 32 bit so on those systems LoadPicture
will be just fine, but there are still quite a few systems running at 16
bit.
Mike
> Although you didn't specifically say so, the clear implication (as
> reinforced below) was that you were saying the VB method of
> loading the jpeg into a StdPicture object would not degrade the
> colour quality on a system ...
Yep, but if your argumentation is based on an implication, then you
should have also accepted his implicit concession about your point:
;-)
"I was loading a 24-bit bitmap running at 16-bit without a reboot,
so those results may not have been entirely accurate..."
Sounds as clear as "Yes you're right, I was wrong" to me.
Could have lived well without the following posts. ;)
Anyway, thanks for pointing that out (was new to me too).
Olaf
> A followup on VBAccelerator: It turns out that
> there's a project there by Steve McMahon,
> vbImageProc2, that uses a custom routine
> to resize. I don't know what to make of this,
> as compared to StretchBlt. Any opinions,
> anyone? I'm pasting it below because it's
> fairly compact.
That's compact? For compact resize code, have a look below:
<g>
LFS
Option Explicit
Const TestFile = "D:\temp\einstein.jpg"
Private Sub Form_Paint()
Dim pic As StdPicture
Set pic = LoadPicture(TestFile)
DrawImage Me.hDC, pic, 100, 80, 0.75
DrawImage Me.hDC, pic, 50, 40, 0.5
DrawImage Me.hDC, pic, 0, 0, 0.25
End Sub
Private Sub DrawImage(ByVal DestDC As Long, ByRef Source As StdPicture, Optional X As Single = 0, Optional Y As Single = 0,
Optional Scaled As Single = 1)
Dim wid As Single, hgt As Single
wid = ScaleX(Source.Width * Scaled, vbHimetric, vbPixels)
hgt = ScaleY(Source.Height * Scaled, vbHimetric, vbPixels)
Source.Render (DestDC), X, Y + hgt - 1, wid, -hgt, 0, 0, Source.Width, Source.Height + ScaleY(1, vbPixels, vbHimetric), 0
End Sub
> Sounds as clear as "Yes you're right, I was wrong" to me
> [Mike Sutton's "so those results may not have been entirely
> accurate"]. Could have lived well without the following posts. ;)
> Anyway, thanks for pointing that out [LoadPicture to StdPicture
> colour depth problem] (was new to me too).
I agree that it could have been left there Olaf, and as far as I am
concerned it would have been except for the fact that in his next post Mike
Sutton said, "Unless your system is (again) operating differently to all
mine". His statement might look rather innocuous at first glance, but there
is history on this one Olaf, which you may not know about. Mike Sutton was
effectively calling me a liar, just as he has done in the past. That's what
got my back up. I was not lying then and I am not lying now. I am NOT a
liar. Mike Sutton's phrase, "yadda, yadda yadda" and his statement that I
was merely "regurgitating a load of rubbish" didn't help matters either,
especially as I was doing no such thing. Mike, as I'm sure everyone here
knows, is a top notch expert when it comes to graphics and I have a great
respect him and for his abilities, but I don't like anyone calling me a
liar. If I say something happens in a specific manner on my own system then
that is exactly what it does. As far as I am concerned the matter rests
here, unless I am again called a liar, in which case I shall respond
appropriately.
sigh... men and their proud (myself included of course) ...<g>
Aside from "WhiskyAndCoke" - here's something that always
works for me (to forget frustrating discussions): :-)
http://www.manhattanrecords.com/raulplayer/player.html
(He's a genious - if possible, use earphones to get all the details,
go directly to 'watch live videos' in the BottomLeft corner - one
has to see, *how* he's playing "all that jazz"...)
Olaf
Wow, what an amazing musician!
Thanks for the link.
Olaf-
Thank you. Thank you. Thank you!
This cat is awesome. Strange how he even moves his head like Stevie
Wonder. What a phenomenal style.
If you're interested in great performance here's a video of one of my
favorite classical pieces - Canon In D by Johann Pachelbel. I can
literally bring myself to tears playing this piece on the piano but this
rock guitar player gets outside and does a great job over a simple drum
and strings track. Great touch and feel and infinitely smooth.
http://www.youtube.com/watch?v=QjA5faZF1A8
---
Stefan Berglund
> What a phenomenal style.
In the meantime he's bringing the trumpet-parts in two-voices.
(this "new style" can be heard in the songs-section)
> http://www.youtube.com/watch?v=QjA5faZF1A8
Yea, not bad for his age - fast fingers, timing could be
somewhat better (but I'm far from playing that good).
To see (and hear) perfect playing on both - Rock- and Acoustic-Guitar,
you should definitely get John Mayers "Every Given Thursday"
http://www.amazon.com/Any-Given-Thursday-John-Mayer/dp/B000083GLC/
(best "Live-DVD" I ever bought)
Olaf
hmm... could it be, that we get somewhat off-topic in the meantime?...;)
> > http://www.manhattanrecords.com/raulplayer/player.html
> Wow, what an amazing musician!
Yep - he's unbelievable; and dangerous - my first thought as I saw
him the very first time on german tv, was to sell my guitar and give
up... ;-)
Olaf
You need FireFox. Go to my site, and click on the "Get Firefox" graphic (I
get a buck <g>) that's on any page. Load it up!
After that, load these extensions:
FlashBlock -- http://flashblock.mozdev.org/
VideoDownloader -- http://javimoya.com/blog/youtube_en.php
With the first, Flash animations won't play until you click on them. With
the second, you can save the video playing on the current page.
--
Working without a .NET?
http://classicvb.org/
Not to worry; the topic got stale a _long_ time ago!
Thanks. I'm using Firefox.....You get a dollar
if someone downloads Firefox via your website?!
I think I want to work for you. :)
I tried javimoya.com but I don't get anything
like a download dialogue. When I paste in
Stefan's link and click "download" it just sends
me to the blog page.
This stuff drives me crazy. It's like the Internet
is turning into one big TV-land, in read-only format.
Anyone can do it, actually. It's a deal through Google's AdSense thingie.
> I tried javimoya.com but I don't get anything
> like a download dialogue. When I paste in
> Stefan's link and click "download" it just sends
> me to the blog page.
Maybe this will work better: https://addons.mozilla.org/firefox/2390/
> This stuff drives me crazy. It's like the Internet
> is turning into one big TV-land, in read-only format.
I think it's gonna kill the cable company's golden goose, actually.
Is there any workaround for this error or is truly an OS limit?
Any examples on how to manage a back-buffer? This is new territory for me...
"Mike D Sutton" wrote:
> > I have an application whereby I draw a plot on a screen - I have numerous
> > forms, each with a picture box. The app works fine on a single monitor.
> > However, if I use it on a dual-monitor PC, I routinely get the "cannot
> > autoredraw" problem. I would like to leave autoredraw = true so that the
> > image doesn't get erased by the other windows when they are moved around or
> > cascaded.
> >
> > Is there any workaround for this error or is truly an OS limit?
>
> In this case simply manage your own back-buffer and re-paint to the form when required - This way you get the benefits
> of AutoRedraw without having to worry about the DDB memory limitations. For even better performance, subclass your
> window and do your drawing in the WM_PAINT message handler, which bypasses VB's drawing entirely and gives you access to
> the update rectangle rather than having to repaint the entire form every time.
> Hope this helps,
>
> Mike
>
> P.s. It's best to post your query to a new thread rather that on the end of an old one, you'll get more people looking
> at your query.
Please fix your date/time settings. It shows October 18.
Have a look at this old post, it demonstrates a simple class that manages all of the GDI internals for you:
http://groups.google.co.uk/group/microsoft.public.vb.winapi.graphics/msg/2f87a10315d8b6c2
Hope this helps,
Mike
Whoops, you caught me peeking at next week's winning lottery numbers.. ;)