![]() |
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. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:51 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