Here's a class that I cobbled together over the last few years from various sources, and heavily modified, that you can use to do image size scaling (using stretchblit), jpeg compression tweaking, take desktop screenshots, ect. You will want to use the:
Public Function ResizeImage(ByVal sourceBitmap As Bitmap, ByVal newWidth As Integer, ByVal newHeight As Integer, Optional ByVal bpp As Short = 24) As Image
method.
code:
Option Strict On
Imports System
Imports System.Runtime.InteropServices
Imports System.Drawing
Imports System.Drawing.Imaging
Imports System.IO
Public Class clsGDI_Graphics
Const STRETCHMODE As Integer = 4
Shared BI_RGB As UInteger = 0
Shared DIB_RGB_COLORS As UInteger = 0
Public Function CaptureScreen() As Image
Return CaptureWindow(User32.GetDesktopWindow())
End Function
Public Function CaptureScreenAndResize(ByVal newWidth As Integer, ByVal newHeight As Integer) As Image
Return CaptureWindowAndResize(User32.GetDesktopWindow(), newWidth, newHeight)
End Function
Public Function CaptureWindowAndResize(ByVal handle As IntPtr, ByVal newWidth As Integer, ByVal newHeight As Integer, _
Optional mode As Int32 = GDI32.StretchBltMode.STRETCH_DELETESCANS) As Image
Dim hdcSrc As IntPtr = User32.GetWindowDC(handle)
Dim windowRect As New User32.RECT()
User32.GetWindowRect(handle, windowRect)
Dim width As Integer = windowRect.right - windowRect.left
Dim height As Integer = windowRect.bottom - windowRect.top
Dim hdcDest As IntPtr = GDI32.CreateCompatibleDC(hdcSrc)
Dim hBitmap As IntPtr = GDI32.CreateCompatibleBitmap(hdcSrc, width, height)
Dim hOld As IntPtr = GDI32.SelectObject(hdcDest, hBitmap)
GDI32.SetStretchBltMode(hdcDest, gdi32.StretchBltMode.STRETCH_HALFTONE)
GDI32.StretchBlt(hdcDest, 0, 0, newWidth, newHeight, hdcSrc, 0, 0, width, height, TernaryRasterOperations.SRCCOPY)
GDI32.SelectObject(hdcDest, hOld)
GDI32.DeleteDC(hdcDest)
User32.ReleaseDC(handle, hdcSrc)
Dim img As Image = Image.FromHbitmap(hBitmap)
GDI32.DeleteObject(hBitmap)
Return img
End Function
Public Function CaptureWindow(ByVal handle As IntPtr) As Image
Dim hdcSrc As IntPtr = User32.GetWindowDC(handle)
Dim windowRect As New User32.RECT()
User32.GetWindowRect(handle, windowRect)
Dim width As Integer = windowRect.right - windowRect.left
Dim height As Integer = windowRect.bottom - windowRect.top
Dim hdcDest As IntPtr = GDI32.CreateCompatibleDC(hdcSrc)
Dim hBitmap As IntPtr = GDI32.CreateCompatibleBitmap(hdcSrc, width, height)
Dim hOld As IntPtr = GDI32.SelectObject(hdcDest, hBitmap)
GDI32.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, GDI32.SRCCOPY)
GDI32.SelectObject(hdcDest, hOld)
GDI32.DeleteDC(hdcDest)
User32.ReleaseDC(handle, hdcSrc)
Dim img As Image = Image.FromHbitmap(hBitmap)
GDI32.DeleteObject(hBitmap)
Return img
End Function
Private Declare Function CreateCompatibleDC Lib "GDI32" (ByVal hDC As Integer) As Integer
Private Declare Function CreateCompatibleBitmap Lib "GDI32" (ByVal hDC As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer) As Integer
Private Declare Function GetDeviceCaps Lib "gdi32" Alias "GetDeviceCaps" (ByVal hdc As Integer, ByVal nIndex As Integer) As Integer
Private Declare Function SelectObject Lib "GDI32" (ByVal hDC As Integer, ByVal hObject As Integer) As Integer
Private Declare Function BitBlt Lib "GDI32" (ByVal srchDC As Integer, ByVal srcX As Integer, ByVal srcY As Integer, ByVal srcW As Integer, ByVal srcH As Integer, ByVal desthDC As Integer, ByVal destX As Integer, ByVal destY As Integer, ByVal op As Integer) As Integer
Private Declare Function DeleteDC Lib "GDI32" (ByVal hDC As Integer) As Integer
Private Declare Function DeleteObject Lib "GDI32" (ByVal hObj As Integer) As Integer
Const SRCCOPY As Integer = &HCC0020
Public Function CaptureWindowFromPrimaryDevice() As Image
Dim hSDC, hMDC As Integer
Dim hBMP, hBMPOld As Integer
Dim FW, FH As Integer
Dim r As Integer
hSDC = GDI32.CreateDC(enumDisplayDevicesForPrimary, "", "", "")
hMDC = CreateCompatibleDC(hSDC)
FW = GetDeviceCaps(hSDC, 8)
FH = GetDeviceCaps(hSDC, 10)
hBMP = CreateCompatibleBitmap(hSDC, FW, FH)
hBMPOld = SelectObject(hMDC, hBMP)
r = BitBlt(hMDC, 0, 0, FW, FH, hSDC, 0, 0, 13369376)
hBMP = SelectObject(hMDC, hBMPOld)
r = DeleteDC(hSDC)
r = DeleteDC(hMDC)
CaptureWindowFromPrimaryDevice = Image.FromHbitmap(New IntPtr(hBMP))
DeleteObject(hBMP)
End Function
Public Sub CaptureWindowToFile(ByVal handle As IntPtr, ByVal filename As String, ByVal format As ImageFormat)
Dim img As Image = CaptureWindow(handle)
img.Save(filename, format)
End Sub
Public Sub CaptureScreenToFile(ByVal filename As String, ByVal format As ImageFormat)
Dim img As Image = CaptureScreen()
img.Save(filename, format)
End Sub
Public Function ByteArrayToImage(ByVal ByteArray() As Byte) As Image
Dim ImageStream As MemoryStream
Try
If ByteArray.GetUpperBound(0) > 0 Then
ImageStream = New MemoryStream(ByteArray)
ByteArrayToImage = Image.FromStream(ImageStream)
Else
ByteArrayToImage = Nothing
End If
Catch ex As Exception
ByteArrayToImage = Nothing
End Try
End Function
Public Function ImageToByteArray(ByRef NewImage As Image, ByRef ByteArray() As Byte, Optional ByVal errMsg As String = "") As Boolean
Dim ImageStream As MemoryStream
ImageToByteArray = True
Try
ReDim ByteArray(0)
If NewImage IsNot Nothing Then
ImageStream = New MemoryStream
NewImage.Save(ImageStream, ImageFormat.Jpeg)
ByteArray = ImageStream.GetBuffer
End If
Catch ex As Exception
ImageToByteArray = False
errMsg = ex.Message
End Try
End Function
Private Function ByteAlignOnWord(ByVal BitDepth As Byte, ByVal Width As Long) As Long
ByteAlignOnWord = (((Width * BitDepth) + &H1F&) And Not &H1F&) \ &H8&
End Function
Public Function ResizeImage(ByVal sourceBitmap As Bitmap, ByVal newWidth As Integer, _
ByVal newHeight As Integer, Optional ByVal bpp As Short = 24) As Image
Dim sourceWidth As Integer = sourceBitmap.Width
Dim sourceHeight As Integer = sourceBitmap.Height
Dim hbm As IntPtr = sourceBitmap.GetHbitmap()
Dim bmi As New BITMAPINFO()
bmi.biSize = 40
bmi.biWidth = newWidth
bmi.biHeight = newHeight
bmi.biPlanes = 1
bmi.biBitCount = bpp
bmi.biCompression = BI_RGB
bmi.biSizeImage = CUInt(Math.Abs(bmi.biHeight) * ByteAlignOnWord(CByte(bmi.biBitCount), bmi.biWidth))
bmi.biXPelsPerMeter = 1000000
bmi.biYPelsPerMeter = 1000000
Dim bits0 As IntPtr
Dim hbm0 As IntPtr = GDI32.CreateDIBSection(IntPtr.Zero, bmi, DIB_RGB_COLORS, bits0, IntPtr.Zero, 0)
Dim sdc As IntPtr = GDI32.GetDC(IntPtr.Zero)
Dim hdc As IntPtr = GDI32.CreateCompatibleDC(sdc)
GDI32.SelectObject(hdc, hbm)
Dim hdc0 As IntPtr = GDI32.CreateCompatibleDC(sdc)
GDI32.SelectObject(hdc0, hbm0)
GDI32.SetStretchBltMode(hdc0, GDI32.StretchBltMode.STRETCH_ORSCANS)
GDI32.StretchBlt(hdc0, 0, 0, newWidth, newHeight, hdc, 0, 0, sourceWidth, sourceHeight, TernaryRasterOperations.SRCCOPY)
Dim finishedImage As System.Drawing.Image = System.Drawing.Image.FromHbitmap(hbm0)
GDI32.DeleteDC(hdc)
GDI32.DeleteDC(hdc0)
User32.ReleaseDC(IntPtr.Zero, sdc)
GDI32.DeleteObject(hbm)
GDI32.DeleteObject(hbm0)
Return finishedImage
End Function
<flags()> _
Enum DisplayDeviceStateFlags As Integer
AttachedToDesktop = &H1
MultiDriver = &H2
PrimaryDevice = &H4
MirroringDriver = &H8
VGACompatible = &H16
Removable = &H20
ModesPruned = &H8000000
Remote = &H4000000
Disconnect = &H2000000
End Enum
<structlayout(layoutkind.sequential,> _
Public Structure DISPLAY_DEVICE
<marshalas(unmanagedtype.u4)> _
Public cb As Integer
<marshalas(unmanagedtype.byvaltstr,> _
Public DeviceName As String
<marshalas(unmanagedtype.byvaltstr,> _
Public DeviceString As String
<marshalas(unmanagedtype.u4)> _
Public StateFlags As DisplayDeviceStateFlags
<marshalas(unmanagedtype.byvaltstr,> _
Public DeviceID As String
<marshalas(unmanagedtype.byvaltstr,> _
Public DeviceKey As String
End Structure
<dllimport("user32.dll")> _
Private Shared Function EnumDisplayDevices(ByVal lpDevice As String, ByVal iDevNum As UInteger, ByRef lpDisplayDevice As DISPLAY_DEVICE, ByVal dwFlags As UInteger) As Boolean
End Function
Public Function enumDisplayDevicesForPrimary() As String
Dim device As DISPLAY_DEVICE = New DISPLAY_DEVICE()
device.cb = Marshal.SizeOf(device)
enumDisplayDevicesForPrimary = ""
Try
Dim id As UInteger = 0
While enumDisplayDevices(Nothing, id, device, 0)
If device.StateFlags.ToString.Contains("PrimaryDevice") Then
Return device.DeviceName
End If
device.cb = Marshal.SizeOf(device)
enumDisplayDevices(device.DeviceName, 0, device, 0)
device.cb = Marshal.SizeOf(device)
id = CUInt(id + 1)
End While
Catch ex As Exception
Console.WriteLine([String].Format("{0}", ex.ToString()))
End Try
End Function
Private Class JpegTools
Private codecs As ImageCodecInfo() = ImageCodecInfo.GetImageEncoders()
Private quality As Long
Public ici As ImageCodecInfo = Nothing
Public ep As New EncoderParameters()
Public compressionRatio As Long
Public Sub new(ByVal _compressionRatio As Long, Optional ByRef errMsg As String = "")
compressionRatio = _compressionRatio
If compressionRatio < 0 then compressionRatio = 0
If compressionRatio > 100 then compressionRatio = 100
quality = (100 - compressionRatio)
Try
For Each codec As ImageCodecInfo In codecs
If codec.MimeType = "image/jpeg" Then
ici = codec
End If
Next
ep.Param(0) = New EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality)
Catch ex As Exception
errMsg = ex.Message
End Try
End Sub
End Class
Private JpgTools As JpegTools
Public Function SaveImgToFile(ByRef img As Image, ByVal fullPathWithFileName As String, ByVal compressionRatio As Long, _
Optional ByRef errMsg As String = "") As Boolean
If JpgTools Is Nothing Then JpgTools = New JpegTools(compressionRatio, errMsg)
If JpgTools.compressionRatio <> compressionRatio then JpgTools = New JpegTools(compressionRatio, errMsg)
If errMsg <> "" then Return False
Try
img.Save(fullPathWithFileName, JpgTools.ici, JpgTools.ep)
Catch ex As Exception
errMsg = ex.Message
Return False
End Try
Return True
End Function
Public Class GDI32
Public Shared SRCCOPY As Integer = &HCC0020
<dllimport("user32.dll")> _
Public Shared Function GetDC(ByVal hwnd As IntPtr) As IntPtr
End Function
<system.runtime.interopservices.dllimport("gdi32.dll")> _
Public Shared Function CreateDIBSection(ByVal hdc As IntPtr, _
ByRef bmi As BITMAPINFO, ByVal Usage As UInteger, ByVal bits As IntPtr, _
ByVal hSection As IntPtr, ByVal dwOffset As UInteger) As IntPtr
End Function
<dllimport("gdi32.dll")> _
Public Shared Function BitBlt(ByVal hObject As IntPtr, ByVal nXDest As Integer, ByVal nYDest As Integer, _
ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal hObjectSource As IntPtr, _
ByVal nXSrc As Integer, ByVal nYSrc As Integer, ByVal dwRop As Integer) As Boolean
End Function
<dllimport("gdi32.dll")> _
Public Shared Function StretchBlt(ByVal hdcDest As IntPtr, _
ByVal nXOriginDest As Integer, _
ByVal nYOriginDest As Integer, _
ByVal nWidthDest As Integer, _
ByVal nHeightDest As Integer, _
ByVal hdcSrc As IntPtr, _
ByVal nXOriginSrc As Integer, _
ByVal nYOriginSrc As Integer, _
ByVal nWidthSrc As Integer, _
ByVal nHeightSrc As Integer, _
ByVal dwRop As TernaryRasterOperations) As Boolean
End Function
Public Enum StretchBltMode As Integer
STRETCH_ANDSCANS = 1
STRETCH_ORSCANS = 2
STRETCH_DELETESCANS = 3
STRETCH_HALFTONE = 4
End Enum
<dllimport("gdi32.dll")> _
Public Shared Function SetStretchBltMode(hdc As IntPtr, iStretchMode As StretchBltMode) As Boolean
End Function
<dllimport("gdi32.dll")> _
Public Shared Function CreateBitmap(ByVal nWidth As Integer, ByVal nHeight As Integer, _
ByVal cPlanes As UInteger, ByVal cBitsPerPel As UInteger, _
ByVal lpvBits As IntPtr) As IntPtr
End Function
<dllimport("gdi32.dll")> _
Public Shared Function CreateDC(ByVal lpDriverName As String, ByVal lpDeviceName As String, _
ByVal lpOutput As String, ByVal lpInitData As String) As Integer
End Function
<dllimport("gdi32.dll")> _
Public Shared Function GetDeviceCaps(ByVal hdc As Integer, ByVal nIndex As Integer) As Integer
End Function
<dllimport("gdi32.dll")> Public Shared Function CreateCompatibleBitmap(ByVal hDC As IntPtr, _
ByVal nWidth As Integer, ByVal nHeight As Integer) As IntPtr
End Function
<dllimport("gdi32.dll")> Public Shared _
Function CreateCompatibleDC(ByVal hDC As IntPtr) As IntPtr
End Function
<dllimport("gdi32.dll")> Public Shared _
Function DeleteDC(ByVal hDC As IntPtr) As Boolean
End Function
<dllimport("gdi32.dll")> Public Shared _
Function DeleteObject(ByVal hObject As IntPtr) As Boolean
End Function
<dllimport("gdi32.dll")> Public Shared _
Function SelectObject(ByVal hDC As IntPtr, ByVal hObject As IntPtr) As IntPtr
End Function
End Class
Private Class User32
<structlayout(layoutkind.sequential)> _
Public Structure RECT
Public left As Integer
Public top As Integer
Public right As Integer
Public bottom As Integer
End Structure
<dllimport("user32.dll",> _
Public Shared Function OpenInputDesktop(ByVal dwFlags As UInteger, _
ByVal fInherit As Boolean, _
ByVal dwDesiredAccess As UInteger) As IntPtr
End Function
<dllimport("user32.dll")> Public Shared _
Function GetDesktopWindow() As IntPtr
End Function
<dllimport("user32.dll")> Public Shared _
Function GetWindowDC(ByVal hWnd As IntPtr) As IntPtr
End Function
<dllimport("user32.dll")> Public Shared _
Function ReleaseDC(ByVal hWnd As IntPtr, ByVal hDC As IntPtr) As IntPtr
End Function
<dllimport("user32.dll")> Public Shared _
Function GetWindowRect(ByVal hWnd As IntPtr, ByRef rect As RECT) As IntPtr
End Function
<dllimport("user32.dll")> _
Public Shared Function InvalidateRect(ByVal hwnd As IntPtr, ByVal rect As IntPtr, _
ByVal bErase As Integer) As Integer
End Function
End Class
Enum TernaryRasterOperations As UInteger
SRCCOPY = &HCC0020
SRCPAINT = &HEE0086
SRCAND = &H8800C6
SRCINVERT = &H660046
SRCERASE = &H440328
NOTSRCCOPY = &H330008
NOTSRCERASE = &H1100A6
MERGECOPY = &HC000CA
MERGEPAINT = &HBB0226
PATCOPY = &HF00021
PATPAINT = &HFB0A09
PATINVERT = &H5A0049
DSTINVERT = &H550009
BLACKNESS = &H42
WHITENESS = &HFF0062
CAPTUREBLT = &H40000000
End Enum
<system.runtime.interopservices.structlayout(system.runtime.interopservices.layoutkind.sequential)> _
Public Structure BITMAPINFO
Public biSize As UInteger
Public biWidth As Integer, biHeight As Integer
Public biPlanes As Short, biBitCount As Short
Public biCompression As UInteger, biSizeImage As UInteger
Public biXPelsPerMeter As Integer, biYPelsPerMeter As Integer
Public biClrUsed As UInteger, biClrImportant As UInteger
<system.runtime.interopservices.marshalas(system.runtime.interopservices.unmanagedtype.byvalarray,> _
Public cols As UInteger()
End Structure
Private Shared Function MAKERGB(ByVal r As Integer, ByVal g As Integer, ByVal b As Integer) As UInteger
Return CUInt(b And 255) Or CUInt((r And 255) << 8) Or CUInt((g And 255) << 16)
End Function
End Class
hope this helps.
- Pete