IRONBARCODEの使用 IronBarcodeを使用してC#スキャナAPIを作成する Jordi Bardia 公開日:2026年1月21日 IronBarcode をダウンロード NuGet ダウンロード DLL ダウンロード 無料トライアル LLM向けのコピー LLM向けのコピー LLM 用の Markdown としてページをコピーする ChatGPTで開く このページについてChatGPTに質問する ジェミニで開く このページについてGeminiに問い合わせる Grokで開く このページについてGrokに質問する 困惑の中で開く このページについてPerplexityに問い合わせる 共有する Facebook で共有 Xでシェア(Twitter) LinkedIn で共有 URLをコピー 記事をメールで送る IronBarcode と ASP.NET Core を使用して RESTful バーコード スキャナー API を作成し、ハードウェアなしで画像、PDF、破損したスキャンからのバーコードを管理し、Windows、Linux、macOS 全体で信頼性の高いパフォーマンスを確保します。 IronBarcode は、ASP.NET Core の RESTful API を通じてプロフェッショナルなバーコード スキャンを可能にし、ハードウェアに依存せずに画像、PDF、破損したスキャンを処理するとともに、組み込みのセキュリティおよびコンプライアンス機能を使用してクロスプラットフォーム展開をサポートします。 エンタープライズバーコードチャレンジ フォーチュン 500 の物流会社のエンタープライズ アーキテクトであると想像してください。 倉庫チームは破損した配送ラベルの処理に苦労し、財務部門はバーコードが埋め込まれた請求書の PDF を何千枚も処理する必要があり、IT セキュリティ チームはグローバル インフラストラクチャ全体にハードウェアの依存関係を導入することなく SOC2 コンプライアンスを満たすソリューションを求めています。 このシナリオにより、当社のエンタープライズ クライアントの 1 社がIronBarcodeの REST API 機能を発見しました。 バーコードを読み取るという単純な要件から始まったものが、今では組織全体で毎月 200 万件を超えるバーコードを処理する完全なスキャン ソリューションへと進化しました。 従来、これには各拠点での高価なハードウェア スキャナー、複雑なドライバー管理、および大規模なセキュリティ レビューが必要でした。 代わりに、破損した倉庫ラベルをスキャンする場合でも、サプライヤーの PDF から請求書データを抽出する場合でも、どの部門でも安全にアクセスできる集中型の RESTful API を構築しました。 このチュートリアルでは、同じプロフェッショナル バーコード スキャナー API の構築について説明します。 破れたラベル、歪んだ画像、複数ページのドキュメントなどの現実世界の課題に対処する安全なエンドポイントを作成する方法を学びます。 さらに重要なことは、エンタープライズ環境に求められるセキュリティ、スケーラビリティ、ベンダーの安定性を備えながらこれを実装する方法がわかることです。 信頼性の高い C# スキャナ API の構築 エンタープライズ バーコード スキャナー API を作成するには、事前にいくつかの重要な懸念事項に対処する必要があります。 セキュリティ チームにはデータ処理に関する保証が必要です。 コンプライアンス担当者は監査証跡を必要とします。 運用チームは、さまざまなプラットフォームにわたる信頼性を要求します。 IronBarcode の完全なドキュメントでは、これらの懸念事項のそれぞれに体系的に対処しています。 RESTful アプローチの優れた点は、そのシンプルさとセキュリティにあります。 安全な API エンドポイントの背後でバーコード処理を集中管理することで、データ フローを完全に制御できます。 クライアント デバイスはバーコード処理ロジックに直接アクセスする必要はありません。 このアーキテクチャは、ゼロトラスト セキュリティ モデルを自然にサポートしながら、既存のエンタープライズ システムとのスムーズな統合を可能にします。 まずは基礎から始めましょう。 IronBarcode の読み取り機能は、企業が遭遇する可能性のあるすべての主要なバーコード形式をサポートしています。 製造業で使用される従来のCode 39 バーコードからマーケティング キャンペーンの最新のQR コードまで、ライブラリはすべてを処理できます。 サポートされているバーコード形式ガイドには、実装を計画するための完全なリファレンスが提供されています。 エンタープライズ シナリオにとってこれが特に価値のあるものとなるのは、ライブラリのフォールト トレランス機能です。 現実世界のバーコードは完璧ではありません。 破損したり、印刷品質が悪くなったり、斜めにスキャンされたりします。 IronBarcode の高度な画像処理はこれらの課題を自動的に処理し、サポート チケットを削減して運用効率を向上させます。 IronBarcodeのインストールと設定 エンタープライズ展開では、依存関係とライセンスを慎重に考慮する必要があります。 IronBarcode は、簡単な NuGet インストールと透過的なライセンスによってこれを簡素化します。 ASP.NET Core プロジェクトを開始する方法は次のとおりです。 Install-Package IronBarCode Install-Package IronBarCode SHELL 特定のプラットフォーム要件を持つエンタープライズ環境の場合は、高度な NuGet インストール ガイドを参照してください。 これには、特定の .NET バージョンをターゲットにしたり、特定のプラットフォーム向けに最適化したりするシナリオが含まれます。 インストールが完了したら、簡単なテストで設定を確認してください。以下のコードは、最小限の設定でライブラリがバーコードを読み取る機能を示しています。 using IronBarCode; // Verify installation with a basic barcode read public class InstallationTest { public static void VerifySetup() { try { // Test with a sample barcode image var result = BarcodeReader.Read("test-barcode.png"); if (result.Any()) { Console.WriteLine($"Success! Detected: {result.First().Value}"); Console.WriteLine($"Format: {result.First().BarcodeType}"); Console.WriteLine($"Confidence: {result.First().Confidence}%"); } else { Console.WriteLine("No barcode detected in test image"); } } catch (Exception ex) { Console.WriteLine($"Setup issue: {ex.Message}"); } } } using IronBarCode; // Verify installation with a basic barcode read public class InstallationTest { public static void VerifySetup() { try { // Test with a sample barcode image var result = BarcodeReader.Read("test-barcode.png"); if (result.Any()) { Console.WriteLine($"Success! Detected: {result.First().Value}"); Console.WriteLine($"Format: {result.First().BarcodeType}"); Console.WriteLine($"Confidence: {result.First().Confidence}%"); } else { Console.WriteLine("No barcode detected in test image"); } } catch (Exception ex) { Console.WriteLine($"Setup issue: {ex.Message}"); } } } Imports IronBarCode ' Verify installation with a basic barcode read Public Class InstallationTest Public Shared Sub VerifySetup() Try ' Test with a sample barcode image Dim result = BarcodeReader.Read("test-barcode.png") If result.Any() Then Console.WriteLine($"Success! Detected: {result.First().Value}") Console.WriteLine($"Format: {result.First().BarcodeType}") Console.WriteLine($"Confidence: {result.First().Confidence}%") Else Console.WriteLine("No barcode detected in test image") End If Catch ex As Exception Console.WriteLine($"Setup issue: {ex.Message}") End Try End Sub End Class $vbLabelText $csharpLabel この検証手順は、エンタープライズ展開にとって非常に重要です。 ライブラリが適切にインストールされ、ライセンスされており、必要なシステム リソースにアクセスできることを確認します。 信頼スコアの出力は、特定のバーコード タイプに対するベースライン期待を確立するのに役立ちます。 実稼働環境での展開の場合は、ライセンス ドキュメントを注意深く確認してください。 エンタープライズ ライセンスは、組織内での無制限の展開をサポートし、複数のデータ センターにわたる拡張に不可欠です。 ライセンス キー構成ガイドでは、 DevOpsプラクティスに適合する環境変数や構成ファイルなど、さまざまなアクティベーション方法について説明します。 企業向けプラットフォーム互換性 企業では異機種混在環境が稼働している可能性があります。 開発は Windows で行われ、ステージングは Linux コンテナーで実行され、一部のチームは macOS を使用する場合があります。 IronBarcode のクロスプラットフォーム互換性により、これらすべてのプラットフォーム間で一貫した動作が保証されます。 コンテナ化されたデプロイメントの場合、 Docker セットアップ ガイドにLinux コンテナに関する具体的な手順が記載されています。 これには、依存関係の処理と、効率的なクラウド展開のためのイメージ サイズの最適化が含まれます。 AzureまたはAWS Lambdaにデプロイする場合は、プラットフォーム固有のガイドに従ってこれらの環境で最適なパフォーマンスを確保します。 ライブラリは、 .NET MAUI 統合を通じてモバイル シナリオもサポートしており、現場の作業員がモバイル スキャン機能を必要とするときに、バーコード スキャン機能をiOSおよびAndroidデバイスに拡張できます。 完全なスキャナAPIコントローラの構築 実際の企業ニーズに対応する、本番環境対応のスキャナー API を構築しましょう。 この実装には、適切なエラー処理、セキュリティ上の考慮事項、パフォーマンスの最適化が含まれます。 using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Authorization; using IronBarCode; using System.Drawing; using System.ComponentModel.DataAnnotations; namespace BarcodeScannerAPI.Controllers { [ApiController] [Route("api/v1/[controller]")] [Authorize] // Require authentication for all endpoints public class ScannerController : ControllerBase { private readonly ILogger<ScannerController> _logger; private readonly IConfiguration _configuration; public ScannerController(ILogger<ScannerController> logger, IConfiguration configuration) { _logger = logger; _configuration = configuration; } // Enhanced result model with audit fields public class ScanResult { public bool Success { get; set; } public List<BarcodeData> Barcodes { get; set; } = new List<BarcodeData>(); public string RequestId { get; set; } = Guid.NewGuid().ToString(); public DateTime ProcessedAt { get; set; } = DateTime.UtcNow; public long ProcessingTimeMs { get; set; } public string ErrorMessage { get; set; } public Dictionary<string, object> Metadata { get; set; } = new Dictionary<string, object>(); } public class BarcodeData { public string Value { get; set; } public string Format { get; set; } public double Confidence { get; set; } public Rectangle Location { get; set; } public int PageNumber { get; set; } // For PDF processing } // Input validation model public class ScanRequest { [Required] public IFormFile File { get; set; } [Range(1, 10)] public int MaxBarcodes { get; set; } = 5; public string[] ExpectedFormats { get; set; } public bool EnableImageCorrection { get; set; } = true; } [HttpPost("scan")] [RequestSizeLimit(52428800)] // 50MB limit public async Task<ActionResult<ScanResult>> ScanDocument([FromForm] ScanRequest request) { var stopwatch = System.Diagnostics.Stopwatch.StartNew(); var result = new ScanResult(); try { // Validate file type for security var allowedExtensions = new[] { ".pdf", ".png", ".jpg", ".jpeg", ".gif", ".tiff", ".bmp" }; var fileExtension = Path.GetExtension(request.File.FileName).ToLowerInvariant(); if (!allowedExtensions.Contains(fileExtension)) { _logger.LogWarning($"Rejected file type: {fileExtension}"); return BadRequest(new ScanResult { Success = false, ErrorMessage = "Unsupported file type. Allowed: PDF, PNG, JPG, GIF, TIFF, BMP" }); } // Process the file using var stream = new MemoryStream(); await request.File.CopyToAsync(stream); var fileBytes = stream.ToArray(); // Log for audit trail _logger.LogInformation($"Processing {request.File.FileName} ({fileBytes.Length} bytes) - RequestId: {result.RequestId}"); // Configure scanner based on requirements var options = ConfigureOptions(request); // Handle different file types BarcodeResults scanResults; if (fileExtension == ".pdf") { var pdfOptions = new PdfBarcodeReaderOptions { Scale = 3, DPI = 300, MaxThreads = 4 }; scanResults = BarcodeReader.ReadPdf(fileBytes, pdfOptions); } else { scanResults = BarcodeReader.Read(fileBytes, options); } // Process results if (scanResults.Any()) { result.Success = true; foreach (var barcode in scanResults.Take(request.MaxBarcodes)) { result.Barcodes.Add(new BarcodeData { Value = barcode.Value, Format = barcode.BarcodeType.ToString(), Confidence = barcode.Confidence, Location = barcode.Bounds, PageNumber = barcode.PageNumber }); } result.Metadata["TotalFound"] = scanResults.Count(); result.Metadata["FileSize"] = fileBytes.Length; result.Metadata["FileName"] = request.File.FileName; _logger.LogInformation($"Successfully scanned {scanResults.Count()} barcodes - RequestId: {result.RequestId}"); } else { result.Success = false; result.ErrorMessage = "No barcodes detected in the document"; _logger.LogWarning($"No barcodes found - RequestId: {result.RequestId}"); } } catch (Exception ex) { _logger.LogError(ex, $"Scanning error - RequestId: {result.RequestId}"); result.Success = false; result.ErrorMessage = "An error occurred during processing"; // Don't expose internal errors to clients if (_configuration.GetValue<bool>("DetailedErrors")) { result.Metadata["Exception"] = ex.Message; } } finally { stopwatch.Stop(); result.ProcessingTimeMs = stopwatch.ElapsedMilliseconds; } return result; } private BarcodeReaderOptions ConfigureOptions(ScanRequest request) { var options = new BarcodeReaderOptions { Speed = ReadingSpeed.Balanced, ExpectMultipleBarcodes = request.MaxBarcodes > 1, RemoveFalsePositive = true, Multithreaded = true, MaxParallelThreads = Environment.ProcessorCount }; // Apply format filtering if specified if (request.ExpectedFormats?.Any() == true) { var formats = BarcodeEncoding.None; foreach (var format in request.ExpectedFormats) { if (Enum.TryParse<BarcodeEncoding>(format, true, out var encoding)) { formats |= encoding; } } options.ExpectBarcodeTypes = formats; } // Enable image correction for damaged barcodes if (request.EnableImageCorrection) { options.ImageFilters = new ImageFilterCollection { new SharpenFilter(2), new ContrastFilter(1.5f), new BrightnessFilter(1.1f) }; options.AutoRotate = true; } return options; } // Batch processing endpoint for high-volume scenarios [HttpPost("scan-batch")] [RequestSizeLimit(524288000)] // 500MB for batch operations public async Task<ActionResult<List<ScanResult>>> ScanBatch(List<IFormFile> files) { if (files == null || !files.Any()) { return BadRequest("No files provided"); } if (files.Count > 50) { return BadRequest("Maximum 50 files per batch"); } var tasks = files.Select(file => ProcessFileAsync(file)); var results = await Task.WhenAll(tasks); _logger.LogInformation($"Batch processed {files.Count} files, {results.Count(r => r.Success)} successful"); return Ok(results); } private async Task<ScanResult> ProcessFileAsync(IFormFile file) { // Reuse the scanning logic var request = new ScanRequest { File = file, EnableImageCorrection = true }; var actionResult = await ScanDocument(request); if (actionResult.Result is OkObjectResult okResult) { return okResult.Value as ScanResult; } else if (actionResult.Result is BadRequestObjectResult badResult) { return badResult.Value as ScanResult; } return new ScanResult { Success = false, ErrorMessage = "Processing failed" }; } } } using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Authorization; using IronBarCode; using System.Drawing; using System.ComponentModel.DataAnnotations; namespace BarcodeScannerAPI.Controllers { [ApiController] [Route("api/v1/[controller]")] [Authorize] // Require authentication for all endpoints public class ScannerController : ControllerBase { private readonly ILogger<ScannerController> _logger; private readonly IConfiguration _configuration; public ScannerController(ILogger<ScannerController> logger, IConfiguration configuration) { _logger = logger; _configuration = configuration; } // Enhanced result model with audit fields public class ScanResult { public bool Success { get; set; } public List<BarcodeData> Barcodes { get; set; } = new List<BarcodeData>(); public string RequestId { get; set; } = Guid.NewGuid().ToString(); public DateTime ProcessedAt { get; set; } = DateTime.UtcNow; public long ProcessingTimeMs { get; set; } public string ErrorMessage { get; set; } public Dictionary<string, object> Metadata { get; set; } = new Dictionary<string, object>(); } public class BarcodeData { public string Value { get; set; } public string Format { get; set; } public double Confidence { get; set; } public Rectangle Location { get; set; } public int PageNumber { get; set; } // For PDF processing } // Input validation model public class ScanRequest { [Required] public IFormFile File { get; set; } [Range(1, 10)] public int MaxBarcodes { get; set; } = 5; public string[] ExpectedFormats { get; set; } public bool EnableImageCorrection { get; set; } = true; } [HttpPost("scan")] [RequestSizeLimit(52428800)] // 50MB limit public async Task<ActionResult<ScanResult>> ScanDocument([FromForm] ScanRequest request) { var stopwatch = System.Diagnostics.Stopwatch.StartNew(); var result = new ScanResult(); try { // Validate file type for security var allowedExtensions = new[] { ".pdf", ".png", ".jpg", ".jpeg", ".gif", ".tiff", ".bmp" }; var fileExtension = Path.GetExtension(request.File.FileName).ToLowerInvariant(); if (!allowedExtensions.Contains(fileExtension)) { _logger.LogWarning($"Rejected file type: {fileExtension}"); return BadRequest(new ScanResult { Success = false, ErrorMessage = "Unsupported file type. Allowed: PDF, PNG, JPG, GIF, TIFF, BMP" }); } // Process the file using var stream = new MemoryStream(); await request.File.CopyToAsync(stream); var fileBytes = stream.ToArray(); // Log for audit trail _logger.LogInformation($"Processing {request.File.FileName} ({fileBytes.Length} bytes) - RequestId: {result.RequestId}"); // Configure scanner based on requirements var options = ConfigureOptions(request); // Handle different file types BarcodeResults scanResults; if (fileExtension == ".pdf") { var pdfOptions = new PdfBarcodeReaderOptions { Scale = 3, DPI = 300, MaxThreads = 4 }; scanResults = BarcodeReader.ReadPdf(fileBytes, pdfOptions); } else { scanResults = BarcodeReader.Read(fileBytes, options); } // Process results if (scanResults.Any()) { result.Success = true; foreach (var barcode in scanResults.Take(request.MaxBarcodes)) { result.Barcodes.Add(new BarcodeData { Value = barcode.Value, Format = barcode.BarcodeType.ToString(), Confidence = barcode.Confidence, Location = barcode.Bounds, PageNumber = barcode.PageNumber }); } result.Metadata["TotalFound"] = scanResults.Count(); result.Metadata["FileSize"] = fileBytes.Length; result.Metadata["FileName"] = request.File.FileName; _logger.LogInformation($"Successfully scanned {scanResults.Count()} barcodes - RequestId: {result.RequestId}"); } else { result.Success = false; result.ErrorMessage = "No barcodes detected in the document"; _logger.LogWarning($"No barcodes found - RequestId: {result.RequestId}"); } } catch (Exception ex) { _logger.LogError(ex, $"Scanning error - RequestId: {result.RequestId}"); result.Success = false; result.ErrorMessage = "An error occurred during processing"; // Don't expose internal errors to clients if (_configuration.GetValue<bool>("DetailedErrors")) { result.Metadata["Exception"] = ex.Message; } } finally { stopwatch.Stop(); result.ProcessingTimeMs = stopwatch.ElapsedMilliseconds; } return result; } private BarcodeReaderOptions ConfigureOptions(ScanRequest request) { var options = new BarcodeReaderOptions { Speed = ReadingSpeed.Balanced, ExpectMultipleBarcodes = request.MaxBarcodes > 1, RemoveFalsePositive = true, Multithreaded = true, MaxParallelThreads = Environment.ProcessorCount }; // Apply format filtering if specified if (request.ExpectedFormats?.Any() == true) { var formats = BarcodeEncoding.None; foreach (var format in request.ExpectedFormats) { if (Enum.TryParse<BarcodeEncoding>(format, true, out var encoding)) { formats |= encoding; } } options.ExpectBarcodeTypes = formats; } // Enable image correction for damaged barcodes if (request.EnableImageCorrection) { options.ImageFilters = new ImageFilterCollection { new SharpenFilter(2), new ContrastFilter(1.5f), new BrightnessFilter(1.1f) }; options.AutoRotate = true; } return options; } // Batch processing endpoint for high-volume scenarios [HttpPost("scan-batch")] [RequestSizeLimit(524288000)] // 500MB for batch operations public async Task<ActionResult<List<ScanResult>>> ScanBatch(List<IFormFile> files) { if (files == null || !files.Any()) { return BadRequest("No files provided"); } if (files.Count > 50) { return BadRequest("Maximum 50 files per batch"); } var tasks = files.Select(file => ProcessFileAsync(file)); var results = await Task.WhenAll(tasks); _logger.LogInformation($"Batch processed {files.Count} files, {results.Count(r => r.Success)} successful"); return Ok(results); } private async Task<ScanResult> ProcessFileAsync(IFormFile file) { // Reuse the scanning logic var request = new ScanRequest { File = file, EnableImageCorrection = true }; var actionResult = await ScanDocument(request); if (actionResult.Result is OkObjectResult okResult) { return okResult.Value as ScanResult; } else if (actionResult.Result is BadRequestObjectResult badResult) { return badResult.Value as ScanResult; } return new ScanResult { Success = false, ErrorMessage = "Processing failed" }; } } } Imports Microsoft.AspNetCore.Mvc Imports Microsoft.AspNetCore.Authorization Imports IronBarCode Imports System.Drawing Imports System.ComponentModel.DataAnnotations Namespace BarcodeScannerAPI.Controllers <ApiController> <Route("api/v1/[controller]")> <Authorize> Public Class ScannerController Inherits ControllerBase Private ReadOnly _logger As ILogger(Of ScannerController) Private ReadOnly _configuration As IConfiguration Public Sub New(logger As ILogger(Of ScannerController), configuration As IConfiguration) _logger = logger _configuration = configuration End Sub ' Enhanced result model with audit fields Public Class ScanResult Public Property Success As Boolean Public Property Barcodes As List(Of BarcodeData) = New List(Of BarcodeData)() Public Property RequestId As String = Guid.NewGuid().ToString() Public Property ProcessedAt As DateTime = DateTime.UtcNow Public Property ProcessingTimeMs As Long Public Property ErrorMessage As String Public Property Metadata As Dictionary(Of String, Object) = New Dictionary(Of String, Object)() End Class Public Class BarcodeData Public Property Value As String Public Property Format As String Public Property Confidence As Double Public Property Location As Rectangle Public Property PageNumber As Integer End Class ' Input validation model Public Class ScanRequest <Required> Public Property File As IFormFile <Range(1, 10)> Public Property MaxBarcodes As Integer = 5 Public Property ExpectedFormats As String() Public Property EnableImageCorrection As Boolean = True End Class <HttpPost("scan")> <RequestSizeLimit(52428800)> Public Async Function ScanDocument(<FromForm> request As ScanRequest) As Task(Of ActionResult(Of ScanResult)) Dim stopwatch = System.Diagnostics.Stopwatch.StartNew() Dim result = New ScanResult() Try ' Validate file type for security Dim allowedExtensions = {".pdf", ".png", ".jpg", ".jpeg", ".gif", ".tiff", ".bmp"} Dim fileExtension = Path.GetExtension(request.File.FileName).ToLowerInvariant() If Not allowedExtensions.Contains(fileExtension) Then _logger.LogWarning($"Rejected file type: {fileExtension}") Return BadRequest(New ScanResult With { .Success = False, .ErrorMessage = "Unsupported file type. Allowed: PDF, PNG, JPG, GIF, TIFF, BMP" }) End If ' Process the file Using stream = New MemoryStream() Await request.File.CopyToAsync(stream) Dim fileBytes = stream.ToArray() ' Log for audit trail _logger.LogInformation($"Processing {request.File.FileName} ({fileBytes.Length} bytes) - RequestId: {result.RequestId}") ' Configure scanner based on requirements Dim options = ConfigureOptions(request) ' Handle different file types Dim scanResults As BarcodeResults If fileExtension = ".pdf" Then Dim pdfOptions = New PdfBarcodeReaderOptions With { .Scale = 3, .DPI = 300, .MaxThreads = 4 } scanResults = BarcodeReader.ReadPdf(fileBytes, pdfOptions) Else scanResults = BarcodeReader.Read(fileBytes, options) End If ' Process results If scanResults.Any() Then result.Success = True For Each barcode In scanResults.Take(request.MaxBarcodes) result.Barcodes.Add(New BarcodeData With { .Value = barcode.Value, .Format = barcode.BarcodeType.ToString(), .Confidence = barcode.Confidence, .Location = barcode.Bounds, .PageNumber = barcode.PageNumber }) Next result.Metadata("TotalFound") = scanResults.Count() result.Metadata("FileSize") = fileBytes.Length result.Metadata("FileName") = request.File.FileName _logger.LogInformation($"Successfully scanned {scanResults.Count()} barcodes - RequestId: {result.RequestId}") Else result.Success = False result.ErrorMessage = "No barcodes detected in the document" _logger.LogWarning($"No barcodes found - RequestId: {result.RequestId}") End If End Using Catch ex As Exception _logger.LogError(ex, $"Scanning error - RequestId: {result.RequestId}") result.Success = False result.ErrorMessage = "An error occurred during processing" ' Don't expose internal errors to clients If _configuration.GetValue(Of Boolean)("DetailedErrors") Then result.Metadata("Exception") = ex.Message End If Finally stopwatch.Stop() result.ProcessingTimeMs = stopwatch.ElapsedMilliseconds End Try Return result End Function Private Function ConfigureOptions(request As ScanRequest) As BarcodeReaderOptions Dim options = New BarcodeReaderOptions With { .Speed = ReadingSpeed.Balanced, .ExpectMultipleBarcodes = request.MaxBarcodes > 1, .RemoveFalsePositive = True, .Multithreaded = True, .MaxParallelThreads = Environment.ProcessorCount } ' Apply format filtering if specified If request.ExpectedFormats?.Any() = True Then Dim formats = BarcodeEncoding.None For Each format In request.ExpectedFormats Dim encoding As BarcodeEncoding If [Enum].TryParse(format, True, encoding) Then formats = formats Or encoding End If Next options.ExpectBarcodeTypes = formats End If ' Enable image correction for damaged barcodes If request.EnableImageCorrection Then options.ImageFilters = New ImageFilterCollection From { New SharpenFilter(2), New ContrastFilter(1.5F), New BrightnessFilter(1.1F) } options.AutoRotate = True End If Return options End Function ' Batch processing endpoint for high-volume scenarios <HttpPost("scan-batch")> <RequestSizeLimit(524288000)> Public Async Function ScanBatch(files As List(Of IFormFile)) As Task(Of ActionResult(Of List(Of ScanResult))) If files Is Nothing OrElse Not files.Any() Then Return BadRequest("No files provided") End If If files.Count > 50 Then Return BadRequest("Maximum 50 files per batch") End If Dim tasks = files.Select(Function(file) ProcessFileAsync(file)) Dim results = Await Task.WhenAll(tasks) _logger.LogInformation($"Batch processed {files.Count} files, {results.Count(Function(r) r.Success)} successful") Return Ok(results) End Function Private Async Function ProcessFileAsync(file As IFormFile) As Task(Of ScanResult) ' Reuse the scanning logic Dim request = New ScanRequest With { .File = file, .EnableImageCorrection = True } Dim actionResult = Await ScanDocument(request) If TypeOf actionResult.Result Is OkObjectResult Then Return DirectCast(actionResult.Result, OkObjectResult).Value ElseIf TypeOf actionResult.Result Is BadRequestObjectResult Then Return DirectCast(actionResult.Result, BadRequestObjectResult).Value End If Return New ScanResult With { .Success = False, .ErrorMessage = "Processing failed" } End Function End Class End Namespace $vbLabelText $csharpLabel このプロフェッショナルな実装には、本番環境の導入に必要な重要な機能がいくつか含まれています。認証により、許可されたユーザーのみがスキャンサービスにアクセスできます。リクエストサイズ制限により、サービス拒否攻撃を防止できます。 完全なログ記録により、コンプライアンス チームが必要とする監査証跡が提供されます。 構造化応答モデルは、バーコード値だけでなく、信頼スコアと位置データも返します。 このメタデータは品質保証プロセスにとって非常に貴重です。 サプライヤーのバーコードのスキャンの信頼性が低い場合、システムは手動で確認するためにフラグを設定できます。 プロフェッショナルなエラー処理 コントローラーが内部例外の詳細をクライアントに公開しないことに注意してください。 これは、情報漏洩を防ぐことでセキュリティのベストプラクティスに従います。 詳細なログ記録では、エラー応答を一般的なままにしながら、デバッグに必要なすべての情報が記録されます。 RequestIdフィールドを使用すると、分散システム全体でエンドツーエンドのトレースが可能になります。 倉庫作業員がスキャンの問題を報告すると、サポート チームは集中ログ システムで正確なリクエストをすぐに見つけることができます。 これにより、生産上の問題の平均解決時間 (MTTR) が大幅に短縮されます。 ProcessingTimeMsによるパフォーマンス監視は、ボトルネックの特定に役立ちます。 特定のバーコード タイプの処理に常に時間がかかる場合は、それに応じて読み取り速度の設定を調整できます。 読み取り速度の例では、さまざまな設定がパフォーマンスにどのように影響するかを示しています。 異なる入力ソースの処理 エンタープライズ システムが単一の形式で標準化されることはほとんどありません。 スキャナー API は、高解像度の倉庫カメラから数十年前のファックス機からの低品質の PDF スキャンまで、あらゆるものを処理する必要があります。 柔軟性を構築する方法は次のとおりです。 // Extended controller with multiple input handlers [ApiController] [Route("api/v1/[controller]")] [Authorize] public class AdvancedScannerController : ControllerBase { private readonly IHttpClientFactory _httpClientFactory; private readonly ILogger<AdvancedScannerController> _logger; public AdvancedScannerController( IHttpClientFactory httpClientFactory, ILogger<AdvancedScannerController> logger) { _httpClientFactory = httpClientFactory; _logger = logger; } // Handle Base64 input (common in web applications) [HttpPost("scan-base64")] public ActionResult<ScanResult> ScanBase64([FromBody] Base64Request request) { if (!ModelState.IsValid) { return BadRequest(ModelState); } try { // Validate Base64 format var base64Data = request.ImageData; if (base64Data.Contains(",")) { // Handle data URL format: "data:image/png;base64,..." base64Data = base64Data.Substring(base64Data.IndexOf(",") + 1); } var imageBytes = Convert.FromBase64String(base64Data); // Implement size validation if (imageBytes.Length > 10 * 1024 * 1024) // 10MB limit { return BadRequest(new ScanResult { Success = false, ErrorMessage = "Image size exceeds 10MB limit" }); } // Configure for web-uploaded images (often lower quality) var options = new BarcodeReaderOptions { Speed = ReadingSpeed.Detailed, ImageFilters = new ImageFilterCollection { new SharpenFilter(3), new ContrastFilter(2), new DeNoise() }, TryInvertColor = true, // Handle inverted barcodes AutoRotate = true }; var results = BarcodeReader.Read(imageBytes, options); return ProcessResults(results, "base64", request.FileName); } catch (FormatException) { return BadRequest(new ScanResult { Success = false, ErrorMessage = "Invalid Base64 format" }); } } // Handle URL input (for cloud storage integration) [HttpPost("scan-url")] public async Task<ActionResult<ScanResult>> ScanFromUrl([FromBody] UrlScanRequest request) { if (!Uri.TryCreate(request.Url, UriKind.Absolute, out var uri)) { return BadRequest(new ScanResult { Success = false, ErrorMessage = "Invalid URL format" }); } // Validate URL domain (security measure) var allowedDomains = _configuration.GetSection("AllowedDomains").Get<string[]>() ?? new[] { "blob.core.windows.net", "s3.amazonaws.com" }; if (!allowedDomains.Any(domain => uri.Host.EndsWith(domain))) { _logger.LogWarning($"Rejected URL from unauthorized domain: {uri.Host}"); return BadRequest(new ScanResult { Success = false, ErrorMessage = "URL domain not authorized" }); } try { using var httpClient = _httpClientFactory.CreateClient("BarcodeScanner"); httpClient.Timeout = TimeSpan.FromSeconds(30); // Add headers to avoid being blocked httpClient.DefaultRequestHeaders.Add("User-Agent", "BarcodeScannerAPI/2.0"); var response = await httpClient.GetAsync(uri); response.EnsureSuccessStatusCode(); // Check content type var contentType = response.Content.Headers.ContentType?.MediaType; if (!IsValidContentType(contentType)) { return BadRequest(new ScanResult { Success = false, ErrorMessage = $"Unsupported content type: {contentType}" }); } var imageBytes = await response.Content.ReadAsByteArrayAsync(); // Use async processing for better scalability var results = await BarcodeReader.ReadAsync(imageBytes); return ProcessResults(results, "url", uri.ToString()); } catch (HttpRequestException ex) { _logger.LogError(ex, $"Failed to download from URL: {uri}"); return BadRequest(new ScanResult { Success = false, ErrorMessage = "Failed to download image from URL" }); } catch (TaskCanceledException) { return BadRequest(new ScanResult { Success = false, ErrorMessage = "Download timeout - file too large or slow connection" }); } } // Handle multi-page PDFs with page-specific processing [HttpPost("scan-pdf-advanced")] public async Task<ActionResult<PdfScanResult>> ScanPdfAdvanced([FromForm] PdfScanRequest request) { using var stream = new MemoryStream(); await request.File.CopyToAsync(stream); var pdfOptions = new PdfBarcodeReaderOptions { Scale = request.Scale ?? 3, DPI = request.DPI ?? 300, PageNumbers = request.PageNumbers, Password = request.Password, MaxThreads = Math.Min(request.MaxThreads ?? 4, Environment.ProcessorCount) }; // For large PDFs, process in chunks if (stream.Length > 50 * 1024 * 1024) // 50MB { _logger.LogInformation($"Large PDF detected ({stream.Length / 1024 / 1024}MB), using chunked processing"); pdfOptions.MaxThreads = 2; // Reduce memory pressure } var results = BarcodeReader.ReadPdf(stream.ToArray(), pdfOptions); // Group results by page var pageResults = results.GroupBy(r => r.PageNumber) .OrderBy(g => g.Key) .Select(g => new PageBarcodeResult { PageNumber = g.Key, BarcodeCount = g.Count(), Barcodes = g.Select(b => new BarcodeData { Value = b.Value, Format = b.BarcodeType.ToString(), Confidence = b.Confidence, Location = b.Bounds }).ToList() }).ToList(); return Ok(new PdfScanResult { Success = true, TotalPages = pageResults.Count, TotalBarcodes = results.Count(), PageResults = pageResults, RequestId = Guid.NewGuid().ToString() }); } // Handle damaged or low-quality barcodes [HttpPost("scan-damaged")] public async Task<ActionResult<ScanResult>> ScanDamagedBarcode([FromForm] IFormFile file) { using var stream = new MemoryStream(); await file.CopyToAsync(stream); // Aggressive image correction for damaged barcodes var options = new BarcodeReaderOptions { Speed = ReadingSpeed.ExtremeDetail, ImageFilters = new ImageFilterCollection { new SharpenFilter(4), new ContrastFilter(3), new BrightnessFilter(1.5f), new BinaryThresholdFilter(128), new DeNoise(3) }, TryInvertColor = true, AutoRotate = true, UseCode39ExtendedMode = true, RemoveFalsePositive = false, // Accept lower confidence Confidence = ConfidenceLevel.Low }; var results = BarcodeReader.Read(stream.ToArray(), options); // If still no results, try with different threshold if (!results.Any()) { options.ImageFilters = new ImageFilterCollection { new AdaptiveThresholdFilter(9), new MedianFilter(3), new Dilate(1) }; results = BarcodeReader.Read(stream.ToArray(), options); } return ProcessResults(results, "damaged", file.FileName); } private bool IsValidContentType(string contentType) { var validTypes = new[] { "image/jpeg", "image/jpg", "image/png", "image/gif", "image/tiff", "image/bmp", "application/pdf" }; return validTypes.Contains(contentType?.ToLower()); } private ActionResult<ScanResult> ProcessResults(BarcodeResults results, string source, string identifier) { var scanResult = new ScanResult { Metadata = new Dictionary<string, object> { ["Source"] = source, ["Identifier"] = identifier, ["ProcessedAt"] = DateTime.UtcNow } }; if (results.Any()) { scanResult.Success = true; scanResult.Barcodes = results.Select(r => new BarcodeData { Value = r.Value, Format = r.BarcodeType.ToString(), Confidence = r.Confidence, Location = r.Bounds }).ToList(); // Log low confidence results for quality monitoring var lowConfidence = results.Where(r => r.Confidence < 70).ToList(); if (lowConfidence.Any()) { _logger.LogWarning($"Low confidence barcodes detected: {lowConfidence.Count} of {results.Count()} from {identifier}"); } } else { scanResult.Success = false; scanResult.ErrorMessage = "No barcodes detected"; } return Ok(scanResult); } } // Request models public class Base64Request { [Required] public string ImageData { get; set; } public string FileName { get; set; } } public class UrlScanRequest { [Required] [Url] public string Url { get; set; } } public class PdfScanRequest { [Required] public IFormFile File { get; set; } public int? Scale { get; set; } public int? DPI { get; set; } public int[] PageNumbers { get; set; } public string Password { get; set; } public int? MaxThreads { get; set; } } // Response models public class PdfScanResult : ScanResult { public int TotalPages { get; set; } public int TotalBarcodes { get; set; } public List<PageBarcodeResult> PageResults { get; set; } } public class PageBarcodeResult { public int PageNumber { get; set; } public int BarcodeCount { get; set; } public List<BarcodeData> Barcodes { get; set; } } // Extended controller with multiple input handlers [ApiController] [Route("api/v1/[controller]")] [Authorize] public class AdvancedScannerController : ControllerBase { private readonly IHttpClientFactory _httpClientFactory; private readonly ILogger<AdvancedScannerController> _logger; public AdvancedScannerController( IHttpClientFactory httpClientFactory, ILogger<AdvancedScannerController> logger) { _httpClientFactory = httpClientFactory; _logger = logger; } // Handle Base64 input (common in web applications) [HttpPost("scan-base64")] public ActionResult<ScanResult> ScanBase64([FromBody] Base64Request request) { if (!ModelState.IsValid) { return BadRequest(ModelState); } try { // Validate Base64 format var base64Data = request.ImageData; if (base64Data.Contains(",")) { // Handle data URL format: "data:image/png;base64,..." base64Data = base64Data.Substring(base64Data.IndexOf(",") + 1); } var imageBytes = Convert.FromBase64String(base64Data); // Implement size validation if (imageBytes.Length > 10 * 1024 * 1024) // 10MB limit { return BadRequest(new ScanResult { Success = false, ErrorMessage = "Image size exceeds 10MB limit" }); } // Configure for web-uploaded images (often lower quality) var options = new BarcodeReaderOptions { Speed = ReadingSpeed.Detailed, ImageFilters = new ImageFilterCollection { new SharpenFilter(3), new ContrastFilter(2), new DeNoise() }, TryInvertColor = true, // Handle inverted barcodes AutoRotate = true }; var results = BarcodeReader.Read(imageBytes, options); return ProcessResults(results, "base64", request.FileName); } catch (FormatException) { return BadRequest(new ScanResult { Success = false, ErrorMessage = "Invalid Base64 format" }); } } // Handle URL input (for cloud storage integration) [HttpPost("scan-url")] public async Task<ActionResult<ScanResult>> ScanFromUrl([FromBody] UrlScanRequest request) { if (!Uri.TryCreate(request.Url, UriKind.Absolute, out var uri)) { return BadRequest(new ScanResult { Success = false, ErrorMessage = "Invalid URL format" }); } // Validate URL domain (security measure) var allowedDomains = _configuration.GetSection("AllowedDomains").Get<string[]>() ?? new[] { "blob.core.windows.net", "s3.amazonaws.com" }; if (!allowedDomains.Any(domain => uri.Host.EndsWith(domain))) { _logger.LogWarning($"Rejected URL from unauthorized domain: {uri.Host}"); return BadRequest(new ScanResult { Success = false, ErrorMessage = "URL domain not authorized" }); } try { using var httpClient = _httpClientFactory.CreateClient("BarcodeScanner"); httpClient.Timeout = TimeSpan.FromSeconds(30); // Add headers to avoid being blocked httpClient.DefaultRequestHeaders.Add("User-Agent", "BarcodeScannerAPI/2.0"); var response = await httpClient.GetAsync(uri); response.EnsureSuccessStatusCode(); // Check content type var contentType = response.Content.Headers.ContentType?.MediaType; if (!IsValidContentType(contentType)) { return BadRequest(new ScanResult { Success = false, ErrorMessage = $"Unsupported content type: {contentType}" }); } var imageBytes = await response.Content.ReadAsByteArrayAsync(); // Use async processing for better scalability var results = await BarcodeReader.ReadAsync(imageBytes); return ProcessResults(results, "url", uri.ToString()); } catch (HttpRequestException ex) { _logger.LogError(ex, $"Failed to download from URL: {uri}"); return BadRequest(new ScanResult { Success = false, ErrorMessage = "Failed to download image from URL" }); } catch (TaskCanceledException) { return BadRequest(new ScanResult { Success = false, ErrorMessage = "Download timeout - file too large or slow connection" }); } } // Handle multi-page PDFs with page-specific processing [HttpPost("scan-pdf-advanced")] public async Task<ActionResult<PdfScanResult>> ScanPdfAdvanced([FromForm] PdfScanRequest request) { using var stream = new MemoryStream(); await request.File.CopyToAsync(stream); var pdfOptions = new PdfBarcodeReaderOptions { Scale = request.Scale ?? 3, DPI = request.DPI ?? 300, PageNumbers = request.PageNumbers, Password = request.Password, MaxThreads = Math.Min(request.MaxThreads ?? 4, Environment.ProcessorCount) }; // For large PDFs, process in chunks if (stream.Length > 50 * 1024 * 1024) // 50MB { _logger.LogInformation($"Large PDF detected ({stream.Length / 1024 / 1024}MB), using chunked processing"); pdfOptions.MaxThreads = 2; // Reduce memory pressure } var results = BarcodeReader.ReadPdf(stream.ToArray(), pdfOptions); // Group results by page var pageResults = results.GroupBy(r => r.PageNumber) .OrderBy(g => g.Key) .Select(g => new PageBarcodeResult { PageNumber = g.Key, BarcodeCount = g.Count(), Barcodes = g.Select(b => new BarcodeData { Value = b.Value, Format = b.BarcodeType.ToString(), Confidence = b.Confidence, Location = b.Bounds }).ToList() }).ToList(); return Ok(new PdfScanResult { Success = true, TotalPages = pageResults.Count, TotalBarcodes = results.Count(), PageResults = pageResults, RequestId = Guid.NewGuid().ToString() }); } // Handle damaged or low-quality barcodes [HttpPost("scan-damaged")] public async Task<ActionResult<ScanResult>> ScanDamagedBarcode([FromForm] IFormFile file) { using var stream = new MemoryStream(); await file.CopyToAsync(stream); // Aggressive image correction for damaged barcodes var options = new BarcodeReaderOptions { Speed = ReadingSpeed.ExtremeDetail, ImageFilters = new ImageFilterCollection { new SharpenFilter(4), new ContrastFilter(3), new BrightnessFilter(1.5f), new BinaryThresholdFilter(128), new DeNoise(3) }, TryInvertColor = true, AutoRotate = true, UseCode39ExtendedMode = true, RemoveFalsePositive = false, // Accept lower confidence Confidence = ConfidenceLevel.Low }; var results = BarcodeReader.Read(stream.ToArray(), options); // If still no results, try with different threshold if (!results.Any()) { options.ImageFilters = new ImageFilterCollection { new AdaptiveThresholdFilter(9), new MedianFilter(3), new Dilate(1) }; results = BarcodeReader.Read(stream.ToArray(), options); } return ProcessResults(results, "damaged", file.FileName); } private bool IsValidContentType(string contentType) { var validTypes = new[] { "image/jpeg", "image/jpg", "image/png", "image/gif", "image/tiff", "image/bmp", "application/pdf" }; return validTypes.Contains(contentType?.ToLower()); } private ActionResult<ScanResult> ProcessResults(BarcodeResults results, string source, string identifier) { var scanResult = new ScanResult { Metadata = new Dictionary<string, object> { ["Source"] = source, ["Identifier"] = identifier, ["ProcessedAt"] = DateTime.UtcNow } }; if (results.Any()) { scanResult.Success = true; scanResult.Barcodes = results.Select(r => new BarcodeData { Value = r.Value, Format = r.BarcodeType.ToString(), Confidence = r.Confidence, Location = r.Bounds }).ToList(); // Log low confidence results for quality monitoring var lowConfidence = results.Where(r => r.Confidence < 70).ToList(); if (lowConfidence.Any()) { _logger.LogWarning($"Low confidence barcodes detected: {lowConfidence.Count} of {results.Count()} from {identifier}"); } } else { scanResult.Success = false; scanResult.ErrorMessage = "No barcodes detected"; } return Ok(scanResult); } } // Request models public class Base64Request { [Required] public string ImageData { get; set; } public string FileName { get; set; } } public class UrlScanRequest { [Required] [Url] public string Url { get; set; } } public class PdfScanRequest { [Required] public IFormFile File { get; set; } public int? Scale { get; set; } public int? DPI { get; set; } public int[] PageNumbers { get; set; } public string Password { get; set; } public int? MaxThreads { get; set; } } // Response models public class PdfScanResult : ScanResult { public int TotalPages { get; set; } public int TotalBarcodes { get; set; } public List<PageBarcodeResult> PageResults { get; set; } } public class PageBarcodeResult { public int PageNumber { get; set; } public int BarcodeCount { get; set; } public List<BarcodeData> Barcodes { get; set; } } Imports System Imports System.Collections.Generic Imports System.IO Imports System.Linq Imports System.Net.Http Imports System.Threading.Tasks Imports Microsoft.AspNetCore.Authorization Imports Microsoft.AspNetCore.Http Imports Microsoft.AspNetCore.Mvc Imports Microsoft.Extensions.Configuration Imports Microsoft.Extensions.Logging <ApiController> <Route("api/v1/[controller]")> <Authorize> Public Class AdvancedScannerController Inherits ControllerBase Private ReadOnly _httpClientFactory As IHttpClientFactory Private ReadOnly _logger As ILogger(Of AdvancedScannerController) Private ReadOnly _configuration As IConfiguration Public Sub New(httpClientFactory As IHttpClientFactory, logger As ILogger(Of AdvancedScannerController), configuration As IConfiguration) _httpClientFactory = httpClientFactory _logger = logger _configuration = configuration End Sub ' Handle Base64 input (common in web applications) <HttpPost("scan-base64")> Public Function ScanBase64(<FromBody> request As Base64Request) As ActionResult(Of ScanResult) If Not ModelState.IsValid Then Return BadRequest(ModelState) End If Try ' Validate Base64 format Dim base64Data = request.ImageData If base64Data.Contains(",") Then ' Handle data URL format: "data:image/png;base64,..." base64Data = base64Data.Substring(base64Data.IndexOf(",") + 1) End If Dim imageBytes = Convert.FromBase64String(base64Data) ' Implement size validation If imageBytes.Length > 10 * 1024 * 1024 Then ' 10MB limit Return BadRequest(New ScanResult With { .Success = False, .ErrorMessage = "Image size exceeds 10MB limit" }) End If ' Configure for web-uploaded images (often lower quality) Dim options = New BarcodeReaderOptions With { .Speed = ReadingSpeed.Detailed, .ImageFilters = New ImageFilterCollection From { New SharpenFilter(3), New ContrastFilter(2), New DeNoise() }, .TryInvertColor = True, ' Handle inverted barcodes .AutoRotate = True } Dim results = BarcodeReader.Read(imageBytes, options) Return ProcessResults(results, "base64", request.FileName) Catch ex As FormatException Return BadRequest(New ScanResult With { .Success = False, .ErrorMessage = "Invalid Base64 format" }) End Try End Function ' Handle URL input (for cloud storage integration) <HttpPost("scan-url")> Public Async Function ScanFromUrl(<FromBody> request As UrlScanRequest) As Task(Of ActionResult(Of ScanResult)) Dim uri As Uri = Nothing If Not Uri.TryCreate(request.Url, UriKind.Absolute, uri) Then Return BadRequest(New ScanResult With { .Success = False, .ErrorMessage = "Invalid URL format" }) End If ' Validate URL domain (security measure) Dim allowedDomains = _configuration.GetSection("AllowedDomains").Get(Of String())() _ ?? New String() {"blob.core.windows.net", "s3.amazonaws.com"} If Not allowedDomains.Any(Function(domain) uri.Host.EndsWith(domain)) Then _logger.LogWarning($"Rejected URL from unauthorized domain: {uri.Host}") Return BadRequest(New ScanResult With { .Success = False, .ErrorMessage = "URL domain not authorized" }) End If Try Using httpClient = _httpClientFactory.CreateClient("BarcodeScanner") httpClient.Timeout = TimeSpan.FromSeconds(30) ' Add headers to avoid being blocked httpClient.DefaultRequestHeaders.Add("User-Agent", "BarcodeScannerAPI/2.0") Dim response = Await httpClient.GetAsync(uri) response.EnsureSuccessStatusCode() ' Check content type Dim contentType = response.Content.Headers.ContentType?.MediaType If Not IsValidContentType(contentType) Then Return BadRequest(New ScanResult With { .Success = False, .ErrorMessage = $"Unsupported content type: {contentType}" }) End If Dim imageBytes = Await response.Content.ReadAsByteArrayAsync() ' Use async processing for better scalability Dim results = Await BarcodeReader.ReadAsync(imageBytes) Return ProcessResults(results, "url", uri.ToString()) End Using Catch ex As HttpRequestException _logger.LogError(ex, $"Failed to download from URL: {uri}") Return BadRequest(New ScanResult With { .Success = False, .ErrorMessage = "Failed to download image from URL" }) Catch ex As TaskCanceledException Return BadRequest(New ScanResult With { .Success = False, .ErrorMessage = "Download timeout - file too large or slow connection" }) End Try End Function ' Handle multi-page PDFs with page-specific processing <HttpPost("scan-pdf-advanced")> Public Async Function ScanPdfAdvanced(<FromForm> request As PdfScanRequest) As Task(Of ActionResult(Of PdfScanResult)) Using stream = New MemoryStream() Await request.File.CopyToAsync(stream) Dim pdfOptions = New PdfBarcodeReaderOptions With { .Scale = If(request.Scale, 3), .DPI = If(request.DPI, 300), .PageNumbers = request.PageNumbers, .Password = request.Password, .MaxThreads = Math.Min(If(request.MaxThreads, 4), Environment.ProcessorCount) } ' For large PDFs, process in chunks If stream.Length > 50 * 1024 * 1024 Then ' 50MB _logger.LogInformation($"Large PDF detected ({stream.Length / 1024 / 1024}MB), using chunked processing") pdfOptions.MaxThreads = 2 ' Reduce memory pressure End If Dim results = BarcodeReader.ReadPdf(stream.ToArray(), pdfOptions) ' Group results by page Dim pageResults = results.GroupBy(Function(r) r.PageNumber) _ .OrderBy(Function(g) g.Key) _ .Select(Function(g) New PageBarcodeResult With { .PageNumber = g.Key, .BarcodeCount = g.Count(), .Barcodes = g.Select(Function(b) New BarcodeData With { .Value = b.Value, .Format = b.BarcodeType.ToString(), .Confidence = b.Confidence, .Location = b.Bounds }).ToList() }).ToList() Return Ok(New PdfScanResult With { .Success = True, .TotalPages = pageResults.Count, .TotalBarcodes = results.Count(), .PageResults = pageResults, .RequestId = Guid.NewGuid().ToString() }) End Using End Function ' Handle damaged or low-quality barcodes <HttpPost("scan-damaged")> Public Async Function ScanDamagedBarcode(<FromForm> file As IFormFile) As Task(Of ActionResult(Of ScanResult)) Using stream = New MemoryStream() Await file.CopyToAsync(stream) ' Aggressive image correction for damaged barcodes Dim options = New BarcodeReaderOptions With { .Speed = ReadingSpeed.ExtremeDetail, .ImageFilters = New ImageFilterCollection From { New SharpenFilter(4), New ContrastFilter(3), New BrightnessFilter(1.5F), New BinaryThresholdFilter(128), New DeNoise(3) }, .TryInvertColor = True, .AutoRotate = True, .UseCode39ExtendedMode = True, .RemoveFalsePositive = False, ' Accept lower confidence .Confidence = ConfidenceLevel.Low } Dim results = BarcodeReader.Read(stream.ToArray(), options) ' If still no results, try with different threshold If Not results.Any() Then options.ImageFilters = New ImageFilterCollection From { New AdaptiveThresholdFilter(9), New MedianFilter(3), New Dilate(1) } results = BarcodeReader.Read(stream.ToArray(), options) End If Return ProcessResults(results, "damaged", file.FileName) End Using End Function Private Function IsValidContentType(contentType As String) As Boolean Dim validTypes = New String() { "image/jpeg", "image/jpg", "image/png", "image/gif", "image/tiff", "image/bmp", "application/pdf" } Return validTypes.Contains(contentType?.ToLower()) End Function Private Function ProcessResults(results As BarcodeResults, source As String, identifier As String) As ActionResult(Of ScanResult) Dim scanResult = New ScanResult With { .Metadata = New Dictionary(Of String, Object) From { {"Source", source}, {"Identifier", identifier}, {"ProcessedAt", DateTime.UtcNow} } } If results.Any() Then scanResult.Success = True scanResult.Barcodes = results.Select(Function(r) New BarcodeData With { .Value = r.Value, .Format = r.BarcodeType.ToString(), .Confidence = r.Confidence, .Location = r.Bounds }).ToList() ' Log low confidence results for quality monitoring Dim lowConfidence = results.Where(Function(r) r.Confidence < 70).ToList() If lowConfidence.Any() Then _logger.LogWarning($"Low confidence barcodes detected: {lowConfidence.Count} of {results.Count()} from {identifier}") End If Else scanResult.Success = False scanResult.ErrorMessage = "No barcodes detected" End If Return Ok(scanResult) End Function End Class ' Request models Public Class Base64Request <Required> Public Property ImageData As String Public Property FileName As String End Class Public Class UrlScanRequest <Required> <Url> Public Property Url As String End Class Public Class PdfScanRequest <Required> Public Property File As IFormFile Public Property Scale As Integer? Public Property DPI As Integer? Public Property PageNumbers As Integer() Public Property Password As String Public Property MaxThreads As Integer? End Class ' Response models Public Class PdfScanResult Inherits ScanResult Public Property TotalPages As Integer Public Property TotalBarcodes As Integer Public Property PageResults As List(Of PageBarcodeResult) End Class Public Class PageBarcodeResult Public Property PageNumber As Integer Public Property BarcodeCount As Integer Public Property Barcodes As List(Of BarcodeData) End Class $vbLabelText $csharpLabel この完全な実装は、実際のエンタープライズ シナリオに対応します。 URL スキャン エンドポイントには、サーバー側リクエスト フォージェリ (SSRF) 攻撃を防ぐためのドメイン検証が含まれています。 Base64 ハンドラーは、Web アプリケーションから画像を受信するときによく使用されるデータ URL プレフィックスを削除します。 破損したバーコード エンドポイントは、IronBarcode の画像修正機能を実証します。 複数のフィルターを適用し、さまざまなアプローチを試すことで、著しく劣化した画像からデータを回復できます。 これは、古い在庫ラベルや天候により損傷した出荷書類を処理するときに非常に役立ちます。 PDFと画像スキャンの選択 PDF は、企業のバーコード スキャンにおいて特有の課題と機会をもたらします。 請求書、出荷明細書、コンプライアンス フォームなどの多くのビジネス ドキュメントは、バーコードが埋め込まれた PDF として届きます。 IronBarcode のPDF バーコード読み取り機能は、これらのシナリオを適切に処理します。 典型的な企業のシナリオを考えてみましょう。買掛金部門は毎月何千もの請求書を受け取りますが、各請求書には自動処理用のバーコードが含まれています。 高品質の PDF を送信するベンダーもあれば、品質の異なるスキャンされたドキュメントを送信するベンダーもあります。 高度な PDF スキャン エンドポイントは、両方のシナリオを処理します。 高品質の PDF の場合、標準設定で十分です。 スキャンされたドキュメントの場合、DPI とスケール パラメータを増やすと検出率が向上します。 ページ固有の処理により、特定のページからバーコードを抽出できます。これは、請求書の最初のページに必ずバーコードがあることが分かっている場合に便利です。 ページごとにグループ化された結果は貴重なコンテキストを提供します。 ワークフロー システムでは、バーコードが含まれているページに基づいてドキュメントをルーティングし、ドキュメントの分類を自動化できます。 複数ページのドキュメント処理に対するこの構造化されたアプローチは、手動プロセスを効率的な自動ワークフローに変換します。 複数のバーコードを効率的に処理 企業文書には、さまざまな目的で使用される複数のバーコードが含まれていることがよくあります。 配送ラベルには、追跡バーコード、製品バーコード、および宛先バーコードが含まれる場合があります。 複数のバーコード シナリオを適切に処理するには、慎重な API 設計が必要です。 バッチ処理エンドポイントは、大量のシナリオを効率的に処理する方法を示します。 複数のファイルを並列処理することで、全体の処理時間を大幅に短縮できます。Task.WhenAllパターンはWhenAllシステムの安定性を維持しながら、最適なリソース利用を実現します。 アプリケーションでバーコードを作成する場合も、IronBarcode は同様に効果的な機能を提供します。 在庫システム用の1D リニア バーコードを生成する必要がある場合でも、モバイル アプリケーション用の2D マトリックス コードを作成する場合でも、同じシンプルな API アプローチが適用されます。 パフォーマンスと精度の向上 エンタープライズ バーコード スキャンにおけるパフォーマンスの最適化は、速度だけではなく、特定のユース ケースに適したバランスを見つけることです。 スキャン パフォーマンスを変革できる高度な最適化手法を見てみましょう。 public class OptimizedScannerService { private readonly ILogger<OptimizedScannerService> _logger; private readonly IMemoryCache _cache; public OptimizedScannerService(ILogger<OptimizedScannerService> logger, IMemoryCache cache) { _logger = logger; _cache = cache; } // Performance-optimized scanning with caching public async Task<ScanResult> ScanWithOptimizationsAsync(byte[] imageData, string cacheKey = null) { // Check cache for repeat scans if (!string.IsNullOrEmpty(cacheKey)) { if (_cache.TryGetValue(cacheKey, out ScanResult cachedResult)) { _logger.LogInformation($"Cache hit for {cacheKey}"); cachedResult.Metadata["CacheHit"] = true; return cachedResult; } } // Determine optimal settings based on image characteristics var settings = await DetermineOptimalSettingsAsync(imageData); // Apply region-specific scanning if applicable if (settings.UseRegionScanning) { return await ScanWithRegionsAsync(imageData, settings); } // Standard optimized scanning var results = await BarcodeReader.ReadAsync(imageData, settings.Options); var scanResult = BuildScanResult(results); // Cache successful results if (!string.IsNullOrEmpty(cacheKey) && scanResult.Success) { _cache.Set(cacheKey, scanResult, TimeSpan.FromMinutes(5)); } return scanResult; } // Intelligent settings determination private async Task<ScanSettings> DetermineOptimalSettingsAsync(byte[] imageData) { var settings = new ScanSettings(); // Quick analysis of image properties using var ms = new MemoryStream(imageData); using var image = Image.FromStream(ms); var width = image.Width; var height = image.Height; var aspectRatio = (double)width / height; _logger.LogInformation($"Image analysis: {width}x{height}, ratio: {aspectRatio:F2}"); // High-resolution images can use faster scanning if (width > 2000 && height > 2000) { settings.Options.Speed = ReadingSpeed.Faster; settings.Options.ExpectBarcodeTypes = BarcodeEncoding.QRCode | BarcodeEncoding.Code128; } // Low-resolution needs more processing else if (width < 800 || height < 800) { settings.Options.Speed = ReadingSpeed.ExtremeDetail; settings.Options.ImageFilters = new ImageFilterCollection { new SharpenFilter(3), new ContrastFilter(2) }; } else { settings.Options.Speed = ReadingSpeed.Balanced; } // Detect if image might contain multiple barcodes based on aspect ratio if (aspectRatio > 2 || aspectRatio < 0.5) { settings.Options.ExpectMultipleBarcodes = true; settings.UseRegionScanning = true; } // Enable rotation correction for potentially skewed images settings.Options.AutoRotate = true; return settings; } // Region-based scanning for large images private async Task<ScanResult> ScanWithRegionsAsync(byte[] imageData, ScanSettings settings) { var allResults = new List<BarcodeResult>(); using var ms = new MemoryStream(imageData); using var image = Image.FromStream(ms); // Define scanning regions for common document layouts var regions = new[] { new Rectangle(0, 0, image.Width / 2, image.Height / 2), // Top-left new Rectangle(image.Width / 2, 0, image.Width / 2, image.Height / 2), // Top-right new Rectangle(0, image.Height / 2, image.Width / 2, image.Height / 2), // Bottom-left new Rectangle(image.Width / 2, image.Height / 2, image.Width / 2, image.Height / 2), // Bottom-right new Rectangle(image.Width / 4, image.Height / 4, image.Width / 2, image.Height / 2) // Center }; var tasks = regions.Select(async region => { var regionOptions = new BarcodeReaderOptions { CropArea = region, Speed = ReadingSpeed.Faster, ExpectMultipleBarcodes = false }; try { return await BarcodeReader.ReadAsync(imageData, regionOptions); } catch (Exception ex) { _logger.LogWarning($"Region scan failed: {ex.Message}"); return new BarcodeResult[0]; } }); var regionResults = await Task.WhenAll(tasks); // Combine and deduplicate results var uniqueResults = regionResults .SelectMany(r => r) .GroupBy(r => r.Value) .Select(g => g.OrderByDescending(r => r.Confidence).First()) .ToList(); return BuildScanResult(uniqueResults); } // Adaptive quality enhancement public async Task<ScanResult> ScanWithAdaptiveEnhancementAsync(byte[] imageData) { var attempts = new List<Func<Task<BarcodeResults>>> { // Attempt 1: Fast scan async () => await BarcodeReader.ReadAsync(imageData, new BarcodeReaderOptions { Speed = ReadingSpeed.Faster, RemoveFalsePositive = true }), // Attempt 2: Standard scan with basic filters async () => await BarcodeReader.ReadAsync(imageData, new BarcodeReaderOptions { Speed = ReadingSpeed.Balanced, ImageFilters = new ImageFilterCollection { new ContrastFilter(1.5f), new SharpenFilter(1) }, TryInvertColor = true }), // Attempt 3: Detailed scan with aggressive filtering async () => await BarcodeReader.ReadAsync(imageData, new BarcodeReaderOptions { Speed = ReadingSpeed.Detailed, ImageFilters = new ImageFilterCollection { new AdaptiveThresholdFilter(11), new DeNoise(2), new MedianFilter(3) }, AutoRotate = true, Confidence = ConfidenceLevel.Low }), // Attempt 4: Extreme processing for damaged barcodes async () => await BarcodeReader.ReadAsync(imageData, new BarcodeReaderOptions { Speed = ReadingSpeed.ExtremeDetail, ImageFilters = new ImageFilterCollection { new BinaryThresholdFilter(100), new Erode(1), new Dilate(2), new SharpenFilter(4) }, RemoveFalsePositive = false, UseCode39ExtendedMode = true, TryInvertColor = true }) }; foreach (var (attempt, index) in attempts.Select((a, i) => (a, i))) { var stopwatch = Stopwatch.StartNew(); var results = await attempt(); stopwatch.Stop(); _logger.LogInformation($"Attempt {index + 1} took {stopwatch.ElapsedMilliseconds}ms, found {results.Count()} barcodes"); if (results.Any()) { var scanResult = BuildScanResult(results); scanResult.Metadata["AttemptNumber"] = index + 1; scanResult.Metadata["ProcessingStrategy"] = GetStrategyName(index); return scanResult; } } return new ScanResult { Success = false, ErrorMessage = "No barcodes found after all enhancement attempts" }; } // Machine learning confidence optimization public class MLOptimizedScanner { private readonly Dictionary<string, double> _formatConfidenceThresholds = new() { { "QRCode", 85.0 }, { "Code128", 90.0 }, { "Code39", 88.0 }, { "DataMatrix", 87.0 }, { "EAN13", 92.0 }, { "PDF417", 86.0 } }; public async Task<ScanResult> ScanWithMLConfidenceAsync(byte[] imageData, string expectedFormat = null) { var options = new BarcodeReaderOptions { Speed = ReadingSpeed.Balanced, Confidence = ConfidenceLevel.Optional }; // If we know the expected format, improve for it if (!string.IsNullOrEmpty(expectedFormat) && Enum.TryParse<BarcodeEncoding>(expectedFormat, out var encoding)) { options.ExpectBarcodeTypes = encoding; } var results = await BarcodeReader.ReadAsync(imageData, options); // Apply ML confidence filtering var confidenceThreshold = expectedFormat != null && _formatConfidenceThresholds.ContainsKey(expectedFormat) ? _formatConfidenceThresholds[expectedFormat] : 80.0; var highConfidenceResults = results .Where(r => r.Confidence >= confidenceThreshold) .ToList(); if (highConfidenceResults.Any()) { return BuildScanResult(highConfidenceResults); } // If no high-confidence results, include lower confidence with warnings var lowConfidenceResults = results .Where(r => r.Confidence < confidenceThreshold) .ToList(); if (lowConfidenceResults.Any()) { var result = BuildScanResult(lowConfidenceResults); result.Metadata["Warning"] = "Low confidence results - manual verification recommended"; result.Metadata["MinConfidence"] = lowConfidenceResults.Min(r => r.Confidence); return result; } return new ScanResult { Success = false, ErrorMessage = "No barcodes met confidence threshold" }; } } private ScanResult BuildScanResult(IEnumerable<BarcodeResult> results) { var resultList = results.ToList(); return new ScanResult { Success = true, Barcodes = resultList.Select(r => new BarcodeData { Value = r.Value, Format = r.BarcodeType.ToString(), Confidence = r.Confidence, Location = r.Bounds }).ToList(), Metadata = new Dictionary<string, object> { ["TotalFound"] = resultList.Count, ["AverageConfidence"] = resultList.Average(r => r.Confidence), ["Formats"] = resultList.Select(r => r.BarcodeType.ToString()).Distinct().ToArray() } }; } private string GetStrategyName(int attemptIndex) { return attemptIndex switch { 0 => "FastScan", 1 => "StandardEnhanced", 2 => "DetailedFiltering", 3 => "ExtremeDamageRecovery", _ => "Unknown" }; } } // Supporting classes public class ScanSettings { public BarcodeReaderOptions Options { get; set; } = new BarcodeReaderOptions(); public bool UseRegionScanning { get; set; } public List<Rectangle> CustomRegions { get; set; } } // Benchmark service for performance testing public class BenchmarkService { private readonly ILogger<BenchmarkService> _logger; public async Task<BenchmarkResult> BenchmarkSettingsAsync(byte[] testImage, int iterations = 10) { var results = new Dictionary<string, BenchmarkData>(); var testConfigurations = new Dictionary<string, BarcodeReaderOptions> { ["Fastest"] = new() { Speed = ReadingSpeed.Faster }, ["Balanced"] = new() { Speed = ReadingSpeed.Balanced }, ["Detailed"] = new() { Speed = ReadingSpeed.Detailed }, ["Parallel"] = new() { Speed = ReadingSpeed.Balanced, Multithreaded = true, MaxParallelThreads = 4 }, ["Filtered"] = new() { Speed = ReadingSpeed.Balanced, ImageFilters = new ImageFilterCollection { new SharpenFilter(2), new ContrastFilter(1.5f) } } }; foreach (var config in testConfigurations) { var times = new List<long>(); var successCount = 0; for (int i = 0; i < iterations; i++) { var sw = Stopwatch.StartNew(); var scanResults = await BarcodeReader.ReadAsync(testImage, config.Value); sw.Stop(); times.Add(sw.ElapsedMilliseconds); if (scanResults.Any()) successCount++; // Small delay between tests await Task.Delay(100); } results[config.Key] = new BenchmarkData { AverageMs = times.Average(), MinMs = times.Min(), MaxMs = times.Max(), SuccessRate = (double)successCount / iterations * 100 }; } return new BenchmarkResult { Results = results }; } } public class BenchmarkData { public double AverageMs { get; set; } public long MinMs { get; set; } public long MaxMs { get; set; } public double SuccessRate { get; set; } } public class BenchmarkResult { public Dictionary<string, BenchmarkData> Results { get; set; } } public class OptimizedScannerService { private readonly ILogger<OptimizedScannerService> _logger; private readonly IMemoryCache _cache; public OptimizedScannerService(ILogger<OptimizedScannerService> logger, IMemoryCache cache) { _logger = logger; _cache = cache; } // Performance-optimized scanning with caching public async Task<ScanResult> ScanWithOptimizationsAsync(byte[] imageData, string cacheKey = null) { // Check cache for repeat scans if (!string.IsNullOrEmpty(cacheKey)) { if (_cache.TryGetValue(cacheKey, out ScanResult cachedResult)) { _logger.LogInformation($"Cache hit for {cacheKey}"); cachedResult.Metadata["CacheHit"] = true; return cachedResult; } } // Determine optimal settings based on image characteristics var settings = await DetermineOptimalSettingsAsync(imageData); // Apply region-specific scanning if applicable if (settings.UseRegionScanning) { return await ScanWithRegionsAsync(imageData, settings); } // Standard optimized scanning var results = await BarcodeReader.ReadAsync(imageData, settings.Options); var scanResult = BuildScanResult(results); // Cache successful results if (!string.IsNullOrEmpty(cacheKey) && scanResult.Success) { _cache.Set(cacheKey, scanResult, TimeSpan.FromMinutes(5)); } return scanResult; } // Intelligent settings determination private async Task<ScanSettings> DetermineOptimalSettingsAsync(byte[] imageData) { var settings = new ScanSettings(); // Quick analysis of image properties using var ms = new MemoryStream(imageData); using var image = Image.FromStream(ms); var width = image.Width; var height = image.Height; var aspectRatio = (double)width / height; _logger.LogInformation($"Image analysis: {width}x{height}, ratio: {aspectRatio:F2}"); // High-resolution images can use faster scanning if (width > 2000 && height > 2000) { settings.Options.Speed = ReadingSpeed.Faster; settings.Options.ExpectBarcodeTypes = BarcodeEncoding.QRCode | BarcodeEncoding.Code128; } // Low-resolution needs more processing else if (width < 800 || height < 800) { settings.Options.Speed = ReadingSpeed.ExtremeDetail; settings.Options.ImageFilters = new ImageFilterCollection { new SharpenFilter(3), new ContrastFilter(2) }; } else { settings.Options.Speed = ReadingSpeed.Balanced; } // Detect if image might contain multiple barcodes based on aspect ratio if (aspectRatio > 2 || aspectRatio < 0.5) { settings.Options.ExpectMultipleBarcodes = true; settings.UseRegionScanning = true; } // Enable rotation correction for potentially skewed images settings.Options.AutoRotate = true; return settings; } // Region-based scanning for large images private async Task<ScanResult> ScanWithRegionsAsync(byte[] imageData, ScanSettings settings) { var allResults = new List<BarcodeResult>(); using var ms = new MemoryStream(imageData); using var image = Image.FromStream(ms); // Define scanning regions for common document layouts var regions = new[] { new Rectangle(0, 0, image.Width / 2, image.Height / 2), // Top-left new Rectangle(image.Width / 2, 0, image.Width / 2, image.Height / 2), // Top-right new Rectangle(0, image.Height / 2, image.Width / 2, image.Height / 2), // Bottom-left new Rectangle(image.Width / 2, image.Height / 2, image.Width / 2, image.Height / 2), // Bottom-right new Rectangle(image.Width / 4, image.Height / 4, image.Width / 2, image.Height / 2) // Center }; var tasks = regions.Select(async region => { var regionOptions = new BarcodeReaderOptions { CropArea = region, Speed = ReadingSpeed.Faster, ExpectMultipleBarcodes = false }; try { return await BarcodeReader.ReadAsync(imageData, regionOptions); } catch (Exception ex) { _logger.LogWarning($"Region scan failed: {ex.Message}"); return new BarcodeResult[0]; } }); var regionResults = await Task.WhenAll(tasks); // Combine and deduplicate results var uniqueResults = regionResults .SelectMany(r => r) .GroupBy(r => r.Value) .Select(g => g.OrderByDescending(r => r.Confidence).First()) .ToList(); return BuildScanResult(uniqueResults); } // Adaptive quality enhancement public async Task<ScanResult> ScanWithAdaptiveEnhancementAsync(byte[] imageData) { var attempts = new List<Func<Task<BarcodeResults>>> { // Attempt 1: Fast scan async () => await BarcodeReader.ReadAsync(imageData, new BarcodeReaderOptions { Speed = ReadingSpeed.Faster, RemoveFalsePositive = true }), // Attempt 2: Standard scan with basic filters async () => await BarcodeReader.ReadAsync(imageData, new BarcodeReaderOptions { Speed = ReadingSpeed.Balanced, ImageFilters = new ImageFilterCollection { new ContrastFilter(1.5f), new SharpenFilter(1) }, TryInvertColor = true }), // Attempt 3: Detailed scan with aggressive filtering async () => await BarcodeReader.ReadAsync(imageData, new BarcodeReaderOptions { Speed = ReadingSpeed.Detailed, ImageFilters = new ImageFilterCollection { new AdaptiveThresholdFilter(11), new DeNoise(2), new MedianFilter(3) }, AutoRotate = true, Confidence = ConfidenceLevel.Low }), // Attempt 4: Extreme processing for damaged barcodes async () => await BarcodeReader.ReadAsync(imageData, new BarcodeReaderOptions { Speed = ReadingSpeed.ExtremeDetail, ImageFilters = new ImageFilterCollection { new BinaryThresholdFilter(100), new Erode(1), new Dilate(2), new SharpenFilter(4) }, RemoveFalsePositive = false, UseCode39ExtendedMode = true, TryInvertColor = true }) }; foreach (var (attempt, index) in attempts.Select((a, i) => (a, i))) { var stopwatch = Stopwatch.StartNew(); var results = await attempt(); stopwatch.Stop(); _logger.LogInformation($"Attempt {index + 1} took {stopwatch.ElapsedMilliseconds}ms, found {results.Count()} barcodes"); if (results.Any()) { var scanResult = BuildScanResult(results); scanResult.Metadata["AttemptNumber"] = index + 1; scanResult.Metadata["ProcessingStrategy"] = GetStrategyName(index); return scanResult; } } return new ScanResult { Success = false, ErrorMessage = "No barcodes found after all enhancement attempts" }; } // Machine learning confidence optimization public class MLOptimizedScanner { private readonly Dictionary<string, double> _formatConfidenceThresholds = new() { { "QRCode", 85.0 }, { "Code128", 90.0 }, { "Code39", 88.0 }, { "DataMatrix", 87.0 }, { "EAN13", 92.0 }, { "PDF417", 86.0 } }; public async Task<ScanResult> ScanWithMLConfidenceAsync(byte[] imageData, string expectedFormat = null) { var options = new BarcodeReaderOptions { Speed = ReadingSpeed.Balanced, Confidence = ConfidenceLevel.Optional }; // If we know the expected format, improve for it if (!string.IsNullOrEmpty(expectedFormat) && Enum.TryParse<BarcodeEncoding>(expectedFormat, out var encoding)) { options.ExpectBarcodeTypes = encoding; } var results = await BarcodeReader.ReadAsync(imageData, options); // Apply ML confidence filtering var confidenceThreshold = expectedFormat != null && _formatConfidenceThresholds.ContainsKey(expectedFormat) ? _formatConfidenceThresholds[expectedFormat] : 80.0; var highConfidenceResults = results .Where(r => r.Confidence >= confidenceThreshold) .ToList(); if (highConfidenceResults.Any()) { return BuildScanResult(highConfidenceResults); } // If no high-confidence results, include lower confidence with warnings var lowConfidenceResults = results .Where(r => r.Confidence < confidenceThreshold) .ToList(); if (lowConfidenceResults.Any()) { var result = BuildScanResult(lowConfidenceResults); result.Metadata["Warning"] = "Low confidence results - manual verification recommended"; result.Metadata["MinConfidence"] = lowConfidenceResults.Min(r => r.Confidence); return result; } return new ScanResult { Success = false, ErrorMessage = "No barcodes met confidence threshold" }; } } private ScanResult BuildScanResult(IEnumerable<BarcodeResult> results) { var resultList = results.ToList(); return new ScanResult { Success = true, Barcodes = resultList.Select(r => new BarcodeData { Value = r.Value, Format = r.BarcodeType.ToString(), Confidence = r.Confidence, Location = r.Bounds }).ToList(), Metadata = new Dictionary<string, object> { ["TotalFound"] = resultList.Count, ["AverageConfidence"] = resultList.Average(r => r.Confidence), ["Formats"] = resultList.Select(r => r.BarcodeType.ToString()).Distinct().ToArray() } }; } private string GetStrategyName(int attemptIndex) { return attemptIndex switch { 0 => "FastScan", 1 => "StandardEnhanced", 2 => "DetailedFiltering", 3 => "ExtremeDamageRecovery", _ => "Unknown" }; } } // Supporting classes public class ScanSettings { public BarcodeReaderOptions Options { get; set; } = new BarcodeReaderOptions(); public bool UseRegionScanning { get; set; } public List<Rectangle> CustomRegions { get; set; } } // Benchmark service for performance testing public class BenchmarkService { private readonly ILogger<BenchmarkService> _logger; public async Task<BenchmarkResult> BenchmarkSettingsAsync(byte[] testImage, int iterations = 10) { var results = new Dictionary<string, BenchmarkData>(); var testConfigurations = new Dictionary<string, BarcodeReaderOptions> { ["Fastest"] = new() { Speed = ReadingSpeed.Faster }, ["Balanced"] = new() { Speed = ReadingSpeed.Balanced }, ["Detailed"] = new() { Speed = ReadingSpeed.Detailed }, ["Parallel"] = new() { Speed = ReadingSpeed.Balanced, Multithreaded = true, MaxParallelThreads = 4 }, ["Filtered"] = new() { Speed = ReadingSpeed.Balanced, ImageFilters = new ImageFilterCollection { new SharpenFilter(2), new ContrastFilter(1.5f) } } }; foreach (var config in testConfigurations) { var times = new List<long>(); var successCount = 0; for (int i = 0; i < iterations; i++) { var sw = Stopwatch.StartNew(); var scanResults = await BarcodeReader.ReadAsync(testImage, config.Value); sw.Stop(); times.Add(sw.ElapsedMilliseconds); if (scanResults.Any()) successCount++; // Small delay between tests await Task.Delay(100); } results[config.Key] = new BenchmarkData { AverageMs = times.Average(), MinMs = times.Min(), MaxMs = times.Max(), SuccessRate = (double)successCount / iterations * 100 }; } return new BenchmarkResult { Results = results }; } } public class BenchmarkData { public double AverageMs { get; set; } public long MinMs { get; set; } public long MaxMs { get; set; } public double SuccessRate { get; set; } } public class BenchmarkResult { public Dictionary<string, BenchmarkData> Results { get; set; } } Imports System Imports System.Collections.Generic Imports System.Drawing Imports System.IO Imports System.Linq Imports System.Threading.Tasks Public Class OptimizedScannerService Private ReadOnly _logger As ILogger(Of OptimizedScannerService) Private ReadOnly _cache As IMemoryCache Public Sub New(logger As ILogger(Of OptimizedScannerService), cache As IMemoryCache) _logger = logger _cache = cache End Sub ' Performance-optimized scanning with caching Public Async Function ScanWithOptimizationsAsync(imageData As Byte(), Optional cacheKey As String = Nothing) As Task(Of ScanResult) ' Check cache for repeat scans If Not String.IsNullOrEmpty(cacheKey) Then Dim cachedResult As ScanResult = Nothing If _cache.TryGetValue(cacheKey, cachedResult) Then _logger.LogInformation($"Cache hit for {cacheKey}") cachedResult.Metadata("CacheHit") = True Return cachedResult End If End If ' Determine optimal settings based on image characteristics Dim settings = Await DetermineOptimalSettingsAsync(imageData) ' Apply region-specific scanning if applicable If settings.UseRegionScanning Then Return Await ScanWithRegionsAsync(imageData, settings) End If ' Standard optimized scanning Dim results = Await BarcodeReader.ReadAsync(imageData, settings.Options) Dim scanResult = BuildScanResult(results) ' Cache successful results If Not String.IsNullOrEmpty(cacheKey) AndAlso scanResult.Success Then _cache.Set(cacheKey, scanResult, TimeSpan.FromMinutes(5)) End If Return scanResult End Function ' Intelligent settings determination Private Async Function DetermineOptimalSettingsAsync(imageData As Byte()) As Task(Of ScanSettings) Dim settings As New ScanSettings() ' Quick analysis of image properties Using ms As New MemoryStream(imageData) Using image As Image = Image.FromStream(ms) Dim width = image.Width Dim height = image.Height Dim aspectRatio = CDbl(width) / height _logger.LogInformation($"Image analysis: {width}x{height}, ratio: {aspectRatio:F2}") ' High-resolution images can use faster scanning If width > 2000 AndAlso height > 2000 Then settings.Options.Speed = ReadingSpeed.Faster settings.Options.ExpectBarcodeTypes = BarcodeEncoding.QRCode Or BarcodeEncoding.Code128 ElseIf width < 800 OrElse height < 800 Then ' Low-resolution needs more processing settings.Options.Speed = ReadingSpeed.ExtremeDetail settings.Options.ImageFilters = New ImageFilterCollection From { New SharpenFilter(3), New ContrastFilter(2) } Else settings.Options.Speed = ReadingSpeed.Balanced End If ' Detect if image might contain multiple barcodes based on aspect ratio If aspectRatio > 2 OrElse aspectRatio < 0.5 Then settings.Options.ExpectMultipleBarcodes = True settings.UseRegionScanning = True End If ' Enable rotation correction for potentially skewed images settings.Options.AutoRotate = True End Using End Using Return settings End Function ' Region-based scanning for large images Private Async Function ScanWithRegionsAsync(imageData As Byte(), settings As ScanSettings) As Task(Of ScanResult) Dim allResults As New List(Of BarcodeResult)() Using ms As New MemoryStream(imageData) Using image As Image = Image.FromStream(ms) ' Define scanning regions for common document layouts Dim regions = { New Rectangle(0, 0, image.Width \ 2, image.Height \ 2), ' Top-left New Rectangle(image.Width \ 2, 0, image.Width \ 2, image.Height \ 2), ' Top-right New Rectangle(0, image.Height \ 2, image.Width \ 2, image.Height \ 2), ' Bottom-left New Rectangle(image.Width \ 2, image.Height \ 2, image.Width \ 2, image.Height \ 2), ' Bottom-right New Rectangle(image.Width \ 4, image.Height \ 4, image.Width \ 2, image.Height \ 2) ' Center } Dim tasks = regions.Select(Async Function(region) Dim regionOptions As New BarcodeReaderOptions With { .CropArea = region, .Speed = ReadingSpeed.Faster, .ExpectMultipleBarcodes = False } Try Return Await BarcodeReader.ReadAsync(imageData, regionOptions) Catch ex As Exception _logger.LogWarning($"Region scan failed: {ex.Message}") Return New BarcodeResult() {} End Try End Function) Dim regionResults = Await Task.WhenAll(tasks) ' Combine and deduplicate results Dim uniqueResults = regionResults. SelectMany(Function(r) r). GroupBy(Function(r) r.Value). Select(Function(g) g.OrderByDescending(Function(r) r.Confidence).First()). ToList() Return BuildScanResult(uniqueResults) End Using End Using End Function ' Adaptive quality enhancement Public Async Function ScanWithAdaptiveEnhancementAsync(imageData As Byte()) As Task(Of ScanResult) Dim attempts = New List(Of Func(Of Task(Of BarcodeResults))) From { ' Attempt 1: Fast scan Async Function() Await BarcodeReader.ReadAsync(imageData, New BarcodeReaderOptions With { .Speed = ReadingSpeed.Faster, .RemoveFalsePositive = True }), ' Attempt 2: Standard scan with basic filters Async Function() Await BarcodeReader.ReadAsync(imageData, New BarcodeReaderOptions With { .Speed = ReadingSpeed.Balanced, .ImageFilters = New ImageFilterCollection From { New ContrastFilter(1.5F), New SharpenFilter(1) }, .TryInvertColor = True }), ' Attempt 3: Detailed scan with aggressive filtering Async Function() Await BarcodeReader.ReadAsync(imageData, New BarcodeReaderOptions With { .Speed = ReadingSpeed.Detailed, .ImageFilters = New ImageFilterCollection From { New AdaptiveThresholdFilter(11), New DeNoise(2), New MedianFilter(3) }, .AutoRotate = True, .Confidence = ConfidenceLevel.Low }), ' Attempt 4: Extreme processing for damaged barcodes Async Function() Await BarcodeReader.ReadAsync(imageData, New BarcodeReaderOptions With { .Speed = ReadingSpeed.ExtremeDetail, .ImageFilters = New ImageFilterCollection From { New BinaryThresholdFilter(100), New Erode(1), New Dilate(2), New SharpenFilter(4) }, .RemoveFalsePositive = False, .UseCode39ExtendedMode = True, .TryInvertColor = True }) } For Each attempt In attempts.Select(Function(a, i) (a, i)) Dim stopwatch = Stopwatch.StartNew() Dim results = Await attempt.a() stopwatch.Stop() _logger.LogInformation($"Attempt {attempt.i + 1} took {stopwatch.ElapsedMilliseconds}ms, found {results.Count()} barcodes") If results.Any() Then Dim scanResult = BuildScanResult(results) scanResult.Metadata("AttemptNumber") = attempt.i + 1 scanResult.Metadata("ProcessingStrategy") = GetStrategyName(attempt.i) Return scanResult End If Next Return New ScanResult With { .Success = False, .ErrorMessage = "No barcodes found after all enhancement attempts" } End Function ' Machine learning confidence optimization Public Class MLOptimizedScanner Private ReadOnly _formatConfidenceThresholds As New Dictionary(Of String, Double) From { {"QRCode", 85.0}, {"Code128", 90.0}, {"Code39", 88.0}, {"DataMatrix", 87.0}, {"EAN13", 92.0}, {"PDF417", 86.0} } Public Async Function ScanWithMLConfidenceAsync(imageData As Byte(), Optional expectedFormat As String = Nothing) As Task(Of ScanResult) Dim options As New BarcodeReaderOptions With { .Speed = ReadingSpeed.Balanced, .Confidence = ConfidenceLevel.Optional } ' If we know the expected format, improve for it If Not String.IsNullOrEmpty(expectedFormat) AndAlso [Enum].TryParse(Of BarcodeEncoding)(expectedFormat, encoding) Then options.ExpectBarcodeTypes = encoding End If Dim results = Await BarcodeReader.ReadAsync(imageData, options) ' Apply ML confidence filtering Dim confidenceThreshold = If(expectedFormat IsNot Nothing AndAlso _formatConfidenceThresholds.ContainsKey(expectedFormat), _formatConfidenceThresholds(expectedFormat), 80.0) Dim highConfidenceResults = results. Where(Function(r) r.Confidence >= confidenceThreshold). ToList() If highConfidenceResults.Any() Then Return BuildScanResult(highConfidenceResults) End If ' If no high-confidence results, include lower confidence with warnings Dim lowConfidenceResults = results. Where(Function(r) r.Confidence < confidenceThreshold). ToList() If lowConfidenceResults.Any() Then Dim result = BuildScanResult(lowConfidenceResults) result.Metadata("Warning") = "Low confidence results - manual verification recommended" result.Metadata("MinConfidence") = lowConfidenceResults.Min(Function(r) r.Confidence) Return result End If Return New ScanResult With { .Success = False, .ErrorMessage = "No barcodes met confidence threshold" } End Function End Class Private Function BuildScanResult(results As IEnumerable(Of BarcodeResult)) As ScanResult Dim resultList = results.ToList() Return New ScanResult With { .Success = True, .Barcodes = resultList.Select(Function(r) New BarcodeData With { .Value = r.Value, .Format = r.BarcodeType.ToString(), .Confidence = r.Confidence, .Location = r.Bounds }).ToList(), .Metadata = New Dictionary(Of String, Object) From { {"TotalFound", resultList.Count}, {"AverageConfidence", resultList.Average(Function(r) r.Confidence)}, {"Formats", resultList.Select(Function(r) r.BarcodeType.ToString()).Distinct().ToArray()} } } End Function Private Function GetStrategyName(attemptIndex As Integer) As String Return attemptIndex Select Case { 0 : "FastScan", 1 : "StandardEnhanced", 2 : "DetailedFiltering", 3 : "ExtremeDamageRecovery", Else : "Unknown" } End Function End Class ' Supporting classes Public Class ScanSettings Public Property Options As BarcodeReaderOptions = New BarcodeReaderOptions() Public Property UseRegionScanning As Boolean Public Property CustomRegions As List(Of Rectangle) End Class ' Benchmark service for performance testing Public Class BenchmarkService Private ReadOnly _logger As ILogger(Of BenchmarkService) Public Async Function BenchmarkSettingsAsync(testImage As Byte(), Optional iterations As Integer = 10) As Task(Of BenchmarkResult) Dim results As New Dictionary(Of String, BenchmarkData)() Dim testConfigurations = New Dictionary(Of String, BarcodeReaderOptions) From { {"Fastest", New BarcodeReaderOptions With {.Speed = ReadingSpeed.Faster}}, {"Balanced", New BarcodeReaderOptions With {.Speed = ReadingSpeed.Balanced}}, {"Detailed", New BarcodeReaderOptions With {.Speed = ReadingSpeed.Detailed}}, {"Parallel", New BarcodeReaderOptions With {.Speed = ReadingSpeed.Balanced, .Multithreaded = True, .MaxParallelThreads = 4}}, {"Filtered", New BarcodeReaderOptions With {.Speed = ReadingSpeed.Balanced, .ImageFilters = New ImageFilterCollection From {New SharpenFilter(2), New ContrastFilter(1.5F)}}} } For Each config In testConfigurations Dim times As New List(Of Long)() Dim successCount = 0 For i = 0 To iterations - 1 Dim sw = Stopwatch.StartNew() Dim scanResults = Await BarcodeReader.ReadAsync(testImage, config.Value) sw.Stop() times.Add(sw.ElapsedMilliseconds) If scanResults.Any() Then successCount += 1 ' Small delay between tests Await Task.Delay(100) Next results(config.Key) = New BenchmarkData With { .AverageMs = times.Average(), .MinMs = times.Min(), .MaxMs = times.Max(), .SuccessRate = CDbl(successCount) / iterations * 100 } Next Return New BenchmarkResult With {.Results = results} End Function End Class Public Class BenchmarkData Public Property AverageMs As Double Public Property MinMs As Long Public Property MaxMs As Long Public Property SuccessRate As Double End Class Public Class BenchmarkResult Public Property Results As Dictionary(Of String, BenchmarkData) End Class $vbLabelText $csharpLabel この高度な最適化アプローチでは、いくつかの専門的なテクニックが実証されています。 インテリジェントな設定決定により、画像のプロパティが分析され、最適な処理パラメータが自動的に選択されます。 最新のカメラで撮影された高解像度の画像はより高速な処理が可能で、低品質のスキャンではフィルタリングが強化されます。 領域ベースのスキャンは、特に大きな形式のドキュメントに効果的です。 画像を領域に分割して並列処理することで、パフォーマンスを大幅に向上させることができます。 この手法は、バーコードの位置が予測可能な標準化されたフォームに特に適しています。 適切なReadingSpeed設定の選択 適応型拡張アプローチでは、成功するまで徐々に積極的な処理手法を試します。 これにより、破損したバーコードも正常に処理しながら、高品質のバーコードを可能な限り高速に処理できるようになります。 信頼しきい値機能は、機械学習を使用して結果を検証し、実稼働環境での誤検知を削減します。 特定の最適化シナリオの場合: -大量処理:特定のバーコードタイプフィルタリングでReadingSpeed.Fasterを使用する -混在品質の文書: ReadingSpeed.Balancedから始めて、適応的な強化を実装します。 -破損または古いバーコード: ReadingSpeed.ExtremeDetailと完全な画像フィルターを使用します -リアルタイムアプリケーション: 一貫したパフォーマンスを実現するためにキャッシュと領域ベースのスキャンを実装します ベンチマーク サービスは、構成についてデータに基づいた意思決定を行うのに役立ちます。 実際のバーコード サンプルを使用してベンチマークを実行し、特定のユース ケースにおける速度と精度の最適なバランスを見つけます。 画像フィルターの影響 画像フィルターを使用すると、認識が難しいバーコードの認識率を大幅に向上させることができます。 画像補正ドキュメントでは、各フィルターの目的について説明しています。 ただし、フィルターを使用すると処理時間も長くなるため、慎重に使用してください。 エンタープライズ展開の場合は、階層型アプローチの実装を検討してください。 最初の試みとしてフィルターなしの高速スキャン 最初の試みが失敗した場合は基本フィルターを適用する 必要な場合にのみ積極的なフィルタリングを使用する 再処理を避けるために結果をキャッシュする この戦略により、困難なケースを正常に処理しながらも、平均応答時間を短縮できます。 方向補正機能は、ユーザーがさまざまな角度でデバイスを保持する可能性があるモバイルでキャプチャされた画像に特に役立ちます。 C# で QR コード画像を作成する スキャンは重要ですが、多くのエンタープライズ アプリケーションではバーコードを生成する必要もあります。 IronBarcode を使用すると、作成も読み取りと同じくらい簡単になります。 さまざまなエンタープライズ シナリオで QR コードを生成する方法は次のとおりです。 public class BarcodeGenerationService { private readonly ILogger<BarcodeGenerationService> _logger; // Generate QR codes for asset tracking public byte[] GenerateAssetQRCode(AssetInfo asset) { // Create JSON payload with asset information var assetData = JsonSerializer.Serialize(new { Id = asset.AssetId, Type = asset.AssetType, Location = asset.CurrentLocation, LastMaintenance = asset.LastMaintenanceDate, Url = "___PROTECTED_URL_45___" }); // Generate QR code with high error correction for durability var qrCode = QRCodeWriter.CreateQrCode(assetData, 500, QRCodeWriter.QrErrorCorrectionLevel.High); // Add company branding qrCode.AddAnnotationTextAboveBarcode($"ASSET: {asset.AssetId}"); qrCode.AddAnnotationTextBelowBarcode(asset.AssetType); qrCode.SetMargins(10); // Style for printing on asset labels qrCode.ChangeBarCodeColor(Color.Black); qrCode.ChangeBackgroundColor(Color.White); return qrCode.ToStream().ToArray(); } // Generate visitor badges with QR codes public GeneratedBarcode CreateVisitorBadgeQR(VisitorInfo visitor) { // Encode visitor information with expiration var visitorData = new { Name = visitor.Name, Company = visitor.Company, Host = visitor.HostEmployee, ValidFrom = visitor.CheckInTime, ValidUntil = visitor.CheckInTime.AddHours(8), AccessLevel = visitor.AccessLevel, BadgeId = Guid.NewGuid().ToString() }; var qrCode = QRCodeWriter.CreateQrCode( JsonSerializer.Serialize(visitorData), 400, QRCodeWriter.QrErrorCorrectionLevel.Medium ); // Add company logo for professional appearance if (File.Exists("company-logo.png")) { qrCode.AddLogo("company-logo.png"); } // Style for badge printing qrCode.SetMargins(15); qrCode.ChangeBarCodeColor(Color.FromArgb(0, 48, 135)); // Company blue // Add visible text for security personnel qrCode.AddAnnotationTextAboveBarcode($"VISITOR: {visitor.Name}"); qrCode.AddAnnotationTextBelowBarcode($"Expires: {visitor.CheckInTime.AddHours(8):HH:mm}"); _logger.LogInformation($"Generated visitor badge for {visitor.Name}, BadgeId: {visitorData.BadgeId}"); return qrCode; } // Generate shipping labels with multiple barcodes public byte[] GenerateShippingLabel(ShippingInfo shipping) { // Create a PDF with multiple barcodes var pdf = new IronPdf.ChromePdfRenderer(); // Generate tracking barcode (Code 128 for USPS/UPS compatibility) var trackingBarcode = BarcodeWriter.CreateBarcode( shipping.TrackingNumber, BarcodeEncoding.Code128 ); trackingBarcode.ResizeTo(300, 75); trackingBarcode.SetMargins(5); // Generate postal code barcode var postalBarcode = BarcodeWriter.CreateBarcode( shipping.PostalCode, BarcodeEncoding.Code128 ); postalBarcode.ResizeTo(200, 50); // Generate QR code with complete shipping data var shippingData = JsonSerializer.Serialize(shipping); var qrCode = QRCodeWriter.CreateQrCode(shippingData, 200); // Combine into shipping label HTML var labelHtml = $@ <html> <body style='font-family: Arial, sans-serif;'> <div style='border: 2px solid black; padding: 20px; width: 4in; height: 6in;'> <h2>SHIPPING LABEL</h2> <hr/> <p><strong>From:</strong><br/>{shipping.SenderAddress}</p> <p><strong>To:</strong><br/>{shipping.RecipientAddress}</p> <hr/> <div style='text-align: center;'> <img src='{trackingBarcode.ToDataUrl()}' alt='Tracking barcode'/> <p>Tracking: {shipping.TrackingNumber}</p> </div> <div style='margin-top: 20px;'> <img src='{postalBarcode.ToDataUrl()}' alt='Postal barcode' style='float: left;'/> <img src='{qrCode.ToDataUrl()}' alt='Shipping QR code' style='float: right; width: 100px;'/> </div> <div style='clear: both; margin-top: 20px; font-size: 10px;'> <p>Service: {shipping.ServiceType} | Weight: {shipping.Weight}lbs</p> </div> </div> </body> </html>"; return pdf.RenderHtmlAsPdf(labelHtml).BinaryData; } // Generate secure document QR codes with encryption public class SecureDocumentQR { private readonly byte[] _encryptionKey; public SecureDocumentQR(byte[] encryptionKey) { _encryptionKey = encryptionKey; } public GeneratedBarcode GenerateSecureDocumentQR(DocumentInfo document) { // Create document reference with security features var documentRef = new { DocumentId = document.Id, Type = document.DocumentType, CreatedDate = document.CreatedDate, Hash = ComputeDocumentHash(document), AccessUrl = "___PROTECTED_URL_46___", ValidUntil = DateTime.UtcNow.AddDays(30) }; // Encrypt sensitive data var jsonData = JsonSerializer.Serialize(documentRef); var encryptedData = EncryptData(jsonData); // Generate QR with encrypted payload var qrCode = QRCodeWriter.CreateQrCode( Convert.ToBase64String(encryptedData), 500, QRCodeWriter.QrErrorCorrectionLevel.High ); // Add visual security indicators qrCode.ChangeBarCodeColor(Color.DarkGreen); qrCode.AddAnnotationTextAboveBarcode("SECURE DOCUMENT"); qrCode.AddAnnotationTextBelowBarcode($"Expires: {documentRef.ValidUntil:yyyy-MM-dd}"); return qrCode; } private string ComputeDocumentHash(DocumentInfo document) { using var sha256 = SHA256.Create(); var hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(document.Content ?? document.Id)); return BitConverter.ToString(hash).Replace("-", ""); } private byte[] EncryptData(string data) { // Simplified encryption - use proper encryption in production using var aes = Aes.Create(); aes.Key = _encryptionKey; aes.GenerateIV(); using var encryptor = aes.CreateEncryptor(); var dataBytes = Encoding.UTF8.GetBytes(data); var encrypted = encryptor.TransformFinalBlock(dataBytes, 0, dataBytes.Length); // Prepend IV for decryption return aes.IV.Concat(encrypted).ToArray(); } } // Batch generation for high-volume scenarios public async Task<List<GeneratedBarcode>> GenerateBatchQRCodesAsync(List<string> data, QRCodeOptions options) { var tasks = data.Select(item => Task.Run(() => { var qr = QRCodeWriter.CreateQrCode( item, options.Size, options.ErrorCorrection ); if (options.IncludeMargins) qr.SetMargins(options.MarginSize); if (options.CustomColor.HasValue) qr.ChangeBarCodeColor(options.CustomColor.Value); return qr; })); return (await Task.WhenAll(tasks)).ToList(); } } // Supporting models public class AssetInfo { public string AssetId { get; set; } public string AssetType { get; set; } public string CurrentLocation { get; set; } public DateTime LastMaintenanceDate { get; set; } } public class VisitorInfo { public string Name { get; set; } public string Company { get; set; } public string HostEmployee { get; set; } public DateTime CheckInTime { get; set; } public string AccessLevel { get; set; } } public class ShippingInfo { public string TrackingNumber { get; set; } public string SenderAddress { get; set; } public string RecipientAddress { get; set; } public string PostalCode { get; set; } public string ServiceType { get; set; } public decimal Weight { get; set; } } public class DocumentInfo { public string Id { get; set; } public string DocumentType { get; set; } public DateTime CreatedDate { get; set; } public string Content { get; set; } } public class QRCodeOptions { public int Size { get; set; } = 400; public QRCodeWriter.QrErrorCorrectionLevel ErrorCorrection { get; set; } = QRCodeWriter.QrErrorCorrectionLevel.Medium; public bool IncludeMargins { get; set; } = true; public int MarginSize { get; set; } = 10; public Color? CustomColor { get; set; } } public class BarcodeGenerationService { private readonly ILogger<BarcodeGenerationService> _logger; // Generate QR codes for asset tracking public byte[] GenerateAssetQRCode(AssetInfo asset) { // Create JSON payload with asset information var assetData = JsonSerializer.Serialize(new { Id = asset.AssetId, Type = asset.AssetType, Location = asset.CurrentLocation, LastMaintenance = asset.LastMaintenanceDate, Url = "___PROTECTED_URL_45___" }); // Generate QR code with high error correction for durability var qrCode = QRCodeWriter.CreateQrCode(assetData, 500, QRCodeWriter.QrErrorCorrectionLevel.High); // Add company branding qrCode.AddAnnotationTextAboveBarcode($"ASSET: {asset.AssetId}"); qrCode.AddAnnotationTextBelowBarcode(asset.AssetType); qrCode.SetMargins(10); // Style for printing on asset labels qrCode.ChangeBarCodeColor(Color.Black); qrCode.ChangeBackgroundColor(Color.White); return qrCode.ToStream().ToArray(); } // Generate visitor badges with QR codes public GeneratedBarcode CreateVisitorBadgeQR(VisitorInfo visitor) { // Encode visitor information with expiration var visitorData = new { Name = visitor.Name, Company = visitor.Company, Host = visitor.HostEmployee, ValidFrom = visitor.CheckInTime, ValidUntil = visitor.CheckInTime.AddHours(8), AccessLevel = visitor.AccessLevel, BadgeId = Guid.NewGuid().ToString() }; var qrCode = QRCodeWriter.CreateQrCode( JsonSerializer.Serialize(visitorData), 400, QRCodeWriter.QrErrorCorrectionLevel.Medium ); // Add company logo for professional appearance if (File.Exists("company-logo.png")) { qrCode.AddLogo("company-logo.png"); } // Style for badge printing qrCode.SetMargins(15); qrCode.ChangeBarCodeColor(Color.FromArgb(0, 48, 135)); // Company blue // Add visible text for security personnel qrCode.AddAnnotationTextAboveBarcode($"VISITOR: {visitor.Name}"); qrCode.AddAnnotationTextBelowBarcode($"Expires: {visitor.CheckInTime.AddHours(8):HH:mm}"); _logger.LogInformation($"Generated visitor badge for {visitor.Name}, BadgeId: {visitorData.BadgeId}"); return qrCode; } // Generate shipping labels with multiple barcodes public byte[] GenerateShippingLabel(ShippingInfo shipping) { // Create a PDF with multiple barcodes var pdf = new IronPdf.ChromePdfRenderer(); // Generate tracking barcode (Code 128 for USPS/UPS compatibility) var trackingBarcode = BarcodeWriter.CreateBarcode( shipping.TrackingNumber, BarcodeEncoding.Code128 ); trackingBarcode.ResizeTo(300, 75); trackingBarcode.SetMargins(5); // Generate postal code barcode var postalBarcode = BarcodeWriter.CreateBarcode( shipping.PostalCode, BarcodeEncoding.Code128 ); postalBarcode.ResizeTo(200, 50); // Generate QR code with complete shipping data var shippingData = JsonSerializer.Serialize(shipping); var qrCode = QRCodeWriter.CreateQrCode(shippingData, 200); // Combine into shipping label HTML var labelHtml = $@ <html> <body style='font-family: Arial, sans-serif;'> <div style='border: 2px solid black; padding: 20px; width: 4in; height: 6in;'> <h2>SHIPPING LABEL</h2> <hr/> <p><strong>From:</strong><br/>{shipping.SenderAddress}</p> <p><strong>To:</strong><br/>{shipping.RecipientAddress}</p> <hr/> <div style='text-align: center;'> <img src='{trackingBarcode.ToDataUrl()}' alt='Tracking barcode'/> <p>Tracking: {shipping.TrackingNumber}</p> </div> <div style='margin-top: 20px;'> <img src='{postalBarcode.ToDataUrl()}' alt='Postal barcode' style='float: left;'/> <img src='{qrCode.ToDataUrl()}' alt='Shipping QR code' style='float: right; width: 100px;'/> </div> <div style='clear: both; margin-top: 20px; font-size: 10px;'> <p>Service: {shipping.ServiceType} | Weight: {shipping.Weight}lbs</p> </div> </div> </body> </html>"; return pdf.RenderHtmlAsPdf(labelHtml).BinaryData; } // Generate secure document QR codes with encryption public class SecureDocumentQR { private readonly byte[] _encryptionKey; public SecureDocumentQR(byte[] encryptionKey) { _encryptionKey = encryptionKey; } public GeneratedBarcode GenerateSecureDocumentQR(DocumentInfo document) { // Create document reference with security features var documentRef = new { DocumentId = document.Id, Type = document.DocumentType, CreatedDate = document.CreatedDate, Hash = ComputeDocumentHash(document), AccessUrl = "___PROTECTED_URL_46___", ValidUntil = DateTime.UtcNow.AddDays(30) }; // Encrypt sensitive data var jsonData = JsonSerializer.Serialize(documentRef); var encryptedData = EncryptData(jsonData); // Generate QR with encrypted payload var qrCode = QRCodeWriter.CreateQrCode( Convert.ToBase64String(encryptedData), 500, QRCodeWriter.QrErrorCorrectionLevel.High ); // Add visual security indicators qrCode.ChangeBarCodeColor(Color.DarkGreen); qrCode.AddAnnotationTextAboveBarcode("SECURE DOCUMENT"); qrCode.AddAnnotationTextBelowBarcode($"Expires: {documentRef.ValidUntil:yyyy-MM-dd}"); return qrCode; } private string ComputeDocumentHash(DocumentInfo document) { using var sha256 = SHA256.Create(); var hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(document.Content ?? document.Id)); return BitConverter.ToString(hash).Replace("-", ""); } private byte[] EncryptData(string data) { // Simplified encryption - use proper encryption in production using var aes = Aes.Create(); aes.Key = _encryptionKey; aes.GenerateIV(); using var encryptor = aes.CreateEncryptor(); var dataBytes = Encoding.UTF8.GetBytes(data); var encrypted = encryptor.TransformFinalBlock(dataBytes, 0, dataBytes.Length); // Prepend IV for decryption return aes.IV.Concat(encrypted).ToArray(); } } // Batch generation for high-volume scenarios public async Task<List<GeneratedBarcode>> GenerateBatchQRCodesAsync(List<string> data, QRCodeOptions options) { var tasks = data.Select(item => Task.Run(() => { var qr = QRCodeWriter.CreateQrCode( item, options.Size, options.ErrorCorrection ); if (options.IncludeMargins) qr.SetMargins(options.MarginSize); if (options.CustomColor.HasValue) qr.ChangeBarCodeColor(options.CustomColor.Value); return qr; })); return (await Task.WhenAll(tasks)).ToList(); } } // Supporting models public class AssetInfo { public string AssetId { get; set; } public string AssetType { get; set; } public string CurrentLocation { get; set; } public DateTime LastMaintenanceDate { get; set; } } public class VisitorInfo { public string Name { get; set; } public string Company { get; set; } public string HostEmployee { get; set; } public DateTime CheckInTime { get; set; } public string AccessLevel { get; set; } } public class ShippingInfo { public string TrackingNumber { get; set; } public string SenderAddress { get; set; } public string RecipientAddress { get; set; } public string PostalCode { get; set; } public string ServiceType { get; set; } public decimal Weight { get; set; } } public class DocumentInfo { public string Id { get; set; } public string DocumentType { get; set; } public DateTime CreatedDate { get; set; } public string Content { get; set; } } public class QRCodeOptions { public int Size { get; set; } = 400; public QRCodeWriter.QrErrorCorrectionLevel ErrorCorrection { get; set; } = QRCodeWriter.QrErrorCorrectionLevel.Medium; public bool IncludeMargins { get; set; } = true; public int MarginSize { get; set; } = 10; public Color? CustomColor { get; set; } } Imports System Imports System.Collections.Generic Imports System.IO Imports System.Linq Imports System.Security.Cryptography Imports System.Text Imports System.Text.Json Imports System.Threading.Tasks Public Class BarcodeGenerationService Private ReadOnly _logger As ILogger(Of BarcodeGenerationService) ' Generate QR codes for asset tracking Public Function GenerateAssetQRCode(asset As AssetInfo) As Byte() ' Create JSON payload with asset information Dim assetData = JsonSerializer.Serialize(New With { .Id = asset.AssetId, .Type = asset.AssetType, .Location = asset.CurrentLocation, .LastMaintenance = asset.LastMaintenanceDate, .Url = "___PROTECTED_URL_45___" }) ' Generate QR code with high error correction for durability Dim qrCode = QRCodeWriter.CreateQrCode(assetData, 500, QRCodeWriter.QrErrorCorrectionLevel.High) ' Add company branding qrCode.AddAnnotationTextAboveBarcode($"ASSET: {asset.AssetId}") qrCode.AddAnnotationTextBelowBarcode(asset.AssetType) qrCode.SetMargins(10) ' Style for printing on asset labels qrCode.ChangeBarCodeColor(Color.Black) qrCode.ChangeBackgroundColor(Color.White) Return qrCode.ToStream().ToArray() End Function ' Generate visitor badges with QR codes Public Function CreateVisitorBadgeQR(visitor As VisitorInfo) As GeneratedBarcode ' Encode visitor information with expiration Dim visitorData = New With { .Name = visitor.Name, .Company = visitor.Company, .Host = visitor.HostEmployee, .ValidFrom = visitor.CheckInTime, .ValidUntil = visitor.CheckInTime.AddHours(8), .AccessLevel = visitor.AccessLevel, .BadgeId = Guid.NewGuid().ToString() } Dim qrCode = QRCodeWriter.CreateQrCode( JsonSerializer.Serialize(visitorData), 400, QRCodeWriter.QrErrorCorrectionLevel.Medium ) ' Add company logo for professional appearance If File.Exists("company-logo.png") Then qrCode.AddLogo("company-logo.png") End If ' Style for badge printing qrCode.SetMargins(15) qrCode.ChangeBarCodeColor(Color.FromArgb(0, 48, 135)) ' Company blue ' Add visible text for security personnel qrCode.AddAnnotationTextAboveBarcode($"VISITOR: {visitor.Name}") qrCode.AddAnnotationTextBelowBarcode($"Expires: {visitor.CheckInTime.AddHours(8):HH:mm}") _logger.LogInformation($"Generated visitor badge for {visitor.Name}, BadgeId: {visitorData.BadgeId}") Return qrCode End Function ' Generate shipping labels with multiple barcodes Public Function GenerateShippingLabel(shipping As ShippingInfo) As Byte() ' Create a PDF with multiple barcodes Dim pdf = New IronPdf.ChromePdfRenderer() ' Generate tracking barcode (Code 128 for USPS/UPS compatibility) Dim trackingBarcode = BarcodeWriter.CreateBarcode( shipping.TrackingNumber, BarcodeEncoding.Code128 ) trackingBarcode.ResizeTo(300, 75) trackingBarcode.SetMargins(5) ' Generate postal code barcode Dim postalBarcode = BarcodeWriter.CreateBarcode( shipping.PostalCode, BarcodeEncoding.Code128 ) postalBarcode.ResizeTo(200, 50) ' Generate QR code with complete shipping data Dim shippingData = JsonSerializer.Serialize(shipping) Dim qrCode = QRCodeWriter.CreateQrCode(shippingData, 200) ' Combine into shipping label HTML Dim labelHtml = $" <html> <body style='font-family: Arial, sans-serif;'> <div style='border: 2px solid black; padding: 20px; width: 4in; height: 6in;'> <h2>SHIPPING LABEL</h2> <hr/> <p><strong>From:</strong><br/>{shipping.SenderAddress}</p> <p><strong>To:</strong><br/>{shipping.RecipientAddress}</p> <hr/> <div style='text-align: center;'> <img src='{trackingBarcode.ToDataUrl()}' alt='Tracking barcode'/> <p>Tracking: {shipping.TrackingNumber}</p> </div> <div style='margin-top: 20px;'> <img src='{postalBarcode.ToDataUrl()}' alt='Postal barcode' style='float: left;'/> <img src='{qrCode.ToDataUrl()}' alt='Shipping QR code' style='float: right; width: 100px;'/> </div> <div style='clear: both; margin-top: 20px; font-size: 10px;'> <p>Service: {shipping.ServiceType} | Weight: {shipping.Weight}lbs</p> </div> </div> </body> </html>" Return pdf.RenderHtmlAsPdf(labelHtml).BinaryData End Function ' Generate secure document QR codes with encryption Public Class SecureDocumentQR Private ReadOnly _encryptionKey As Byte() Public Sub New(encryptionKey As Byte()) _encryptionKey = encryptionKey End Sub Public Function GenerateSecureDocumentQR(document As DocumentInfo) As GeneratedBarcode ' Create document reference with security features Dim documentRef = New With { .DocumentId = document.Id, .Type = document.DocumentType, .CreatedDate = document.CreatedDate, .Hash = ComputeDocumentHash(document), .AccessUrl = "___PROTECTED_URL_46___", .ValidUntil = DateTime.UtcNow.AddDays(30) } ' Encrypt sensitive data Dim jsonData = JsonSerializer.Serialize(documentRef) Dim encryptedData = EncryptData(jsonData) ' Generate QR with encrypted payload Dim qrCode = QRCodeWriter.CreateQrCode( Convert.ToBase64String(encryptedData), 500, QRCodeWriter.QrErrorCorrectionLevel.High ) ' Add visual security indicators qrCode.ChangeBarCodeColor(Color.DarkGreen) qrCode.AddAnnotationTextAboveBarcode("SECURE DOCUMENT") qrCode.AddAnnotationTextBelowBarcode($"Expires: {documentRef.ValidUntil:yyyy-MM-dd}") Return qrCode End Function Private Function ComputeDocumentHash(document As DocumentInfo) As String Using sha256 = SHA256.Create() Dim hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(If(document.Content, document.Id))) Return BitConverter.ToString(hash).Replace("-", "") End Using End Function Private Function EncryptData(data As String) As Byte() ' Simplified encryption - use proper encryption in production Using aes = Aes.Create() aes.Key = _encryptionKey aes.GenerateIV() Using encryptor = aes.CreateEncryptor() Dim dataBytes = Encoding.UTF8.GetBytes(data) Dim encrypted = encryptor.TransformFinalBlock(dataBytes, 0, dataBytes.Length) ' Prepend IV for decryption Return aes.IV.Concat(encrypted).ToArray() End Using End Using End Function End Class ' Batch generation for high-volume scenarios Public Async Function GenerateBatchQRCodesAsync(data As List(Of String), options As QRCodeOptions) As Task(Of List(Of GeneratedBarcode)) Dim tasks = data.Select(Function(item) Task.Run(Function() Dim qr = QRCodeWriter.CreateQrCode( item, options.Size, options.ErrorCorrection ) If options.IncludeMargins Then qr.SetMargins(options.MarginSize) End If If options.CustomColor.HasValue Then qr.ChangeBarCodeColor(options.CustomColor.Value) End If Return qr End Function)) Return (Await Task.WhenAll(tasks)).ToList() End Function End Class ' Supporting models Public Class AssetInfo Public Property AssetId As String Public Property AssetType As String Public Property CurrentLocation As String Public Property LastMaintenanceDate As DateTime End Class Public Class VisitorInfo Public Property Name As String Public Property Company As String Public Property HostEmployee As String Public Property CheckInTime As DateTime Public Property AccessLevel As String End Class Public Class ShippingInfo Public Property TrackingNumber As String Public Property SenderAddress As String Public Property RecipientAddress As String Public Property PostalCode As String Public Property ServiceType As String Public Property Weight As Decimal End Class Public Class DocumentInfo Public Property Id As String Public Property DocumentType As String Public Property CreatedDate As DateTime Public Property Content As String End Class Public Class QRCodeOptions Public Property Size As Integer = 400 Public Property ErrorCorrection As QRCodeWriter.QrErrorCorrectionLevel = QRCodeWriter.QrErrorCorrectionLevel.Medium Public Property IncludeMargins As Boolean = True Public Property MarginSize As Integer = 10 Public Property CustomColor As Color? End Class $vbLabelText $csharpLabel これらの生成例は、エンタープライズ固有のユースケースを示しています。 資産追跡 QR コードには、メンテナンス履歴と資産管理システムへの直接リンクが含まれています。 訪問者バッジには、セキュリティコンプライアンスのために有効期限とアクセス レベルが組み込まれています。 配送ラベルは、運送業者の要件を満たすために複数のバーコード形式を組み合わせます。 安全なドキュメント QR 実装では、機密データの暗号化を統合する方法を示します。 このアプローチにより、たとえ誰かが QR コードをキャプチャしたとしても、適切な復号化キーがなければ情報にアクセスできなくなります。 これは、コンプライアンス文書、財務記録、または機密通信にとって不可欠です。 本番環境への展開に向けた次のステップ IronBarcode を使用してエンタープライズ バーコード スキャナー API を構築すると、デジタル変革イニシアチブの信頼できる基盤が提供されます。 完全な形式のサポート、高度な画像処理、およびクロスプラットフォームの互換性の組み合わせにより、現代の企業の複雑な要件に対応します。 実装に関する重要なポイント: 1.セキュリティ第一: 適切な認証、入力検証、監査ログを最初から実装する 2.パフォーマンスの最適化: ユースケースに応じて適切なスキャン速度とキャッシュ戦略を使用する 3.エラー処理: エッジケースを適切に処理し、意味のあるフィードバックを提供する回復力のあるシステムを構築する 4.スケーラビリティ: 非同期パターンと効率的なリソース管理を活用し、水平スケーリングを念頭に設計する 実稼働環境での展開では、次の追加リソースを検討してください。 最新の機能と改善点については変更ログを確認してください 特殊なエンタープライズ形式を含む新しい形式のサポートを検討 デスクトップ アプリケーション用のMSI インストーラーの展開を実装する 実稼働環境に合わせてライセンスキーを適切に設定する IronBarcode のエンタープライズ機能は、基本的なスキャン機能を超えています。 ライブラリのスタイル カスタマイズ機能により、ブランド化されたバーコードを生成できます。 Unicode バーコードのサポートにより、グローバルな互換性が保証されます。 バーコード マージンやエラー修正レベルなどの高度な機能により、出力品質を細かく制御できます。 エンタープライズサポートとリソース ミッションクリティカルなバーコード ソリューションを実装する場合、信頼できるサポートが重要です。 IronBarcode は以下を提供します: SLA保証付きの専用エンタープライズサポート カスタム要件に対するエンジニアリング リクエストのサポート 定期的なセキュリティアップデートとCVE監視 一般的なシナリオの完全なトラブルシューティングガイド 手動のバーコード処理から自動化された API 駆動型処理までのプロセスにより、運用効率が向上します。 何千もの出荷文書の処理、訪問者のアクセスの管理、企業資産の追跡など、どのような作業であっても、IronBarcode は企業環境に求められる信頼性と機能を提供します。 バーコード処理を変革する準備はできていますか? 無料トライアルを開始して、プロフェッショナルなバーコード処理がもたらす違いを体験してください。 完全なAPI ドキュメントでは詳細な実装ガイダンスが提供されており、例のセクションでは一般的なシナリオですぐに使用できるコードが提供されています。 企業には、ニーズに合わせて拡張でき、セキュリティ コンプライアンスを維持し、すべてのプラットフォームで一貫した結果を提供するバーコード ソリューションが必要です。 IronBarcode は、長期サポートと継続的な改善に取り組む企業によって支えられ、まさにそれを実現します。 今すぐスキャナー API の構築を開始し、重要なバーコード処理のニーズを満たすために IronBarcode を信頼している何千もの企業に加わってください。 よくある質問 C#でスキャナーAPIを構築するためにIronBarcodeを使用する主な利点は何ですか? IronBarcodeは、開発者が強力で実用的なバーコードスキャナーAPIを迅速に作成できるようにし、複雑さを最小限に抑えます。複雑なスキャナーSDKの統合を排除することで、プロセスを簡素化します。 IronBarcodeは損傷したバーコード入力を処理できますか? はい、IronBarcodeは、実際のアプリケーションで高信頼性を確保するために、損傷したスキャン入力からのバーコードデータでも処理するように設計されています。 C#スキャナーAPIでIronBarcodeが処理できる入力タイプは何ですか? IronBarcode は、画像や PDF などのさまざまな入力からバーコードデータを処理でき、異なるスキャンニーズに対応する柔軟なソリューションを提供します。 IronBarcodeを使用してバーコードスキャナーAPIを構築するためのチュートリアルはありますか? はい、このウェブページには、IronBarcodeを使用してRESTfulバーコードスキャンエンドポイントを構築するためのコード例を含む包括的なチュートリアルが提供されています。 IronBarcodeを使用してバーコードスキャナーAPIをどのくらい早く設定できますか? IronBarcodeを使用することで、開発者は数分でバーコードスキャナーAPIを設定でき、開発時間と労力を合理化できます。 IronBarcodeは複雑なSDK統合を必要としますか? いいえ、IronBarcodeは、複雑なスキャナーSDKの統合を排除し、開発者がバーコードスキャン機能を実装しやすくします。 IronBarcodeを使用してスキャナーAPIを構築する言語は何ですか? IronBarcodeは、.NETフレームワークを活用して堅牢なパフォーマンスを実現するために、C#で使用されます。 Jordi Bardia 今すぐエンジニアリングチームとチャット ソフトウェアエンジニア Jordiは、最も得意な言語がPython、C#、C++であり、Iron Softwareでそのスキルを発揮していない時は、ゲームプログラミングをしています。製品テスト、製品開発、研究の責任を分担し、Jordiは継続的な製品改善において多大な価値を追加しています。この多様な経験は彼を挑戦させ続け、興味を持たせており、Iron Softwareで働くことの好きな側面の一つだと言います。Jordiはフロリダ州マイアミで育ち、フロリダ大学でコンピュータサイエンスと統計学を学びました。 関連する記事 更新日 2026年1月22日 ASP.NETバーコードスキャナチュートリアル:C#バーコードジェネレータガイド IronBarcodeを使用してASP.NETでバーコードをスキャンする方法を学びます 詳しく読む 公開日 2026年1月21日 C#でのデータマトリクスジェネレータ:IronBarcodeによる完全ガイド データマトリックス生成C#チュートリアル。IronBarcodeでECC200データマトリックスバーコードを作成する方法を学びます。2Dバーコード生成のためのシンプルなコード例。 詳しく読む 公開日 2026年1月21日 IronBarcodeを使用したXamarinバーコードジェネレータでプロ品質のバーコードを作成する Xamarin Barcode Generatorを使用してプロ品質のバーコードを作成する方法を学びます。 詳しく読む MAUIバーコードスキャナチュートリアル:IronBarcodeとカメラの統合VB .NET を使用して Crystal レ...
更新日 2026年1月22日 ASP.NETバーコードスキャナチュートリアル:C#バーコードジェネレータガイド IronBarcodeを使用してASP.NETでバーコードをスキャンする方法を学びます 詳しく読む
公開日 2026年1月21日 C#でのデータマトリクスジェネレータ:IronBarcodeによる完全ガイド データマトリックス生成C#チュートリアル。IronBarcodeでECC200データマトリックスバーコードを作成する方法を学びます。2Dバーコード生成のためのシンプルなコード例。 詳しく読む
公開日 2026年1月21日 IronBarcodeを使用したXamarinバーコードジェネレータでプロ品質のバーコードを作成する Xamarin Barcode Generatorを使用してプロ品質のバーコードを作成する方法を学びます。 詳しく読む