Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Barcode aus Bild auslesen (https://www.delphipraxis.net/160487-barcode-aus-bild-auslesen.html)

DSCHUCH 15. Mai 2011 19:41

Barcode aus Bild auslesen
 
Hallo,

kennt jemand eine Komponenten, mit der man aus einem Bild Barcodes auslesen kann? Derzeit verwenden wir BarcodeReader als Active-X, funktioniert eigentlich gut und ich habe auch nichts anderes gefunden, aber vielleicht auch etwas übersehen.

http://www.imagesinfo.com/products/barcode-reader/

Schönen Abend.

Sir Rufo 15. Mai 2011 21:17

AW: Barcode aus Bild auslesen
 
Da gäbe es noch http://www.qualitysoft.de/

DSCHUCH 16. Mai 2011 08:35

AW: Barcode aus Bild auslesen
 
sehr gut, sogar deutsch. ^^

Andreas Schilling 16. Mai 2011 09:10

AW: Barcode aus Bild auslesen
 
Wir arbeiten damit.
http://www.java4less.com/barcodedelp...odesdelphi.php

Coffeecoder 16. Mai 2011 09:14

AW: Barcode aus Bild auslesen
 
Zitat:

Zitat von Andreas Schilling (Beitrag 1101034)

Sieht sehr interessant aus :)

Mfg Coffeecoder

generic 16. Mai 2011 12:26

AW: Barcode aus Bild auslesen
 
Zitat:

Zitat von Andreas Schilling (Beitrag 1101034)

Das erzeugt nur Barcodes - Erkennung kann ich dort nicht finden.

Andreas Schilling 16. Mai 2011 12:35

AW: Barcode aus Bild auslesen
 
Stimmt, aber der Anbieter war schon richtig. Ich hatte auf die Schnelle den ersten Link ausgewählt wo das Wort Barcode drinnen vorkam. Hier also der richtige Link.
http://www.java4less.com/vision/vision.php

squetk 16. Mai 2011 14:06

AW: Barcode aus Bild auslesen
 
Eine Open Source Variante wäre unter
http://zbar.sourceforge.net/index.html zu finden.
Ist zwar keine Delphi-Komponente, steuern wir aber mit Delphi.

himitsu 29. Jun 2011 14:40

AW: Barcode aus Bild auslesen
 
@qsquetk: Wie macht ihr das denn?

Ich hab's ja schon geschafft die ZBar-DLL anzusprechen, aber die Ergebnisse lassen zu Wünschen übrig.
Von 6 ausreichend guten Strichcodes auf einem eingescannten A4 Bild (~1600x2300 Pixelchen) werden nur 1 bis 5 erkannt + ein paar "nichtexistierende" Codes :lol:
Und das auch erst, wenn ich das Bild in kleineren Schritten um bis zu 90° drehe.
(die Nichtexistierende kann man bestimmt/vermutlich noch über dernen "Quallitätsangabe" rausfiltern)

Deren vorkompilierte EXE erkennt aber wesentlich mehr und zuverlässiger nur das, was auch drauf ist.
Auch ohne das Bild zu drehen und einfach nur wagerecht+senkrecht zu scannen.


[add]Achtung, das ist der nichtfunktionierende Code ... der Richtige wurde später gepostet :zwinker:[/add]
Delphi-Quellcode:
bmp := TBitmap.Create;
bmp.PixelFormat := pf8bit;
try
  bmp.Width := Source.Width;
  bmp.Height := Source.Height;
  bmp.Canvas.Draw(0, 0, Source);
  bmp.Width := (bmp.Width + 3) and not 3; // damit die Scannlines direkt aneinander liegen und alles zusammen übergeben werden kann
  bytesPerLine := (bmp.Width + 3) and not 3;
  p := bmp.ScanLine[bmp.Height - 1]; // die Bildzeilen gehen von unten nach oben
//for i := (bytesPerLine * bmp.Height) - 1 downto 0 do
//  if p[i] > 200 then p[i] := 255 else p[i] := 0;
  scanner := zbar_image_scanner_create;
  image := zbar_image_create;
  try
    zbar_image_set_format(image, 'Y800');
    zbar_image_set_size(image, bmp.Width, bmp.Height);
    zbar_image_set_data(image, p, bmp.Height * bytesPerLine, nil);

    // Disable all symbologies?
    zbar_image_scanner_set_config(scanner, ZBAR_NONE, ZBAR_CFG_ENABLE, 0);

    // Set the resolution of the scanner to 4 pixels.  Helps with skewed and poor quality bar codes.
    stat := zbar_image_scanner_set_config(scanner, ZBAR_NONE, ZBAR_CFG_X_DENSITY, Density);
    if stat <> 0 then raise Exception.Create('set config failed');

    stat := zbar_image_scanner_set_config(scanner, ZBAR_NONE, ZBAR_CFG_Y_DENSITY, Density);
    if stat <> 0 then raise Exception.Create('set config failed');

    for stype in BarType do begin
      // Enable the requested symbology
      stat := zbar_image_scanner_set_config(scanner, stype, ZBAR_CFG_ENABLE, 1);
      if stat <> 0 then raise Exception.Create('set config failed');

      // Enable the use of a check digit is requested
      if CheckDigit then
        zbar_image_scanner_set_config(scanner, stype, ZBAR_CFG_ADD_CHECK, 1);
    end;

    //
    count := zbar_scan_image(scanner, image);
    if count > 0 then begin
      symbol := zbar_image_first_symbol(image);
      while Assigned(symbol) do begin
        if AddBarType then
          Codes.Add(zbar_get_symbol_name(zbar_symbol_get_type(symbol)) + Codes.NameValueSeparator + zbar_symbol_get_data(symbol))
        else
          Codes.Add(zbar_symbol_get_data(symbol));

        // für's Debuggen markieren, was wo gefunden wurde
        SetLength(points, zbar_symbol_get_loc_size(symbol));
        if points <> nil then begin
          for i := 0 to Length(points) - 1 do begin
            points[i].X := zbar_symbol_get_loc_x(symbol, i);
            points[i].Y := bmp.Height - zbar_symbol_get_loc_y(symbol, i) - 1;
          end;
          bmp.Canvas.Brush.Style := bsDiagCross;
          bmp.Canvas.Brush.Color := clFuchsia;
          bmp.Canvas.Pen.Color := clFuchsia;
          bmp.Canvas.Pen.Width := 1;
          bmp.Canvas.Polyline(points);
          bmp.Canvas.Pen.Width := 4;
          bmp.Canvas.Ellipse(points[0].X - 15, points[0].Y - 15, points[0].X + 16, points[0].Y + 16);
          bmp.Canvas.Brush.Style := bsClear;
          bmp.Canvas.Font.Color := clRed;
          bmp.Canvas.Font.Size := 20;
          bmp.Canvas.TextOut(points[0].X + 14, points[0].Y + 14, zbar_symbol_get_data(symbol));
        end;

        symbol := zbar_symbol_next(symbol);
      end;
    end;

    // ebenfalls für's Debuggen
    bmp.SaveToFile(...);
  finally
    zbar_image_destroy(image);
    zbar_image_scanner_destroy(scanner);
  end;
finally
  bmp.Free;
end;

Die DLL wäre ja eigentlich recht schön, aber aktuell bin ich eher der Meinung, da es besser ist, wenn ich deren EXE aufrufe und dessen Ausgabe auslese. :?

himitsu 30. Jun 2011 13:21

AW: Barcode aus Bild auslesen
 
Liste der Anhänge anzeigen (Anzahl: 3)
So, hat mich etwas nerven gekostet, aber jetzt geht's :firejump:

Delphi-Quellcode:
uses
  ZBar;

type
  TZbarSymbolTypes = set of zbar_symbol_type_e;

procedure ReadBarcode(Codes: TStrings; Source: TGraphic; AddBarType: Boolean = False;
  BarTypes: TZbarSymbolTypes = []; CheckDigit: Boolean = True; Density: Integer = 1);
var
  bmp: TBitmap;
  bytesPerLine, count, i: Integer;
  p, pg: PByte;
//processor: zbar_processor_t;
  scanner: zbar_image_scanner_t;
  image: zbar_image_t;
  stype: zbar_symbol_type_e;
  symbol: zbar_symbol_t;
  symboltype: zbar_symbol_type_t;
begin
  if BarTypes = [] then BarTypes := [ZBAR_EAN8, ZBAR_UPCE, ZBAR_ISBN10, ZBAR_UPCA, ZBAR_EAN13, ZBAR_ISBN13, ZBAR_I25, ZBAR_CODE39, ZBAR_CODE128];

  bmp := TBitmap.Create;
  bmp.PixelFormat := pf32bit;;
  try
    bmp.Width := Source.Width;
    bmp.Height := Source.Height;
    bmp.Canvas.Draw(0, 0, Source);

  //processor := zbar_processor_create(0);
  //Assert(Assigned(processor), 'zbar-processor');
  //try
  //  if zbar_processor_init(processor, nil, Ord(False)) <> 0 then begin
  //    zbar_processor_error_spew(processor, 0);
  //    Assert(False, 'zbar-processor_init');
  //  end;
  //  zbar_processor_set_visible(processor, 0);

      scanner := zbar_image_scanner_create;
      Assert(Assigned(scanner), 'zbar-scanner');
      try
        zbar_image_scanner_set_config(scanner, ZBAR_NONE, ZBAR_CFG_ENABLE, 0);

        i := zbar_image_scanner_set_config(scanner, ZBAR_NONE, ZBAR_CFG_X_DENSITY, Density);
        Assert(i = 0, 'zbar-set_config');

        i := zbar_image_scanner_set_config(scanner, ZBAR_NONE, ZBAR_CFG_Y_DENSITY, Density);
        Assert(i = 0, 'zbar-set_config');

        for stype in BarTypes do begin
          i := zbar_image_scanner_set_config(scanner, stype, ZBAR_CFG_ENABLE, 1);
          Assert(i = 0, 'zbar-set_config');

          if CheckDigit then
            zbar_image_scanner_set_config(scanner, stype, ZBAR_CFG_ADD_CHECK, 1);
        end;

        image := zbar_image_create;
        Assert(Assigned(image), 'zbar-image');
        try
          bytesPerLine := bmp.Width;
          p := bmp.ScanLine[bmp.Height - 1]; // die Bildzeilen gehen von unten nach oben
          pg := GetMemory(bmp.Height * bytesPerLine);
          try
            for i := bmp.Height * bytesPerLine downto 0 do
              pg[i] := Round(p[i*4]*0.3 + p[i*4+1]*0.59 + p[i*4+2]*0.11);

            zbar_image_set_format(image, 'Y800');
            zbar_image_set_size(image, bmp.Width, bmp.Height);
            zbar_image_set_data(image, pg, bmp.Height * bytesPerLine, nil);

            count := zbar_scan_image(scanner, image);
          //zbar_process_image(processor, image); count := 1;
          finally
            FreeMemory(pg);
          end;

          if count > 0 then begin
            symbol := zbar_image_first_symbol(image);
            while Assigned(symbol) do begin
              symboltype := zbar_symbol_get_type(symbol);
              if AddBarType then
                Codes.Add(String(AnsiString(zbar_get_symbol_name(symboltype)) + AnsiString(zbar_get_addon_name(symboltype)))
                  + Codes.NameValueSeparator + String(AnsiString(zbar_symbol_get_data(symbol))))
              else
                Codes.Add(String(AnsiString(zbar_symbol_get_data(symbol))));

              symbol := zbar_symbol_next(symbol);
            end;
          end;
        finally
          zbar_image_destroy(image);
        end;
      finally
        zbar_image_scanner_destroy(scanner);
      end;
  //finally
  //  zbar_processor_destroy(processor);
  //end;
  finally
    bmp.Free;
  end;
end;
Wer schräge Barcodes einscännen will/muß, der braucht einfach nur das Bild zu drehen, denn die ZBar-Barcode-Komponente scännt nur in 90°-Winkeln (wagerecht und senkrecht).
z.B. von 0° bis <90° in 10°-Schritten
oder einfach nur noch einmal 45°
oder 0°, 22°, 45° und 68°

Da könnte man z.B. direkt in den Block nach
Delphi-Quellcode:
image := zbar_image_create;
eine entsprechende Schleife einbauen.
Eventuell dann auch noch die StringListe mit .Sort:=True und .Duplicates:=dupIgnore .

Delphi-Quellcode:
procedure RotateBitmap(Dest, Source: TBitmap; Winkel: Double; Hintergrund: TColor = clWhite; GroesseAnpassen: Boolean = True);
type
//TArray = array[0..0] of Byte; {pf8bit}
//TArray = array[0..0] of array[0..1] of Byte; {pf16bit}
//TArray = array[0..0] of array[0..2] of Byte; {pf24bit}
  TArray = array[0..0] of array[0..3] of Byte; {pf32bit}
  PArray = ^TArray;
var
  rw: Boolean;
  CT, ST: Double;
  I, J, X, Y, SrcW, SrcH, SrcWD, SrcHD, SrcWD2, SrcHD2: Integer;
  ScanS, ScanD: array of PArray;
  XCT, XST: Integer;
  YCT, YST: array of Integer;
begin
//Source.PixelFormat := pf8bit;
//Source.PixelFormat := pf16bit;
//Source.PixelFormat := pf24bit;
  Source.PixelFormat := pf32bit;
  Dest.PixelFormat := Source.PixelFormat;
  Winkel := 360 - Winkel;
  while Winkel > 360 do Winkel := Winkel - 360;
  while Winkel < 0 do Winkel := Winkel + 360;
  Winkel := Winkel * PI / 180;
  ST := Sin(Winkel);
  CT := Cos(Winkel);
  rw := Frac(Winkel / 90) = 0;
  if not GroesseAnpassen then begin
    Dest.Width := Source.Width;
    Dest.Height := Source.Height;
  end else if ST * CT < 0 then begin
    Dest.Width := Round(Abs(Source.Width * CT - Source.Height * ST));
    Dest.Height := Round(Abs(Source.Width * ST - Source.Height * CT));
  end else begin
    Dest.Width := Round(Abs(Source.Width * CT + Source.Height * ST));
    Dest.Height := Round(Abs(Source.Width * ST + Source.Height * CT));
  end;
  with Dest.Canvas do begin
    Brush.Style := bsSolid;
    Brush.Color := Hintergrund;
    FillRect(ClipRect);
  end;
  SrcWD := Source.Width;
  SrcHD := Source.Height;
  SrcWD2 := Source.Width div 2;
  SrcHD2 := Source.Height div 2;
  if CT < 0 then Dec(SrcWD2);
  if ST < 0 then Dec(SrcHD2);
  SetLength(ScanS, Source.Height);
  SetLength(ScanD, Dest.Height);
  for I := Source.Height - 1 downto 0 do ScanS[I] := Source.ScanLine[I];
  for I := Dest.Height  - 1 downto 0 do ScanD[I] := Dest.ScanLine[I];
  SetLength(YCT, Dest.Height);
  SetLength(YST, Dest.Height);
  for J := 0 to Dest.Height - 1 do begin
    if rw then
      Y := Trunc(J - Dest.Height / 2 + 0.5)
    else
      Y := J - Dest.Height div 2;
    YCT[J] := Round(Y * CT * 4 + 2);
    YST[J] := Round(Y * ST * 4 + 2);
  end;
  for I := 0 to Dest.Width - 1 do begin
    if rw then
      X := Trunc(I - Dest.Width / 2)
    else
      X := I - Dest.Width div 2;
    XCT := Round((X * CT + SrcWD2) * 4);
    XST := Round((X * ST + SrcHD2) * 4);
    for J := 0 to Dest.Height - 1 do begin
      SrcW := (XCT - YST[J]) shr 2; {... div 4}
      SrcH := (XST + YCT[J]) shr 2;
      if (SrcH >= 0) and (SrcH < SrcHD) and (SrcW >= 0) and (SrcW < SrcWD) then
        ScanD[J][I] := ScanS[SrcH][SrcW];
    end;
  end;
end;
Benötigt wird nur die angehängte Zbar.pas und die libzbar-0.dll von zbar.sourceforge.net, bzw. aus dem Anhang.


Das die Zbar.pas wurde natürlich auch gleich mit auf Unicode angepaßt ... läuft aber weiterhin auch mit ANSI.

gravedigger 30. Jun 2011 19:39

AW: Barcode aus Bild auslesen
 
Hallo himitsu,

wäre ja zu schön gewesen (Barcodes aus Bildern lesen).
Ich bekomme aber leider beim Aufruf von ReadBarCode immer nur eine Exception Abstrakter Fehler.
(Getestet mit 2009 und XE)

Sonniger Gruß aus Kamen
Frank

himitsu 30. Jun 2011 20:09

AW: Barcode aus Bild auslesen
 
Wo kommt denn der Fehler?

Hier in XE läuft es zuindestens endlich mal. :)


Delphi-Quellcode:
uses PngImage, JPeg;

P := TPicture.Create;
try
  P.LoadFromFile(S);
  ReadBarcode(Memo1.Lines, P.Graphic);
finally
  P.Free;
end;
Das TPicture kann auch ein TImage.Picture sein oder statt dem P.Graphic direkt TBitmap, TJPEGImage, TPNGImage oder andere TGraphic-Nachfahren.


[add]
Du hast hoffentlich nicht direkt ein TStrings verwendet? :lol: (TStringList)

gravedigger 1. Jul 2011 07:02

AW: Barcode aus Bild auslesen
 
Jepp,

jetzt funkioniert's.
Lag am TPicture, das ich TStrings nicht direkt verwenden kann weiß ich.

Gruß aus dem sonnigen Dortmund
Frank

viglu 10. Jul 2012 09:22

AW: Barcode aus Bild auslesen
 
Hallo,

Habe die zbar.pas genommen und getested. Mit einfachen 1D Barcodes funktionniert Zbar auch gut.
Aber ich möchte QRCode lesen.
Die ZBAR_QRCODE = 64, habe ich hinzugfügt, und aktiviere ihn auch.
Bekomme aber nie ein Resultat. Muss beim QRCode etwas spezielles gemacht werden?

bani 16. Jun 2016 09:08

AW: Barcode aus Bild auslesen
 
Hallo zusammen

Ich wollte dies heute auch testen. Ich bekomme, sobald ich zbar.pas einbinde den Fehler:
Runtime error 217 al 00428357

Delphi XE4

Gruss

Bani

himitsu 16. Jun 2016 09:19

AW: Barcode aus Bild auslesen
 
RuntimeError 217 = STATUS_CONTROL_C_EXIT aka reControlBreak
Klingt nach einem vergessenen "Haltepunkt".

Aber natürlich wäre es einfacher zu finden, wenn du den Debugger benutzt und schaust wo im Quellcode es knallt. :stupid:

bani 16. Jun 2016 09:47

AW: Barcode aus Bild auslesen
 
Zitat:

Zitat von himitsu (Beitrag 1340292)
RuntimeError 217 = STATUS_CONTROL_C_EXIT aka reControlBreak
Klingt nach einem vergessenen "Haltepunkt".

Aber natürlich wäre es einfacher zu finden, wenn du den Debugger benutzt und schaust wo im Quellcode es knallt. :stupid:

Hallo Himitsu

Danke für die schnelle Antwort

Das ist meine ganzer Code, also kann ich gar keine Haltepunkte setzen:

unit formMain;

interface

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, zbar;

type
TfrmMain = class(TForm)
private
{ Private-Deklarationen }
public
{ Public-Deklarationen }
end;

var
frmMain: TfrmMain;

implementation

{$R *.dfm}

end.

himitsu 16. Jun 2016 09:50

AW: Barcode aus Bild auslesen
 
Und jetzt benutzt du die Taste F9 (oder F7 und F8) und schaust nach "wo" diese Exception auftritt.

bani 16. Jun 2016 10:01

AW: Barcode aus Bild auslesen
 
Er fliegt in System - procedure InitUnits; raus :-(

wegen dem:
DllHandle := LoadLibrary('libzbar-0.dll');
if DllHandle = 0 then
RaiseLastOSError;

ich kann die DLL auch nicht mit regsvr32 registrieren

Braucht es weitere DLL's?

PS: Ich habe Windows 7 64 Bit...

TiGü 16. Jun 2016 10:39

AW: Barcode aus Bild auslesen
 
Kopiere doch mal die DLL "libzbar-0.dll" direkt in in Ordner, wo deine Anwendung liegt.

bani 16. Jun 2016 10:44

AW: Barcode aus Bild auslesen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von TiGü (Beitrag 1340303)
Kopiere doch mal die DLL "libzbar-0.dll" direkt in in Ordner, wo deine Anwendung liegt.

Habe ich auch schon.

Mit Despendency Walker meldet er die Fehler: siehe Anhang

Ich glaube, dass das nichts wird. Ichbrauche eine einfache Funktion um 2D Barcode aus PDF oder einem Bild auszulesen, und nicht mehr..

himitsu 16. Jun 2016 10:50

AW: Barcode aus Bild auslesen
 
Also die DLL läd garantiert nicht selber diese WinRT-DLLs.

Wieso eigentlich WinRT? :gruebel:
Für welche Platform kompilierst du denn? (am Besten für Win32 ... weiß grade nicht, ob es auch eine Win64-DLL gibt, aber WinRT gibt es garantiert nicht)

Zitat:

Zitat von bani (Beitrag 1340301)
ich kann die DLL auch nicht mit regsvr32 registrieren

Damit registriert man COM-Libraries (ActiveX und Co.)
und da die DLL diese API nicht unterstützt ...

bani 16. Jun 2016 11:07

AW: Barcode aus Bild auslesen
 
Danke für die Hilfe. Ich suche weiter nach einer Alternative...

bytecook 16. Jun 2016 12:28

AW: Barcode aus Bild auslesen
 
Zitat:

Zitat von bani (Beitrag 1340308)
Danke für die Hilfe. Ich suche weiter nach einer Alternative...

http://www.consert.net/shop/?page=sh...ory_id=rvision

Miese Formatierung aber als Ausgang extrem brauchbar :P
Und alles ohne DLL...


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:27 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz