Das Forentreffen 2018 findet am 20./21. April in Dresden statt. Weitere Infos hier
Zur Homepage des Deutschsprachige Xbase-Entwickler e. V.
Xbase++-Wiki des Deutschsprachige Xbase-Entwickler e. V.

Bitmap vergleichen

Grafische Primitive, XbaseParts und Darstellungsfragen allgemein.

Moderator: Moderatoren

Antworten
Benutzeravatar
Rudolf
Programmier-Gott
Programmier-Gott
Beiträge: 1304
Registriert: Mo, 02. Jan 2006 23:03
Wohnort: Salzburg/Österreich
Kontaktdaten:

Bitmap vergleichen

Beitrag von Rudolf » Do, 29. Sep 2016 12:30

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
Dateianhänge

[Die Dateierweiterung bmp wurde deaktiviert und kann nicht länger angezeigt werden.]

[Die Dateierweiterung bmp wurde deaktiviert und kann nicht länger angezeigt werden.]


Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 13768
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Kontaktdaten:

Re: Bitmap vergleichen

Beitrag von brandelh » Do, 29. Sep 2016 12:39

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.
Gruß
Hubert

Benutzeravatar
Rudolf
Programmier-Gott
Programmier-Gott
Beiträge: 1304
Registriert: Mo, 02. Jan 2006 23:03
Wohnort: Salzburg/Österreich
Kontaktdaten:

Re: Bitmap vergleichen

Beitrag von Rudolf » Do, 29. Sep 2016 12:44

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

Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 13768
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Kontaktdaten:

Re: Bitmap vergleichen

Beitrag von brandelh » Do, 29. Sep 2016 13:09

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.
Gruß
Hubert

Benutzeravatar
Rudolf
Programmier-Gott
Programmier-Gott
Beiträge: 1304
Registriert: Mo, 02. Jan 2006 23:03
Wohnort: Salzburg/Österreich
Kontaktdaten:

Re: Bitmap vergleichen

Beitrag von Rudolf » Do, 29. Sep 2016 14:04

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

Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 13768
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Kontaktdaten:

Re: Bitmap vergleichen

Beitrag von brandelh » Do, 29. Sep 2016 17:15

Ein Fenster MUSS ja NICHT sichtbar sein ;-)
Aber schau mal nach ob XbpBitmap nicht auch ein Windowshandle hat bzw. die zugeordnete Presentationspace ...
Gruß
Hubert

Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 10579
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg

Re: Bitmap vergleichen

Beitrag von AUGE_OHR » Do, 29. Sep 2016 19:21

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.
gruss by OHR
Jimmy

Benutzeravatar
Rudolf
Programmier-Gott
Programmier-Gott
Beiträge: 1304
Registriert: Mo, 02. Jan 2006 23:03
Wohnort: Salzburg/Österreich
Kontaktdaten:

Re: Bitmap vergleichen

Beitrag von Rudolf » Do, 29. Sep 2016 19:57

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

Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 13768
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Kontaktdaten:

Re: Bitmap vergleichen

Beitrag von brandelh » Fr, 30. Sep 2016 10:20

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.
Gruß
Hubert

Benutzeravatar
Rudolf
Programmier-Gott
Programmier-Gott
Beiträge: 1304
Registriert: Mo, 02. Jan 2006 23:03
Wohnort: Salzburg/Österreich
Kontaktdaten:

Re: Bitmap vergleichen

Beitrag von Rudolf » Fr, 30. Sep 2016 10:47

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

Antworten