Seite 1 von 1

Bitmap vergleichen

Verfasst: Do, 29. Sep 2016 12:30
von Rudolf
Hallo,
ich muss ein Bitmap mit Unterschrift untersuchen ob etwas drinsteht. Wenn keine Unterschrift erfasst wurde, steht nur eine Überschrift im Bitmap, sonst die Strokes von der Schrift. Ich denke am einfachsten wäre in der Mitte von links nach rechts durchschauen ob ein Pixel gesetzt wurde. Hat jemand eine Idee wie sowas gehen könnte oder einen anderen Vorschlag ? Habe auch versucht die chr(255) zu zählen, also Leerstellen, geht nicht da immer die selbe Anzahl zurückkommt. Die Länge vom Image Buffer ist bei beiden immer 6531950 Bytes und die Anzahl der chr(255) immer 6531949 Bytes, obwohl in einem Bitmap eine Unterschrift enthalten ist.
Grüße
Rudolf

Re: Bitmap vergleichen

Verfasst: Do, 29. Sep 2016 12:39
von brandelh
Ich meine man kann die Farbe eines Pixels abfragen, allerdings finde ich eben weder in XbpBitmap() noch bei den Gra-Funktionen das passende. (war wohl in B4A)

Wenn es eine BMP ist, kannst du aber die Bytes direkt prüfen (offset auf die Überschrift) schau dir mal eine leere BMP im HEX-Editor an.

Re: Bitmap vergleichen

Verfasst: Do, 29. Sep 2016 12:44
von Rudolf
Hallo Hubert,
habe den Buffer schon durchsucht, aber mir ist der Aufbau eines Bitmaps nicht geläufig. Ich dachte eben dass die chr(255) leere Pixel bedeuten und wenn ich diese zähle kann ich vergleichen. Ich befürchte auch dass das Durchsuchen relativ langsam ist, alleine numat() zum zählen dauert schon relativ lange, zumindest im Debugger. Wenn ich also eine Zeile direkt auslesen könnte wäre ich sicher am schnellsten. Werde mal den Bitmap Aufbau googeln, vielleicht finde ich etwas.
Grüße
Rudolf

Re: Bitmap vergleichen

Verfasst: Do, 29. Sep 2016 13:09
von brandelh
was ganz anderes, woher kommt diese Bitmap ?
Wenn du die erzeugst, kannst ja den String mit dem Inhalt (ohne Header) mit dem neuen String vergleichen # hat sich was geändert.
Ob das dann tatsächlich eine Unterschrift ist, kannste eh nicht ermitteln.
In der Windows API gibt es GetPixel() ... braucht aber einen Device Context.

Re: Bitmap vergleichen

Verfasst: Do, 29. Sep 2016 14:04
von Rudolf
Hallo Hubert,
habe bei Roger ein Beispiel in PixelColor über GDI gefunden, nur wird hier mit nDC := GetWindowDC(o:getHWnd()) gearbeitet. Müsste nur rausfinden wie ich das mit meinem Bitmap im Buffer machen könnte, Anzeigen geht nicht, würde im Ablauf stören.
Grüße
Rudolf

Code: Alles auswählen

#command  GDIFUNCTION <Func>([<x,...>]) ;
       => ;
FUNCTION <Func>([<x>]);;
STATIC scHCall := nil ;;
IF scHCall == nil ;;
  IF snHdll == nil ;;
    snHDll := DllLoad('GDI32.DLL') ;;
  ENDIF ;;
  scHCall := DllPrepareCall(snHDll,DLL_STDCALL,<(Func)>) ;;
ENDIF ;;
RETURN DllExecuteCall(scHCall,<x>)

GDIFUNCTION GetPixel( nHDC, x, y)
GDIFUNCTION SetPixel( nHDC, x, y, n )
DLLFUNCTION GetWindowDC( hwnd ) USING STDCALL FROM USER32.DLL

Re: Bitmap vergleichen

Verfasst: Do, 29. Sep 2016 17:15
von brandelh
Ein Fenster MUSS ja NICHT sichtbar sein ;-)
Aber schau mal nach ob XbpBitmap nicht auch ein Windowshandle hat bzw. die zugeordnete Presentationspace ...

Re: Bitmap vergleichen

Verfasst: Do, 29. Sep 2016 19:21
von AUGE_OHR
du erzeugst doch zuerst ein Bitmap wo nur : "Unterschrift XY" steht -> abspeichern
wenn eine Unterschrift getätigt wurde ( oder auch nicht ) -> abspeichern.

nun kannst du einfach die Grösse vergleichen.

Re: Bitmap vergleichen

Verfasst: Do, 29. Sep 2016 19:57
von Rudolf
Hallo, ich habs, muss nur noch den Dialog unterdrücken, mit HIDE funktioniert es nicht, werde versuchen das Fenster außerhalb des Bildschirms zu platzieren. Wenn ich eine Zeile vergleiche geht es schnell und reicht völlig.
Grüße
Rudolf

Code: Alles auswählen

#INCLUDE "dll.CH"
#INCLUDE "dcdialog.CH"

#define CRLF  chr(13) + CHR(10)
STATIC snHdll

FUNCTION Main()
******************************************************************
LOCAL GetList[0], GetOptions, oSay, hDC1, oStatic1, aPixel, oDlg

@ 0,0 DCSTATIC TYPE XBPSTATIC_TYPE_BITMAP CAPTION "unterschrift1.bmp" OBJECT oStatic1 PREEVAL {|o|o:autoSize := .t.} ;
     EVAL {|o|hDC1 := GetWindowDC(o:getHWnd()),aPixel := Array(o:caption:xSize,o:caption:ySize)}

DCGETOPTIONS PIXEL

DCREAD GUI FIT OPTIONS GetOptions EVAL {||dc_guimemoedit(testpixel(hDC1,aPixel,oStatic1,oSay))} PARENT @oDlg
oDlg:destroy()

RETURN nil

* ---------


FUNCTION testpixel(hDC,aPixel,oStatic)
******************************************************************
LOCAL i, j, nXSize := Len(aPixel), nYSize := Len(aPixel[1]),cCheck := "",nFilled := 0,oScrn,nFail := 0,nTotal := 0,aColor,nColor,nStartRow ,nEndRow,cResponse := "",nStartCol,nEndCol,cImg := "",cChar := " "
oScrn := DC_WaitOn()

nStartRow := 1 //int(nYSize/2) //only one row for testing
nEndRow   := nYSize//int(nYSize/2)+1

nStartCol := 0
nEndCol   := nXSize

FOR i := nStartCol TO nEndCol
  FOR j := nStartRow to nEndRow
     cChar := " "
     nColor := GetPixel(hDC,i-1,j-1)
     if !empty(nColor)
          aColor := GraGetRGBIntensity(AutomationTranslateColor(nColor,.T.))
          if valtype(aColor) = "A"
               if aColor[1] # 255 .or. aColor[2] # 255 .or. aColor[3] # 255
                    nFilled++
                    cChar := "*"
               endif
          else
               cChar := "?"
               nFail++
               cResponse += ntrim(i) + " - " + ntrim(j) + " " + ntrim(nColor) + CRLF
          endif
          nTotal++
     else
          cChar := "-"
     endif
     cImg += cChar
  NEXT
  cImg += CRLF
NEXT
dc_impl(oScrn)
cResponse := "Size:" + ntrim(nXSize) + "x" + ntrim(nYSize) + CRLF + "Total:" + ntrim(nTotal) + CRLF + "Fail:" + ntrim(nFail) + CRLF + "Filled:" + ntrim(nFilled) + CRLF + cImg
return cResponse


function ntrim(n)
******************************************************************

return rtrim(ltrim(str(n,10,0)))



* ---------

PROC appsys ; RETURN

* ---------


#command  GDIFUNCTION <Func>([<x,...>]) ;
       => ;
FUNCTION <Func>([<x>]);;
STATIC scHCall := nil ;;
IF scHCall == nil ;;
  IF snHdll == nil ;;
    snHDll := DllLoad('GDI32.DLL') ;;
  ENDIF ;;
  scHCall := DllPrepareCall(snHDll,DLL_STDCALL,<(Func)>) ;;
ENDIF ;;
RETURN DllExecuteCall(scHCall,<x>)

GDIFUNCTION GetPixel( nHDC, x, y)
GDIFUNCTION SetPixel( nHDC, x, y, n )
DLLFUNCTION GetWindowDC( hwnd ) USING STDCALL FROM USER32.DLL

Re: Bitmap vergleichen

Verfasst: Fr, 30. Sep 2016 10:20
von brandelh
Hallo,

schau mal das hier funktioniert auch ;-)

Code: Alles auswählen

PROCEDURE Main
   LOCAL sOrg, sNew

   sOrg := memoread( "253_ht_unterschrift.bmp" )
   sNew := memoread( "253_ht_unterschrift-UT.bmp" )

   IF sOrg == sNew
      msgbox("Dateien sind gleich !")
   ELSE
      msgbox("Dateien sind unterschiedlich !")
   ENDIF

RETURN
Falls das schon im RAM (XbpBitmap()) ist, kann man auch die Strings direkt vergleichen :

XbpBitmap:setBuffer()

Der Vergleich ist viel schneller als Pixelweise auslesen.

Re: Bitmap vergleichen

Verfasst: Fr, 30. Sep 2016 10:47
von Rudolf
Hallo Hubert,
Wenn das Feld ohne Unterschrift komplett leer wäre dann wäre es viel einfacher, ist es aber nicht, ist leider ein wenig komplizierter. Ich schneide die Bitmaps automatisiert aus PDFs aus wo sie auch unterschiedliche Labels oder andere Texte enthalten können. Jedes Formular kann anders sein. Ich habe nur die Position und Größe vom Unterschriften Feld. Es können auch Pixel vom Rand der um das Feld gezeichnet wird dabei sein da die Position und Größe nicht exakt stimmen. Jetzt nehme ich einfach eine Zeile aus der Mitte raus und prüfe auf Pixel, zur Sicherheit schneide ich noch 10 Pixel vom rechten und linken Rand weg, dann wird es noch genauer. Das geht sehr schnell da nur eine Pixel Zeile geprüft wird und ist sehr zuverlässig.
Grüße
Rudolf