Skip to main content
The OCRService provides methods to perform optical character recognition (OCR) on images using Tesseract OCR. It supports both C++ and Node.js backend implementations and follows Angular v21+ best practices with functional dependency injection.

Overview

This service extends BaseService and uses:
  • Tesseract OCR for text extraction from images
  • C++ backend via .NET Core API
  • Node.js backend as an alternative processing engine
  • RxJS Observables for async operations
  • Type-safe interfaces for response handling
The service requires backend APIs to be configured in the ConfigService with keys baseUrlNetCoreCPPEntry and baseUrlNodeJsOcr.

Installation

The service is provided at root level and uses functional dependency injection:
import { OCRService } from '@services/__AI/OCRService/ocr.service';
import { inject } from '@angular/core';

export class MyComponent {
  private ocrService = inject(OCRService);
}

Interface

OCRResponse

Strongly typed interface for OCR API responses:
export interface OCRResponse {
  message: string;
  status?: string;
  data?: any;
}
message
string
required
The primary response message containing extracted text or error information
status
string
Optional status indicator for the operation
data
any
Optional additional data from the OCR processing

Methods

Version information methods

These methods retrieve version information from the C++ Tesseract backend.

_GetTesseract_CPPSTDVersion()

Returns the C++ standard library version used by the backend.
_GetTesseract_CPPSTDVersion(): Observable<string>
Returns: Observable emitting the C++ STD version string Example:
const ocrService = inject(OCRService);

ocrService._GetTesseract_CPPSTDVersion().subscribe(version => {
  console.log('C++ STD Version:', version);
});

_GetTesseract_AppVersion()

Returns the application version of the Tesseract backend.
_GetTesseract_AppVersion(): Observable<string>
Returns: Observable emitting the application version string Example:
ocrService._GetTesseract_AppVersion().subscribe(version => {
  console.log('App Version:', version);
});

_GetTesseract_APIVersion()

Returns the Tesseract API version.
_GetTesseract_APIVersion(): Observable<string>
Returns: Observable emitting the API version string Example:
ocrService._GetTesseract_APIVersion().subscribe(version => {
  console.log('API Version:', version);
});

OCR processing methods

uploadBase64ImageCPP()

Processes a Base64-encoded image using the C++ backend with Tesseract OCR.
uploadBase64ImageCPP(base64Image: string): Observable<OCRResponse>
base64Image
string
required
Base64-encoded image string (with or without data URI prefix)
Returns: Observable emitting OCRResponse with extracted text Example:
const ocrService = inject(OCRService);
const imageData = 'data:image/png;base64,iVBORw0KGgoAAAANS...';

ocrService.uploadBase64ImageCPP(imageData).subscribe({
  next: (response) => {
    console.log('Extracted text:', response.message);
    console.log('Status:', response.status);
  },
  error: (err) => console.error('OCR failed:', err)
});

uploadBase64ImageNodeJs()

Processes a Base64-encoded image using the Node.js backend with Tesseract OCR.
uploadBase64ImageNodeJs(base64Image: string): Observable<OCRResponse>
base64Image
string
required
Base64-encoded image string (with or without data URI prefix)
Returns: Observable emitting OCRResponse with extracted text Example:
const ocrService = inject(OCRService);
const imageData = 'data:image/jpeg;base64,/9j/4AAQSkZJRg...';

ocrService.uploadBase64ImageNodeJs(imageData).subscribe({
  next: (response) => {
    console.log('Extracted text:', response.message);
  },
  error: (err) => console.error('OCR failed:', err)
});

Complete usage example

Here’s a complete example showing how to capture an image from a file input and perform OCR:
import { Component, inject } from '@angular/core';
import { OCRService, OCRResponse } from '@services/__AI/OCRService/ocr.service';
import { CommonModule } from '@angular/common';

@Component({
  selector: 'app-ocr-demo',
  standalone: true,
  imports: [CommonModule],
  template: `
    <input type="file" accept="image/*" (change)="onFileSelected($event)" />
    <button (click)="processWithCPP()" [disabled]="!imageData">Process with C++</button>
    <button (click)="processWithNodeJs()" [disabled]="!imageData">Process with Node.js</button>
    
    @if (loading) {
      <p>Processing image...</p>
    }
    
    @if (result) {
      <div>
        <h3>Extracted Text:</h3>
        <pre>{{ result.message }}</pre>
      </div>
    }
  `
})
export class OcrDemoComponent {
  private ocrService = inject(OCRService);
  
  imageData: string | null = null;
  result: OCRResponse | null = null;
  loading = false;

  onFileSelected(event: Event): void {
    const file = (event.target as HTMLInputElement).files?.[0];
    if (!file) return;

    const reader = new FileReader();
    reader.onload = () => {
      this.imageData = reader.result as string;
    };
    reader.readAsDataURL(file);
  }

  processWithCPP(): void {
    if (!this.imageData) return;
    
    this.loading = true;
    this.ocrService.uploadBase64ImageCPP(this.imageData).subscribe({
      next: (response) => {
        this.result = response;
        this.loading = false;
      },
      error: (err) => {
        console.error('OCR failed:', err);
        this.loading = false;
      }
    });
  }

  processWithNodeJs(): void {
    if (!this.imageData) return;
    
    this.loading = true;
    this.ocrService.uploadBase64ImageNodeJs(this.imageData).subscribe({
      next: (response) => {
        this.result = response;
        this.loading = false;
      },
      error: (err) => {
        console.error('OCR failed:', err);
        this.loading = false;
      }
    });
  }
}

Angular v21+ features

This service demonstrates modern Angular patterns:

Functional dependency injection

Replaces constructor-based injection with inject() function:
private readonly http = inject(HttpClient);
private readonly _configService = inject(ConfigService);

Readonly properties

Ensures immutability after service instantiation:
private readonly __baseUrl = `${this._configService.getConfigValue('baseUrlNetCoreCPPEntry')}api/ocr/`;

Observable-signal interop ready

All methods return Observables compatible with toSignal() and rxResource():
import { toSignal } from '@angular/core/rxjs-interop';

const apiVersion = toSignal(ocrService._GetTesseract_APIVersion(), { initialValue: 'Loading...' });

Backend configuration

Ensure your environment.ts or configuration includes:
export const environment = {
  externalConfig: {
    baseUrlNetCoreCPPEntry: 'https://your-cpp-backend.com/',
    baseUrlNodeJsOcr: 'https://your-nodejs-backend.com/'
  }
};

Build docs developers (and LLMs) love