Results 1 to 9 of 9

Thread: Problem with getting raw image bytes from WIA

  1. #1

    Thread Starter
    Frenzied Member
    Join Date
    Oct 2008
    Posts
    1,058

    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)?

  2. #2
    Frenzied Member
    Join Date
    Feb 2003
    Posts
    1,395

    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

  3. #3
    PowerPoster
    Join Date
    Feb 2006
    Posts
    22,751

    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.

  4. #4

    Thread Starter
    Frenzied Member
    Join Date
    Oct 2008
    Posts
    1,058

    Re: Problem with getting raw image bytes from WIA

    Quote Originally Posted by dilettante View Post
    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.

  5. #5
    PowerPoster
    Join Date
    Feb 2006
    Posts
    22,751

    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.

  6. #6

    Thread Starter
    Frenzied Member
    Join Date
    Oct 2008
    Posts
    1,058

    Re: Problem with getting raw image bytes from WIA

    Quote Originally Posted by dilettante View Post
    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.

  7. #7
    PowerPoster
    Join Date
    Feb 2006
    Posts
    22,751

    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.

  8. #8

    Thread Starter
    Frenzied Member
    Join Date
    Oct 2008
    Posts
    1,058

    Re: Problem with getting raw image bytes from WIA

    Quote Originally Posted by dilettante View Post
    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?

  9. #9

    Thread Starter
    Frenzied Member
    Join Date
    Oct 2008
    Posts
    1,058

    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
  •  



Click Here to Expand Forum to Full Width