![]() |
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. ![]() Schönen Abend. |
AW: Barcode aus Bild auslesen
Da gäbe es noch
![]() |
AW: Barcode aus Bild auslesen
sehr gut, sogar deutsch. ^^
|
AW: Barcode aus Bild auslesen
|
AW: Barcode aus Bild auslesen
Zitat:
Mfg Coffeecoder |
AW: Barcode aus Bild auslesen
Zitat:
|
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.
![]() |
AW: Barcode aus Bild auslesen
Eine Open Source Variante wäre unter
![]() Ist zwar keine Delphi-Komponente, steuern wir aber mit Delphi. |
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. :? |
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:
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).
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; 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:
eine entsprechende Schleife einbauen.
image := zbar_image_create;
Eventuell dann auch noch die StringListe mit .Sort:=True und .Duplicates:=dupIgnore .
Delphi-Quellcode:
Benötigt wird nur die angehängte Zbar.pas und die libzbar-0.dll von
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; ![]() Das die Zbar.pas wurde natürlich auch gleich mit auf Unicode angepaßt ... läuft aber weiterhin auch mit ANSI. |
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 |
AW: Barcode aus Bild auslesen
Wo kommt denn der Fehler?
Hier in XE läuft es zuindestens endlich mal. :)
Delphi-Quellcode:
Das TPicture kann auch ein TImage.Picture sein oder statt dem P.Graphic direkt TBitmap, TJPEGImage, TPNGImage oder andere TGraphic-Nachfahren.
uses PngImage, JPeg;
P := TPicture.Create; try P.LoadFromFile(S); ReadBarcode(Memo1.Lines, P.Graphic); finally P.Free; end; [add] Du hast hoffentlich nicht direkt ein TStrings verwendet? :lol: (TStringList) |
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 |
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? |
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 |
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: |
AW: Barcode aus Bild auslesen
Zitat:
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. |
AW: Barcode aus Bild auslesen
Und jetzt benutzt du die Taste F9 (oder F7 und F8) und schaust nach "wo" diese Exception auftritt.
|
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... |
AW: Barcode aus Bild auslesen
Kopiere doch mal die DLL "libzbar-0.dll" direkt in in Ordner, wo deine Anwendung liegt.
|
AW: Barcode aus Bild auslesen
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
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.. |
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:
und da die DLL diese API nicht unterstützt ... |
AW: Barcode aus Bild auslesen
Danke für die Hilfe. Ich suche weiter nach einer Alternative...
|
AW: Barcode aus Bild auslesen
Zitat:
![]() Miese Formatierung aber als Ausgang extrem brauchbar :P Und alles ohne DLL... |
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:24 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz