2024-12-24 13:05:54 -03:00
|
|
|
use gb_core::{Error, Result};
|
|
|
|
use image::{DynamicImage, ImageOutputFormat};
|
|
|
|
use std::io::Cursor;
|
|
|
|
use tesseract::Tesseract;
|
|
|
|
use tempfile::NamedTempFile;
|
|
|
|
use std::io::Write;
|
2024-12-23 00:54:50 -03:00
|
|
|
|
2024-12-24 13:05:54 -03:00
|
|
|
pub struct ImageProcessor;
|
2024-12-22 20:56:52 -03:00
|
|
|
|
|
|
|
impl ImageProcessor {
|
2024-12-24 13:05:54 -03:00
|
|
|
pub fn new() -> Self {
|
|
|
|
Self
|
2024-12-22 20:56:52 -03:00
|
|
|
}
|
|
|
|
|
2024-12-24 13:05:54 -03:00
|
|
|
pub async fn extract_text(&self, image: &DynamicImage) -> Result<String> {
|
|
|
|
// Create a temporary file
|
|
|
|
let mut temp_file = NamedTempFile::new()
|
2024-12-23 00:54:50 -03:00
|
|
|
.map_err(|e| Error::internal(format!("Failed to create temp file: {}", e)))?;
|
2024-12-24 13:05:54 -03:00
|
|
|
|
|
|
|
// Convert image to PNG and write to temp file
|
|
|
|
let mut cursor = Cursor::new(Vec::new());
|
|
|
|
image.write_to(&mut cursor, ImageOutputFormat::Png)
|
|
|
|
.map_err(|e| Error::internal(format!("Failed to encode image: {}", e)))?;
|
|
|
|
|
|
|
|
temp_file.write_all(&cursor.into_inner())
|
|
|
|
.map_err(|e| Error::internal(format!("Failed to write to temp file: {}", e)))?;
|
2024-12-22 20:56:52 -03:00
|
|
|
|
2024-12-24 13:05:54 -03:00
|
|
|
// Initialize Tesseract and process image
|
|
|
|
let api = Tesseract::new(None, Some("eng"))
|
2024-12-23 00:54:50 -03:00
|
|
|
.map_err(|e| Error::internal(format!("Failed to initialize Tesseract: {}", e)))?;
|
|
|
|
|
2024-12-24 10:09:14 -03:00
|
|
|
api.set_image(temp_file.path().to_str().unwrap())
|
2024-12-24 13:05:54 -03:00
|
|
|
.map_err(|e| Error::internal(format!("Failed to set image: {}", e)))?
|
|
|
|
.recognize()
|
|
|
|
.map_err(|e| Error::internal(format!("Failed to recognize text: {}", e)))?
|
|
|
|
.get_text()
|
2024-12-23 00:54:50 -03:00
|
|
|
.map_err(|e| Error::internal(format!("Failed to get text: {}", e)))
|
2024-12-22 20:56:52 -03:00
|
|
|
}
|
2024-12-23 00:54:50 -03:00
|
|
|
}
|