2024-01-02 13:53:21 +01:00
|
|
|
import 'dart:io';
|
2023-11-21 19:48:58 +01:00
|
|
|
import 'package:cpd_app/http_utils.dart';
|
|
|
|
import 'package:cpd_app/image_uploader.dart';
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:flutter/services.dart';
|
2024-01-02 13:53:21 +01:00
|
|
|
import 'language_utils.dart';
|
|
|
|
import 'package:image_picker/image_picker.dart';
|
2024-01-10 23:39:33 +01:00
|
|
|
import 'package:fluttertoast/fluttertoast.dart';
|
2023-11-21 19:48:58 +01:00
|
|
|
|
|
|
|
class OCRPage extends StatefulWidget {
|
2024-01-02 13:53:21 +01:00
|
|
|
const OCRPage({Key? key}) : super(key: key);
|
2023-11-21 19:48:58 +01:00
|
|
|
|
|
|
|
@override
|
2024-01-10 23:39:33 +01:00
|
|
|
State<OCRPage> createState() => OCRPageState();
|
2023-11-21 19:48:58 +01:00
|
|
|
}
|
|
|
|
|
2024-01-10 23:39:33 +01:00
|
|
|
class OCRPageState extends State<OCRPage> {
|
|
|
|
List<String> tessLangCodes = LanguageUtils.tessLanguages.keys.toList();
|
|
|
|
String extractedText = '';
|
2023-11-21 19:48:58 +01:00
|
|
|
final ImageUploader _imageUploader = ImageUploader();
|
|
|
|
final HttpUtils _httpUtils = HttpUtils();
|
2024-01-02 13:53:21 +01:00
|
|
|
String _selectedLanguage = 'Auto';
|
2024-01-10 23:39:33 +01:00
|
|
|
XFile? selectedImage;
|
2023-11-21 19:48:58 +01:00
|
|
|
|
2024-01-10 23:39:33 +01:00
|
|
|
Future<void> getText(Uint8List imageBytes, String selectedLanguage) async {
|
2024-01-02 13:53:21 +01:00
|
|
|
setState(() {
|
2024-01-10 23:39:33 +01:00
|
|
|
extractedText = '';
|
2024-01-02 13:53:21 +01:00
|
|
|
});
|
2023-11-21 19:48:58 +01:00
|
|
|
|
2024-01-10 23:39:33 +01:00
|
|
|
if (!(await _httpUtils.internetConnectivityCheck())) {
|
|
|
|
_httpUtils.triggerNoInetToast();
|
|
|
|
return;
|
|
|
|
}
|
2024-01-02 13:53:21 +01:00
|
|
|
String text = '';
|
2024-01-10 23:39:33 +01:00
|
|
|
// ignore: use_build_context_synchronously
|
|
|
|
_httpUtils.showProgressBar(context);
|
|
|
|
try {
|
|
|
|
if (Platform.isWindows) {
|
|
|
|
if (selectedLanguage == 'Auto') {
|
|
|
|
String lang = await _httpUtils.checkLang(imageBytes, 'image.jpg');
|
|
|
|
String mappedLang = LanguageUtils.reMapping[lang]!;
|
|
|
|
text =
|
|
|
|
await _httpUtils.extractTextKnownSource(imageBytes, mappedLang);
|
|
|
|
} else {
|
|
|
|
String langCode =
|
|
|
|
LanguageUtils.translatorLanguages[selectedLanguage]!;
|
|
|
|
text = await _httpUtils.extractTextKnownSource(imageBytes, langCode);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (selectedLanguage == 'Auto') {
|
|
|
|
String lang = await _httpUtils.checkLang(imageBytes, 'image.jpg');
|
|
|
|
text = await _imageUploader.performOcr(imageBytes, 'image.jpg', lang);
|
|
|
|
} else {
|
|
|
|
String langCode = LanguageUtils.tessLanguages[selectedLanguage]!;
|
|
|
|
text = await _imageUploader.performOcr(
|
|
|
|
imageBytes, 'image.jpg', langCode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} finally {
|
|
|
|
// ignore: use_build_context_synchronously
|
|
|
|
_httpUtils.hideProgressBar(context);
|
|
|
|
}
|
|
|
|
if (text == "") {
|
|
|
|
Fluttertoast.showToast(
|
|
|
|
msg: "Text could not be extracted",
|
|
|
|
toastLength: Toast.LENGTH_SHORT,
|
|
|
|
gravity: ToastGravity.BOTTOM,
|
|
|
|
timeInSecForIosWeb: 1,
|
|
|
|
backgroundColor: const Color.fromARGB(255, 161, 120, 17),
|
|
|
|
textColor: Colors.white,
|
|
|
|
fontSize: 16.0,
|
|
|
|
);
|
2024-01-02 13:53:21 +01:00
|
|
|
} else {
|
2024-01-10 23:39:33 +01:00
|
|
|
setState(() {
|
|
|
|
extractedText = text;
|
|
|
|
selectedImage = null;
|
|
|
|
});
|
2024-01-02 13:53:21 +01:00
|
|
|
}
|
2023-11-21 19:48:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
return Scaffold(
|
2024-01-10 23:39:33 +01:00
|
|
|
backgroundColor: const Color.fromARGB(99, 78, 72, 72),
|
2023-11-21 19:48:58 +01:00
|
|
|
appBar: AppBar(
|
2024-01-10 23:39:33 +01:00
|
|
|
backgroundColor: const Color.fromARGB(255, 161, 120, 17),
|
2023-11-21 19:48:58 +01:00
|
|
|
title: const Text('OCR'),
|
2024-01-10 23:39:33 +01:00
|
|
|
actions: [
|
|
|
|
IconButton(
|
|
|
|
icon: const Icon(Icons.wifi),
|
|
|
|
onPressed: () async {
|
|
|
|
if (!await _httpUtils.internetConnectivityCheck()) {
|
|
|
|
_httpUtils.triggerNoInetToast();
|
|
|
|
} else {
|
|
|
|
_httpUtils.triggerConnectedToast();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
),
|
|
|
|
],
|
2023-11-21 19:48:58 +01:00
|
|
|
),
|
|
|
|
body: Center(
|
|
|
|
child: Column(
|
|
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
|
|
children: <Widget>[
|
2024-01-02 13:53:21 +01:00
|
|
|
DropdownButton<String>(
|
|
|
|
value: _selectedLanguage,
|
2024-01-10 23:39:33 +01:00
|
|
|
style: const TextStyle(color: Colors.white),
|
|
|
|
dropdownColor: const Color(0xFF4E4848),
|
2024-01-02 13:53:21 +01:00
|
|
|
onChanged: (newValue) {
|
|
|
|
setState(() {
|
|
|
|
_selectedLanguage = newValue!;
|
|
|
|
});
|
|
|
|
},
|
2024-01-10 23:39:33 +01:00
|
|
|
items:
|
|
|
|
tessLangCodes.map<DropdownMenuItem<String>>((String value) {
|
2024-01-02 13:53:21 +01:00
|
|
|
return DropdownMenuItem<String>(
|
|
|
|
value: value,
|
|
|
|
child: Text(value),
|
|
|
|
);
|
|
|
|
}).toList(),
|
|
|
|
),
|
2024-01-10 23:39:33 +01:00
|
|
|
//Image preview hier
|
|
|
|
selectedImage != null
|
|
|
|
? Container(
|
2024-01-02 13:53:21 +01:00
|
|
|
width: MediaQuery.of(context).size.width * 0.8,
|
|
|
|
height: MediaQuery.of(context).size.height * 0.4,
|
2024-01-10 23:39:33 +01:00
|
|
|
decoration: BoxDecoration(
|
|
|
|
border: Border.all(
|
|
|
|
color: const Color.fromARGB(255, 161, 120, 17),
|
|
|
|
width: 1.0,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
child: Image.file(File(selectedImage!.path)),
|
2024-01-02 13:53:21 +01:00
|
|
|
)
|
|
|
|
: Container(),
|
|
|
|
ElevatedButton(
|
|
|
|
onPressed: () async {
|
|
|
|
final ImagePicker picker = ImagePicker();
|
|
|
|
final XFile? image =
|
|
|
|
await picker.pickImage(source: ImageSource.gallery);
|
|
|
|
if (image != null) {
|
|
|
|
setState(() {
|
2024-01-10 23:39:33 +01:00
|
|
|
selectedImage = image;
|
2024-01-02 13:53:21 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
},
|
2024-01-10 23:39:33 +01:00
|
|
|
style: ElevatedButton.styleFrom(
|
|
|
|
backgroundColor: const Color.fromARGB(255, 161, 120, 17),
|
|
|
|
foregroundColor: const Color.fromARGB(255, 0, 0, 0)),
|
2024-01-02 13:53:21 +01:00
|
|
|
child: const Text('Select Image'),
|
|
|
|
),
|
2023-11-21 19:48:58 +01:00
|
|
|
ElevatedButton(
|
2024-01-10 23:39:33 +01:00
|
|
|
onPressed: selectedImage != null
|
2024-01-02 13:53:21 +01:00
|
|
|
? () async {
|
2024-01-10 23:39:33 +01:00
|
|
|
if (selectedImage != null && selectedImage!.path != "") {
|
|
|
|
File imageFile = File(selectedImage!.path);
|
2024-01-02 13:53:21 +01:00
|
|
|
List<int> imageBytes = imageFile.readAsBytesSync();
|
2024-01-10 23:39:33 +01:00
|
|
|
await getText(
|
2024-01-02 13:53:21 +01:00
|
|
|
Uint8List.fromList(imageBytes), _selectedLanguage);
|
2024-01-10 23:39:33 +01:00
|
|
|
} else if (selectedImage != null &&
|
|
|
|
selectedImage!.path == "") {
|
|
|
|
Uint8List? list = await selectedImage?.readAsBytes();
|
|
|
|
await getText(list!, _selectedLanguage);
|
2024-01-02 13:53:21 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
: null,
|
2024-01-10 23:39:33 +01:00
|
|
|
style: ElevatedButton.styleFrom(
|
|
|
|
backgroundColor: const Color.fromARGB(255, 161, 120, 17),
|
|
|
|
foregroundColor: const Color.fromARGB(255, 0, 0, 0)),
|
2024-01-02 13:53:21 +01:00
|
|
|
child: const Text('Extract Text'),
|
2023-11-21 19:48:58 +01:00
|
|
|
),
|
2024-01-10 23:39:33 +01:00
|
|
|
extractedText.isNotEmpty
|
2024-01-02 13:53:21 +01:00
|
|
|
? Expanded(
|
|
|
|
child: Padding(
|
|
|
|
padding: const EdgeInsets.all(8.0),
|
|
|
|
child: TextFormField(
|
|
|
|
readOnly: true,
|
2024-01-10 23:39:33 +01:00
|
|
|
initialValue: extractedText,
|
2024-01-02 13:53:21 +01:00
|
|
|
maxLines: null,
|
2024-01-10 23:39:33 +01:00
|
|
|
style: const TextStyle(color: Colors.white),
|
2024-01-02 13:53:21 +01:00
|
|
|
decoration: const InputDecoration(
|
|
|
|
labelText: 'Extracted Text',
|
|
|
|
border: OutlineInputBorder(),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
)
|
|
|
|
: Container(),
|
2024-01-10 23:39:33 +01:00
|
|
|
|
|
|
|
extractedText.isNotEmpty
|
|
|
|
? TextButton(
|
|
|
|
onPressed: () {
|
|
|
|
Clipboard.setData(ClipboardData(text: extractedText));
|
|
|
|
},
|
|
|
|
style: TextButton.styleFrom(
|
|
|
|
backgroundColor: const Color.fromARGB(0, 33, 149, 243),
|
|
|
|
foregroundColor: const Color.fromARGB(255, 161, 120, 17),
|
|
|
|
),
|
|
|
|
child: const Text('Copy to Clipboard'),
|
|
|
|
)
|
|
|
|
: const SizedBox(),
|
2023-11-21 19:48:58 +01:00
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|