Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Google's ML Kit for Flutter is a set of [Flutter plugins](https://flutter.io/pla
| [Pose Detection (Beta)](https://developers.google.com/ml-kit/vision/pose-detection) | [google_mlkit_pose_detection](https://pub.dev/packages/google_mlkit_pose_detection) [![Pub Version](https://img.shields.io/pub/v/google_mlkit_pose_detection)](https://pub.dev/packages/google_mlkit_pose_detection) | [![GitHub](https://img.shields.io/badge/github-%23121011.svg?style=for-the-badge&logo=github&logoColor=white)](https://github.com/flutter-ml/google_ml_kit_flutter/tree/master/packages/google_mlkit_pose_detection) | ✅ | ✅ |
| [Selfie Segmentation (Beta)](https://developers.google.com/ml-kit/vision/selfie-segmentation) | [google_mlkit_selfie_segmentation](https://pub.dev/packages/google_mlkit_selfie_segmentation) [![Pub Version](https://img.shields.io/pub/v/google_mlkit_selfie_segmentation)](https://pub.dev/packages/google_mlkit_selfie_segmentation) | [![GitHub](https://img.shields.io/badge/github-%23121011.svg?style=for-the-badge&logo=github&logoColor=white)](https://github.com/flutter-ml/google_ml_kit_flutter/tree/master/packages/google_mlkit_selfie_segmentation) | ✅ | ✅ |
| [Subject Segmentation (Beta)](https://developers.google.com/ml-kit/vision/subject-segmentation) | [google_mlkit_subject_segmentation](https://pub.dev/packages/google_mlkit_subject_segmentation) [![Pub Version](https://img.shields.io/pub/v/google_mlkit_subject_segmentation)](https://pub.dev/packages/google_mlkit_subject_segmentation) | [![GitHub](https://img.shields.io/badge/github-%23121011.svg?style=for-the-badge&logo=github&logoColor=white)](https://github.com/flutter-ml/google_ml_kit_flutter/tree/master/packages/google_mlkit_subject_segmentation) | ✅ | ❌ |
| [Document Scanner (Beta)](https://developers.google.com/ml-kit/vision/doc-scanner) | [google_mlkit_document_scanner](https://pub.dev/packages/google_mlkit_document_scanner) [![Pub Version](https://img.shields.io/pub/v/google_mlkit_document_scanner)](https://pub.dev/packages/google_mlkit_document_scanner) | [![GitHub](https://img.shields.io/badge/github-%23121011.svg?style=for-the-badge&logo=github&logoColor=white)](https://github.com/flutter-ml/google_ml_kit_flutter/tree/master/packages/google_mlkit_document_scanner) | ✅ | ❌ |
| [Document Scanner](https://developers.google.com/ml-kit/vision/doc-scanner) | [google_mlkit_document_scanner](https://pub.dev/packages/google_mlkit_document_scanner) [![Pub Version](https://img.shields.io/pub/v/google_mlkit_document_scanner)](https://pub.dev/packages/google_mlkit_document_scanner) | [![GitHub](https://img.shields.io/badge/github-%23121011.svg?style=for-the-badge&logo=github&logoColor=white)](https://github.com/flutter-ml/google_ml_kit_flutter/tree/master/packages/google_mlkit_document_scanner) | ✅ | ❌ |

### Natural Language APIs

Expand Down
149 changes: 69 additions & 80 deletions packages/example/lib/vision_detector_views/document_scanner_view.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import 'dart:collection';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter_pdfview/flutter_pdfview.dart';
import 'package:google_mlkit_document_scanner/google_mlkit_document_scanner.dart';

typedef MenuEntry = DropdownMenuEntry<String>;
const List<String> list = <String>['Select option', 'pdf', 'jpeg', 'pdf-jpeg'];

class DocumentScannerView extends StatefulWidget {
@override
State<DocumentScannerView> createState() => _DocumentScannerViewState();
Expand All @@ -12,7 +16,11 @@ class DocumentScannerView extends StatefulWidget {
class _DocumentScannerViewState extends State<DocumentScannerView> {
DocumentScanner? _documentScanner;
DocumentScanningResult? _result;

static final List<MenuEntry> menuEntries = UnmodifiableListView<MenuEntry>(
list.map<MenuEntry>((String name) => MenuEntry(
value: name,
label:
name == 'Select option' ? name : 'Scan ${name.toUpperCase()}')));
@override
void dispose() {
_documentScanner?.close();
Expand All @@ -27,103 +35,84 @@ class _DocumentScannerViewState extends State<DocumentScannerView> {
centerTitle: true,
elevation: 0,
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.document_scanner_outlined,
size: 50,
),
SizedBox(width: 8),
ElevatedButton(
style: ButtonStyle(
backgroundColor:
WidgetStateProperty.all<Color>(Colors.black),
shape: WidgetStateProperty.all(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
),
onPressed: () => startScan(DocumentFormat.pdf),
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 4),
child: const Text(
'Scan PDF',
style: TextStyle(color: Colors.white),
),
body: SingleChildScrollView(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.document_scanner_outlined,
size: 50,
),
SizedBox(width: 8),
DropdownMenu<String>(
initialSelection: list.first,
onSelected: (String? value) {
if (value != null) {
if (value == 'pdf') {
startScan({DocumentFormat.pdf});
}
if (value == 'jpeg') {
startScan({DocumentFormat.jpeg});
}
if (value == 'pdf-jpeg') {
startScan(
{DocumentFormat.pdf, DocumentFormat.jpeg});
}
}
},
dropdownMenuEntries: menuEntries),
],
),
if (_result?.pdf != null) ...[
Padding(
padding: const EdgeInsets.only(
top: 16, bottom: 8, right: 8, left: 8),
child: Align(
alignment: Alignment.centerLeft,
child: Text('PDF Document:')),
),
SizedBox(width: 8),
ElevatedButton(
style: ButtonStyle(
backgroundColor:
WidgetStateProperty.all<Color>(Colors.black),
shape: WidgetStateProperty.all(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
),
onPressed: () => startScan(DocumentFormat.jpeg),
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 4),
child: const Text(
'Scan JPEG',
style: TextStyle(color: Colors.white),
),
SizedBox(
height: 300,
child: PDFView(
filePath: _result!.pdf!.uri,
enableSwipe: true,
swipeHorizontal: true,
autoSpacing: false,
pageFling: false,
),
),
],
),
if (_result?.pdf != null) ...[
Padding(
padding: const EdgeInsets.only(
top: 16, bottom: 8, right: 8, left: 8),
child: Align(
alignment: Alignment.centerLeft,
child: Text('PDF Document:')),
),
SizedBox(
height: 300,
child: PDFView(
filePath: _result!.pdf!.uri,
enableSwipe: true,
swipeHorizontal: true,
autoSpacing: false,
pageFling: false,
if (_result?.images?.isNotEmpty == true) ...[
Padding(
padding: const EdgeInsets.only(
top: 16, bottom: 8, right: 8, left: 8),
child: Align(
alignment: Alignment.centerLeft,
child: Text('Images [0]:')),
),
),
],
if (_result?.images.isNotEmpty == true) ...[
Padding(
padding: const EdgeInsets.only(
top: 16, bottom: 8, right: 8, left: 8),
child: Align(
alignment: Alignment.centerLeft,
child: Text('Images [0]:')),
),
SizedBox(
height: 400, child: Image.file(File(_result!.images.first))),
SizedBox(
height: 400,
child: Image.file(File(_result!.images!.first))),
],
],
],
),
),
),
);
}

void startScan(DocumentFormat format) async {
void startScan(Set<DocumentFormat> formats) async {
try {
_result = null;
setState(() {});
_documentScanner?.close();
_documentScanner = DocumentScanner(
options: DocumentScannerOptions(
documentFormat: format,
documentFormats: formats,
mode: ScannerMode.full,
isGalleryImport: false,
pageLimit: 1,
Expand Down
9 changes: 7 additions & 2 deletions packages/google_mlkit_document_scanner/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ The document scanner API provides a high-quality fully fledged UI flow that is c

### iOS

This feature is still in Beta, and it is only available for Android. Stay tune for updates in [Google's website](https://developers.google.com/ml-kit/vision/doc-scanner) and request the feature [here](https://github.com/googlesamples/mlkit/issues).
This feature is only available for Android. Stay tune for updates in [Google's website](https://developers.google.com/ml-kit/vision/doc-scanner) and request the feature [here](https://github.com/googlesamples/mlkit/issues).

### Android

Expand All @@ -70,8 +70,13 @@ This feature is still in Beta, and it is only available for Android. Stay tune f
#### Create an instance of `DocumentScannerOptions`

```dart
// set output document formats
const Set<DocumentFormat> documentFormats = {
DocumentFormat.jpeg,
DocumentFormat.pdf
};
DocumentScannerOptions documentOptions = DocumentScannerOptions(
documentFormat: DocumentFormat.jpeg, // set output document format
documentFormats: documentFormats,
mode: ScannerMode.filter, // to control what features are enabled
pageLimit: 1, // setting a limit to the number of pages scanned
isGalleryImport: true, // importing from the photo gallery
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,6 @@ android {
}

dependencies {
implementation("com.google.android.gms:play-services-mlkit-document-scanner:16.0.0-beta1")
implementation("com.google.android.gms:play-services-mlkit-document-scanner:16.0.0")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.0-milestone-1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Original file line number Diff line number Diff line change
Expand Up @@ -95,17 +95,21 @@ public void onFailure(@NonNull Exception e) {
private GmsDocumentScannerOptions parseOptions(Map<String, Object> options) {
boolean isGalleryImportAllowed = (boolean) options.get("isGalleryImport");
int pageLimit = (int) options.get("pageLimit");
int format;
switch ((String) Objects.requireNonNull(options.get("format"))) {
case "pdf":
format = GmsDocumentScannerOptions.RESULT_FORMAT_PDF;
break;
case "jpeg":
format = GmsDocumentScannerOptions.RESULT_FORMAT_JPEG;
break;
default:
throw new IllegalArgumentException("Not a format:" + options.get("format"));
List<String> formatStrings = (List<String>) options.get("formats");
List<Integer> formatConstants = new ArrayList<>();
for (String format: formatStrings) {
switch (format) {
case "pdf":
formatConstants.add(GmsDocumentScannerOptions.RESULT_FORMAT_PDF);
break;
case "jpeg":
formatConstants.add(GmsDocumentScannerOptions.RESULT_FORMAT_JPEG);
break;
default:
throw new IllegalArgumentException("Not a format:" + options.get("format"));
}
}

int mode;
switch ((String) options.get("mode")) {
case "base":
Expand All @@ -120,7 +124,21 @@ private GmsDocumentScannerOptions parseOptions(Map<String, Object> options) {
default:
throw new IllegalArgumentException("Not a mode:" + options.get("mode"));
}
GmsDocumentScannerOptions.Builder builder = new GmsDocumentScannerOptions.Builder().setGalleryImportAllowed(isGalleryImportAllowed).setPageLimit(pageLimit).setResultFormats(format).setScannerMode(mode);
GmsDocumentScannerOptions.Builder builder = new GmsDocumentScannerOptions
.Builder()
.setGalleryImportAllowed(isGalleryImportAllowed)
.setPageLimit(pageLimit)
.setScannerMode(mode);

// Set formats
if (!formatConstants.isEmpty()) {
if(formatConstants.size() > 1) {
builder.setResultFormats(formatConstants.get(0), formatConstants.get(1));
} else {
builder.setResultFormats(formatConstants.get(0));
}

}
return builder.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class DocumentScanner {
class DocumentScannerOptions {
/// Constructor for [DocumentScannerOptions].
DocumentScannerOptions({
this.documentFormat = DocumentFormat.jpeg,
this.documentFormats = const {DocumentFormat.jpeg},
this.pageLimit = 1,
this.mode = ScannerMode.full,
this.isGalleryImport = false,
Expand All @@ -46,7 +46,7 @@ class DocumentScannerOptions {

/// Sets scanner result formats.
/// Available formats: PDF, JPG and default format is JPG.
final DocumentFormat documentFormat;
final Set<DocumentFormat> documentFormats;

/// Sets the scanner mode which determines what features are enabled. default = ScannerModel.full.
final ScannerMode mode;
Expand All @@ -57,7 +57,7 @@ class DocumentScannerOptions {
/// Returns a json representation of an instance of [DocumentScannerOptions].
Map<String, dynamic> toJson() => {
'pageLimit': pageLimit,
'format': documentFormat.name,
'formats': documentFormats.map((f) => f.name).toList(),
'mode': mode.name,
'isGalleryImport': isGalleryImport,
};
Expand All @@ -82,7 +82,7 @@ class DocumentScanningResult {
final DocumentScanningResultPdf? pdf;

/// Returns the scanned images or null if `DocumentFormat.jpeg` was not specified when creating the scanner options.
final List<String> images;
final List<String>? images;

/// Constructor to create an instance of [DocumentScanningResult].
DocumentScanningResult({required this.pdf, required this.images});
Expand Down