├── ios ├── Assets │ └── .gitkeep ├── Classes │ ├── ImageJpegPlugin.h │ └── ImageJpegPlugin.m ├── .gitignore └── image_jpeg.podspec ├── android ├── gradle.properties ├── settings.gradle ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── com │ │ └── yangyxd │ │ └── imagejpeg │ │ └── ImageJpegPlugin.java └── build.gradle ├── example ├── android │ ├── gradle.properties │ ├── app │ │ ├── src │ │ │ └── main │ │ │ │ ├── res │ │ │ │ ├── drawable │ │ │ │ │ ├── test.jpg │ │ │ │ │ └── launch_background.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ └── values │ │ │ │ │ └── styles.xml │ │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── imagejpegexample │ │ │ │ │ └── MainActivity.java │ │ │ │ └── AndroidManifest.xml │ │ └── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ ├── settings.gradle │ └── build.gradle ├── ios │ ├── Flutter │ │ ├── Debug.xcconfig │ │ ├── Release.xcconfig │ │ └── AppFrameworkInfo.plist │ ├── Runner │ │ ├── AppDelegate.h │ │ ├── Assets.xcassets │ │ │ ├── test.imageset │ │ │ │ ├── test.jpg │ │ │ │ └── Contents.json │ │ │ ├── LaunchImage.imageset │ │ │ │ ├── LaunchImage.png │ │ │ │ ├── LaunchImage@2x.png │ │ │ │ ├── LaunchImage@3x.png │ │ │ │ ├── README.md │ │ │ │ └── Contents.json │ │ │ └── AppIcon.appiconset │ │ │ │ ├── Icon-App-20x20@1x.png │ │ │ │ ├── Icon-App-20x20@2x.png │ │ │ │ ├── Icon-App-20x20@3x.png │ │ │ │ ├── Icon-App-29x29@1x.png │ │ │ │ ├── Icon-App-29x29@2x.png │ │ │ │ ├── Icon-App-29x29@3x.png │ │ │ │ ├── Icon-App-40x40@1x.png │ │ │ │ ├── Icon-App-40x40@2x.png │ │ │ │ ├── Icon-App-40x40@3x.png │ │ │ │ ├── Icon-App-60x60@2x.png │ │ │ │ ├── Icon-App-60x60@3x.png │ │ │ │ ├── Icon-App-76x76@1x.png │ │ │ │ ├── Icon-App-76x76@2x.png │ │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ │ ├── Icon-App-83.5x83.5@2x.png │ │ │ │ └── Contents.json │ │ ├── main.m │ │ ├── AppDelegate.m │ │ ├── Info.plist │ │ └── Base.lproj │ │ │ ├── Main.storyboard │ │ │ └── LaunchScreen.storyboard │ ├── Runner.xcodeproj │ │ ├── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── xcschemes │ │ │ │ └── Runner.xcscheme │ │ └── project.pbxproj │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── WorkspaceSettings.xcsettings │ └── Podfile ├── README.md ├── .metadata ├── test │ └── widget_test.dart ├── .gitignore ├── pubspec.yaml └── lib │ └── main.dart ├── CHANGELOG.md ├── image_jpeg.iml ├── LICENSE ├── image_jpeg_android.iml ├── pubspec.yaml ├── README.md └── lib └── image_jpeg.dart /ios/Assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'image_jpeg' 2 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | -------------------------------------------------------------------------------- /ios/Classes/ImageJpegPlugin.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface ImageJpegPlugin : NSObject 4 | @end 5 | -------------------------------------------------------------------------------- /example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/test.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangyxd/image_jpeg/HEAD/example/android/app/src/main/res/drawable/test.jpg -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : FlutterAppDelegate 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/test.imageset/test.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangyxd/image_jpeg/HEAD/example/ios/Runner/Assets.xcassets/test.imageset/test.jpg -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangyxd/image_jpeg/HEAD/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangyxd/image_jpeg/HEAD/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangyxd/image_jpeg/HEAD/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangyxd/image_jpeg/HEAD/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangyxd/image_jpeg/HEAD/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangyxd/image_jpeg/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangyxd/image_jpeg/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangyxd/image_jpeg/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangyxd/image_jpeg/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangyxd/image_jpeg/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangyxd/image_jpeg/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangyxd/image_jpeg/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangyxd/image_jpeg/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangyxd/image_jpeg/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangyxd/image_jpeg/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangyxd/image_jpeg/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangyxd/image_jpeg/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangyxd/image_jpeg/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangyxd/image_jpeg/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangyxd/image_jpeg/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangyxd/image_jpeg/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangyxd/image_jpeg/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yangyxd/image_jpeg/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # image_jpeg_example 2 | 3 | Demonstrates how to use the image_jpeg plugin. 4 | 5 | ## Getting Started 6 | 7 | For help getting started with Flutter, view our online 8 | [documentation](https://flutter.io/). 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char* argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip 7 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 449e3c2a0add25c3c2a241fa6a1b212a9ad313d6 8 | channel: master 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildSystemType 6 | Original 7 | 8 | 9 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.1.1 2 | 3 | * Modifying description information 4 | 5 | ## 1.1.0 6 | 7 | * Add blurImage, loadResImage 8 | * Add getResImageInfo, encodeImageWithRes 9 | * Add encodeJpegWithBuffer 10 | * Add params: rotate, blur, blurZoom 11 | 12 | ## 1.0.0 13 | 14 | * TODO: Add getImgInfo, Can get image width, height, size. 15 | 16 | ## 0.0.1 17 | 18 | * TODO: Describe initial release. 19 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/example/imagejpegexample/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.imagejpegexample; 2 | 3 | import android.os.Bundle; 4 | import io.flutter.app.FlutterActivity; 5 | import io.flutter.plugins.GeneratedPluginRegistrant; 6 | 7 | public class MainActivity extends FlutterActivity { 8 | @Override 9 | protected void onCreate(Bundle savedInstanceState) { 10 | super.onCreate(savedInstanceState); 11 | GeneratedPluginRegistrant.registerWith(this); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #include "AppDelegate.h" 2 | #include "GeneratedPluginRegistrant.h" 3 | 4 | @implementation AppDelegate 5 | 6 | - (BOOL)application:(UIApplication *)application 7 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 8 | [GeneratedPluginRegistrant registerWithRegistry:self]; 9 | // Override point for customization after application launch. 10 | return [super application:application didFinishLaunchingWithOptions:launchOptions]; 11 | } 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/test.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "test.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "test.jpg", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "test.jpg", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vagrant/ 3 | .sconsign.dblite 4 | .svn/ 5 | 6 | .DS_Store 7 | *.swp 8 | profile 9 | 10 | DerivedData/ 11 | build/ 12 | GeneratedPluginRegistrant.h 13 | GeneratedPluginRegistrant.m 14 | 15 | .generated/ 16 | 17 | *.pbxuser 18 | *.mode1v3 19 | *.mode2v3 20 | *.perspectivev3 21 | 22 | !default.pbxuser 23 | !default.mode1v3 24 | !default.mode2v3 25 | !default.perspectivev3 26 | 27 | xcuserdata 28 | 29 | *.moved-aside 30 | 31 | *.pyc 32 | *sync/ 33 | Icon? 34 | .tags* 35 | 36 | /Flutter/Generated.xcconfig 37 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() 4 | 5 | def plugins = new Properties() 6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') 7 | if (pluginsFile.exists()) { 8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } 9 | } 10 | 11 | plugins.each { name, path -> 12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() 13 | include ":$name" 14 | project(":$name").projectDir = pluginDirectory 15 | } 16 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | jcenter() 5 | } 6 | 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:3.1.2' 9 | } 10 | } 11 | 12 | allprojects { 13 | repositories { 14 | google() 15 | jcenter() 16 | } 17 | } 18 | 19 | rootProject.buildDir = '../build' 20 | subprojects { 21 | project.buildDir = "${rootProject.buildDir}/${project.name}" 22 | } 23 | subprojects { 24 | project.evaluationDependsOn(':app') 25 | } 26 | 27 | task clean(type: Delete) { 28 | delete rootProject.buildDir 29 | } 30 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | group 'com.yangyxd.imagejpeg' 2 | version '1.0-SNAPSHOT' 3 | 4 | buildscript { 5 | repositories { 6 | google() 7 | jcenter() 8 | } 9 | 10 | dependencies { 11 | classpath 'com.android.tools.build:gradle:3.0.1' 12 | } 13 | } 14 | 15 | rootProject.allprojects { 16 | repositories { 17 | google() 18 | jcenter() 19 | } 20 | } 21 | 22 | apply plugin: 'com.android.library' 23 | 24 | android { 25 | compileSdkVersion 28 26 | 27 | defaultConfig { 28 | minSdkVersion 16 29 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 30 | } 31 | lintOptions { 32 | disable 'InvalidPackage' 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /ios/image_jpeg.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html 3 | # 4 | Pod::Spec.new do |s| 5 | s.name = 'image_jpeg' 6 | s.version = '0.0.1' 7 | s.summary = 'Flutter plugin image encode jpeg.' 8 | s.description = <<-DESC 9 | Flutter plugin image encode jpeg. 10 | DESC 11 | s.homepage = 'http://example.com' 12 | s.license = { :file => '../LICENSE' } 13 | s.author = { 'Your Company' => 'email@example.com' } 14 | s.source = { :path => '.' } 15 | s.source_files = 'Classes/**/*' 16 | s.public_header_files = 'Classes/**/*.h' 17 | s.dependency 'Flutter' 18 | 19 | s.ios.deployment_target = '8.0' 20 | end 21 | 22 | -------------------------------------------------------------------------------- /example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /image_jpeg.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /example/test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // To perform an interaction with a widget in your test, use the WidgetTester utility that Flutter 3 | // provides. For example, you can send tap and scroll gestures. You can also use WidgetTester to 4 | // find child widgets in the widget tree, read text, and verify that the values of widget properties 5 | // are correct. 6 | 7 | import 'package:flutter/material.dart'; 8 | import 'package:flutter_test/flutter_test.dart'; 9 | 10 | import 'package:image_jpeg_example/main.dart'; 11 | 12 | void main() { 13 | testWidgets('Verify Platform version', (WidgetTester tester) async { 14 | // Build our app and trigger a frame. 15 | await tester.pumpWidget(new MyApp()); 16 | 17 | // Verify that platform version is retrieved. 18 | expect( 19 | find.byWidgetPredicate( 20 | (Widget widget) => 21 | widget is Text && widget.data.startsWith('Running on:'), 22 | ), 23 | findsOneWidget); 24 | }); 25 | } 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.lock 4 | *.log 5 | *.pyc 6 | *.swp 7 | .DS_Store 8 | .atom/ 9 | .buildlog/ 10 | .history 11 | .svn/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # Visual Studio Code related 20 | .vscode/ 21 | 22 | # Flutter/Dart/Pub related 23 | **/doc/api/ 24 | .dart_tool/ 25 | .flutter-plugins 26 | .packages 27 | .pub-cache/ 28 | .pub/ 29 | build/ 30 | 31 | # Android related 32 | **/android/**/gradle-wrapper.jar 33 | **/android/.gradle 34 | **/android/captures/ 35 | **/android/gradlew 36 | **/android/gradlew.bat 37 | **/android/local.properties 38 | **/android/**/GeneratedPluginRegistrant.java 39 | 40 | # iOS/XCode related 41 | **/ios/**/*.mode1v3 42 | **/ios/**/*.mode2v3 43 | **/ios/**/*.moved-aside 44 | **/ios/**/*.pbxuser 45 | **/ios/**/*.perspectivev3 46 | **/ios/**/*sync/ 47 | **/ios/**/.sconsign.dblite 48 | **/ios/**/.tags* 49 | **/ios/**/.vagrant/ 50 | **/ios/**/DerivedData/ 51 | **/ios/**/Icon? 52 | **/ios/**/Pods/ 53 | **/ios/**/.symlinks/ 54 | **/ios/**/profile 55 | **/ios/**/xcuserdata 56 | **/ios/.generated/ 57 | **/ios/Flutter/App.framework 58 | **/ios/Flutter/Flutter.framework 59 | **/ios/Flutter/Generated.xcconfig 60 | **/ios/Flutter/app.flx 61 | **/ios/Flutter/app.zip 62 | **/ios/Flutter/flutter_assets/ 63 | **/ios/ServiceDefinitions.json 64 | **/ios/Runner/GeneratedPluginRegistrant.* 65 | 66 | # Exceptions to above rules. 67 | !**/ios/**/default.mode1v3 68 | !**/ios/**/default.mode2v3 69 | !**/ios/**/default.pbxuser 70 | !**/ios/**/default.perspectivev3 71 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 72 | -------------------------------------------------------------------------------- /example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | image_jpeg_example 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /image_jpeg_android.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: image_jpeg 2 | description: Flutter plug-in for image compression JPEG upload supports image blurring, rotation processing, and loading resource files and memory images (bytes). 3 | version: 1.1.1 4 | author: yangyxd 5 | homepage: https://github.com/yangyxd/image_jpeg 6 | 7 | dependencies: 8 | flutter: 9 | sdk: flutter 10 | 11 | # For information on the generic Dart part of this file, see the 12 | # following page: https://www.dartlang.org/tools/pub/pubspec 13 | 14 | # The following section is specific to Flutter. 15 | flutter: 16 | plugin: 17 | androidPackage: com.yangyxd.imagejpeg 18 | pluginClass: ImageJpegPlugin 19 | 20 | # To add assets to your plugin package, add an assets section, like this: 21 | # assets: 22 | # - images/a_dot_burr.jpeg 23 | # - images/a_dot_ham.jpeg 24 | # 25 | # For details regarding assets in packages, see 26 | # https://flutter.io/assets-and-images/#from-packages 27 | # 28 | # An image asset can refer to one or more resolution-specific "variants", see 29 | # https://flutter.io/assets-and-images/#resolution-aware. 30 | 31 | # To add custom fonts to your plugin package, add a fonts section here, 32 | # in this "flutter" section. Each entry in this list should have a 33 | # "family" key with the font family name, and a "fonts" key with a 34 | # list giving the asset and other descriptors for the font. For 35 | # example: 36 | # fonts: 37 | # - family: Schyler 38 | # fonts: 39 | # - asset: fonts/Schyler-Regular.ttf 40 | # - asset: fonts/Schyler-Italic.ttf 41 | # style: italic 42 | # - family: Trajan Pro 43 | # fonts: 44 | # - asset: fonts/TrajanPro.ttf 45 | # - asset: fonts/TrajanPro_Bold.ttf 46 | # weight: 700 47 | # flutter packages pub publish 48 | # For details regarding fonts in packages, see 49 | # https://flutter.io/custom-fonts/#from-packages 50 | 51 | environment: 52 | sdk: ">=2.0.0-dev.28.0 <3.0.0" 53 | flutter: ">=0.1.4 <2.0.0" 54 | 55 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 26 | 27 | android { 28 | compileSdkVersion 27 29 | 30 | lintOptions { 31 | disable 'InvalidPackage' 32 | } 33 | 34 | defaultConfig { 35 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 36 | applicationId "com.example.imagejpegexample" 37 | minSdkVersion 16 38 | targetSdkVersion 27 39 | versionCode flutterVersionCode.toInteger() 40 | versionName flutterVersionName 41 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 42 | } 43 | 44 | buildTypes { 45 | release { 46 | // TODO: Add your own signing config for the release build. 47 | // Signing with the debug keys for now, so `flutter run --release` works. 48 | signingConfig signingConfigs.debug 49 | } 50 | } 51 | } 52 | 53 | flutter { 54 | source '../..' 55 | } 56 | 57 | dependencies { 58 | testImplementation 'junit:junit:4.12' 59 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 60 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 61 | } 62 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 8 | 9 | 10 | 15 | 19 | 26 | 30 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /example/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | def parse_KV_file(file, separator='=') 8 | file_abs_path = File.expand_path(file) 9 | if !File.exists? file_abs_path 10 | return []; 11 | end 12 | pods_ary = [] 13 | skip_line_start_symbols = ["#", "/"] 14 | File.foreach(file_abs_path) { |line| 15 | next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } 16 | plugin = line.split(pattern=separator) 17 | if plugin.length == 2 18 | podname = plugin[0].strip() 19 | path = plugin[1].strip() 20 | podpath = File.expand_path("#{path}", file_abs_path) 21 | pods_ary.push({:name => podname, :path => podpath}); 22 | else 23 | puts "Invalid plugin specification: #{line}" 24 | end 25 | } 26 | return pods_ary 27 | end 28 | 29 | target 'Runner' do 30 | # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock 31 | # referring to absolute paths on developers' machines. 32 | system('rm -rf .symlinks') 33 | system('mkdir -p .symlinks/plugins') 34 | 35 | # Flutter Pods 36 | generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig') 37 | if generated_xcode_build_settings.empty? 38 | puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter packages get is executed first." 39 | end 40 | generated_xcode_build_settings.map { |p| 41 | if p[:name] == 'FLUTTER_FRAMEWORK_DIR' 42 | symlink = File.join('.symlinks', 'flutter') 43 | File.symlink(File.dirname(p[:path]), symlink) 44 | pod 'Flutter', :path => File.join(symlink, File.basename(p[:path])) 45 | end 46 | } 47 | 48 | # Plugin Pods 49 | plugin_pods = parse_KV_file('../.flutter-plugins') 50 | plugin_pods.map { |p| 51 | symlink = File.join('.symlinks', 'plugins', p[:name]) 52 | File.symlink(p[:path], symlink) 53 | pod p[:name], :path => File.join(symlink, 'ios') 54 | } 55 | end 56 | 57 | post_install do |installer| 58 | installer.pods_project.targets.each do |target| 59 | target.build_configurations.each do |config| 60 | config.build_settings['ENABLE_BITCODE'] = 'NO' 61 | end 62 | end 63 | end 64 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: image_jpeg_example 2 | description: Demonstrates how to use the image_jpeg plugin. 3 | 4 | # The following defines the version and build number for your application. 5 | # A version number is three numbers separated by dots, like 1.2.43 6 | # followed by an optional build number separated by a +. 7 | # Both the version and the builder number may be overridden in flutter 8 | # build by specifying --build-name and --build-number, respectively. 9 | # Read more about versioning at semver.org. 10 | version: 1.0.0+1 11 | 12 | environment: 13 | sdk: ">=2.0.0-dev.68.0 <3.0.0" 14 | 15 | dependencies: 16 | flutter: 17 | sdk: flutter 18 | 19 | # The following adds the Cupertino Icons font to your application. 20 | # Use with the CupertinoIcons class for iOS style icons. 21 | cupertino_icons: ^0.1.2 22 | path_provider: ^0.4.1 23 | 24 | image_picker: "^0.4.10" 25 | zoomable_image: ^1.2.1+1 26 | 27 | 28 | dev_dependencies: 29 | flutter_test: 30 | sdk: flutter 31 | 32 | image_jpeg: 33 | path: ../ 34 | 35 | # For information on the generic Dart part of this file, see the 36 | # following page: https://www.dartlang.org/tools/pub/pubspec 37 | 38 | # The following section is specific to Flutter. 39 | flutter: 40 | 41 | # The following line ensures that the Material Icons font is 42 | # included with your application, so that you can use the icons in 43 | # the material Icons class. 44 | uses-material-design: true 45 | 46 | # To add assets to your application, add an assets section, like this: 47 | # assets: 48 | # - images/a_dot_burr.jpeg 49 | # - images/a_dot_ham.jpeg 50 | 51 | # An image asset can refer to one or more resolution-specific "variants", see 52 | # https://flutter.io/assets-and-images/#resolution-aware. 53 | 54 | # For details regarding adding assets from package dependencies, see 55 | # https://flutter.io/assets-and-images/#from-packages 56 | 57 | # To add custom fonts to your application, add a fonts section here, 58 | # in this "flutter" section. Each entry in this list should have a 59 | # "family" key with the font family name, and a "fonts" key with a 60 | # list giving the asset and other descriptors for the font. For 61 | # example: 62 | # fonts: 63 | # - family: Schyler 64 | # fonts: 65 | # - asset: fonts/Schyler-Regular.ttf 66 | # - asset: fonts/Schyler-Italic.ttf 67 | # style: italic 68 | # - family: Trajan Pro 69 | # fonts: 70 | # - asset: fonts/TrajanPro.ttf 71 | # - asset: fonts/TrajanPro_Bold.ttf 72 | # weight: 700 73 | # 74 | # For details regarding fonts from package dependencies, 75 | # see https://flutter.io/custom-fonts/#from-packages 76 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # image_jpeg 2 | 3 | [![pub package](https://img.shields.io/pub/v/image_jpeg.svg)](https://pub.dartlang.org/packages/image_jpeg) 4 | ![GitHub](https://img.shields.io/github/license/yangyxd/image_jpeg.svg) 5 | [![GitHub stars](https://img.shields.io/github/stars/yangyxd/image_jpeg.svg?style=social&label=Stars)](https://github.com/yangyxd/image_jpeg) 6 | 7 | Flutter plug-in for image compression JPEG upload supports image blurring, rotation processing, and loading resource files and memory images (bytes). 8 | 9 | ## Usage 10 | To use this plugin, add `image_jpeg` as a dependency in your `pubspec.yaml` file. 11 | 12 | ## ROADMAP 13 | 14 | * [x] Compressed to JPEG 15 | * [x] Image Zoom 16 | * [x] Image Rotate 17 | * [x] Get image information (width, height, fileSize, lastModified) 18 | * [x] Gaussian Blur 19 | * [x] Loading resource images 20 | 21 | > Supported Platforms 22 | > * Android 23 | > * IOS 24 | 25 | ## Examples 26 | 27 | * [Examples App](https://github.com/yangyxd/image_jpeg/tree/master/example) - Demonstrates how to use the image_jpeg plugin. 28 | 29 | ```dart 30 | import 'package:image_jpeg/image_jpeg.dart'; 31 | 32 | // 调用 encodeJpeg ,返回输出的文件名 33 | String newfileName = await ImageJpeg.encodeJpeg(imageFile.path, newfile, 70, JpgImageWidth, JpgImageHeigh); 34 | 35 | // 调用encodeImageWithRes从资源文件中加载并处理,返回bytes 36 | List data = await ImageJpeg.encodeImageWithRes(resName, 70, 'drawable', 1000, 1000, 0, 10, 4); 37 | 38 | // 加载资源文件(可以不是图像) 39 | List data = await ImageJpeg.loadResFile(resName); 40 | 41 | // 高斯模糊 42 | List data = await ImageJpeg.blurImageWithFlie(imageFile.path, 10, 4, 0); 43 | 44 | // 获取资源文件信息 45 | var sv = await ImageJpeg.getResImageInfo(resName); 46 | 47 | // 获取文件信息 48 | var sv = await ImageJpeg.getInfo(imageFile.path); 49 | 50 | ``` 51 | 52 | ## License MIT 53 | 54 | Copyright (c) 2018 55 | 56 | Permission is hereby granted, free of charge, to any person obtaining a copy 57 | of this software and associated documentation files (the "Software"), to deal 58 | in the Software without restriction, including without limitation the rights 59 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 60 | copies of the Software, and to permit persons to whom the Software is 61 | furnished to do so, subject to the following conditions: 62 | 63 | The above copyright notice and this permission notice shall be included in all 64 | copies or substantial portions of the Software. 65 | 66 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 67 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 68 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 69 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 70 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 71 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 72 | SOFTWARE. 73 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 40 | 41 | 42 | 43 | 44 | 45 | 56 | 58 | 64 | 65 | 66 | 67 | 68 | 69 | 75 | 77 | 83 | 84 | 85 | 86 | 88 | 89 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /lib/image_jpeg.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:typed_data'; 3 | import 'dart:io'; 4 | import 'package:flutter/services.dart'; 5 | 6 | class ImageJpeg { 7 | static const MethodChannel _channel = const MethodChannel('image_jpeg'); 8 | 9 | /// encode JPEG 10 | static Future encodeJpeg(String srcPath, String targetPath, int quality, int maxWidth, int maxHeight, [int rotate = 0, int blur = 0, int blurZoom = 0]) async { 11 | final Map params = { 12 | 'srcPath': srcPath, 13 | 'targetPath': targetPath, 14 | 'quality': quality, // 0~100 15 | 'maxWidth': maxWidth, // default 5000 16 | 'maxHeight': maxHeight, // default 5000 17 | 'rotate': rotate, 18 | 'blur': blur, 19 | 'blurZoom' : blurZoom, 20 | }; 21 | final String result = await _channel.invokeMethod('encodeJpeg', params); 22 | return result; 23 | } 24 | 25 | /// encode Buffer JPEG 26 | static Future> encodeJpegWithBuffer(List image, int quality, int maxWidth, int maxHeight, [int rotate = 0, int blur = 0, int blurZoom = 0]) async { 27 | final result = await _channel.invokeMethod('encodeJpegWithBuffer', [ 28 | Uint8List.fromList(image), 29 | quality, 30 | maxWidth, 31 | maxHeight, 32 | rotate, 33 | blur, 34 | blurZoom 35 | ]); 36 | if (result == null) return null; 37 | return convertDynamic(result); 38 | } 39 | 40 | /// encode Buffer JPEG with Res 41 | static Future> encodeImageWithRes(String resName, int quality, [String resType = '', int maxWidth = 0, int maxHeight = 0, int rotate = 0, int blur = 0, int blurZoom = 0]) async { 42 | final result = await _channel.invokeMethod('encodeImageWithRes', [ 43 | resName, 44 | quality, 45 | maxWidth, 46 | maxHeight, 47 | rotate, 48 | blur, 49 | blurZoom, 50 | resType, 51 | ]); 52 | if (result == null) return null; 53 | return convertDynamic(result); 54 | } 55 | 56 | /// blur image 57 | static Future> blurImage(List image, int blur, [int blurZoom = 0, int rotate = 0, int quality = 90]) async { 58 | return encodeJpegWithBuffer(image, quality, 0, 0, rotate, blur, blurZoom); 59 | } 60 | 61 | /// blur image File 62 | static Future> blurImageWithFlie(String imageFile, int blur, [int blurZoom = 0, int rotate = 0, int quality = 90]) async { 63 | File f = new File(imageFile); 64 | if (!f.existsSync()) 65 | return null; 66 | return blurImage(f.readAsBytesSync(), blur, blurZoom, rotate, quality); 67 | } 68 | 69 | /// load res file 70 | static Future> loadResFile(String resName, [String resType]) async { 71 | final result = await _channel.invokeMethod("loadResFile", [resName, resType]); 72 | return convertDynamic(result); 73 | } 74 | 75 | // get image info 76 | static Future getInfo(String imageFile) async { 77 | Object map = await _channel.invokeMethod("getImgInfo", { 78 | 'imageFile': imageFile, 79 | }); 80 | if (map != null && map is Map) { 81 | return new ImageInfo(width: map['width'] ?? 0, 82 | height: map['height'] ?? 0, 83 | size: map['size'] ?? 0, 84 | lastModified: map['lastModified'] ?? 0, 85 | error: map['error'], 86 | ); 87 | } 88 | return null; 89 | } 90 | 91 | // get Resources image info 92 | static Future getResImageInfo(String resName, [String resType = '']) async { 93 | Object map = await _channel.invokeMethod("getResImgInfo", { 94 | 'resName': resName, 95 | 'resType': resType, 96 | }); 97 | if (map != null && map is Map) { 98 | return new ImageInfo(width: map['width'] ?? 0, 99 | height: map['height'] ?? 0, 100 | size: map['size'] ?? 0, 101 | resId: map['resId'] ?? 0, 102 | error: map['error'], 103 | ); 104 | } 105 | return null; 106 | } 107 | 108 | /// convert [List] to [List] 109 | static List convertDynamic(List list) { 110 | return list.where((item) => item is int).map((item) => item as int).toList(); 111 | } 112 | 113 | /// convert List to Uint8List 114 | static Uint8List convertToUint8List(List list) { 115 | return Uint8List.fromList(list); 116 | } 117 | } 118 | 119 | /// 图像信息 120 | class ImageInfo { 121 | final int width; 122 | final int height; 123 | final int size; 124 | final int resId; 125 | final int lastModified; 126 | final String error; 127 | const ImageInfo({this.width, this.height, this.size, this.resId, this.lastModified, this.error}); 128 | @override 129 | String toString() { 130 | return "{width: $width, heigh: $height, size: $size, resId: $resId, error: $error}"; 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'dart:typed_data'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'dart:async'; 5 | 6 | import 'package:flutter/services.dart'; 7 | import 'package:image_jpeg/image_jpeg.dart'; 8 | import 'package:image_picker/image_picker.dart'; 9 | import 'package:zoomable_image/zoomable_image.dart'; 10 | import 'dart:io'; 11 | 12 | 13 | void main() => runApp(new MaterialApp( 14 | home: MyApp(), 15 | )); 16 | 17 | class MyApp extends StatefulWidget { 18 | @override 19 | _MyAppState createState() => new _MyAppState(); 20 | } 21 | 22 | class _MyAppState extends State { 23 | String _hintMsg = ''; 24 | String _newfile; 25 | bool _roate = false; 26 | bool _blur = false; 27 | Uint8List imgbuffer; 28 | double blurValue = 1.0; 29 | double blurZomm = 1.0; 30 | 31 | @override 32 | void initState() { 33 | super.initState(); 34 | } 35 | 36 | @override 37 | Widget build(BuildContext context) { 38 | var image = imgbuffer != null && !imgbuffer.isEmpty ? MemoryImage(imgbuffer) : 39 | _newfile == null ? null : FileImageEx(File(_newfile)); 40 | 41 | return new MaterialApp( 42 | home: new Scaffold( 43 | appBar: new AppBar( 44 | title: const Text('Plugin example app'), 45 | ), 46 | body: new Center( 47 | child: Column( 48 | mainAxisSize: MainAxisSize.min, 49 | children: [ 50 | SizedBox(height: 8.0), 51 | Row( 52 | children: [ 53 | SizedBox(width: 16.0), 54 | RaisedButton(onPressed: () { 55 | _selectImage(); 56 | }, child: Text('压缩图片')), 57 | Checkbox(value: _roate, onChanged: (v) { 58 | setState(() { 59 | _roate = v; 60 | }); 61 | }), 62 | Text('旋转'), 63 | SizedBox(width: 8.0), 64 | Checkbox(value: _blur, onChanged: (v) { 65 | setState(() { 66 | _blur = v; 67 | }); 68 | }), 69 | Text('高斯模糊'), 70 | ], 71 | ), 72 | Row( 73 | children: [ 74 | SizedBox(width: 16.0), 75 | Column( 76 | mainAxisAlignment: MainAxisAlignment.start, 77 | children: [ 78 | RaisedButton(onPressed: () { 79 | _blurImage(); 80 | }, child: Text('模糊图片')), 81 | RaisedButton(onPressed: () { 82 | _encodeResImage(); 83 | }, child: Text('资源图片')), 84 | RaisedButton(onPressed: () { 85 | _loadResImage(); 86 | }, child: Text('加载资源')), 87 | ], 88 | ), 89 | SizedBox(width: 8.0), 90 | Column( 91 | children: [ 92 | Slider( 93 | value: blurValue, 94 | onChanged: (v) { 95 | setState(() { 96 | blurValue = v; 97 | }); 98 | }, 99 | ), 100 | Slider( 101 | value: blurZomm, 102 | onChanged: (v) { 103 | setState(() { 104 | blurZomm = v; 105 | }); 106 | }, 107 | ), 108 | Text("$_hintMsg", style: TextStyle( 109 | color: Colors.black, 110 | fontSize: 11.0, 111 | fontWeight: FontWeight.w300, 112 | shadows: [ 113 | Shadow(blurRadius: 4.0), 114 | ] 115 | )) 116 | ], 117 | ), 118 | SizedBox(width: 4.0), 119 | ], 120 | ), 121 | SizedBox(height: 0.0), 122 | Expanded( 123 | child: GestureDetector( 124 | child: Container( 125 | margin: const EdgeInsets.all(2.0), 126 | width: double.infinity, 127 | child: image == null ? null : Image(image: image), 128 | decoration: BoxDecoration( 129 | border: Border.all( 130 | color: Colors.black12, 131 | width: 0.5, 132 | ) 133 | ), 134 | ), 135 | onTap: imgbuffer == null && _newfile == null ? null : () { 136 | _openNewPage(image); 137 | }, 138 | ), 139 | ) 140 | ], 141 | ), 142 | ), 143 | ), 144 | ); 145 | } 146 | 147 | void _openNewPage(ImageProvider image) { 148 | Navigator.push(context, MaterialPageRoute( 149 | builder: (context) { 150 | return new Scaffold( 151 | body: ZoomableImage( 152 | image, 153 | placeholder: const Center(child: const CircularProgressIndicator()), 154 | backgroundColor: Colors.black, 155 | onTap: () { 156 | Navigator.pop(context); 157 | }, 158 | ), 159 | ); 160 | }, 161 | )); 162 | } 163 | 164 | _deleteLastFile(String newfile) { 165 | if (_newfile != null && _newfile != newfile) { 166 | File f = new File(_newfile); 167 | f.delete(); 168 | } 169 | _newfile = newfile; 170 | } 171 | 172 | _selectImage() async { 173 | File imageFile = await ImagePicker.pickImage(source: ImageSource.gallery); 174 | 175 | if (imageFile == null) { 176 | print("null"); 177 | return; 178 | } 179 | 180 | print("srcfile: " + imageFile.path); 181 | var t = new DateTime.now().millisecondsSinceEpoch; 182 | String newfile = await ImageJpeg.encodeJpeg(imageFile.path, null, 65, 1360, 1360, _roate ? 90 : 0, 183 | _blur ? (blurValue * 100).toInt() : 0, (blurZomm * 10).toInt()); 184 | var t2 = new DateTime.now().millisecondsSinceEpoch; 185 | if (newfile == null || newfile.isEmpty) { 186 | updateMsg("无效的图像文件"); 187 | } else { 188 | _deleteLastFile(newfile); 189 | imgbuffer = null; 190 | var sv = await ImageJpeg.getInfo(imageFile.path); 191 | var nv = await ImageJpeg.getInfo(newfile); 192 | if (sv != null) { 193 | updateMsg("newfile: " + newfile); 194 | updateMsg("用时: ${t2 - t}ms \n原文件: ${getRollupSize(sv.size)}, ${sv.width}*${sv.height} \n新文件: ${getRollupSize(nv.size)}, ${nv.width}*${nv.height} \n压缩率: ${(nv.size / sv.size * 100).toStringAsFixed(2)}%"); 195 | } else 196 | updateMsg("获取文件信息失败"); 197 | //f.delete(); 198 | } 199 | } 200 | 201 | _blurImage() async { 202 | File imageFile = await ImagePicker.pickImage(source: ImageSource.gallery); 203 | print("srcfile: " + imageFile.path); 204 | var t = new DateTime.now().millisecondsSinceEpoch; 205 | List data = await ImageJpeg.blurImageWithFlie(imageFile.path, (blurValue * 100).toInt(), (blurZomm * 10).toInt(), _roate ? 100 : 0); 206 | var t2 = new DateTime.now().millisecondsSinceEpoch; 207 | if (data == null || data.isEmpty) { 208 | updateMsg("无效的图像文件"); 209 | } else { 210 | _deleteLastFile(null); 211 | imgbuffer = ImageJpeg.convertToUint8List(data); 212 | var sv = await ImageJpeg.getInfo(imageFile.path); 213 | if (sv != null) 214 | updateMsg("用时: ${t2 - t}ms \n图像大小: ${getRollupSize(sv.size)}, ${sv.width}*${sv.height} \n输出大小: ${getRollupSize(data == null ? 0 : data.length)}"); 215 | else 216 | updateMsg("获取文件信息失败"); 217 | } 218 | } 219 | 220 | _encodeResImage() async { 221 | var t = new DateTime.now().millisecondsSinceEpoch; 222 | var resName = Platform.isIOS ? "test.jpg" : "test"; 223 | List data = await ImageJpeg.encodeImageWithRes(resName, 70, 'drawable', 1000, 1000, _roate ? 90 : 0, 224 | _blur ? (blurValue * 100).toInt() : 0, (blurZomm * 10).toInt()); 225 | var t2 = new DateTime.now().millisecondsSinceEpoch; 226 | if (data == null || data.isEmpty) { 227 | updateMsg("无效的图像文件"); 228 | } else { 229 | _deleteLastFile(null); 230 | imgbuffer = ImageJpeg.convertToUint8List(data); 231 | var sv = await ImageJpeg.getResImageInfo(resName, "drawable"); 232 | if (sv != null) 233 | updateMsg("用时: ${t2 - t}ms \n资源ID: ${sv.resId} \n图像大小: ${getRollupSize(sv.size)}, ${sv.width}*${sv.height} \n输出大小: ${getRollupSize(data == null ? 0 : data.length)}"); 234 | else 235 | updateMsg("获取文件信息失败"); 236 | } 237 | } 238 | 239 | _loadResImage() async { 240 | var t = new DateTime.now().millisecondsSinceEpoch; 241 | var resName = Platform.isIOS ? "AppIcon" : "ic_launcher"; 242 | List data = await ImageJpeg.loadResFile(resName); 243 | var t2 = new DateTime.now().millisecondsSinceEpoch; 244 | if (data == null || data.isEmpty) { 245 | updateMsg("无效的图像文件"); 246 | } else { 247 | _deleteLastFile(null); 248 | imgbuffer = ImageJpeg.convertToUint8List(data); 249 | var sv = await ImageJpeg.getResImageInfo(resName); 250 | if (sv != null) 251 | updateMsg("用时: ${t2 - t}ms \n资源ID: ${sv.resId} \n图像大小: ${getRollupSize(sv.size)}, ${sv.width}*${sv.height} \n输出大小: ${getRollupSize(data == null ? 0 : data.length)}"); 252 | else 253 | updateMsg("获取文件信息失败"); 254 | } 255 | } 256 | 257 | void updateMsg(final String msg) { 258 | print(msg); 259 | setState(() { 260 | _hintMsg = msg; 261 | }); 262 | } 263 | 264 | static const RollupSize_Units = ["GB", "MB", "KB", "B"]; 265 | /// 返回文件大小字符串 266 | static String getRollupSize(int size) { 267 | int idx = 3; 268 | int r1 = 0; 269 | String result = ""; 270 | while (idx >= 0) { 271 | int s1 = size % 1024; 272 | size = size >> 10; 273 | if (size == 0 || idx == 0) { 274 | r1 = (r1 * 100) ~/ 1024; 275 | if (r1 > 0) { 276 | if (r1 >= 10) 277 | result = "$s1.$r1${RollupSize_Units[idx]}"; 278 | else 279 | result = "$s1.0$r1${RollupSize_Units[idx]}"; 280 | } else 281 | result = s1.toString() + RollupSize_Units[idx]; 282 | break; 283 | } 284 | r1 = s1; 285 | idx--; 286 | } 287 | return result; 288 | } 289 | } 290 | 291 | class FileImageEx extends FileImage { 292 | int fileSize = 0; 293 | FileImageEx(File file, { double scale = 1.0 }) 294 | : assert(file != null), 295 | assert(scale != null), 296 | super(file, scale: scale) { 297 | if (file.existsSync()) 298 | fileSize = file.lengthSync(); 299 | } 300 | 301 | @override 302 | bool operator ==(dynamic other) { 303 | if (other.runtimeType != runtimeType) 304 | return false; 305 | final FileImageEx typedOther = other; 306 | return file?.path == typedOther.file?.path 307 | && scale == typedOther.scale && fileSize == typedOther.fileSize; 308 | } 309 | } -------------------------------------------------------------------------------- /ios/Classes/ImageJpegPlugin.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import "ImageJpegPlugin.h" 3 | 4 | @implementation ImageJpegPlugin 5 | + (void)registerWithRegistrar:(NSObject*)registrar { 6 | FlutterMethodChannel* channel = [FlutterMethodChannel 7 | methodChannelWithName:@"image_jpeg" 8 | binaryMessenger:[registrar messenger]]; 9 | ImageJpegPlugin* instance = [[ImageJpegPlugin alloc] init]; 10 | [registrar addMethodCallDelegate:instance channel:channel]; 11 | } 12 | 13 | - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { 14 | if ([@"encodeJpeg" isEqualToString:call.method]) { 15 | NSString *srcPath = call.arguments[@"srcPath"]; 16 | NSString *targetPath = call.arguments[@"targetPath"]; 17 | NSString *squality = call.arguments[@"quality"]; 18 | NSString *smaxWidth = call.arguments[@"maxWidth"]; 19 | NSString *smaxHeight = call.arguments[@"maxHeight"]; 20 | NSString *srotate = call.arguments[@"rotate"]; 21 | NSString *sblur = call.arguments[@"blur"]; 22 | NSString *sblurZoom = call.arguments[@"blurZoom"]; 23 | 24 | int mw = 0; 25 | int mh = 0; 26 | int quality = 70; 27 | int rotate = 0; 28 | int blur = 0; 29 | int blurZoom = 0; 30 | 31 | @try{ 32 | quality = [squality intValue]; 33 | mw = [smaxWidth intValue]; 34 | mh = [smaxHeight intValue]; 35 | rotate = [srotate intValue]; 36 | blur = [sblur intValue]; 37 | blurZoom = [sblurZoom intValue]; 38 | } @catch(NSException *e){ } 39 | 40 | if (targetPath == nil || targetPath == NULL || [targetPath isKindOfClass:[NSNull class]]) { 41 | targetPath = [srcPath stringByAppendingString: @".jpg"]; 42 | } 43 | 44 | UIImage *image = [UIImage imageWithContentsOfFile:srcPath]; // init image 45 | NSData *data = [self processImage:image 46 | mw:mw 47 | mh:mh 48 | rotate:rotate 49 | blur:blur 50 | blurZoom:blurZoom 51 | quality:quality 52 | ]; 53 | 54 | if ([[NSFileManager defaultManager] createFileAtPath:targetPath contents:data attributes:nil]) { 55 | result(targetPath); 56 | } else { 57 | result([FlutterError errorWithCode:@"Encode Jpeg Failed" 58 | message:@"Temporary file could not be created" 59 | details:nil]); 60 | } 61 | 62 | } else if ([@"encodeJpegWithBuffer" isEqualToString:call.method]) { 63 | NSArray *args = call.arguments; 64 | FlutterStandardTypedData *list = args[0]; 65 | int quality = [args[1] intValue]; 66 | int mw = [args[2] intValue]; 67 | int mh = [args[3] intValue]; 68 | int rotate = [args[4] intValue]; 69 | int blur = [args[5] intValue]; 70 | int blurZoom = [args[6] intValue]; 71 | 72 | UIImage *image = [[UIImage alloc] initWithData:list.data]; 73 | NSData *data = [self processImage:image 74 | mw:mw 75 | mh:mh 76 | rotate:rotate 77 | blur:blur 78 | blurZoom:blurZoom 79 | quality:quality 80 | ]; 81 | 82 | NSMutableArray *array = [NSMutableArray array]; 83 | Byte *bytes = data.bytes; 84 | for (int i = 0; i < data.length; ++i) { 85 | [array addObject:@(bytes[i])]; 86 | } 87 | result(array); 88 | 89 | } else if ([@"encodeImageWithRes" isEqualToString:call.method]) { 90 | NSArray *args = call.arguments; 91 | NSString *resName = args[0]; 92 | int quality = [args[1] intValue]; 93 | int mw = [args[2] intValue]; 94 | int mh = [args[3] intValue]; 95 | int rotate = [args[4] intValue]; 96 | int blur = [args[5] intValue]; 97 | int blurZoom = [args[6] intValue]; 98 | 99 | UIImage *image = [UIImage imageNamed:resName]; 100 | 101 | if (image == nil || image == NULL || [image isKindOfClass:[NSNull class]]) { 102 | result(NULL); 103 | } else { 104 | NSData *data = [self processImage:image 105 | mw:mw 106 | mh:mh 107 | rotate:rotate 108 | blur:blur 109 | blurZoom:blurZoom 110 | quality:quality 111 | ]; 112 | 113 | NSMutableArray *array = [NSMutableArray array]; 114 | Byte *bytes = data.bytes; 115 | for (int i = 0; i < data.length; ++i) { 116 | [array addObject:@(bytes[i])]; 117 | } 118 | result(array); 119 | } 120 | 121 | } else if ([@"loadResFile" isEqualToString:call.method]) { 122 | NSArray *args = call.arguments; 123 | NSString *resName = args[0]; 124 | 125 | UIImage *image = [UIImage imageNamed:resName]; 126 | if (image == nil || image == NULL || [image isKindOfClass:[NSNull class]]) { 127 | result(NULL); 128 | } else { 129 | NSData *data = UIImagePNGRepresentation(image); 130 | if (!data) { 131 | data = UIImageJPEGRepresentation(image, 0.85); 132 | } 133 | 134 | NSMutableArray *array = [NSMutableArray array]; 135 | Byte *bytes = data.bytes; 136 | for (int i = 0; i < data.length; ++i) { 137 | [array addObject:@(bytes[i])]; 138 | } 139 | result(array); 140 | } 141 | 142 | } else if ([@"getImgInfo" isEqualToString:call.method]) { 143 | NSString *srcPath = call.arguments[@"imageFile"]; 144 | [self getImgInfo:result fileName:srcPath]; 145 | 146 | } else if ([@"getResImgInfo" isEqualToString:call.method]) { 147 | NSString *resName = call.arguments[@"resName"]; 148 | [self getResImgInfo:result resName:resName]; 149 | 150 | } else { 151 | result(FlutterMethodNotImplemented); 152 | } 153 | } 154 | 155 | - (NSData *)processImage:(UIImage *)image 156 | mw: (int) mw 157 | mh: (int) mh 158 | rotate: (int) rotate 159 | blur: (int) blur 160 | blurZoom: (int) blurZoom 161 | quality: (int) quality 162 | { 163 | if (mw < 0) mw = 0; 164 | if (mh < 0) mh = 0; 165 | if (quality < 0) quality = 0; 166 | if (quality > 100) quality = 100; 167 | if (blur < 0) blur = 0; 168 | if (blur > 100) blur = 100; 169 | if (blurZoom < 0) blurZoom = 0; 170 | 171 | // 缩放 172 | if (mw > 0 && mh > 0) { 173 | NSNumber *nmw = [NSNumber numberWithInt:mw]; 174 | NSNumber *nmh = [NSNumber numberWithInt:mh]; 175 | image = [self scaledImage:image maxWidth:nmw maxHeight:nmh]; 176 | } 177 | 178 | // 旋转 179 | if (rotate % 360 != 0){ 180 | image = [self rotate: image rotate: rotate]; 181 | } 182 | 183 | // 高斯模糊 184 | if (blur > 0) { 185 | image = [self blurImage:image blur:blur blurZoom:blurZoom]; 186 | } 187 | 188 | // 压缩 189 | CGFloat compression = quality / 100; 190 | NSData *data = UIImageJPEGRepresentation(image, compression); 191 | return data; 192 | } 193 | 194 | - (UIImage *)scaledImage:(UIImage *)image 195 | maxWidth:(NSNumber *)maxWidth 196 | maxHeight:(NSNumber *)maxHeight { 197 | double originalWidth = image.size.width; 198 | double originalHeight = image.size.height; 199 | 200 | bool hasMaxWidth = maxWidth != (id)[NSNull null]; 201 | bool hasMaxHeight = maxHeight != (id)[NSNull null]; 202 | 203 | double width = hasMaxWidth ? MIN([maxWidth doubleValue], originalWidth) : originalWidth; 204 | double height = hasMaxHeight ? MIN([maxHeight doubleValue], originalHeight) : originalHeight; 205 | 206 | bool shouldDownscaleWidth = hasMaxWidth && [maxWidth doubleValue] < originalWidth; 207 | bool shouldDownscaleHeight = hasMaxHeight && [maxHeight doubleValue] < originalHeight; 208 | bool shouldDownscale = shouldDownscaleWidth || shouldDownscaleHeight; 209 | 210 | if (shouldDownscale) { 211 | double downscaledWidth = (height / originalHeight) * originalWidth; 212 | double downscaledHeight = (width / originalWidth) * originalHeight; 213 | 214 | if (width < height) { 215 | if (!hasMaxWidth) { 216 | width = downscaledWidth; 217 | } else { 218 | height = downscaledHeight; 219 | } 220 | } else if (height < width) { 221 | if (!hasMaxHeight) { 222 | height = downscaledHeight; 223 | } else { 224 | width = downscaledWidth; 225 | } 226 | } else { 227 | if (originalWidth < originalHeight) { 228 | width = downscaledWidth; 229 | } else if (originalHeight < originalWidth) { 230 | height = downscaledHeight; 231 | } 232 | } 233 | } 234 | 235 | return [self scaleImageWithMP: image w:width h:height]; 236 | } 237 | 238 | - (UIImage *)rotate:(UIImage*)image 239 | rotate:(CGFloat) rotate { 240 | return [self imageRotatedByDegrees: image deg:rotate]; 241 | } 242 | 243 | - (UIImage *)imageRotatedByDegrees:(UIImage*)oldImage deg:(CGFloat)degrees{ 244 | UIView *rotatedViewBox = [[UIView alloc] initWithFrame:CGRectMake(0,0,oldImage.size.width, oldImage.size.height)]; 245 | CGAffineTransform t = CGAffineTransformMakeRotation(degrees * M_PI / 180); 246 | rotatedViewBox.transform = t; 247 | CGSize rotatedSize = rotatedViewBox.frame.size; 248 | 249 | UIGraphicsBeginImageContext(rotatedSize); 250 | CGContextRef bitmap = UIGraphicsGetCurrentContext(); 251 | 252 | // Move the origin to the middle of the image so we will rotate and scale around the center. 253 | CGContextTranslateCTM(bitmap, rotatedSize.width/2, rotatedSize.height/2); 254 | 255 | // Rotate the image context 256 | CGContextRotateCTM(bitmap, (degrees * M_PI / 180)); 257 | 258 | // draw the rotated/scaled image into the context 259 | CGContextScaleCTM(bitmap, 1.0, -1.0); 260 | CGContextDrawImage(bitmap, CGRectMake(-oldImage.size.width / 2, -oldImage.size.height / 2, oldImage.size.width, oldImage.size.height), [oldImage CGImage]); 261 | 262 | UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); 263 | UIGraphicsEndImageContext(); 264 | return newImage; 265 | } 266 | 267 | - (UIImage *)blurImage:(UIImage*)image blur:(CGFloat)blur blurZoom:(CGFloat)blurZoom { 268 | double aw = image.size.width; 269 | double ah = image.size.height; 270 | if (blurZoom > 0) { 271 | image = [self scaleImageWithMP:image w:(aw / blurZoom) h:(ah / blurZoom)]; 272 | } 273 | 274 | blur = blur / 100.0f * 25.0f; 275 | if (blur > 25.0f) blur = 25.0f; 276 | 277 | CIContext *context = [CIContext contextWithOptions:nil]; 278 | CIImage *inputImage = [CIImage imageWithCGImage:image.CGImage]; 279 | 280 | CIFilter *filter = [CIFilter filterWithName:@"CIGaussianBlur"]; 281 | [filter setValue:inputImage forKey:kCIInputImageKey]; 282 | NSNumber *number = [NSNumber numberWithFloat:blur]; 283 | [filter setValue:number forKey:@"inputRadius"]; 284 | 285 | CIImage *result = [filter valueForKey:kCIOutputImageKey]; 286 | CGImageRef cgImage = [context createCGImage:result fromRect:[inputImage extent]]; 287 | 288 | UIImage *returnImage = [UIImage imageWithCGImage:cgImage]; 289 | CGImageRelease(cgImage); 290 | 291 | if (blurZoom > 0) { 292 | return [self scaleImageWithMP:returnImage w:aw h:ah]; 293 | } else 294 | return returnImage; 295 | } 296 | 297 | - (UIImage *) scaleImageWithMP: (UIImage*) image w:(CGFloat) w h:(CGFloat) h { 298 | UIGraphicsBeginImageContextWithOptions(CGSizeMake(w, h), NO, 1.0); 299 | [image drawInRect:CGRectMake(0, 0, w, h)]; 300 | 301 | UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext(); 302 | UIGraphicsEndImageContext(); 303 | return scaledImage; 304 | } 305 | 306 | - (void) getImgInfo:(FlutterResult)callback 307 | fileName: (NSString *) fileName { 308 | 309 | NSFileManager *manager = [NSFileManager defaultManager]; 310 | BOOL isDir; 311 | BOOL isFile = [manager fileExistsAtPath:fileName isDirectory:&isDir]; 312 | 313 | if (!isDir) { 314 | if (!isFile) { 315 | callback(@{ 316 | @"file": fileName, 317 | @"error": @("file doesn't exist or is not a file") 318 | }); 319 | } else { 320 | UIImage *image = [UIImage imageWithContentsOfFile:fileName]; 321 | 322 | callback(@{ 323 | @"file": fileName, 324 | @"width": @((int) image.size.width), 325 | @"height": @((int)image.size.height), 326 | @"size": @([manager attributesOfItemAtPath:fileName error:nil].fileSize) 327 | }); 328 | } 329 | } else { 330 | callback(@{ 331 | @"file": fileName, 332 | @"error": @("file doesn't exist or is not a file") 333 | }); 334 | } 335 | } 336 | 337 | - (void) getResImgInfo:(FlutterResult)callback 338 | resName: (NSString *) resName { 339 | 340 | UIImage *image = [UIImage imageNamed:resName]; 341 | 342 | if (image == nil || image == NULL || [image isKindOfClass:[NSNull class]]) { 343 | callback(@{ 344 | @"resName": resName, 345 | @"error": @("resources doesn't exist") 346 | }); 347 | } else { 348 | NSData *data = UIImagePNGRepresentation(image); 349 | if (!data) { 350 | data = UIImageJPEGRepresentation(image, 0.85); 351 | } 352 | double dataLength = [data length] * 1.0; 353 | 354 | callback(@{ 355 | @"resName": resName, 356 | @"width": @((int) image.size.width), 357 | @"height": @((int)image.size.height), 358 | @"size": @((int) dataLength) 359 | }); 360 | } 361 | } 362 | 363 | 364 | @end 365 | -------------------------------------------------------------------------------- /android/src/main/java/com/yangyxd/imagejpeg/ImageJpegPlugin.java: -------------------------------------------------------------------------------- 1 | package com.yangyxd.imagejpeg; 2 | 3 | import io.flutter.plugin.common.MethodChannel; 4 | import io.flutter.plugin.common.MethodChannel.MethodCallHandler; 5 | import io.flutter.plugin.common.MethodChannel.Result; 6 | import io.flutter.plugin.common.MethodCall; 7 | import io.flutter.plugin.common.PluginRegistry.Registrar; 8 | 9 | import android.content.res.AssetFileDescriptor; 10 | import android.content.res.Resources; 11 | import android.graphics.Bitmap; 12 | import android.graphics.BitmapFactory; 13 | import android.graphics.Matrix; 14 | import android.os.Build; 15 | import android.os.Environment; 16 | import android.renderscript.Allocation; 17 | import android.renderscript.Element; 18 | import android.renderscript.RenderScript; 19 | import android.renderscript.ScriptIntrinsicBlur; 20 | import android.util.Log; 21 | 22 | import java.io.ByteArrayOutputStream; 23 | import java.io.File; 24 | import java.io.FileOutputStream; 25 | import java.io.IOException; 26 | import java.io.InputStream; 27 | import java.util.HashMap; 28 | import java.util.List; 29 | 30 | /** 31 | * ImageJpegPlugin 32 | */ 33 | public class ImageJpegPlugin implements MethodCallHandler { 34 | private final Registrar mRegistrar; 35 | 36 | /** 37 | * Plugin registration. 38 | */ 39 | public static void registerWith(Registrar registrar) { 40 | final MethodChannel channel = new MethodChannel(registrar.messenger(), "image_jpeg"); 41 | channel.setMethodCallHandler(new ImageJpegPlugin(registrar)); 42 | } 43 | 44 | private ImageJpegPlugin(Registrar registrar) { 45 | this.mRegistrar = registrar; 46 | } 47 | 48 | @Override 49 | public void onMethodCall(MethodCall call, Result result) { 50 | String method = call.method; 51 | 52 | if ("encodeJpeg".equals(method)) { 53 | // 压缩图像 54 | String srcPath = call.argument("srcPath"); 55 | String targetPath = call.argument("targetPath"); 56 | int quality = call.argument("quality"); 57 | int maxWidth = call.argument("maxWidth"); 58 | int maxHeight = call.argument("maxHeight"); 59 | int rotate = call.argument("rotate"); 60 | int blur = call.argument("blur"); 61 | int blurZoom = call.argument("blurZoom"); 62 | 63 | if (srcPath == null || srcPath.length() == 0) { 64 | result.error("Filename not valid", null, null); 65 | return; 66 | } 67 | 68 | if (maxWidth < 0) maxWidth = 0; 69 | if (maxHeight < 0) maxHeight = 0; 70 | if (quality < 0) quality = 0; 71 | if (quality > 100) quality = 100; 72 | 73 | if (targetPath == null || targetPath.length() == 0) 74 | targetPath = srcPath + ".jpg"; 75 | 76 | String newPath = compressImage(srcPath, targetPath, quality, maxWidth, maxHeight, rotate, blur, blurZoom); 77 | if (newPath == null || newPath.length() == 0) 78 | result.error("Encode Jpeg Failed", null, null); 79 | else 80 | result.success(newPath); 81 | 82 | } else if ("getImgInfo".equals(method)) { 83 | 84 | String imageFile = call.argument("imageFile"); 85 | this.getImgInfo(result, imageFile); 86 | 87 | } else if ("getResImgInfo".equals(method)) { 88 | 89 | String resName = call.argument("resName"); 90 | String resType = call.argument("resType"); 91 | if (resType == null || resType.length() == 0) 92 | resType = "mipmap"; 93 | String packageName = mRegistrar.activity().getPackageName(); 94 | Resources res = mRegistrar.activity().getResources(); 95 | int id = getResID(res, resName, resType, packageName); 96 | if (id != 0) { 97 | this.getImgInfo(result, res, id); 98 | } else 99 | result.success(null); 100 | 101 | } else if ("encodeJpegWithBuffer".equals(method)) { 102 | 103 | try { 104 | List args = (List) call.arguments; 105 | byte[] arr = (byte[]) args.get(0); 106 | int quality = (int) args.get(1); 107 | int maxWidth = (int) args.get(2); 108 | int maxHeight = (int) args.get(3); 109 | int rotate = (int) args.get(4); 110 | int blur = (int) args.get(5); 111 | int blurZoom = (int) args.get(6); 112 | 113 | if (maxWidth < 0) maxWidth = 0; 114 | if (maxHeight < 0) maxHeight = 0; 115 | if (quality < 0) quality = 0; 116 | if (quality > 100) quality = 100; 117 | 118 | result.success(compressBytesImage(arr, quality, maxWidth, maxHeight, rotate, blur, blurZoom)); 119 | } catch (Exception e) { 120 | e.printStackTrace(); 121 | result.success(null); 122 | } 123 | 124 | } else if ("encodeImageWithRes".equals(method)) { 125 | try { 126 | List args = (List) call.arguments; 127 | String resName = (String) args.get(0); 128 | int quality = (int) args.get(1); 129 | int maxWidth = (int) args.get(2); 130 | int maxHeight = (int) args.get(3); 131 | int rotate = (int) args.get(4); 132 | int blur = (int) args.get(5); 133 | int blurZoom = (int) args.get(6); 134 | String resType = null; 135 | if (args.size() > 7) { 136 | resType = (String) args.get(7); 137 | } 138 | if (resType == null || resType.length() == 0) 139 | resType = "mipmap"; 140 | 141 | if (maxWidth < 0) maxWidth = 0; 142 | if (maxHeight < 0) maxHeight = 0; 143 | if (quality < 0) quality = 0; 144 | if (quality > 100) quality = 100; 145 | 146 | String packageName = mRegistrar.activity().getPackageName(); 147 | result.success(compressResImage(resName, resType, packageName, quality, maxWidth, maxHeight, rotate, blur, blurZoom)); 148 | } catch (Exception e) { 149 | e.printStackTrace(); 150 | //Toast.makeText(mRegistrar.activity(), e.getMessage(), Toast.LENGTH_LONG).show(); 151 | result.success(null); 152 | } 153 | 154 | } else if ("loadResFile".equals(method)) { 155 | 156 | try { 157 | List args = (List) call.arguments; 158 | String resName = (String) args.get(0); 159 | String resType = (String) args.get(1); 160 | if (resType == null || resType.length() == 0) 161 | resType = "mipmap"; 162 | String packageName = mRegistrar.activity().getPackageName(); 163 | Resources res = mRegistrar.activity().getResources(); 164 | int id = res.getIdentifier(resName, resType, packageName); 165 | if (id != 0) { 166 | InputStream is = res.openRawResource(id); 167 | ByteArrayOutputStream bs = new ByteArrayOutputStream(); 168 | byte[] buffer = new byte[4096]; 169 | while (true) { 170 | int len = is.read(buffer); 171 | if (len > 0) bs.write(buffer, 0, len); 172 | if (len < buffer.length) 173 | break; 174 | } 175 | is.close(); 176 | result.success(bs.toByteArray()); 177 | } else 178 | result.success(null); 179 | } catch (Exception e) { 180 | e.printStackTrace(); 181 | result.success(null); 182 | } 183 | 184 | } else { 185 | result.notImplemented(); 186 | } 187 | } 188 | 189 | public String compressImage(String filePath, String targetPath, int quality, int maxWidth, int maxHeight, int rotate, int blur, int blurZoom) { 190 | //Log.d("image_jpeg", String.format("srcfile: %s", filePath)); 191 | //Log.d("image_jpeg", String.format("mw: %d, mh: %d, quality: %d, targetfile: %s", maxWidth, maxHeight, quality, targetPath)); 192 | 193 | try { 194 | Bitmap bm = getSmallBitmap(filePath, maxWidth, maxHeight); 195 | // 旋转处理 196 | bm = rotateImage(bm, rotate); 197 | // 高斯模糊 198 | if (blur > 0) bm = blurImage(bm, blur, blurZoom); 199 | 200 | //Log.d("image_jpeg", String.format("nw: %d, nh: %d", bm.getWidth(), bm.getHeight())); 201 | 202 | File outputFile = getOutputFile(targetPath, true); 203 | if (outputFile == null) { 204 | return null; 205 | } 206 | FileOutputStream out = new FileOutputStream(outputFile); 207 | bm.compress(Bitmap.CompressFormat.JPEG, quality, out); 208 | 209 | //Log.d("image_jpeg", String.format("targerSize: %d, outputfile: %s", out.getChannel().size(), outputFile.getPath())); 210 | 211 | out.close(); 212 | return outputFile.getPath(); 213 | 214 | } catch (Exception e) { 215 | Log.d("image_jpeg", e.getMessage()); 216 | return null; 217 | } 218 | } 219 | 220 | public byte[] compressBytesImage(byte[] buffer, int quality, int maxWidth, int maxHeight, int rotate, int blur, int blurZoom) { 221 | try { 222 | Bitmap bm = getSmallBitmap(buffer, maxWidth, maxHeight); 223 | // 旋转处理 224 | bm = rotateImage(bm, rotate); 225 | // 高斯模糊 226 | if (blur > 0) bm = blurImage(bm, blur, blurZoom); 227 | 228 | ByteArrayOutputStream out = new ByteArrayOutputStream(); 229 | bm.compress(Bitmap.CompressFormat.JPEG, quality, out); 230 | return out.toByteArray(); 231 | } catch (Exception e) { 232 | Log.d("image_jpeg", e.getMessage()); 233 | return null; 234 | } 235 | } 236 | 237 | public byte[] compressResImage(String resName, String resType, String packageName, int quality, int maxWidth, int maxHeight, int rotate, int blur, int blurZoom) throws IOException { 238 | Resources res = mRegistrar.activity().getResources(); 239 | int id = res.getIdentifier(resName, resType, packageName); //getResID(res, resName, resType, packageName); 240 | if (id == 0) throw new IOException("No resources found"); 241 | 242 | Bitmap bm = getSmallBitmap(res, id, maxWidth, maxHeight); 243 | if (bm == null) throw new IOException("Bitmap is null"); 244 | // 旋转处理 245 | bm = rotateImage(bm, rotate); 246 | // 高斯模糊 247 | if (blur > 0) bm = blurImage(bm, blur, blurZoom); 248 | 249 | ByteArrayOutputStream out = new ByteArrayOutputStream(); 250 | bm.compress(Bitmap.CompressFormat.JPEG, quality, out); 251 | bm = null; 252 | return out.toByteArray(); 253 | } 254 | 255 | public Bitmap rotateImage(Bitmap bm, int rotate) { 256 | if (rotate % 360 != 0) { 257 | Matrix matrix = new Matrix(); 258 | matrix.setRotate((float) rotate); 259 | return Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, false); 260 | } else 261 | return bm; 262 | } 263 | 264 | public Bitmap blurImage(Bitmap bm, int blur, int blurZoom) { 265 | if (blur > 0 && android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { 266 | RenderScript rs = RenderScript.create(mRegistrar.activity()); 267 | ScriptIntrinsicBlur _blur = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)); 268 | int w = bm.getWidth(); 269 | int h = bm.getHeight(); 270 | Bitmap _temp; 271 | if (blurZoom == 0) { 272 | _temp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); 273 | } else { 274 | int tw = w / blurZoom; 275 | int th = h / blurZoom; 276 | bm = Bitmap.createScaledBitmap(bm, tw, th, false); 277 | _temp = Bitmap.createBitmap(tw, th, Bitmap.Config.ARGB_8888); 278 | } 279 | Allocation _in = Allocation.createFromBitmap(rs, bm); 280 | Allocation _out = Allocation.createFromBitmap(rs, _temp); 281 | _blur.setRadius(Math.min(25.0f, (((float) blur) / 100.0f) * 25.0f)); // 0 ~ 25 282 | _blur.setInput(_in); 283 | _blur.forEach(_out); 284 | _out.copyTo(_temp); 285 | rs.destroy(); 286 | if (blurZoom == 0) 287 | return Bitmap.createBitmap(_temp); 288 | else 289 | return Bitmap.createScaledBitmap(_temp, w, h, true); 290 | } else 291 | return bm; 292 | } 293 | 294 | public File getOutputFile(String afile, boolean canTry) { 295 | try { 296 | File outputFile = new File(afile); 297 | if (!outputFile.exists()) { 298 | outputFile.getParentFile().mkdirs(); 299 | } else { 300 | outputFile.delete(); 301 | } 302 | return outputFile; 303 | } catch (Exception e) { 304 | if (!canTry) 305 | return null; 306 | String fileName = getFileName(afile); 307 | File v = null; 308 | try { 309 | v = getOutputFile(mRegistrar.context().getCacheDir().getPath() + fileName, false); 310 | if (v != null) return v; 311 | v = getOutputFile(Environment.getExternalStorageDirectory().getAbsolutePath() + fileName, false); 312 | } catch (Exception e1) { 313 | return null; 314 | } 315 | return v; 316 | } 317 | } 318 | 319 | public String getFileName(String pathandname){ 320 | int start = pathandname.lastIndexOf("/"); 321 | int end = pathandname.lastIndexOf("."); 322 | if (start!=-1 && end!=-1) 323 | return pathandname.substring(start+1, end); 324 | else 325 | return pathandname; 326 | } 327 | 328 | public static Bitmap getSmallBitmap(String filePath, int maxWidth, int maxHeight) { 329 | final BitmapFactory.Options options = new BitmapFactory.Options(); 330 | if (maxWidth > 0 && maxHeight > 0) { 331 | options.inJustDecodeBounds = true; 332 | BitmapFactory.decodeFile(filePath, options); 333 | options.inSampleSize = calculateInSampleSize(options, maxWidth, maxHeight); 334 | //Log.d("image_jpeg", String.format("outRatio: %d", options.inSampleSize)); 335 | } 336 | options.inJustDecodeBounds = false; 337 | return BitmapFactory.decodeFile(filePath, options); 338 | } 339 | 340 | public static Bitmap getSmallBitmap(byte[] buffer, int maxWidth, int maxHeight) { 341 | final BitmapFactory.Options options = new BitmapFactory.Options(); 342 | if (maxWidth > 0 && maxHeight > 0) { 343 | options.inJustDecodeBounds = true; 344 | BitmapFactory.decodeByteArray(buffer, 0, buffer.length); 345 | options.inSampleSize = calculateInSampleSize(options, maxWidth, maxHeight); 346 | } 347 | options.inJustDecodeBounds = false; 348 | return BitmapFactory.decodeByteArray(buffer, 0, buffer.length); 349 | } 350 | 351 | public static Bitmap getSmallBitmap(Resources res, int resId, int maxWidth, int maxHeight) throws IOException { 352 | final BitmapFactory.Options options = new BitmapFactory.Options(); 353 | if (maxWidth > 0 && maxHeight > 0) { 354 | InputStream _is = res.openRawResource(resId); 355 | options.inJustDecodeBounds = true; 356 | BitmapFactory.decodeStream(_is, null, options); 357 | options.inSampleSize = calculateInSampleSize(options, maxWidth, maxHeight); 358 | _is.close(); 359 | } 360 | InputStream _is = res.openRawResource(resId); 361 | options.inJustDecodeBounds = false; 362 | Bitmap bm = BitmapFactory.decodeStream(_is, null, options); 363 | _is.close(); 364 | return bm; 365 | } 366 | 367 | public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { 368 | final int width = options.outWidth; 369 | final int height = options.outHeight; 370 | int inSampleSize = 1; 371 | if (height > reqHeight || width > reqWidth) { 372 | final int heightRatio = Math.round((float) height / (float) reqHeight); 373 | final int widthRatio = Math.round((float) width / (float) reqWidth); 374 | inSampleSize = heightRatio > widthRatio ? heightRatio : widthRatio; 375 | Log.d("image_jpeg", String.format("w: %d, h: %d, wRatio: %d, hRatio: %d", width, height, widthRatio, heightRatio)); 376 | }; 377 | return inSampleSize; 378 | } 379 | 380 | public static int getResID(Resources res, String name, String resType, String packageName) { 381 | int id = 0; 382 | if (res != null && name != null && name.length() > 0) { 383 | try { 384 | id = res.getIdentifier(name, resType, packageName); 385 | } catch (Exception e) { 386 | e.printStackTrace(); 387 | } 388 | } 389 | return id; 390 | } 391 | 392 | public void getImgInfo(Result successResult, String fileName) { 393 | HashMap map = new HashMap(); 394 | map.put("file", fileName); 395 | try { 396 | File f = new File(fileName); 397 | final BitmapFactory.Options options = new BitmapFactory.Options(); 398 | options.inJustDecodeBounds = true; 399 | if (f.exists() && f.isFile()) { 400 | map.put("size", f.length()); 401 | map.put("lastModified", f.lastModified()); 402 | BitmapFactory.decodeFile(fileName, options); 403 | map.put("width", options.outWidth); 404 | map.put("height", options.outHeight); 405 | } else { 406 | map.put("error", "file doesn't exist or is not a file"); 407 | } 408 | successResult.success(map); 409 | } catch (Exception e) { 410 | map.put("error", e.getMessage()); 411 | successResult.success(map); 412 | } 413 | } 414 | 415 | public void getImgInfo(Result successResult, Resources res, int resId) { 416 | HashMap map = new HashMap(); 417 | map.put("resId", resId); 418 | try { 419 | if (resId != 0) { 420 | final BitmapFactory.Options options = new BitmapFactory.Options(); 421 | options.inJustDecodeBounds = true; 422 | AssetFileDescriptor af = res.openRawResourceFd(resId); 423 | map.put("size", af.getLength()); 424 | af.close(); 425 | InputStream is = res.openRawResource(resId); 426 | BitmapFactory.decodeStream(is, null, options); 427 | is.close(); 428 | map.put("width", options.outWidth); 429 | map.put("height", options.outHeight); 430 | } else { 431 | map.put("error", "resources doesn't exist"); 432 | } 433 | successResult.success(map); 434 | } catch (Exception e) { 435 | map.put("error", e.getMessage()); 436 | successResult.success(map); 437 | } 438 | } 439 | 440 | } 441 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 11 | 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */ = {isa = PBXBuildFile; fileRef = 2D5378251FAA1A9400D5DBA9 /* flutter_assets */; }; 12 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 13 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; 14 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 15 | 6FC8181E14010E20F5C5783D /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9693A71D24215CE633B6CE2D /* libPods-Runner.a */; }; 16 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; 17 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 18 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; 19 | 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; 20 | 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; 21 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 22 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 23 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 24 | /* End PBXBuildFile section */ 25 | 26 | /* Begin PBXCopyFilesBuildPhase section */ 27 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 28 | isa = PBXCopyFilesBuildPhase; 29 | buildActionMask = 2147483647; 30 | dstPath = ""; 31 | dstSubfolderSpec = 10; 32 | files = ( 33 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, 34 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, 35 | ); 36 | name = "Embed Frameworks"; 37 | runOnlyForDeploymentPostprocessing = 0; 38 | }; 39 | /* End PBXCopyFilesBuildPhase section */ 40 | 41 | /* Begin PBXFileReference section */ 42 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 43 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 44 | 2D5378251FAA1A9400D5DBA9 /* flutter_assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = flutter_assets; path = Flutter/flutter_assets; sourceTree = SOURCE_ROOT; }; 45 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 46 | 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; 47 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 48 | 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 49 | 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 50 | 9693A71D24215CE633B6CE2D /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 51 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 52 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 53 | 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; 54 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 55 | 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 56 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 57 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 58 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 59 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 60 | /* End PBXFileReference section */ 61 | 62 | /* Begin PBXFrameworksBuildPhase section */ 63 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 64 | isa = PBXFrameworksBuildPhase; 65 | buildActionMask = 2147483647; 66 | files = ( 67 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, 68 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, 69 | 6FC8181E14010E20F5C5783D /* libPods-Runner.a in Frameworks */, 70 | ); 71 | runOnlyForDeploymentPostprocessing = 0; 72 | }; 73 | /* End PBXFrameworksBuildPhase section */ 74 | 75 | /* Begin PBXGroup section */ 76 | 455942AFD2726A03A57DD602 /* Frameworks */ = { 77 | isa = PBXGroup; 78 | children = ( 79 | 9693A71D24215CE633B6CE2D /* libPods-Runner.a */, 80 | ); 81 | name = Frameworks; 82 | sourceTree = ""; 83 | }; 84 | 5953AB2CD90B74CBF2D46C71 /* Pods */ = { 85 | isa = PBXGroup; 86 | children = ( 87 | ); 88 | name = Pods; 89 | sourceTree = ""; 90 | }; 91 | 9740EEB11CF90186004384FC /* Flutter */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | 2D5378251FAA1A9400D5DBA9 /* flutter_assets */, 95 | 3B80C3931E831B6300D905FE /* App.framework */, 96 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 97 | 9740EEBA1CF902C7004384FC /* Flutter.framework */, 98 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 99 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 100 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 101 | ); 102 | name = Flutter; 103 | sourceTree = ""; 104 | }; 105 | 97C146E51CF9000F007C117D = { 106 | isa = PBXGroup; 107 | children = ( 108 | 9740EEB11CF90186004384FC /* Flutter */, 109 | 97C146F01CF9000F007C117D /* Runner */, 110 | 97C146EF1CF9000F007C117D /* Products */, 111 | 5953AB2CD90B74CBF2D46C71 /* Pods */, 112 | 455942AFD2726A03A57DD602 /* Frameworks */, 113 | ); 114 | sourceTree = ""; 115 | }; 116 | 97C146EF1CF9000F007C117D /* Products */ = { 117 | isa = PBXGroup; 118 | children = ( 119 | 97C146EE1CF9000F007C117D /* Runner.app */, 120 | ); 121 | name = Products; 122 | sourceTree = ""; 123 | }; 124 | 97C146F01CF9000F007C117D /* Runner */ = { 125 | isa = PBXGroup; 126 | children = ( 127 | 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */, 128 | 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */, 129 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 130 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 131 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 132 | 97C147021CF9000F007C117D /* Info.plist */, 133 | 97C146F11CF9000F007C117D /* Supporting Files */, 134 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 135 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 136 | ); 137 | path = Runner; 138 | sourceTree = ""; 139 | }; 140 | 97C146F11CF9000F007C117D /* Supporting Files */ = { 141 | isa = PBXGroup; 142 | children = ( 143 | 97C146F21CF9000F007C117D /* main.m */, 144 | ); 145 | name = "Supporting Files"; 146 | sourceTree = ""; 147 | }; 148 | /* End PBXGroup section */ 149 | 150 | /* Begin PBXNativeTarget section */ 151 | 97C146ED1CF9000F007C117D /* Runner */ = { 152 | isa = PBXNativeTarget; 153 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 154 | buildPhases = ( 155 | 1B166B0FC41718A70C65BB74 /* [CP] Check Pods Manifest.lock */, 156 | 9740EEB61CF901F6004384FC /* Run Script */, 157 | 97C146EA1CF9000F007C117D /* Sources */, 158 | 97C146EB1CF9000F007C117D /* Frameworks */, 159 | 97C146EC1CF9000F007C117D /* Resources */, 160 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 161 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 162 | C28405C8C9C905241031A9B1 /* [CP] Embed Pods Frameworks */, 163 | ); 164 | buildRules = ( 165 | ); 166 | dependencies = ( 167 | ); 168 | name = Runner; 169 | productName = Runner; 170 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 171 | productType = "com.apple.product-type.application"; 172 | }; 173 | /* End PBXNativeTarget section */ 174 | 175 | /* Begin PBXProject section */ 176 | 97C146E61CF9000F007C117D /* Project object */ = { 177 | isa = PBXProject; 178 | attributes = { 179 | LastUpgradeCheck = 0910; 180 | ORGANIZATIONNAME = "The Chromium Authors"; 181 | TargetAttributes = { 182 | 97C146ED1CF9000F007C117D = { 183 | CreatedOnToolsVersion = 7.3.1; 184 | }; 185 | }; 186 | }; 187 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 188 | compatibilityVersion = "Xcode 3.2"; 189 | developmentRegion = English; 190 | hasScannedForEncodings = 0; 191 | knownRegions = ( 192 | en, 193 | Base, 194 | ); 195 | mainGroup = 97C146E51CF9000F007C117D; 196 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 197 | projectDirPath = ""; 198 | projectRoot = ""; 199 | targets = ( 200 | 97C146ED1CF9000F007C117D /* Runner */, 201 | ); 202 | }; 203 | /* End PBXProject section */ 204 | 205 | /* Begin PBXResourcesBuildPhase section */ 206 | 97C146EC1CF9000F007C117D /* Resources */ = { 207 | isa = PBXResourcesBuildPhase; 208 | buildActionMask = 2147483647; 209 | files = ( 210 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 211 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 212 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, 213 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 214 | 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */, 215 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 216 | ); 217 | runOnlyForDeploymentPostprocessing = 0; 218 | }; 219 | /* End PBXResourcesBuildPhase section */ 220 | 221 | /* Begin PBXShellScriptBuildPhase section */ 222 | 1B166B0FC41718A70C65BB74 /* [CP] Check Pods Manifest.lock */ = { 223 | isa = PBXShellScriptBuildPhase; 224 | buildActionMask = 2147483647; 225 | files = ( 226 | ); 227 | inputFileListPaths = ( 228 | ); 229 | inputPaths = ( 230 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 231 | "${PODS_ROOT}/Manifest.lock", 232 | ); 233 | name = "[CP] Check Pods Manifest.lock"; 234 | outputFileListPaths = ( 235 | ); 236 | outputPaths = ( 237 | "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", 238 | ); 239 | runOnlyForDeploymentPostprocessing = 0; 240 | shellPath = /bin/sh; 241 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 242 | showEnvVarsInLog = 0; 243 | }; 244 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 245 | isa = PBXShellScriptBuildPhase; 246 | buildActionMask = 2147483647; 247 | files = ( 248 | ); 249 | inputPaths = ( 250 | ); 251 | name = "Thin Binary"; 252 | outputPaths = ( 253 | ); 254 | runOnlyForDeploymentPostprocessing = 0; 255 | shellPath = /bin/sh; 256 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; 257 | }; 258 | 9740EEB61CF901F6004384FC /* Run Script */ = { 259 | isa = PBXShellScriptBuildPhase; 260 | buildActionMask = 2147483647; 261 | files = ( 262 | ); 263 | inputPaths = ( 264 | ); 265 | name = "Run Script"; 266 | outputPaths = ( 267 | ); 268 | runOnlyForDeploymentPostprocessing = 0; 269 | shellPath = /bin/sh; 270 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 271 | }; 272 | C28405C8C9C905241031A9B1 /* [CP] Embed Pods Frameworks */ = { 273 | isa = PBXShellScriptBuildPhase; 274 | buildActionMask = 2147483647; 275 | files = ( 276 | ); 277 | inputFileListPaths = ( 278 | ); 279 | inputPaths = ( 280 | "${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", 281 | "${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework", 282 | ); 283 | name = "[CP] Embed Pods Frameworks"; 284 | outputFileListPaths = ( 285 | ); 286 | outputPaths = ( 287 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework", 288 | ); 289 | runOnlyForDeploymentPostprocessing = 0; 290 | shellPath = /bin/sh; 291 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; 292 | showEnvVarsInLog = 0; 293 | }; 294 | /* End PBXShellScriptBuildPhase section */ 295 | 296 | /* Begin PBXSourcesBuildPhase section */ 297 | 97C146EA1CF9000F007C117D /* Sources */ = { 298 | isa = PBXSourcesBuildPhase; 299 | buildActionMask = 2147483647; 300 | files = ( 301 | 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */, 302 | 97C146F31CF9000F007C117D /* main.m in Sources */, 303 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 304 | ); 305 | runOnlyForDeploymentPostprocessing = 0; 306 | }; 307 | /* End PBXSourcesBuildPhase section */ 308 | 309 | /* Begin PBXVariantGroup section */ 310 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 311 | isa = PBXVariantGroup; 312 | children = ( 313 | 97C146FB1CF9000F007C117D /* Base */, 314 | ); 315 | name = Main.storyboard; 316 | sourceTree = ""; 317 | }; 318 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 319 | isa = PBXVariantGroup; 320 | children = ( 321 | 97C147001CF9000F007C117D /* Base */, 322 | ); 323 | name = LaunchScreen.storyboard; 324 | sourceTree = ""; 325 | }; 326 | /* End PBXVariantGroup section */ 327 | 328 | /* Begin XCBuildConfiguration section */ 329 | 97C147031CF9000F007C117D /* Debug */ = { 330 | isa = XCBuildConfiguration; 331 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 332 | buildSettings = { 333 | ALWAYS_SEARCH_USER_PATHS = NO; 334 | CLANG_ANALYZER_NONNULL = YES; 335 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 336 | CLANG_CXX_LIBRARY = "libc++"; 337 | CLANG_ENABLE_MODULES = YES; 338 | CLANG_ENABLE_OBJC_ARC = YES; 339 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 340 | CLANG_WARN_BOOL_CONVERSION = YES; 341 | CLANG_WARN_COMMA = YES; 342 | CLANG_WARN_CONSTANT_CONVERSION = YES; 343 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 344 | CLANG_WARN_EMPTY_BODY = YES; 345 | CLANG_WARN_ENUM_CONVERSION = YES; 346 | CLANG_WARN_INFINITE_RECURSION = YES; 347 | CLANG_WARN_INT_CONVERSION = YES; 348 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 349 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 350 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 351 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 352 | CLANG_WARN_STRICT_PROTOTYPES = YES; 353 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 354 | CLANG_WARN_UNREACHABLE_CODE = YES; 355 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 356 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 357 | COPY_PHASE_STRIP = NO; 358 | DEBUG_INFORMATION_FORMAT = dwarf; 359 | ENABLE_STRICT_OBJC_MSGSEND = YES; 360 | ENABLE_TESTABILITY = YES; 361 | GCC_C_LANGUAGE_STANDARD = gnu99; 362 | GCC_DYNAMIC_NO_PIC = NO; 363 | GCC_NO_COMMON_BLOCKS = YES; 364 | GCC_OPTIMIZATION_LEVEL = 0; 365 | GCC_PREPROCESSOR_DEFINITIONS = ( 366 | "DEBUG=1", 367 | "$(inherited)", 368 | ); 369 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 370 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 371 | GCC_WARN_UNDECLARED_SELECTOR = YES; 372 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 373 | GCC_WARN_UNUSED_FUNCTION = YES; 374 | GCC_WARN_UNUSED_VARIABLE = YES; 375 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 376 | MTL_ENABLE_DEBUG_INFO = YES; 377 | ONLY_ACTIVE_ARCH = YES; 378 | SDKROOT = iphoneos; 379 | TARGETED_DEVICE_FAMILY = "1,2"; 380 | }; 381 | name = Debug; 382 | }; 383 | 97C147041CF9000F007C117D /* Release */ = { 384 | isa = XCBuildConfiguration; 385 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 386 | buildSettings = { 387 | ALWAYS_SEARCH_USER_PATHS = NO; 388 | CLANG_ANALYZER_NONNULL = YES; 389 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 390 | CLANG_CXX_LIBRARY = "libc++"; 391 | CLANG_ENABLE_MODULES = YES; 392 | CLANG_ENABLE_OBJC_ARC = YES; 393 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 394 | CLANG_WARN_BOOL_CONVERSION = YES; 395 | CLANG_WARN_COMMA = YES; 396 | CLANG_WARN_CONSTANT_CONVERSION = YES; 397 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 398 | CLANG_WARN_EMPTY_BODY = YES; 399 | CLANG_WARN_ENUM_CONVERSION = YES; 400 | CLANG_WARN_INFINITE_RECURSION = YES; 401 | CLANG_WARN_INT_CONVERSION = YES; 402 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 403 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 404 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 405 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 406 | CLANG_WARN_STRICT_PROTOTYPES = YES; 407 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 408 | CLANG_WARN_UNREACHABLE_CODE = YES; 409 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 410 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 411 | COPY_PHASE_STRIP = NO; 412 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 413 | ENABLE_NS_ASSERTIONS = NO; 414 | ENABLE_STRICT_OBJC_MSGSEND = YES; 415 | GCC_C_LANGUAGE_STANDARD = gnu99; 416 | GCC_NO_COMMON_BLOCKS = YES; 417 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 418 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 419 | GCC_WARN_UNDECLARED_SELECTOR = YES; 420 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 421 | GCC_WARN_UNUSED_FUNCTION = YES; 422 | GCC_WARN_UNUSED_VARIABLE = YES; 423 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 424 | MTL_ENABLE_DEBUG_INFO = NO; 425 | SDKROOT = iphoneos; 426 | TARGETED_DEVICE_FAMILY = "1,2"; 427 | VALIDATE_PRODUCT = YES; 428 | }; 429 | name = Release; 430 | }; 431 | 97C147061CF9000F007C117D /* Debug */ = { 432 | isa = XCBuildConfiguration; 433 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 434 | buildSettings = { 435 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 436 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 437 | ENABLE_BITCODE = NO; 438 | FRAMEWORK_SEARCH_PATHS = ( 439 | "$(inherited)", 440 | "$(PROJECT_DIR)/Flutter", 441 | ); 442 | INFOPLIST_FILE = Runner/Info.plist; 443 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 444 | LIBRARY_SEARCH_PATHS = ( 445 | "$(inherited)", 446 | "$(PROJECT_DIR)/Flutter", 447 | ); 448 | PRODUCT_BUNDLE_IDENTIFIER = com.example.imageJpegExample; 449 | PRODUCT_NAME = "$(TARGET_NAME)"; 450 | VERSIONING_SYSTEM = "apple-generic"; 451 | }; 452 | name = Debug; 453 | }; 454 | 97C147071CF9000F007C117D /* Release */ = { 455 | isa = XCBuildConfiguration; 456 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 457 | buildSettings = { 458 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 459 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 460 | ENABLE_BITCODE = NO; 461 | FRAMEWORK_SEARCH_PATHS = ( 462 | "$(inherited)", 463 | "$(PROJECT_DIR)/Flutter", 464 | ); 465 | INFOPLIST_FILE = Runner/Info.plist; 466 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 467 | LIBRARY_SEARCH_PATHS = ( 468 | "$(inherited)", 469 | "$(PROJECT_DIR)/Flutter", 470 | ); 471 | PRODUCT_BUNDLE_IDENTIFIER = com.example.imageJpegExample; 472 | PRODUCT_NAME = "$(TARGET_NAME)"; 473 | VERSIONING_SYSTEM = "apple-generic"; 474 | }; 475 | name = Release; 476 | }; 477 | /* End XCBuildConfiguration section */ 478 | 479 | /* Begin XCConfigurationList section */ 480 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 481 | isa = XCConfigurationList; 482 | buildConfigurations = ( 483 | 97C147031CF9000F007C117D /* Debug */, 484 | 97C147041CF9000F007C117D /* Release */, 485 | ); 486 | defaultConfigurationIsVisible = 0; 487 | defaultConfigurationName = Release; 488 | }; 489 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 490 | isa = XCConfigurationList; 491 | buildConfigurations = ( 492 | 97C147061CF9000F007C117D /* Debug */, 493 | 97C147071CF9000F007C117D /* Release */, 494 | ); 495 | defaultConfigurationIsVisible = 0; 496 | defaultConfigurationName = Release; 497 | }; 498 | /* End XCConfigurationList section */ 499 | }; 500 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 501 | } 502 | --------------------------------------------------------------------------------