Jump to content

Convert pixel data to byte, best strategy ?


Myicq
 Share

Recommended Posts

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.

Link to comment
Share on other sites

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
Link to comment
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.

Link to comment
Share on other sites

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.

Link to comment
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.

Link to comment
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.

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...