Sign in to follow this  
Followers 0
Myicq

Convert pixel data to byte, best strategy ?

6 posts in this topic

#1 ·  Posted (edited)

I have an (binary B/W) image that I need to convert to a more compact format.

The principle is as follows:

  • Image is always an integer of 32 pixel both X and Y. Other sizes will be padded. That part is simple.
  • Only 2 colors, always BMP source

What I would like to do is to read the image pixel data from upper left to lower right, each time 8 pixel. The pixel data will be bits in each byte, so that the bottom pixel is highest bit value. 

Example, for the lower right corner:

........o
........o
........o
........o
........o
........o
........X
........X

In the example, there is 2 pixel black of 8. The white ones symbolized by "o". This means that the reading would be from start

11000000  (binary)  ==> 0xC0 in final file.

My thoughts so far:

I could probably read each pixel value and add bits. But I fear it would be a slow process. Another strategy I could think of is to convert to pbm P1 format, and make an array of 0 and 1. Thereby simply getting binary strings.

If anyone have ideas, I would be more than happy to receive them.

Edited by Myicq

I am just a hobby programmer, and nothing great to publish right now.

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

I could probably read each pixel value and add bits. But I fear it would be a slow process.

Well, I'm no expert, but it looks like using >this might help you out with any slowness. Particularly this bit;

 

- For even more performance, you can capture the content of a screen memory (SnapShot, takes about the same time as or PixelSearch PixelGetColor) then do all the research you want in this snapshots (very fast functions : nearly 1000 times as fast as the native PixelGetColor).

Edited by TheBytemaster

Share this post


Link to post
Share on other sites

Well, I'm no expert, but it looks like using >this might help you out with any slowness. Particularly this bit;

 

Isn't this for working with images from screen ? I don't want to take images from screen, or even display them. I have some files on a drive, made with a graphis software like PhotoShop. 

But I will look over the resource anyway. Thanks


I am just a hobby programmer, and nothing great to publish right now.

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

I have made a test where I read each pixel, but it's painfully slow.

    ; Initialize GDI+ library
    _GDIPlus_Startup()

      ; Load screen capture bitmap from file
    $hImage = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\template.bmp")

    ; get size
    $iH = _GDIPlus_ImageGetHeight($hImage)
    $iW = _GDIPlus_ImageGetWidth($hImage)
    MemoWrite("Height of image : " & $iH )
    MemoWrite("Width: " & $iW )
    ; not sure how to get from hImage to hBitmap.. so do this instead.
    ; takes around .22 msec to create from file.
    $hBitmap = _GDIPlus_BitmapCreateFromFile(@ScriptDir & "\template.bmp")
    ; this is the slow part.
    $t = TimerInit()
    for $myCol = 0 to $iW-1
            for $myRow = 0 to $iH -1
                    $pixcol = _GDIPlus_BitmapGetPixel($hBitmap, $myCol, $myRow)
            Next
    Next
    memowrite ("Width = " & $iw & " x Height = " & $iH & " took " & TimerDiff($t) & " msec")
 

A picture of 32x32 pixel takes 14 msec. This is ok. But an image sized 1152x3680 takes over 60 seconds.

The original program I would like to mimic uses scanlines. But I don't know how to work with these.

Edit: attached template with sample image 1152 x 3680

 

template.zip

Edited by Myicq

I am just a hobby programmer, and nothing great to publish right now.

Share this post


Link to post
Share on other sites

I have something what works, a modified example from help file.

But is this the fastest way to get pixel values ?

My template from before is now read in around 11-13 seconds, compared to 60 seconds with getPixel(x,y)

 
#include <Constants.au3>
#include <GUIConstantsEx.au3>
#include <GDIPlus.au3>

Example()
 
 
 
Func Example()
    Local $sFile = @ScriptDir & "\template.bmp"
 
    _GDIPlus_Startup()
    Local $hImage = _GDIPlus_ImageLoadFromFile($sFile) ;create an image object based on a file

    Local $iW = _GDIPlus_ImageGetWidth($hImage), $iH = _GDIPlus_ImageGetHeight($hImage) ;get width and height of the image

    ; what is difference between bitmap and image ?
    Local $hBitmap = _GDIPlus_BitmapCreateFromFile($sFile)

    Local $tBitmapData = _GDIPlus_BitmapLockBits($hBitmap, 0, 0, $iW, $iH, $GDIP_ILMREAD, $GDIP_PXF32ARGB)
    Local $iScan0 = DllStructGetData($tBitmapData, "Scan0") ;get scan0 (pixel data) from locked bitmap

    ; the struct must match the format of pixel data...
    Local $tPixel = DllStructCreate("int[" & $iW * $iH & "];", $iScan0)

    Local $iPixel, $iRowOffset
    Local $out = ""

    $t = TimerInit()
 
    ; this should be 4 x (w * H) because we use int[ ] = 32 bit.
    ConsoleWrite("Struct size " & DllStructGetSize($tPixel) & @LF)
    ; ============================================================================
    ; Read vertically...
    ; go over each column
    For $myColumn = 1 To $iH

        ; then for each row
        For $myRow = 1 To $iW
            ; index starts at 1
            ; pixel at col 1, row 2 is at 1 + iW
            $pixelIndex = ($myRow - 1) * $iW + $myColumn
;~             ConsoleWrite("col =" & $myColumn & ", row = " & $myrow & " : " & $pixelIndex & @LF)
            ; USE: DllStructGetData ( Struct, Element [, index = Default]

            $iPixel = DllStructGetData($tPixel, 1, $pixelIndex) ;get pixel color
            $out &=hex($iPixel)& @CRLF
        Next
    Next

    ConsoleWrite("Reading vertically ==> " & TimerDiff($t) & @LF)


;~     $out2 = ""
;~     For $iY = 0 To $iH - 1
;~         $iRowOffset = $iY * $iW + 1
;~         For $iX = 0 To $iW - 1 ;get each pixel in each line and row
;~              ConsoleWrite("Rowoffset : " & $iRowOffset & " iY: " & $iY & " iX" & $iX & " i: " & $iRowOffset + $iX & @LF)
;~             $iPixel = DllStructGetData($tPixel, 1, $iRowOffset + $iX) ;get pixel color
;~             $out2 &= $iPixel & @CRLF
;~         Next
;~     Next

;~     ConsoleWrite("Reading horizontally ==> " & TimerDiff($t) & @LF)


    _GDIPlus_BitmapUnlockBits($hBitmap, $tBitmapData) ;unlocks a portion of a bitmap that was locked by _GDIPlus_BitmapLockBits
    FileDelete(@ScriptDir & "\pixels.txt")
    FileWrite(@ScriptDir & "\pixels.txt", $out)
;~     FileDelete(@ScriptDir & "\pixels2.txt")
;~     FileWrite(@ScriptDir & "\pixels2.txt", $out2)


    ;cleanup resources
    _GDIPlus_ImageDispose($hImage)
;~     _GDIPlus_GraphicsDispose($hContext)
    _GDIPlus_BitmapDispose($hBitmap)
;~     _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_Shutdown()
;~     GUIDelete($hGUI)
EndFunc   ;==>Example
 
 

I am just a hobby programmer, and nothing great to publish right now.

Share this post


Link to post
Share on other sites

Isn't this for working with images from screen ? I don't want to take images from screen, or even display them. I have some files on a drive, made with a graphis software like PhotoShop. 

But I will look over the resource anyway. Thanks

Er. Derp, I misread what you had said in the OP. My bad.  :sweating:

I was hoping that I would find a way to load bitmaps into memory for use with that library, but so far I can't see anything like that.

I'm actually working on a script that will deal with a very complicated and time-sensitive array of screenshots over time, processing a bit from each screen in memory and combining them into one image, so I'll likely be looking around in that wrapper quite a bit. I'll let you know if I come across a solution to your problem.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0