-
Aug 22nd, 2014, 02:35 PM
#1
Thread Starter
Frenzied Member
Problem with getting raw image bytes from WIA
Ok, so I'm trying to extract the raw RGB data from a known good BMP file that I'm loading through WIA. I've gotten the code like this so far.
Code:
Dim TempImageFile As ImageFile
dim PixelBytes() as byte
Set TempImageFile = New ImageFile
TempImageFile.LoadFile "c:\testfolder\test.bmp"
PixelBytes() = TempImageFile.ARGBData.BinaryData
Set TempImageFile = Nothing
Unfortunately on the line that says "PixelBytes() = TempImageFile.ARGBData.BinaryData" the program generates this error:
Run-time error '-2145320838 (8021007a)':
The Vector's Type is not compatible with this operation.
What am I doing wrong? Isn't the BinaryData entry of the ARGBData vector simply a byte array that contains all of the bytes of the decoded BMP file in raw form (starting with the first byte of the first pixel, and ending with the last byte of the last pixel)?
-
Aug 22nd, 2014, 03:19 PM
#2
Re: Problem with getting raw image bytes from WIA
Why not use the GetDIBits API function?
Code:
Option Explicit
Private Type BITMAPINFOHEADER
bmSize As Long
bmWidth As Long
bmHeight As Long
bmPlanes As Integer
bmBitCount As Integer
bmCompression As Long
bmSizeImage As Long
bmXPelsPerMeter As Long
bmYPelsPerMeter As Long
bmClrUsed As Long
bmClrImportant As Long
End Type
Private Type RGBTRIPLE
rgbBlue As Byte
rgbGreen As Byte
rgbRed As Byte
End Type
Private Type BITMAPINFO
bmHeader As BITMAPINFOHEADER
bmColors(0 To 255) As RGBTRIPLE
End Type
Private Const BI_RGB As Long = 0
Private Const DIB_RGB_COLORS As Long = 0
Private Declare Function GetDIBits Lib "Gdi32.dll" (ByVal hDC 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
-
Aug 22nd, 2014, 03:58 PM
#3
Re: Problem with getting raw image bytes from WIA
You chose the wrong property. Try:
Code:
Dim PixelBytes() As Byte
With New ImageFile
.LoadFile "test.bmp"
PixelBytes = .FileData.BinaryData
End With
As the docs say:
The ARGBData property returns a Vector of Long values that contain raw ARGB bitmap data. Each Long value represents a pixel. The first value corresponds to the pixel at the upper left and proceeds to the right, then down. When organized this way, the count of Long values in the Vector will be the product of the image's width and height.
FileData property. Retrieves the raw image file as a Vector of bytes.
Last edited by dilettante; Aug 22nd, 2014 at 04:03 PM.
-
Aug 22nd, 2014, 07:39 PM
#4
Thread Starter
Frenzied Member
Re: Problem with getting raw image bytes from WIA
Originally Posted by dilettante
You chose the wrong property. Try:
Code:
Dim PixelBytes() As Byte
With New ImageFile
.LoadFile "test.bmp"
PixelBytes = .FileData.BinaryData
End With
As the docs say:
Actually what you mentioned takes the entire file data (meaning the headers and everything that would be present in the file, not just the image data, and any data that is present in there will not be retrievable if it's compressed). That's why I wanted to copy the RGBAData to a byte array, as that is what contains the raw pixel values.
I did find a way around this though. By using Set TempStdPicture = TempImageFile.FileData.Picture and then using the Windows API function GetObject on TempStdPicture (an StdPicture object), I was able to get a pointer to the raw bytes and copy the raw image bytes to a byte array with the CopyMemory API function.
Last edited by Ben321; Aug 22nd, 2014 at 07:43 PM.
-
Aug 22nd, 2014, 08:09 PM
#5
Re: Problem with getting raw image bytes from WIA
Sorry, I wasn't trying to mislead you.
I knew better too, I just wasn't paying close enough attention and I didn't verify the results.
-
Jul 25th, 2021, 08:45 PM
#6
Thread Starter
Frenzied Member
Re: Problem with getting raw image bytes from WIA
Originally Posted by dilettante
Sorry, I wasn't trying to mislead you.
I knew better too, I just wasn't paying close enough attention and I didn't verify the results.
Hey Dilettante, I know this thread is MEGA OLD, but I'm still having this problem years later (working on a new program now, the old program probably died long ago from lack of being able to solve this problem, but I don't remember because it was so long ago, but I'm still having the same issues for getting raw pixel values from WIA now), and figured I shouldn't start a new thread for something I'd previously discussed and am still having problems with. My previous solution to this problem was to simply use third party software to convert any picture I wanted to load in my program to a BMP file first, and then load it with VB6's own LoadPicture function. However, this isn't going to be good in the long run, especially if I ever release any image processing software on a commercial basis. I don't want to have to tell my customers to download 3rd party software to convert their pics to BMP before using my software to process the images. I want a way to load any common image file into my software and then expose the raw image bytes (not the file bytes, but rather the raw RGBA values of each pixel) so that I can edit it in the software. I know LoadPicture can later be used with GetDiBits to get the pixels, but that doesn't work for TIF or PNG images, and PNG images are now a common file format. LoadPicture only works with BMP, JPG, and GIF.
So Dilettante, if you have a solution to this problem now, please let me know. Thanks in advance.
-
Jul 25th, 2021, 10:32 PM
#7
Re: Problem with getting raw image bytes from WIA
WIA 2.0 does not provide an elegant solution for this. It relies strongly on its Vector class, and pixel operations for ARGB data are VERY slow using the version of WIA 2.0 provided in Windows now. You could speed that up if you have the redist version of the DLL but then you need to use Fusion manifests to redirect the process to your private assembly. That can get messy for IDE runs.
Basically too many script kiddies were using WIA 2.0 to remove DRM from video, so Microsoft crippled some things and "added molasses" elsewhere. As part of that even quite a few still-picture operations were impacted.
Instead you will probably be better off using GDI+ Flat API calls yourself. More work but that's life in the VB world where we've attracted too many miscreants.
I don't have anything on hand that loads GDI+ Bitmaps and extracts the raw "bits" in a prescribed pixel format. Maybe someone else has some code in his toolbox for this, but it's a requirement most programs don't have.
Look up GdipBitmapLockBits() and GdipBitmapUnlockBits(). I haven't used them recently myself.
-
Jul 25th, 2021, 10:52 PM
#8
Thread Starter
Frenzied Member
Re: Problem with getting raw image bytes from WIA
Originally Posted by dilettante
WIA 2.0 does not provide an elegant solution for this. It relies strongly on its Vector class, and pixel operations for ARGB data are VERY slow using the version of WIA 2.0 provided in Windows now. You could speed that up if you have the redist version of the DLL but then you need to use Fusion manifests to redirect the process to your private assembly. That can get messy for IDE runs.
Basically too many script kiddies were using WIA 2.0 to remove DRM from video, so Microsoft crippled some things and "added molasses" elsewhere. As part of that even quite a few still-picture operations were impacted.
Instead you will probably be better off using GDI+ Flat API calls yourself. More work but that's life in the VB world where we've attracted too many miscreants.
I don't have anything on hand that loads GDI+ Bitmaps and extracts the raw "bits" in a prescribed pixel format. Maybe someone else has some code in his toolbox for this, but it's a requirement most programs don't have.
Look up GdipBitmapLockBits() and GdipBitmapUnlockBits(). I haven't used them recently myself.
How was it possibly used to remove DRM from video? WIA ActiveX DLL (as used in VB6) can only process still pictures, not video files (for that you need to use 3rd party software like FFMPEG). Also, if the current version of the WIA 2.0 AX DLL has some restrictions, why do you need to use special assemblies? Why not just install the old WIA 2.0 SDK and overwrite the current version of the WIA 2.0 AX DLL with the old version (rollback to the previous version)? Also, what exactly did MS modify in the WIA 2.0 AX DLL?
-
Jul 25th, 2021, 11:14 PM
#9
Thread Starter
Frenzied Member
Re: Problem with getting raw image bytes from WIA
Also, by the way, I figured out a way to use GetDIBits and SetDIBits with Vector.Picture function which returns a StdPicture object, as this contains a Handle property which is just the bitmap handle (or possibly a DIB handle) to the actual GDI image stored in it. I can use the GetDIBits function then to extract the pixel data to an array of Longs, and likewise take that array of Longs and display it on a VB6 form with the SetDIBits function. Below is code that when loading the form loads any WIA 2.0 supported image file, gets the pixel data (converted to 8-bits-per-channel so you lose extra bitdepth for 16-bits-per-channel TIF or PNG images unfortunately) and then resizes it so it is stretched to fit the dimensions of the VB6 form, and then displays it. Note this is performed only once, when the form loads, so if you resize the form the image doesn't re-stretch to fit the new size of the form. For best results, make sure your form's AutoRedraw property is set to True.
Code:
Private Declare Function GetDIBits Lib "gdi32.dll" (ByVal hDC 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 SetDIBits Lib "gdi32.dll" (ByVal hDC 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 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 Sub Form_Load()
Dim ImgFile As ImageFile
Dim Vec As Vector
Dim Pix() As Long
Dim Pix2() As Long
Dim PicW As Long
Dim PicH As Long
Dim PicW2 As Long
Dim PicH2 As Long
Dim BMIH As BITMAPINFOHEADER
Dim x As Long
Dim y As Long
Set ImgFile = New ImageFile
ImgFile.LoadFile Picture_Filename_String_Goes_Here
PicW = ImgFile.Width
PicH = ImgFile.Height
With BMIH
.biSize = 40
.biPlanes = 1
.biBitCount = 32
.biWidth = PicW
.biHeight = -PicH
End With
ReDim Pix(PicW - 1, PicH - 1)
GetDIBits hDC, ImgFile.ARGBData.Picture(PicW, PicH).Handle, 0, PicH, Pix(0, 0), BMIH, 0
PicW2 = ScaleWidth
PicH2 = ScaleHeight
ReDim Pix2(PicW2 - 1, PicH2 - 1)
For y = 0 To PicH2 - 1
For x = 0 To PicW2 - 1
Pix2(x, y) = Pix(x / (PicW2 - 1) * (PicW - 1), y / (PicH2 - 1) * (PicH - 1))
Next x
Next y
With BMIH
.biWidth = PicW2
.biHeight = -PicH2
End With
SetDIBits hDC, Image.Handle, 0, PicH2, Pix2(0, 0), BMIH, 0
End Sub
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
|