初始化

This commit is contained in:
谢宇宁
2026-09-15 15:44:13 +07:00
commit a23ba685e9
1065 changed files with 101122 additions and 0 deletions
@@ -0,0 +1,83 @@
library flutter_native_image;
import 'dart:io';
import 'dart:math' as math;
import 'package:flutter_image_compress/flutter_image_compress.dart';
import 'package:image/image.dart' as img;
import 'package:path/path.dart' as p;
class ImageProperties {
const ImageProperties({
required this.width,
required this.height,
});
final int width;
final int height;
}
class FlutterNativeImage {
static Future<ImageProperties> getImageProperties(String path) async {
final bytes = await File(path).readAsBytes();
final decodedImage = img.decodeImage(bytes);
if (decodedImage == null) {
throw StateError('Unable to decode image at $path');
}
return ImageProperties(
width: decodedImage.width,
height: decodedImage.height,
);
}
static Future<File> compressImage(
String path, {
int quality = 95,
int percentage = 100,
int? targetWidth,
int? targetHeight,
}) async {
final sourceFile = File(path);
final properties = await getImageProperties(path);
final extension = p.extension(path).toLowerCase();
final format = _formatForExtension(extension);
final resizedWidth = targetWidth ??
math.max(1, (properties.width * percentage / 100).round());
final resizedHeight = targetHeight ??
math.max(1, (properties.height * percentage / 100).round());
final targetPath = p.join(
sourceFile.parent.path,
'${p.basenameWithoutExtension(path)}_compressed_${DateTime.now().microsecondsSinceEpoch}${extension.isEmpty ? '.jpg' : extension}',
);
final compressedFile = await FlutterImageCompress.compressAndGetFile(
path,
targetPath,
minWidth: resizedWidth,
minHeight: resizedHeight,
quality: quality,
format: format,
keepExif: true,
);
if (compressedFile == null) {
throw StateError('Unable to compress image at $path');
}
return File(compressedFile.path);
}
static CompressFormat _formatForExtension(String extension) {
switch (extension) {
case '.png':
return CompressFormat.png;
case '.heic':
return CompressFormat.heic;
case '.webp':
return CompressFormat.webp;
default:
return CompressFormat.jpeg;
}
}
}
+15
View File
@@ -0,0 +1,15 @@
name: flutter_native_image
description: Lightweight compatibility wrapper for the deprecated flutter_native_image API.
publish_to: "none"
version: 0.0.6+compat
environment:
sdk: ">=3.0.0 <4.0.0"
flutter: ">=3.0.0"
dependencies:
flutter:
sdk: flutter
flutter_image_compress: ^2.3.0
image: ^4.3.0
path: ^1.9.1
@@ -0,0 +1,33 @@
library image_gallery_saver;
import 'dart:typed_data';
import 'package:image_gallery_saver_plus/image_gallery_saver_plus.dart';
class ImageGallerySaver {
static Future<dynamic> saveImage(
Uint8List imageBytes, {
int quality = 80,
String? name,
bool isReturnImagePathOfIOS = false,
}) async {
return await ImageGallerySaverPlus.saveImage(
imageBytes,
quality: quality,
name: name,
isReturnImagePathOfIOS: isReturnImagePathOfIOS,
);
}
static Future<dynamic> saveFile(
String file, {
String? name,
bool isReturnPathOfIOS = false,
}) async {
return await ImageGallerySaverPlus.saveFile(
file,
name: name,
isReturnPathOfIOS: isReturnPathOfIOS,
);
}
}
+13
View File
@@ -0,0 +1,13 @@
name: image_gallery_saver
description: Lightweight compatibility wrapper for the deprecated image_gallery_saver API.
publish_to: "none"
version: 2.0.3+compat
environment:
sdk: ">=3.0.0 <4.0.0"
flutter: ">=3.0.0"
dependencies:
flutter:
sdk: flutter
image_gallery_saver_plus: ^4.0.1
+121
View File
@@ -0,0 +1,121 @@
library image_pickers;
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:image_picker/image_picker.dart';
enum GalleryMode {
image,
video,
}
class UIConfig {
const UIConfig({this.uiThemeColor});
final Color? uiThemeColor;
}
class CropConfig {
const CropConfig({this.enableCrop = true});
final bool enableCrop;
}
class Media {
const Media({this.path});
final String? path;
}
class ImagePickers {
static final ImagePicker _picker = ImagePicker();
static Future<List<Media>> pickerPaths({
UIConfig? uiConfig,
GalleryMode galleryMode = GalleryMode.image,
int selectCount = 1,
bool showCamera = false,
CropConfig? cropConfig,
}) async {
switch (galleryMode) {
case GalleryMode.video:
final video = await _picker.pickVideo(source: ImageSource.gallery);
return video == null ? const [] : [Media(path: video.path)];
case GalleryMode.image:
if (selectCount > 1) {
final images = await _picker.pickMultiImage(limit: selectCount);
return images.map((file) => Media(path: file.path)).toList();
}
final image = await _picker.pickImage(source: ImageSource.gallery);
return image == null ? const [] : [Media(path: image.path)];
}
}
static Future<void> previewImages(List<String> images, int index) async {
if (images.isEmpty) {
return;
}
await Get.to(
() => _ImagePreviewPage(
images: images,
initialIndex: index,
),
transition: Transition.fadeIn,
);
}
}
class _ImagePreviewPage extends StatefulWidget {
const _ImagePreviewPage({
required this.images,
required this.initialIndex,
});
final List<String> images;
final int initialIndex;
@override
State<_ImagePreviewPage> createState() => _ImagePreviewPageState();
}
class _ImagePreviewPageState extends State<_ImagePreviewPage> {
late final PageController _controller = PageController(initialPage: widget.initialIndex);
late int _currentIndex = widget.initialIndex;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
backgroundColor: Colors.black,
elevation: 0,
title: Text('${_currentIndex + 1}/${widget.images.length}'),
),
body: PageView.builder(
controller: _controller,
itemCount: widget.images.length,
onPageChanged: (value) {
setState(() {
_currentIndex = value;
});
},
itemBuilder: (context, index) {
return InteractiveViewer(
minScale: 0.8,
maxScale: 4,
child: Center(
child: Image.file(
File(widget.images[index]),
fit: BoxFit.contain,
),
),
);
},
),
);
}
}
+14
View File
@@ -0,0 +1,14 @@
name: image_pickers
description: Lightweight compatibility wrapper for the deprecated image_pickers API.
publish_to: "none"
version: 2.0.4+compat
environment:
sdk: ">=3.0.0 <4.0.0"
flutter: ">=3.0.0"
dependencies:
flutter:
sdk: flutter
get: ^4.6.6
image_picker: ^1.2.1