120 lines
3.6 KiB
Dart
120 lines
3.6 KiB
Dart
import 'dart:io';
|
|
import 'dart:ui' as ui;
|
|
import 'dart:ui';
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/services.dart';
|
|
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
|
import 'package:gal/gal.dart';
|
|
import 'package:http/http.dart' as http;
|
|
import 'package:jinzhi_flutter_app/common/services/device_header_service.dart';
|
|
import 'package:permission_handler/permission_handler.dart';
|
|
|
|
class ImageUtil {
|
|
static const String _albumName = 'jinzhi';
|
|
|
|
static Stream<FileResponse> downloadImage(String url, String key) {
|
|
return DefaultCacheManager().getFileStream(
|
|
url,
|
|
key: key,
|
|
withProgress: true,
|
|
);
|
|
}
|
|
|
|
static Future<String> downloadImageInFile(String url, String key) async {
|
|
final file = await DefaultCacheManager().getSingleFile(url, key: key);
|
|
return file.path;
|
|
}
|
|
|
|
static Future<bool> requestForImagePermission() async {
|
|
if (Platform.isIOS) {
|
|
PermissionStatus photoStatus = await Permission.photosAddOnly.status;
|
|
if (photoStatus != PermissionStatus.granted) {
|
|
photoStatus = await Permission.photosAddOnly.request();
|
|
if (photoStatus != PermissionStatus.granted) {
|
|
return false;
|
|
}
|
|
}
|
|
} else if (Platform.isAndroid) {
|
|
int? sdkInt = DeviceHeaderService.to.androidDeviceInfo?.version.sdkInt;
|
|
if (sdkInt != null && sdkInt >= 33) {
|
|
// ✅ Android 13+ 不需要读权限,直接返回 true
|
|
// gal 插件内部通过 MediaStore 写入
|
|
return true;
|
|
} else {
|
|
// ✅ Android 10-12 仍可能需要 storage 权限
|
|
final status = await Permission.storage.request();
|
|
return status.isGranted;
|
|
}
|
|
} else {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static Future<void> saveImage(FileInfo fileInfo) async {
|
|
await Gal.putImage(fileInfo.file.path, album: _albumName);
|
|
}
|
|
|
|
static Future<void> saveImageData(ByteData byteData) async {
|
|
Uint8List imageBytes = byteData.buffer.asUint8List();
|
|
await Gal.putImageBytes(
|
|
imageBytes,
|
|
name: 'XWallpaper_share',
|
|
album: _albumName,
|
|
);
|
|
}
|
|
|
|
static Future<void> saveImageUint8List(Uint8List imageBytes) async {
|
|
await Gal.putImageBytes(
|
|
imageBytes,
|
|
name: 'XWallpaper_share',
|
|
album: _albumName,
|
|
);
|
|
}
|
|
|
|
static Future<void> saveUIImageData(ui.Image image) async {
|
|
final byteData = await image.toByteData(format: ui.ImageByteFormat.png);
|
|
Uint8List imageBytes = byteData!.buffer.asUint8List();
|
|
await Gal.putImageBytes(
|
|
imageBytes,
|
|
name: 'XWallpaper_share',
|
|
album: _albumName,
|
|
);
|
|
}
|
|
|
|
static Future<Uint8List> createTransparentImage(double aspectRatio) async {
|
|
double minSize = 100;
|
|
|
|
double width = minSize * aspectRatio;
|
|
double height = minSize;
|
|
|
|
final recorder = PictureRecorder();
|
|
final canvas = Canvas(
|
|
recorder,
|
|
Rect.fromLTWH(0, 0, width.toDouble(), height.toDouble()),
|
|
);
|
|
final paint = Paint()..color = Colors.transparent;
|
|
canvas.drawRect(
|
|
Rect.fromLTWH(0.0, 0.0, width.toDouble(), height.toDouble()),
|
|
paint,
|
|
);
|
|
|
|
final picture = recorder.endRecording();
|
|
final img = await picture.toImage(width.toInt(), height.toInt());
|
|
final pngBytes = await img.toByteData(format: ImageByteFormat.png);
|
|
|
|
return pngBytes!.buffer.asUint8List();
|
|
}
|
|
|
|
// 下载图片并返回 Uint8List(简单实现)
|
|
static Future<Uint8List?> fetchThumbBytes(String? url) async {
|
|
if (url == null || url.isEmpty) return null;
|
|
try {
|
|
final resp = await http.get(Uri.parse(url));
|
|
if (resp.statusCode == 200) return resp.bodyBytes;
|
|
} catch (_) {}
|
|
return null;
|
|
}
|
|
}
|