From 9599ac4c8f4638effd87505d398328c59016c656 Mon Sep 17 00:00:00 2001 From: faithoflifedev Date: Sun, 8 Sep 2024 15:25:12 -0400 Subject: [PATCH] web platform support --- packages/google_vision/CHANGELOG.md | 10 +- packages/google_vision/README.md | 17 +- packages/google_vision/bin/vision.dart | 16 +- .../example/document_text_detection_file.dart | 10 +- .../example/doument_text_detection.dart | 11 +- packages/google_vision/example/example.dart | 32 +- .../example/label_detection.dart | 5 +- .../example/landmark_detection.dart | 9 +- .../google_vision/example/logo_detection.dart | 9 +- packages/google_vision/example/pubspec.yaml | 1 + .../google_vision/example/text_detection.dart | 22 +- .../google_vision/example/web_detection.dart | 23 +- packages/google_vision/lib/google_vision.dart | 10 - .../google_vision/lib/google_vision_cli.dart | 9 + packages/google_vision/lib/meta.dart | 2 +- .../lib/src/cmd/vision_crop_hint_command.dart | 71 ++-- .../lib/src/cmd/vision_detect_command.dart | 27 +- .../lib/src/cmd/vision_helper_command.dart | 87 +++-- .../lib/src/cmd/vision_highlight_command.dart | 12 +- .../src/cmd/vision_safe_search_command.dart | 22 +- .../lib/src/cmd/vision_score_command.dart | 8 +- .../lib/src/google_vision_base.dart | 333 +++--------------- .../lib/src/google_vision_file.dart | 4 + .../src/model/annotate_image_requests.dart | 31 -- .../src/model/annotate_image_requests.g.dart | 21 -- .../google_vision/lib/src/model/feature.dart | 3 + .../lib/src/model/feature.g.dart | 1 + .../lib/src/model/input_config.dart | 24 +- .../lib/src/model/json_image.dart | 8 - .../lib/src/token_generator.dart | 21 +- packages/google_vision/lib/src/util/util.dart | 5 - packages/google_vision/pubspec.yaml | 9 +- packages/google_vision/tool/README.md | 15 +- 33 files changed, 319 insertions(+), 569 deletions(-) create mode 100644 packages/google_vision/lib/google_vision_cli.dart delete mode 100644 packages/google_vision/lib/src/model/annotate_image_requests.dart delete mode 100644 packages/google_vision/lib/src/model/annotate_image_requests.g.dart diff --git a/packages/google_vision/CHANGELOG.md b/packages/google_vision/CHANGELOG.md index c134fdc..bc22574 100644 --- a/packages/google_vision/CHANGELOG.md +++ b/packages/google_vision/CHANGELOG.md @@ -1,12 +1,14 @@ # Changelog -## 1.4.0 +## 2.0.0 -* switch to Singleton +* added web platform support +* removed deprecated classes and methods +* logging with the `loggy` package -## 1.4.0 +## 1.4.0+1 -* switch to Singleton +* better reporting of web platform support ## 1.4.0 diff --git a/packages/google_vision/README.md b/packages/google_vision/README.md index d07d9cc..91f6d56 100644 --- a/packages/google_vision/README.md +++ b/packages/google_vision/README.md @@ -1,6 +1,5 @@ # Google Vision Images REST API Client - [![pub package](https://img.shields.io/pub/v/google_vision.svg)](https://pub.dartlang.org/packages/google_vision) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) @@ -11,9 +10,9 @@ Native [Dart](https://dart.dev/) package that integrates Google Vision features, - [Google Vision Images REST API Client](#google-vision-images-rest-api-client) - [Project Status](#project-status) - [Recent Changes](#recent-changes) + - [New for v2.0.0](#new-for-v200) - [New for v1.4.0](#new-for-v140) - [New for v1.3.0](#new-for-v130) - - [New for v1.2.0](#new-for-v120) - [Getting Started](#getting-started) - [pubspec.yaml](#pubspecyaml) - [Obtaining Authentication/Authorization Credentials](#obtaining-authenticationauthorization-credentials) @@ -25,7 +24,6 @@ Native [Dart](https://dart.dev/) package that integrates Google Vision features, - [Contributors](#contributors) - [Contributing](#contributing) - ## Project Status [![Build Status](https://github.com/faithoflifedev/google_vision/workflows/Dart/badge.svg)](https://github.com/faithoflifedev/google_vision/actions) [![github last commit](https://shields.io/github/last-commit/faithoflifedev/google_vision)](https://shields.io/github/last-commit/faithoflifedev/google_vision) [![github build](https://img.shields.io/github/actions/workflow/status/faithoflifedev/google_vision_workspace/dart.yaml?branch=main)](https://shields.io/github/workflow/status/faithoflifedev/google_vision/Dart) [![github issues](https://shields.io/github/issues/faithoflifedev/google_vision)](https://shields.io/github/issues/faithoflifedev/google_vision) @@ -36,6 +34,14 @@ Please feel free to submit PRs for any additional helper methods, or report an [ ## Recent Changes +### New for v2.0.0 + - Even though this package worked when used with the `web` platform the **pub.dev** analyzer would not show it as `web` platform compatible due to the use of the `universal_io` package which has a dependency on `dart:io`. This version has removed the `universal_io` dependency from the core package, so some related method signatures have been removed. + - The deprecated methods from in v1.3.x have been removed in this version. + - Logging functionality has been added to the package + ```dart + final googleVision = await GoogleVision(LogLevel.all).withJwtFile('service_credentials.json'); + ``` + ### New for v1.4.0 - A breaking change from the previous version is that the `GoogleVision` class now follows the Singleton design pattern. Now the object is instantiated as follows: ```dart @@ -51,9 +57,6 @@ final googleVision = await GoogleVision().withJwtFile('service_credentials.json' - This version of the package supports both the `image` and `file` annotation APIs for Google Vision. The previous versions of the package supported only the `image` API. - A number of methods and classes have been **Deprecated** in this version. All the provided examples still work without any changes, so the changes in this package should not cause any issue to existing code. - The `file` functionality added to this release allows for the annotation of file formats that have pages or frames, specifically `pdf`, `tiff` and `gif`. Google Vision allows annotation of up to 5 pages/frames. - -### New for v1.2.0 - - helper methods that simplify any `single` detection so a simple face detection can be performed with the `faceDetection(JsonImage jsonImage)` method, see the table below. ## Getting Started @@ -64,7 +67,7 @@ To use this package, add the dependency to your `pubspec.yaml` file: ```yaml dependencies: ... - google_vision: ^1.4.0 + google_vision: ^2.0.0 ``` ### Obtaining Authentication/Authorization Credentials diff --git a/packages/google_vision/bin/vision.dart b/packages/google_vision/bin/vision.dart index 3ffe235..7f5392b 100644 --- a/packages/google_vision/bin/vision.dart +++ b/packages/google_vision/bin/vision.dart @@ -1,18 +1,20 @@ import 'package:args/command_runner.dart'; -import 'package:google_vision/google_vision.dart'; +import 'package:google_vision/google_vision_cli.dart'; import 'package:universal_io/io.dart'; +/// Attempt to retrieve the 'home' folder of the user if running on a desktop. +String? get _userHome => + Platform.environment['HOME'] ?? Platform.environment['USERPROFILE']; + void main(List arguments) async { CommandRunner('vision', 'A command line interface for making API requests to the Google Vision.') - ..argParser.addOption( - 'pages', - abbr: 'p', - valueHelp: 'comma delimited list of pages to process (max 5)', - ) ..argParser.addOption('credential-file', - defaultsTo: '${Util.userHome}/.vision/credentials.json', + defaultsTo: '$_userHome/.vision/credentials.json', valueHelp: 'credentials file path') + ..argParser.addOption('log-level', + allowed: ['all', 'debug', 'info', 'warning', 'error', 'off'], + defaultsTo: 'off') ..addCommand(VisionCropHintCommand()) ..addCommand(VisionDetectCommand()) ..addCommand(VisionHighlightCommand()) diff --git a/packages/google_vision/example/document_text_detection_file.dart b/packages/google_vision/example/document_text_detection_file.dart index f36dfb5..1db4941 100644 --- a/packages/google_vision/example/document_text_detection_file.dart +++ b/packages/google_vision/example/document_text_detection_file.dart @@ -2,15 +2,19 @@ import 'package:google_vision/google_vision.dart'; import 'package:universal_io/io.dart'; void main() async { - final googleVision = - await GoogleVision().withJwtFile('service_credentials.json'); + final googleVision = await GoogleVision() + .withJwt(File('service_credentials.json').readAsStringSync()); print('checking...'); const int page = 1; + const fileName = 'sample_image/allswell.pdf'; + + final file = File(fileName); + final annotateFileResponses = await googleVision.file.documentTextDetection( - InputConfig.fromFilePath('sample_image/allswell.pdf'), + InputConfig.fromBuffer(file.readAsBytesSync().buffer), pages: [page], ); diff --git a/packages/google_vision/example/doument_text_detection.dart b/packages/google_vision/example/doument_text_detection.dart index 4f17a64..3e2d294 100644 --- a/packages/google_vision/example/doument_text_detection.dart +++ b/packages/google_vision/example/doument_text_detection.dart @@ -1,13 +1,16 @@ import 'package:google_vision/google_vision.dart'; +import 'package:universal_io/io.dart'; void main() async { - final googleVision = - await GoogleVision().withJwtFile('service_credentials.json'); + final googleVision = await GoogleVision() + .withJwt(File('service_credentials.json').readAsStringSync()); + + final inputImage = await File('sample_image/census2010.jpg').readAsBytes(); print('checking...'); - final fullTextAnnotation = await googleVision.documentTextDetection( - JsonImage.fromFilePath('sample_image/census2010.jpg')); + final fullTextAnnotation = await googleVision.image + .documentTextDetection(JsonImage.fromBuffer(inputImage.buffer)); for (var page in fullTextAnnotation!.pages) { print('Page Language: ${page.property?.detectedLanguages}'); diff --git a/packages/google_vision/example/example.dart b/packages/google_vision/example/example.dart index b8bf56f..ca24f10 100644 --- a/packages/google_vision/example/example.dart +++ b/packages/google_vision/example/example.dart @@ -1,25 +1,27 @@ import 'package:google_vision/google_vision.dart'; +import 'package:universal_io/io.dart'; void main() async { - final googleVision = - await GoogleVision().withJwtFile('service_credentials.json'); + final googleVision = await GoogleVision() + .withJwt(File('service_credentials.json').readAsStringSync()); - final requests = AnnotationRequests(requests: [ - AnnotationRequest( - // You may want to crop or shrink the image to the area of interest to - // safe bandwidth/upload time, but that's optional. - jsonImage: JsonImage.fromFilePath( - 'sample_image/young-man-smiling-and-thumbs-up.jpg'), - features: [ - Feature(maxResults: 10, type: AnnotationType.faceDetection), - Feature(maxResults: 10, type: AnnotationType.objectLocalization), - ]) - ]); + final requests = [ + AnnotateImageRequest( + // You may want to crop or shrink the image to the area of interest to + // safe bandwidth/upload time, but that's optional. + jsonImage: JsonImage.fromGsUri( + 'gs://gvision-demo/young-man-smiling-and-thumbs-up.jpg'), + features: [ + Feature(maxResults: 10, type: AnnotationType.faceDetection), + Feature(maxResults: 10, type: AnnotationType.objectLocalization), + ], + ) + ]; print('checking...'); - AnnotatedResponses annotatedResponses = - await googleVision.annotate(requests: requests); + final annotatedResponses = + await googleVision.image.annotate(requests: requests); print(annotatedResponses.responses.first.annotations); } diff --git a/packages/google_vision/example/label_detection.dart b/packages/google_vision/example/label_detection.dart index f65cf94..eafe90d 100644 --- a/packages/google_vision/example/label_detection.dart +++ b/packages/google_vision/example/label_detection.dart @@ -1,8 +1,9 @@ import 'package:google_vision/google_vision.dart'; +import 'package:universal_io/io.dart'; void main() async { - final googleVision = - await GoogleVision().withJwtFile('service_credentials.json'); + final googleVision = await GoogleVision() + .withJwt(File('service_credentials.json').readAsStringSync()); print('checking...'); diff --git a/packages/google_vision/example/landmark_detection.dart b/packages/google_vision/example/landmark_detection.dart index 2f4d4a6..3c43ffa 100644 --- a/packages/google_vision/example/landmark_detection.dart +++ b/packages/google_vision/example/landmark_detection.dart @@ -1,13 +1,16 @@ import 'package:google_vision/google_vision.dart'; +import 'package:universal_io/io.dart'; void main() async { - final googleVision = - await GoogleVision().withJwtFile('service_credentials.json'); + final googleVision = await GoogleVision() + .withJwt(File('service_credentials.json').readAsStringSync()); + + final inputImage = await File('sample_image/cn_tower.jpg').readAsBytes(); print('checking...'); final landmarkAnnotationsResponse = await googleVision.image - .labelDetection(JsonImage.fromFilePath('sample_image/cn_tower.jpg')); + .labelDetection(JsonImage.fromBuffer(inputImage.buffer)); for (var landmarkAnnotation in landmarkAnnotationsResponse) { print('score: ${landmarkAnnotation.score}'); diff --git a/packages/google_vision/example/logo_detection.dart b/packages/google_vision/example/logo_detection.dart index f7f17ec..4371aa6 100644 --- a/packages/google_vision/example/logo_detection.dart +++ b/packages/google_vision/example/logo_detection.dart @@ -1,13 +1,16 @@ import 'package:google_vision/google_vision.dart'; +import 'package:universal_io/io.dart'; void main() async { - final googleVision = - await GoogleVision().withJwtFile('service_credentials.json'); + final googleVision = await GoogleVision() + .withJwt(File('service_credentials.json').readAsStringSync()); + + final inputImage = await File('sample_image/logo.png').readAsBytes(); print('checking...'); final logoAnnotationsResponses = await googleVision.image - .logoDetection(JsonImage.fromFilePath('sample_image/logo.png')); + .logoDetection(JsonImage.fromBuffer(inputImage.buffer)); for (var logoAnnotation in logoAnnotationsResponses) { print('Logo: ${logoAnnotation.description}'); diff --git a/packages/google_vision/example/pubspec.yaml b/packages/google_vision/example/pubspec.yaml index 888f022..35832a2 100644 --- a/packages/google_vision/example/pubspec.yaml +++ b/packages/google_vision/example/pubspec.yaml @@ -13,4 +13,5 @@ dependencies: pcanvas: ^1.1.0 google_vision: path: ../ + mime: ^1.0.6 universal_io: ^2.2.2 diff --git a/packages/google_vision/example/text_detection.dart b/packages/google_vision/example/text_detection.dart index 5777e56..d49400d 100644 --- a/packages/google_vision/example/text_detection.dart +++ b/packages/google_vision/example/text_detection.dart @@ -2,23 +2,21 @@ import 'package:google_vision/google_vision.dart'; import 'package:universal_io/io.dart'; void main() async { - final googleVision = - await GoogleVision().withJwtFile('service_credentials.json'); + final googleVision = await GoogleVision() + .withJwt(File('service_credentials.json').readAsStringSync()); final imageFile = File('sample_image/structures.png').readAsBytesSync(); print('checking...'); - final annotatedResponses = await googleVision.annotate( - requests: AnnotationRequests( - requests: [ - AnnotationRequest( - jsonImage: JsonImage(byteBuffer: imageFile.buffer), - features: [ - Feature(maxResults: 10, type: AnnotationType.textDetection) - ]) - ], - ), + final annotatedResponses = await googleVision.image.annotate( + requests: [ + AnnotateImageRequest( + jsonImage: JsonImage(byteBuffer: imageFile.buffer), + features: [ + Feature(maxResults: 10, type: AnnotationType.textDetection) + ]) + ], ); for (var textAnnotation diff --git a/packages/google_vision/example/web_detection.dart b/packages/google_vision/example/web_detection.dart index a07620c..d6a6f66 100644 --- a/packages/google_vision/example/web_detection.dart +++ b/packages/google_vision/example/web_detection.dart @@ -2,23 +2,22 @@ import 'package:google_vision/google_vision.dart'; import 'package:universal_io/io.dart'; void main() async { - final googleVision = - await GoogleVision().withJwtFile('service_credentials.json'); + final googleVision = await GoogleVision() + .withJwt(File('service_credentials.json').readAsStringSync()); final imageFile = File('sample_image/structures.png').readAsBytesSync(); print('checking...'); - AnnotatedResponses annotatedResponses = await googleVision.annotate( - requests: AnnotateImageRequests( - requests: [ - AnnotateImageRequest( - jsonImage: JsonImage(byteBuffer: imageFile.buffer), - features: [ - Feature(maxResults: 10, type: AnnotationType.webDetection) - ]) - ], - ), + BatchAnnotateImagesResponse annotatedResponses = + await googleVision.image.annotate( + requests: [ + AnnotateImageRequest( + jsonImage: JsonImage(byteBuffer: imageFile.buffer), + features: [ + Feature(maxResults: 10, type: AnnotationType.webDetection) + ]) + ], ); print(annotatedResponses); diff --git a/packages/google_vision/lib/google_vision.dart b/packages/google_vision/lib/google_vision.dart index dfe3c2d..418bf0f 100644 --- a/packages/google_vision/lib/google_vision.dart +++ b/packages/google_vision/lib/google_vision.dart @@ -9,21 +9,11 @@ export 'src/google_vision_image.dart'; export 'src/annotate_json_serializable.dart'; export 'src/token_generator.dart'; -export 'src/cmd/vision_crop_hint_command.dart'; -export 'src/cmd/vision_detect_command.dart'; -export 'src/cmd/vision_helper_command.dart'; -export 'src/cmd/vision_highlight_command.dart'; -export 'src/cmd/vision_safe_search_command.dart'; -export 'src/cmd/vision_score_command.dart'; -export 'src/cmd/vision_version_command.dart'; - export 'src/model/annotate_file_request.dart'; export 'src/model/annotate_file_response.dart'; export 'src/model/annotate_image_response.dart'; export 'src/model/batch_annotate_images_response.dart'; export 'src/model/annotate_image_request.dart'; -// TODO: remove this depricated class in the next verion -export 'src/model/annotate_image_requests.dart'; export 'src/model/batch_annotate_files_response.dart'; export 'src/model/block.dart'; export 'src/model/bounding_poly.dart'; diff --git a/packages/google_vision/lib/google_vision_cli.dart b/packages/google_vision/lib/google_vision_cli.dart new file mode 100644 index 0000000..19f731e --- /dev/null +++ b/packages/google_vision/lib/google_vision_cli.dart @@ -0,0 +1,9 @@ +library google_vision_cli; + +export 'src/cmd/vision_crop_hint_command.dart'; +export 'src/cmd/vision_detect_command.dart'; +export 'src/cmd/vision_helper_command.dart'; +export 'src/cmd/vision_highlight_command.dart'; +export 'src/cmd/vision_safe_search_command.dart'; +export 'src/cmd/vision_score_command.dart'; +export 'src/cmd/vision_version_command.dart'; diff --git a/packages/google_vision/lib/meta.dart b/packages/google_vision/lib/meta.dart index 0c42dbf..36983b2 100644 --- a/packages/google_vision/lib/meta.dart +++ b/packages/google_vision/lib/meta.dart @@ -6,4 +6,4 @@ library meta; import 'dart:convert' show json; final pubSpec = json.decode( - '{"name":"google_vision","version":"1.4.0","homepage":"https://github.com/faithoflifedev/google_vision/tree/main/packages/google_vision","environment":{"sdk":">=3.2.0 <4.0.0"},"description":"Allows you to add Google Visions image labeling, face, logo, and landmark detection, OCR, and detection of explicit content, into cross platform applications.","dependencies":{"args":"^2.5.0","collection":"^1.18.0","crypto_keys_plus":"^0.4.0","dio":"^5.6.0","http":"^1.2.2","image":"^4.1.7","jose_plus":"^0.4.6","json_annotation":"^4.9.0","mime":"^1.0.6","retrofit":"^4.2.0","universal_io":"^2.2.2"},"dev_dependencies":{"build_runner":"^2.4.11","grinder":"^0.9.5","json_serializable":"^6.8.0","lints":"^4.0.0","publish_tools":"^1.0.0+4","retrofit_generator":"^8.2.1"},"executables":{"vision":""},"repository":"https://github.com/faithoflifedev/google_vision","funding":["https://www.buymeacoffee.com/faithoflif2"]}'); + '{"name":"google_vision","version":"2.0.0","homepage":"https://github.com/faithoflifedev/google_vision/tree/main/packages/google_vision","environment":{"sdk":">=3.2.0 <4.0.0"},"description":"Allows you to add Google Visions image labeling, face, logo, and landmark detection, OCR, and detection of explicit content, into cross platform applications.","dependencies":{"args":"^2.5.0","collection":"^1.18.0","crypto_keys_plus":"^0.4.0","dio":"^5.7.0","flutter_loggy_dio":"^3.1.0","http":"^1.2.2","image":"^4.1.7","jose_plus":"^0.4.6","json_annotation":"^4.9.0","loggy":"^2.0.3","mime":"^1.0.6","retrofit":"^4.4.0","universal_io":"^2.2.2","universal_platform":"^1.1.0"},"dev_dependencies":{"build_runner":"^2.4.11","grinder":"^0.9.5","json_serializable":"^6.8.0","lints":"^4.0.0","publish_tools":"^1.0.0+4","retrofit_generator":"^8.2.1"},"executables":{"vision":""},"repository":"https://github.com/faithoflifedev/google_vision","funding":["https://www.buymeacoffee.com/faithoflif2"]}'); diff --git a/packages/google_vision/lib/src/cmd/vision_crop_hint_command.dart b/packages/google_vision/lib/src/cmd/vision_crop_hint_command.dart index ea2b0e4..75aeb84 100644 --- a/packages/google_vision/lib/src/cmd/vision_crop_hint_command.dart +++ b/packages/google_vision/lib/src/cmd/vision_crop_hint_command.dart @@ -1,5 +1,7 @@ +import 'package:args/command_runner.dart'; +import 'package:dio/dio.dart'; import 'package:google_vision/google_vision.dart'; -import 'package:universal_io/io.dart'; +import 'package:google_vision/google_vision_cli.dart'; /// Set of crop hints that are used to generate new crops when serving images. class VisionCropHintCommand extends VisionHelper { @@ -8,7 +10,7 @@ class VisionCropHintCommand extends VisionHelper { @override String get description => - 'Set of crop hints that are used to generate new crops when serving images.'; + 'Set of crop hints that are used to generate new crops when serving images. When using this command with multi-page or multi-frame files like TIFFs and PDFs you must also provide a value for the the \'--pages\' argument.'; /// Set of crop hints that are used to generate new crops when serving images. VisionCropHintCommand() { @@ -17,6 +19,11 @@ class VisionCropHintCommand extends VisionHelper { mandatory: true, valueHelp: 'image file path', help: 'The path to the file that will be processed.') + ..addOption( + 'pages', + abbr: 'p', + valueHelp: 'comma delimited list of pages to process (max 5)', + ) ..addOption('aspect-ratios', valueHelp: 'aspect ratios', help: @@ -25,41 +32,41 @@ class VisionCropHintCommand extends VisionHelper { @override void run() async { - final googleVision = await GoogleVision().withJwtFile( - globalResults!['credential-file'], - 'https://www.googleapis.com/auth/cloud-vision'); + try { + await initializeGoogleVision(); - final imageFile = File(argResults!['image-file']); + final aspectRatios = argResults?['aspect-ratios'] == null + ? null + : argResults!['aspect-ratios'] + .toString() + .split(',') + .map((aspectRatio) => double.parse(aspectRatio)) + .toList(); - final aspectRatios = argResults?['aspect-ratios'] == null - ? null - : argResults!['aspect-ratios'] - .toString() - .split(',') - .map((aspectRatio) => double.parse(aspectRatio)) - .toList(); + final imageContext = aspectRatios != null + ? ImageContext( + cropHintsParams: CropHintsParams(aspectRatios: aspectRatios), + ) + : null; - final imageContext = aspectRatios != null - ? ImageContext( - cropHintsParams: CropHintsParams(aspectRatios: aspectRatios), - ) - : null; + if (pages != null) { + final annotatedResponses = await googleVision.file.cropHints( + InputConfig.fromBuffer(imageBytes.buffer), + imageContext: imageContext, + pages: pages!, + ); - if (pages != null) { - final annotatedResponses = await annotateFile( - imageFile, - imageContext: imageContext, - pages: pages!, - ); + print(annotatedResponses); + } else { + final annotatedResponses = await googleVision.image.cropHints( + JsonImage.fromBuffer(imageBytes.buffer), + imageContext: imageContext, + ); - print(annotatedResponses.responses); - } else { - final annotatedResponses = await googleVision.image.cropHints( - JsonImage.fromFile(imageFile), - imageContext: imageContext, - ); - - print(annotatedResponses?.cropHints); + print(annotatedResponses?.cropHints); + } + } on DioException catch (err) { + throw UsageException('API usage error:', err.usage); } } } diff --git a/packages/google_vision/lib/src/cmd/vision_detect_command.dart b/packages/google_vision/lib/src/cmd/vision_detect_command.dart index 1b8dc9f..2cdc231 100644 --- a/packages/google_vision/lib/src/cmd/vision_detect_command.dart +++ b/packages/google_vision/lib/src/cmd/vision_detect_command.dart @@ -1,4 +1,5 @@ -import 'package:universal_io/io.dart'; +import 'package:args/command_runner.dart'; +import 'package:dio/dio.dart'; import 'vision_helper_command.dart'; @@ -19,6 +20,11 @@ class VisionDetectCommand extends VisionHelper { mandatory: true, valueHelp: 'image file path', help: 'The path to the file that will be processed.') + ..addOption( + 'pages', + abbr: 'p', + valueHelp: 'comma delimited list of pages to process (max 5)', + ) ..addOption('features', mandatory: true, help: @@ -32,17 +38,20 @@ class VisionDetectCommand extends VisionHelper { @override void run() async { - final imageFile = File(argResults!['image-file']); + try { + await initializeGoogleVision(); - if (pages != null) { - final annotatedResponses = await annotateFile(imageFile, pages: pages!); + if (pages != null) { + final annotatedResponses = await annotateFile(); - print(annotatedResponses.responses); - } else { - final annotatedResponses = - await annotateImage(imageFile.readAsBytesSync().buffer); + print(annotatedResponses.responses); + } else { + final annotatedResponses = await annotateImage(); - print(annotatedResponses.responses); + print(annotatedResponses.responses); + } + } on DioException catch (err) { + throw UsageException('API usage error:', err.usage); } } } diff --git a/packages/google_vision/lib/src/cmd/vision_helper_command.dart b/packages/google_vision/lib/src/cmd/vision_helper_command.dart index 4827d84..4688aad 100644 --- a/packages/google_vision/lib/src/cmd/vision_helper_command.dart +++ b/packages/google_vision/lib/src/cmd/vision_helper_command.dart @@ -3,6 +3,7 @@ import 'dart:typed_data'; import 'package:args/command_runner.dart'; import 'package:dio/dio.dart'; import 'package:google_vision/google_vision.dart'; +import 'package:loggy/loggy.dart'; import 'package:universal_io/io.dart'; /// Helper method to that retrieves error message string. @@ -18,36 +19,52 @@ extension UsageExtension on DioException { abstract class VisionHelper extends Command { GoogleVision? _googleVision; + GoogleVision get googleVision => _googleVision!; + List? pages; - GoogleVision get googleVision => _googleVision!; + late final File imageFile; + + late final Uint8List imageBytes; Future initializeGoogleVision() async { - _googleVision = - await GoogleVision().withJwtFile(globalResults!['credential-file']); + final logLevel = _toLogLevel(globalResults!['log-level']); + + _googleVision = await GoogleVision(logLevel) + .withJwt(credentialsFromFile(File(globalResults!['credential-file']))); + + imageFile = File(argResults!['image-file']); + + imageBytes = await imageFile.readAsBytes(); - pages = - (argResults!['pages'] as String?)?.split(',').map(int.parse).toList(); + if (argResults != null && argResults!['pages'] != null) { + pages = + (argResults!['pages'] as String?)?.split(',').map(int.parse).toList(); + } } + String credentialsFromFile(File file) => file.readAsStringSync(); + + String credentialsFromFileName(String fileName) => + credentialsFromFile(File(fileName)); + /// Helper method to get the features from the command line. - List getFeatures([String? features]) => - (argResults!['features'] as String) - .split(',') - .map( - (element) => Feature( - maxResults: int.parse(argResults!['max-results']), - type: AnnotationType.values.byName(element)), - ) - .toList(); + List getFeatures() => (argResults!['features'] as String) + .split(',') + .map( + (element) => Feature( + maxResults: int.parse(argResults!['max-results']), + type: _toAnnotationType(element), + ), + ) + .toList(); /// Helper methods used by most of the cli commands. - Future annotateImage(ByteBuffer buffer, - [String? features]) async { + Future annotateImage() { final requests = [ AnnotateImageRequest( - jsonImage: JsonImage(byteBuffer: buffer), - features: getFeatures(features), + jsonImage: JsonImage(byteBuffer: imageBytes.buffer), + features: getFeatures(), ) ]; @@ -55,18 +72,26 @@ abstract class VisionHelper extends Command { } /// Helper methods used by most of the cli commands. - Future annotateFile( - File file, { - String? features, + Future annotateFile({ ImageContext? imageContext, - required List pages, - }) async => - googleVision.file.annotate(requests: [ - AnnotateFileRequest( - inputConfig: InputConfig.fromFile(file), - features: getFeatures(features), - imageContext: imageContext, - pages: pages, - ) - ]); + }) async { + return googleVision.file.annotate(requests: [ + AnnotateFileRequest( + inputConfig: InputConfig.fromBuffer(imageBytes.buffer), + features: getFeatures(), + imageContext: imageContext, + pages: pages, + ) + ]); + } + + /// Helper method to convert string from cli argument to enum. + static AnnotationType _toAnnotationType(type) => AnnotationType.values + .firstWhere((annotationType) => annotationType.type == type.trim(), + orElse: () => AnnotationType.typeUnspecified); + + /// Helper method to convert string from cli argument to enum. + static LogLevel _toLogLevel(String name) => LogLevel.values.firstWhere( + (logLevel) => logLevel.name.toLowerCase() == name.trim().toLowerCase(), + orElse: () => LogLevel.off); } diff --git a/packages/google_vision/lib/src/cmd/vision_highlight_command.dart b/packages/google_vision/lib/src/cmd/vision_highlight_command.dart index c8c5c34..bb4db28 100644 --- a/packages/google_vision/lib/src/cmd/vision_highlight_command.dart +++ b/packages/google_vision/lib/src/cmd/vision_highlight_command.dart @@ -3,8 +3,8 @@ import 'dart:typed_data'; import 'package:args/command_runner.dart'; import 'package:dio/dio.dart'; import 'package:google_vision/google_vision.dart'; +import 'package:google_vision/google_vision_cli.dart'; import 'package:image/image.dart' as img; -import 'package:universal_io/io.dart'; /// Draw a box to highlight any objects detected. class VisionHighlightCommand extends VisionHelper { @@ -12,7 +12,8 @@ class VisionHighlightCommand extends VisionHelper { String get name => 'highlight'; @override - String get description => 'Draw a box to highlight any objects detected.'; + String get description => + 'Draw a box to highlight any objects detected. This command does not work with some multi-page or multi-frame files like TIFFs and PDFs.'; /// Draw a box to highlight any objects detected. VisionHighlightCommand() { @@ -76,12 +77,9 @@ class VisionHighlightCommand extends VisionHelper { try { await initializeGoogleVision(); - final Uint8List encodedBytes = - File(argResults!['image-file']).readAsBytesSync(); + final annotatedResponses = await annotateImage(); - final annotatedResponses = await annotateImage(encodedBytes.buffer); - - final img.Image decodedBytes = img.decodeImage(encodedBytes)!; + final img.Image decodedBytes = img.decodeImage(imageBytes)!; for (var annotatedResponse in annotatedResponses.responses) { // check for faces diff --git a/packages/google_vision/lib/src/cmd/vision_safe_search_command.dart b/packages/google_vision/lib/src/cmd/vision_safe_search_command.dart index 8bb9820..4763857 100644 --- a/packages/google_vision/lib/src/cmd/vision_safe_search_command.dart +++ b/packages/google_vision/lib/src/cmd/vision_safe_search_command.dart @@ -1,5 +1,7 @@ +import 'package:args/command_runner.dart'; +import 'package:dio/dio.dart'; import 'package:google_vision/google_vision.dart'; -import 'package:universal_io/io.dart'; +import 'package:google_vision/google_vision_cli.dart'; /// SafeSearch Detection detects explicit content such as adult content or /// violent content within an image. @@ -9,7 +11,7 @@ class VisionSafeSearchCommand extends VisionHelper { @override String get description => - 'SafeSearch Detection detects explicit content such as adult content or violent content within an image.'; + 'SafeSearch Detection detects explicit content such as adult content or violent content within an image. This command does not work with some multi-page or multi-frame files like TIFFs and PDFs.'; /// SafeSearch Detection detects explicit content such as adult content or /// violent content within an image. @@ -22,15 +24,15 @@ class VisionSafeSearchCommand extends VisionHelper { @override void run() async { - final googleVision = await GoogleVision().withJwtFile( - globalResults!['credential-file'], - 'https://www.googleapis.com/auth/cloud-vision'); + try { + await initializeGoogleVision(); - final imageFile = File(argResults!['image-file']); + final safeSearchDetection = await googleVision.image + .safeSearchDetection(JsonImage.fromBuffer(imageBytes.buffer)); - final safeSearchDetection = await googleVision.image - .safeSearchDetection(JsonImage.fromFile(imageFile)); - - print(safeSearchDetection); + print(safeSearchDetection); + } on DioException catch (err) { + throw UsageException('API usage error:', err.usage); + } } } diff --git a/packages/google_vision/lib/src/cmd/vision_score_command.dart b/packages/google_vision/lib/src/cmd/vision_score_command.dart index 0b4eab4..00576fa 100644 --- a/packages/google_vision/lib/src/cmd/vision_score_command.dart +++ b/packages/google_vision/lib/src/cmd/vision_score_command.dart @@ -3,7 +3,7 @@ import 'dart:convert'; import 'package:args/command_runner.dart'; import 'package:dio/dio.dart'; import 'package:google_vision/google_vision.dart'; -import 'package:universal_io/io.dart'; +import 'package:google_vision/google_vision_cli.dart'; /// For OBJECT_LOCALIZATION, get the score(s) for the object specified with /// "look-for". @@ -13,7 +13,7 @@ class VisionScoreCommand extends VisionHelper { @override String get description => - 'For OBJECT_LOCALIZATION, get the score(s) for the object specified with "look-for".'; + 'For OBJECT_LOCALIZATION, get the score(s) for the object specified with "look-for". This command does not work with some multi-page or multi-frame files like TIFFs and PDFs.'; /// For OBJECT_LOCALIZATION, get the score(s) for the object specified with /// "look-for". @@ -42,9 +42,7 @@ class VisionScoreCommand extends VisionHelper { try { await initializeGoogleVision(); - final imageFile = File(argResults!['image-file']).readAsBytesSync(); - - final annotatedResponses = await annotateImage(imageFile.buffer); + final annotatedResponses = await annotateImage(); final scores = []; diff --git a/packages/google_vision/lib/src/google_vision_base.dart b/packages/google_vision/lib/src/google_vision_base.dart index b576941..e21e15b 100644 --- a/packages/google_vision/lib/src/google_vision_base.dart +++ b/packages/google_vision/lib/src/google_vision_base.dart @@ -1,12 +1,12 @@ -import 'dart:io'; - import 'package:dio/dio.dart'; +import 'package:flutter_loggy_dio/flutter_loggy_dio.dart'; import 'package:google_vision/google_vision.dart'; +import 'package:loggy/loggy.dart'; /// Integrates Google Vision features, including painter labeling, face, logo, /// and landmark detection, optical character recognition (OCR), and detection /// of explicit content, into applications. -class GoogleVision { +class GoogleVision with UiLoggy { static final GoogleVision _instance = GoogleVision._internal(); final dio = Dio(); @@ -31,30 +31,29 @@ class GoogleVision { // Private constructor GoogleVision._internal(); - factory GoogleVision() => _instance; - - void setAuthHeader() { - if (_token != null) { - dio.options.headers[HttpHeaders.authorizationHeader] = 'Bearer $_token'; + factory GoogleVision([LogLevel logLevel = LogLevel.off]) { + if (logLevel != LogLevel.off) { + _instance.dio.interceptors.add(LoggyDioInterceptor( + requestBody: true, + responseBody: true, + requestHeader: true, + responseHeader: true, + requestLevel: logLevel, + responseLevel: logLevel, + errorLevel: logLevel, + )); } - if (_apiKey != null) { - dio.options.queryParameters['key'] = _apiKey; - } - } - - Future confirmToken() async { - if (tokenGenerator == null) { - throw Exception(); - } else { - if (tokenExpiry.isBefore(DateTime.now())) { - final tokenData = await tokenGenerator!.generate(); - - _token = tokenData.accessToken; + Loggy.initLoggy( + logPrinter: const PrettyPrinter( + showColors: true, + ), + logOptions: LogOptions( + logLevel, + ), + ); - tokenExpiry.add(Duration(seconds: tokenData.expiresIn)); - } - } + return _instance; } /// Authenticate using an API key. @@ -73,13 +72,11 @@ class GoogleVision { /// Authenticate using the supplied token generator Future withGenerator(TokenGenerator generator) async { - final googleVision = GoogleVision(); - - googleVision.tokenGenerator = generator; + tokenGenerator = generator; - await googleVision.confirmToken(); + await confirmToken(); - return googleVision; + return this; } /// Authenticated with JWT. @@ -87,274 +84,38 @@ class GoogleVision { String credentials, [ String scope = 'https://www.googleapis.com/auth/cloud-platform', ]) async { - GoogleVision googleVision = GoogleVision(); - - googleVision.tokenGenerator = JwtGenerator( + tokenGenerator = JwtGenerator( credentials: credentials, scope: scope, - dio: googleVision.dio, - ); - - await googleVision.confirmToken(); - - return googleVision; - } - - /// Authenticated with JWT. - Future withJwtFile( - String credentialsFileName, [ - String scope = 'https://www.googleapis.com/auth/cloud-platform', - ]) async { - GoogleVision googleVision = GoogleVision(); - - googleVision.tokenGenerator = JwtGenerator.fromFile( - credentialsFile: credentialsFileName, - scope: scope, - dio: googleVision.dio, - ); - - await googleVision.confirmToken(); - - return googleVision; - } - - @Deprecated('Use [GoogleVisionImage.annotate] instead.') - Future annotate({ - required AnnotateImageRequests requests, - String? parent, - }) async { - final batchAnnotateImagesResponse = await image.annotate( - requests: requests.requests, - parent: parent, - ); - - return AnnotatedResponses(responses: batchAnnotateImagesResponse.responses); - } - - /// Higher level method for a single detection type as specified by [annotationType], - @Deprecated('Use [GoogleVisionImage.detection] instead.') - Future detection( - JsonImage jsonImage, - AnnotationType annotationType, { - int maxResults = 10, - }) async { - final annotatedResponses = await image.annotate( - requests: [ - AnnotateImageRequest( - jsonImage: jsonImage, - features: [ - Feature( - maxResults: maxResults, - type: annotationType, - ), - ], - ) - ], - ); - - return annotatedResponses.responses.first; - } - - /// Crop Hints suggests vertices for a crop region on an image. - @Deprecated('Use [GoogleVisionImage.cropHints] instead.') - Future cropHints( - JsonImage jsonImage, { - int maxResults = 10, - }) async { - final annotatedResponses = await detection( - jsonImage, - AnnotationType.cropHints, - maxResults: maxResults, - ); - - return annotatedResponses.cropHintsAnnotation; - } - - /// Extracts text from an image (or file); the response is optimized for dense - /// text and documents. The JSON includes page, block, paragraph, word, and - /// break information. A specific use of [documentTextDetection] is to detect - /// handwriting in an image. - @Deprecated('Use [GoogleVisionImage.documentTextDetection] instead.') - Future documentTextDetection( - JsonImage jsonImage, { - int maxResults = 10, - }) async { - final annotatedResponses = await detection( - jsonImage, - AnnotationType.documentTextDetection, - maxResults: maxResults, - ); - - return annotatedResponses.fullTextAnnotation; - } - - /// Face Detection detects multiple faces within an image along with the - /// associated key facial attributes such as emotional state or wearing - /// head-wear. - @Deprecated('Use [GoogleVisionImage.faceDetection] instead.') - Future> faceDetection( - JsonImage jsonImage, { - int maxResults = 10, - }) async { - final annotatedResponses = await detection( - jsonImage, - AnnotationType.faceDetection, - maxResults: maxResults, - ); - - return annotatedResponses.faceAnnotations; - } - - /// The Image Properties feature detects general attributes of the image, such - /// as dominant color. - @Deprecated('Use [GoogleVisionImage.imageProperties] instead.') - Future imageProperties( - JsonImage jsonImage, { - int maxResults = 10, - }) async { - final annotatedResponses = await detection( - jsonImage, - AnnotationType.imageProperties, - maxResults: maxResults, - ); - - return annotatedResponses.imagePropertiesAnnotation; - } - - /// Labels can identify general objects, locations, activities, animal - /// species, products, and more. Labels are returned in English only. - @Deprecated('Use [GoogleVisionImage.labelDetection] instead.') - Future> labelDetection( - JsonImage jsonImage, { - int maxResults = 10, - }) async { - final annotatedResponses = await detection( - jsonImage, - AnnotationType.labelDetection, - maxResults: maxResults, - ); - - return annotatedResponses.labelAnnotations; - } - - /// Landmark Detection detects popular natural and human-made structures - /// within an image. - @Deprecated('Use [GoogleVisionImage.landmarkDetection] instead.') - Future> landmarkDetection( - JsonImage jsonImage, { - int maxResults = 10, - }) async { - final annotatedResponses = await detection( - jsonImage, - AnnotationType.landmarkDetection, - maxResults: maxResults, - ); - - return annotatedResponses.landmarkAnnotations; - } - - /// Logo Detection detects popular product logos within an image. - @Deprecated('Use [GoogleVisionImage.logoDetection] instead.') - Future> logoDetection( - JsonImage jsonImage, { - int maxResults = 10, - }) async { - final annotatedResponses = await detection( - jsonImage, - AnnotationType.logoDetection, - maxResults: maxResults, - ); - - return annotatedResponses.logoAnnotations; - } - - /// The Vision API can detect and extract multiple objects in an image with - /// Object Localization. - /// - /// Object localization identifies multiple objects in an image and provides a - /// [LocalizedObjectAnnotation] for each object in the image. Each - /// [LocalizedObjectAnnotation] identifies information about the object, the - /// position of the object, and rectangular bounds for the region of the image - /// that contains the object. - /// - /// Object localization identifies both significant and less-prominent objects in an image. - @Deprecated('Use [GoogleVisionImage.objectLocalization] instead.') - Future> objectLocalization( - JsonImage jsonImage, { - int maxResults = 10, - }) async { - final annotatedResponses = await detection( - jsonImage, - AnnotationType.objectLocalization, - maxResults: maxResults, + dio: dio, ); - return annotatedResponses.localizedObjectAnnotations; - } - - /// Run Product Search. - @Deprecated('Use [GoogleVisionImage.productSearch] instead.') - Future productSearch( - JsonImage jsonImage, { - int maxResults = 10, - }) async { - final annotatedResponses = await detection( - jsonImage, - AnnotationType.productSearch, - maxResults: maxResults, - ); + await confirmToken(); - return annotatedResponses.productSearchResults; + return this; } - /// SafeSearch Detection detects explicit content such as adult content or - /// violent content within an image. This feature uses five categories (adult, - /// spoof, medical, violence, and racy) and returns the likelihood that each - /// is present in a given image. See the SafeSearchAnnotation page for details - /// on these fields. - @Deprecated('Use [GoogleVisionImage.safeSearchDetection] instead.') - Future safeSearchDetection( - JsonImage jsonImage, { - int maxResults = 10, - }) async { - final annotatedResponses = await detection( - jsonImage, - AnnotationType.safeSearchDetection, - maxResults: maxResults, - ); + void setAuthHeader() { + if (_token != null) { + dio.options.headers['authorization'] = 'Bearer $_token'; + } - return annotatedResponses.safeSearchAnnotation; + if (_apiKey != null) { + dio.options.queryParameters['key'] = _apiKey; + } } - /// Detects and extracts text from any image. For example, a photograph might - /// contain a street sign or traffic sign. The JSON includes the entire - /// extracted string, as well as individual words, and their bounding boxes. - @Deprecated('Use [GoogleVisionImage.textDetection] instead.') - Future> textDetection( - JsonImage jsonImage, { - int maxResults = 10, - }) async { - final annotatedResponses = await detection( - jsonImage, - AnnotationType.textDetection, - maxResults: maxResults, - ); - - return annotatedResponses.textAnnotations; - } + Future confirmToken() async { + if (tokenGenerator == null) { + throw Exception(); + } else { + if (tokenExpiry.isBefore(DateTime.now())) { + final tokenData = await tokenGenerator!.generate(); - /// Web Detection detects Web references to an image. - @Deprecated('Use [GoogleVisionImage.webDetection] instead.') - Future webDetection( - JsonImage jsonImage, { - int maxResults = 10, - }) async { - final annotatedResponses = await detection( - jsonImage, - AnnotationType.webDetection, - maxResults: maxResults, - ); + _token = tokenData.accessToken; - return annotatedResponses.webDetection; + tokenExpiry.add(Duration(seconds: tokenData.expiresIn)); + } + } } } diff --git a/packages/google_vision/lib/src/google_vision_file.dart b/packages/google_vision/lib/src/google_vision_file.dart index 414a548..95bd347 100644 --- a/packages/google_vision/lib/src/google_vision_file.dart +++ b/packages/google_vision/lib/src/google_vision_file.dart @@ -34,6 +34,7 @@ class GoogleVisionFile { Future> detection( InputConfig inputConfig, AnnotationType annotationType, { + ImageContext? imageContext, int maxResults = 10, List? pages, String? parent, @@ -48,6 +49,7 @@ class GoogleVisionFile { maxResults: maxResults, ), ], + imageContext: imageContext, pages: pages, ) ], @@ -60,6 +62,7 @@ class GoogleVisionFile { /// Crop Hints suggests vertices for a crop region on an image. Future> cropHints( InputConfig inputConfig, { + ImageContext? imageContext, int maxResults = 10, List? pages, String? parent, @@ -67,6 +70,7 @@ class GoogleVisionFile { final annotatedFileResponses = await detection( inputConfig, AnnotationType.cropHints, + imageContext: imageContext, maxResults: maxResults, pages: pages, parent: parent, diff --git a/packages/google_vision/lib/src/model/annotate_image_requests.dart b/packages/google_vision/lib/src/model/annotate_image_requests.dart deleted file mode 100644 index ae4f60d..0000000 --- a/packages/google_vision/lib/src/model/annotate_image_requests.dart +++ /dev/null @@ -1,31 +0,0 @@ -import 'dart:convert'; - -import 'package:google_vision/google_vision.dart'; -import 'package:json_annotation/json_annotation.dart'; - -part 'annotate_image_requests.g.dart'; - -/// Request for performing Google Cloud Vision API tasks over a user-provided -/// image, with user-requested features, and with context information. -@JsonSerializable(explicitToJson: true) -class AnnotateImageRequests implements AnnotateJsonSerializable { - final List requests; - - AnnotateImageRequests({ - required this.requests, - }); - - factory AnnotateImageRequests.fromJson(Map json) => - _$AnnotateImageRequestsFromJson(json); - - @override - Map toJson() => _$AnnotateImageRequestsToJson(this); - - @override - String toString() => jsonEncode(toJson()); -} - -@Deprecated('Use AnnotateImageRequests instead.') -class AnnotationRequests extends AnnotateImageRequests { - AnnotationRequests({required super.requests}); -} diff --git a/packages/google_vision/lib/src/model/annotate_image_requests.g.dart b/packages/google_vision/lib/src/model/annotate_image_requests.g.dart deleted file mode 100644 index 0c3566c..0000000 --- a/packages/google_vision/lib/src/model/annotate_image_requests.g.dart +++ /dev/null @@ -1,21 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'annotate_image_requests.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -AnnotateImageRequests _$AnnotateImageRequestsFromJson( - Map json) => - AnnotateImageRequests( - requests: (json['requests'] as List) - .map((e) => AnnotateImageRequest.fromJson(e as Map)) - .toList(), - ); - -Map _$AnnotateImageRequestsToJson( - AnnotateImageRequests instance) => - { - 'requests': instance.requests.map((e) => e.toJson()).toList(), - }; diff --git a/packages/google_vision/lib/src/model/feature.dart b/packages/google_vision/lib/src/model/feature.dart index 9030a77..2c92ab2 100644 --- a/packages/google_vision/lib/src/model/feature.dart +++ b/packages/google_vision/lib/src/model/feature.dart @@ -31,6 +31,9 @@ class Feature { @JsonEnum(valueField: 'type') enum AnnotationType { + /// unspecified + typeUnspecified('TYPE_UNSPECIFIED'), + /// Face detection faceDetection('FACE_DETECTION'), diff --git a/packages/google_vision/lib/src/model/feature.g.dart b/packages/google_vision/lib/src/model/feature.g.dart index 073dec1..f4ece38 100644 --- a/packages/google_vision/lib/src/model/feature.g.dart +++ b/packages/google_vision/lib/src/model/feature.g.dart @@ -17,6 +17,7 @@ Map _$FeatureToJson(Feature instance) => { }; const _$AnnotationTypeEnumMap = { + AnnotationType.typeUnspecified: 'TYPE_UNSPECIFIED', AnnotationType.faceDetection: 'FACE_DETECTION', AnnotationType.landmarkDetection: 'LANDMARK_DETECTION', AnnotationType.logoDetection: 'LOGO_DETECTION', diff --git a/packages/google_vision/lib/src/model/input_config.dart b/packages/google_vision/lib/src/model/input_config.dart index 3cb80c8..74e6758 100644 --- a/packages/google_vision/lib/src/model/input_config.dart +++ b/packages/google_vision/lib/src/model/input_config.dart @@ -2,7 +2,6 @@ import 'dart:convert'; import 'dart:typed_data'; import 'package:mime/mime.dart'; -import 'package:universal_io/io.dart'; import 'gcs_source.dart'; @@ -46,8 +45,9 @@ class InputConfig { 'mimeType': mimeType, }; - factory InputConfig.fromBuffer(ByteBuffer buffer, String mimeType) => - InputConfig(content: buffer, mimeType: mimeType); + factory InputConfig.fromBuffer(ByteBuffer buffer, [String? mimeType]) => + InputConfig( + content: buffer, mimeType: mimeType ?? mimeTypeFromContent(buffer)); factory InputConfig.fromGsUri(String gsUri) => InputConfig( gcsSource: GcsSource(uri: gsUri), @@ -55,21 +55,6 @@ class InputConfig { gsUri.split('/').last, )); - factory InputConfig.fromFile(File file) => InputConfig( - content: file.readAsBytesSync().buffer, - mimeType: mimeTypeFromFile( - file, - )); - - factory InputConfig.fromFilePath(String fileNameAndPath) { - final content = File(fileNameAndPath).readAsBytesSync().buffer; - - return InputConfig( - content: content, - mimeType: mimeTypeFromContent(content), - ); - } - static String mimeTypeFromFileName(String fileName) { final mimeType = lookupMimeType(fileName.split('/').last); @@ -91,9 +76,6 @@ class InputConfig { return mimeType; } - static String mimeTypeFromFile(File file) => - mimeTypeFromContent(file.readAsBytesSync().buffer); - @override String toString() => json.encode(toJson()); } diff --git a/packages/google_vision/lib/src/model/json_image.dart b/packages/google_vision/lib/src/model/json_image.dart index a93a0ea..3f58355 100644 --- a/packages/google_vision/lib/src/model/json_image.dart +++ b/packages/google_vision/lib/src/model/json_image.dart @@ -1,8 +1,6 @@ import 'dart:convert'; import 'dart:typed_data'; -import 'package:universal_io/io.dart'; - /// A class that holds the details of an image that can be converted to/from JSON. class JsonImage { final String? imageUri; @@ -23,12 +21,6 @@ class JsonImage { factory JsonImage.fromGsUri(String gsUri) => JsonImage(imageUri: gsUri); - factory JsonImage.fromFile(File file) => - JsonImage(byteBuffer: file.readAsBytesSync().buffer); - - factory JsonImage.fromFilePath(String fileNameAndPath) => - JsonImage(byteBuffer: File(fileNameAndPath).readAsBytesSync().buffer); - factory JsonImage.fromJson(Map json) => JsonImage( byteBuffer: json.containsKey('content') ? base64.decode(json['content']).buffer diff --git a/packages/google_vision/lib/src/token_generator.dart b/packages/google_vision/lib/src/token_generator.dart index 1bf4ae9..df89e91 100644 --- a/packages/google_vision/lib/src/token_generator.dart +++ b/packages/google_vision/lib/src/token_generator.dart @@ -4,8 +4,7 @@ import 'package:crypto_keys_plus/crypto_keys.dart'; import 'package:dio/dio.dart'; import 'package:google_vision/google_vision.dart'; import 'package:jose_plus/jose.dart'; - -import 'package:universal_io/io.dart'; +// import 'package:universal_io/io.dart'; abstract class TokenGenerator { Future generate(); @@ -25,15 +24,15 @@ class JwtGenerator implements TokenGenerator { }) : jwtCredentials = JwtCredentials.fromJson( {'settings': jsonDecode(credentials), 'scope': scope}); - factory JwtGenerator.fromFile({ - required String credentialsFile, - required String scope, - required Dio dio, - }) => - JwtGenerator( - credentials: File(credentialsFile).readAsStringSync(), - scope: scope, - dio: dio); + // factory JwtGenerator.fromFile({ + // required String credentialsFile, + // required String scope, + // required Dio dio, + // }) => + // JwtGenerator( + // credentials: File(credentialsFile).readAsStringSync(), + // scope: scope, + // dio: dio); /// generate a OAuth2 refresh token from JWT credentials @override diff --git a/packages/google_vision/lib/src/util/util.dart b/packages/google_vision/lib/src/util/util.dart index 52da698..94e8f11 100644 --- a/packages/google_vision/lib/src/util/util.dart +++ b/packages/google_vision/lib/src/util/util.dart @@ -3,7 +3,6 @@ import 'dart:typed_data'; import 'package:collection/collection.dart'; import 'package:image/image.dart' as img; -import 'package:universal_io/io.dart'; Function listEquality = const ListEquality().equals; @@ -57,10 +56,6 @@ class Util { return locationUri.queryParameters['upload_id']!; } - /// Attempt to retrieve the 'home' folder of the user if running on a desktop. - static String? get userHome => - Platform.environment['HOME'] ?? Platform.environment['USERPROFILE']; - static ImageEncoding getImageEncoding(List bytes) { Uint8List headerBytes = Uint8List.fromList(bytes.sublist(0, 16)); // Adjust the size based on the maximum header size for the formats you're interested in. diff --git a/packages/google_vision/pubspec.yaml b/packages/google_vision/pubspec.yaml index 9ff5944..470d715 100644 --- a/packages/google_vision/pubspec.yaml +++ b/packages/google_vision/pubspec.yaml @@ -1,6 +1,6 @@ name: google_vision description: Allows you to add Google Visions image labeling, face, logo, and landmark detection, OCR, and detection of explicit content, into cross platform applications. -version: 1.4.0 +version: 2.0.0 repository: https://github.com/faithoflifedev/google_vision homepage: https://github.com/faithoflifedev/google_vision/tree/main/packages/google_vision @@ -14,14 +14,17 @@ dependencies: args: ^2.5.0 collection: ^1.18.0 crypto_keys_plus: ^0.4.0 - dio: ^5.6.0 + dio: ^5.7.0 + flutter_loggy_dio: ^3.1.0 http: ^1.2.2 image: ^4.1.7 jose_plus: ^0.4.6 json_annotation: ^4.9.0 + loggy: ^2.0.3 mime: ^1.0.6 - retrofit: ^4.2.0 + retrofit: ^4.4.0 universal_io: ^2.2.2 + universal_platform: ^1.1.0 dev_dependencies: build_runner: ^2.4.11 diff --git a/packages/google_vision/tool/README.md b/packages/google_vision/tool/README.md index 2aae7c4..70446a3 100644 --- a/packages/google_vision/tool/README.md +++ b/packages/google_vision/tool/README.md @@ -1,6 +1,5 @@ # Google Vision Images REST API Client - [![pub package](https://img.shields.io/pub/v/google_vision.svg)](https://pub.dartlang.org/packages/google_vision) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) @@ -11,9 +10,9 @@ Native [Dart](https://dart.dev/) package that integrates Google Vision features, - [Google Vision Images REST API Client](#google-vision-images-rest-api-client) - [Project Status](#project-status) - [Recent Changes](#recent-changes) + - [New for v2.0.0](#new-for-v200) - [New for v1.4.0](#new-for-v140) - [New for v1.3.0](#new-for-v130) - - [New for v1.2.0](#new-for-v120) - [Getting Started](#getting-started) - [pubspec.yaml](#pubspecyaml) - [Obtaining Authentication/Authorization Credentials](#obtaining-authenticationauthorization-credentials) @@ -25,7 +24,6 @@ Native [Dart](https://dart.dev/) package that integrates Google Vision features, - [Contributors](#contributors) - [Contributing](#contributing) - ## Project Status [![Build Status](https://github.com/faithoflifedev/google_vision/workflows/Dart/badge.svg)](https://github.com/faithoflifedev/google_vision/actions) [![github last commit](https://shields.io/github/last-commit/faithoflifedev/google_vision)](https://shields.io/github/last-commit/faithoflifedev/google_vision) [![github build](https://img.shields.io/github/actions/workflow/status/faithoflifedev/google_vision_workspace/dart.yaml?branch=main)](https://shields.io/github/workflow/status/faithoflifedev/google_vision/Dart) [![github issues](https://shields.io/github/issues/faithoflifedev/google_vision)](https://shields.io/github/issues/faithoflifedev/google_vision) @@ -36,6 +34,14 @@ Please feel free to submit PRs for any additional helper methods, or report an [ ## Recent Changes +### New for v2.0.0 + - Even though this package worked when used with the `web` platform the **pub.dev** analyzer would not show it as `web` platform compatible due to the use of the `universal_io` package which has a dependency on `dart:io`. This version has removed the `universal_io` dependency from the core package, so some related method signatures have been removed. + - The deprecated methods from in v1.3.x have been removed in this version. + - Logging functionality has been added to the package + ```dart + final googleVision = await GoogleVision(LogLevel.all).withJwtFile('service_credentials.json'); + ``` + ### New for v1.4.0 - A breaking change from the previous version is that the `GoogleVision` class now follows the Singleton design pattern. Now the object is instantiated as follows: ```dart @@ -51,9 +57,6 @@ final googleVision = await GoogleVision().withJwtFile('service_credentials.json' - This version of the package supports both the `image` and `file` annotation APIs for Google Vision. The previous versions of the package supported only the `image` API. - A number of methods and classes have been **Deprecated** in this version. All the provided examples still work without any changes, so the changes in this package should not cause any issue to existing code. - The `file` functionality added to this release allows for the annotation of file formats that have pages or frames, specifically `pdf`, `tiff` and `gif`. Google Vision allows annotation of up to 5 pages/frames. - -### New for v1.2.0 - - helper methods that simplify any `single` detection so a simple face detection can be performed with the `faceDetection(JsonImage jsonImage)` method, see the table below. ## Getting Started