|
-
Mar 11th, 2019, 07:57 PM
#1
Thread Starter
Fanatic Member
SetDIBitsToDevice , GetDIBits (Blurry text)
Hi all,
The following simple test code takes a snapshot of the desktop screen, produces a BMP image in memory , retrieves all the pixels in the BMP ,replace the white pixels with green pixels and finally copy the altered BMP back to the screen using the SetDIBitsToDevice GDI API.
Problem:
Although the code works, the resulting text is blurred/reddish.
Question:
Is there a way of getting a smooth text ?
I have also used the TransparentBlt API in another code but I i get the same text-blurring problem.
Code:
Option Explicit
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
Type RGBQUAD
rgbBlue As Byte
rgbGreen As Byte
rgbRed As Byte
rgbReserved As Byte
End Type
Type BITMAPINFO
bmiHeader As BITMAPINFOHEADER
bmiColors As RGBQUAD
End Type
Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long
Declare Function CreateCompatibleBitmap Lib "gdi32" (ByVal hdc As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long
Declare Function GetDIBits Lib "gdi32" (ByVal aHDC As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits As Any, lpBI As BITMAPINFO, ByVal wUsage As Long) As Long
Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long
Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
Declare Function BitBlt Lib "gdi32" (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
Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hdc As Long) As Long
Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long
Declare Function SetDIBitsToDevice Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal dx As Long, ByVal dy As Long, ByVal SrcX As Long, ByVal SrcY As Long, ByVal Scan As Long, ByVal NumScans As Long, Bits As Any, BitsInfo As BITMAPINFO, ByVal wUsage As Long) As Long
Declare Function GetSystemMetrics Lib "user32" (ByVal nIndex As Long) As Long
Const DIB_RGB_COLORS = 0
Const SM_CXSCREEN = 0
Const SM_CYSCREEN = 1
Const SRCCOPY = &HCC0020
Const CAPTUREBLT = &H40000000
Const BI_RGB = 0&
Function getScreenBMP(hdcSrc As Long) As Long
Dim nScreenWidth As Long, nScreenHeight As Long
Dim hCaptureDC As Long, hBitmap As Long, hOld As Long
nScreenWidth = GetSystemMetrics(SM_CXSCREEN)
nScreenHeight = GetSystemMetrics(SM_CYSCREEN)
' // Create compatible DC, create a compatible bitmap and copy the screen using BitBlt()
hCaptureDC = CreateCompatibleDC(hdcSrc)
hBitmap = CreateCompatibleBitmap(hdcSrc, nScreenWidth, nScreenHeight)
hOld = SelectObject(hCaptureDC, hBitmap)
'Make a copy of the screen
'TODO: take subset
Call BitBlt(hCaptureDC, 0, 0, nScreenWidth, nScreenHeight, hdcSrc, 0, 0, SRCCOPY Or CAPTUREBLT)
Call SelectObject(hCaptureDC, hOld) ' // always select the previously selected object once done
Call DeleteDC(hCaptureDC)
getScreenBMP = hBitmap
End Function
Sub testMain()
Dim myBMInfo As BITMAPINFO
Dim lpPixels() As RGBQUAD
Dim hdc As Long, hBitmap As Long
hdc = GetDC(0)
hBitmap = getScreenBMP(hdc)
myBMInfo.bmiHeader.biSize = LenB(myBMInfo.bmiHeader)
' // Get the BITMAPINFO structure from the bitmap
Call GetDIBits(hdc, hBitmap, 0, 0, vbNull, myBMInfo, DIB_RGB_COLORS)
' // create the bitmap buffer
' ReDim lpPixels(myBMInfo.bmiHeader.biSizeImage / 4)
ReDim lpPixels(myBMInfo.bmiHeader.biWidth, myBMInfo.bmiHeader.biHeight)
' // Better do this here - the original bitmap might have BI_BITFILEDS, which makes it
' // necessary to read the color table - you might not want this.
myBMInfo.bmiHeader.biCompression = BI_RGB
' // get the actual bitmap buffer
Call GetDIBits(hdc, hBitmap, 0, myBMInfo.bmiHeader.biHeight, lpPixels(1, 1), myBMInfo, DIB_RGB_COLORS)
Dim x As Long, y As Long
'// replace white pixels with green pixels
For x = 0 To myBMInfo.bmiHeader.biWidth
For y = 0 To myBMInfo.bmiHeader.biHeight
If lpPixels(x, y).rgbGreen = 255 And lpPixels(x, y).rgbBlue = 255 And lpPixels(x, y).rgbRed = 255 Then
lpPixels(x, y).rgbGreen = 255: lpPixels(x, y).rgbBlue = 0: lpPixels(x, y).rgbRed = 0
End If
Next y
Next x
SetDIBitsToDevice hdc, 0, 0, myBMInfo.bmiHeader.biWidth, myBMInfo.bmiHeader.biHeight, 0, 0, 0, myBMInfo.bmiHeader.biHeight, lpPixels(1, 1), myBMInfo, DIB_RGB_COLORS
Call DeleteObject(hBitmap)
Call ReleaseDC(vbNull, hdc)
End Sub
This is what I get : (Notice the blurred text)

Also, Does the GDI+ provide a better alternative ?
Regards.
-
Mar 11th, 2019, 08:19 PM
#2
Re: SetDIBitsToDevice , GetDIBits (Blurry text)
I would think that the text is blended into the background. The area around the text edges are not crisp so you will have black text with probably a grayish edge where the black was blended into the original white background. When you replace white with green, those blended pixels are not pure white (RGB 255,255,255). That is likely the reason for the blurriness.
A better alternative? Not really. If you try to change a range of colors from White to near-white, you may get better results around the text, but then other near-white colors may be converted to green that you didn't want to be green
P.S. vbNull is not the value zero: MsgBox vbNull
-
Mar 11th, 2019, 08:32 PM
#3
Thread Starter
Fanatic Member
Re: SetDIBitsToDevice , GetDIBits (Blurry text)
-
Mar 11th, 2019, 08:33 PM
#4
Thread Starter
Fanatic Member
Re: SetDIBitsToDevice , GetDIBits (Blurry text)
@LaVolpe
So I guess there is no way of remeding this text blurring issue ?
Also, I was wondering if there is a way of replacing the targeted color in one bulk instead of looping through each pixel to gain speed ? Iterating the pixels in the BMP one by one is very slow.
And how about the GDI+ library ?
Thanks.
Late edit:
I could replace the color without looping via the use of the TransparentBlt API function but I was wondering if there is another way .
Last edited by JAAFAR; Mar 11th, 2019 at 08:38 PM.
-
Mar 11th, 2019, 10:18 PM
#5
Re: SetDIBitsToDevice , GetDIBits (Blurry text)
Isn't this just ClearType or other antialiasing of text? You could turn all of that off, but who wants to live with the result?
Or maybe I'm just missing something too subtle for me to grasp right now. Allergy meds, bleh.
-
Mar 12th, 2019, 03:27 AM
#6
Re: SetDIBitsToDevice , GetDIBits (Blurry text)
I agree with dilettante.
Text on screen is anti aliased (whether by ClearType or something else), so making a screenshot and replace white with green will give very odd results.
-
Mar 12th, 2019, 05:47 AM
#7
Re: SetDIBitsToDevice , GetDIBits (Blurry text)
You could try :
If. SourceR = sourceG and sourceR=sourceB then
TargetR=0:targerG=sourceG:targetB=0.. Maybe too much greenish result
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|