├── .gitignore
├── .metadata
├── CHANGELOG.md
├── LICENSE
├── README.md
├── analysis_options.yaml
├── android
├── .gitignore
├── CMakeLists.txt
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
├── settings.gradle
└── src
│ ├── main
│ ├── AndroidManifest.xml
│ └── kotlin
│ │ └── com
│ │ └── example
│ │ └── bitmap
│ │ └── BitmapPlugin.kt
│ └── test
│ └── kotlin
│ └── com
│ └── example
│ └── bitmap
│ └── BitmapPluginTest.kt
├── example
├── .gitignore
├── .metadata
├── README.md
├── android
│ ├── .gitignore
│ ├── app
│ │ ├── build.gradle
│ │ └── src
│ │ │ ├── debug
│ │ │ └── AndroidManifest.xml
│ │ │ ├── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── kotlin
│ │ │ │ └── com
│ │ │ │ │ └── example
│ │ │ │ │ └── example
│ │ │ │ │ └── MainActivity.kt
│ │ │ └── res
│ │ │ │ ├── drawable-v21
│ │ │ │ └── launch_background.xml
│ │ │ │ ├── drawable
│ │ │ │ └── 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-night
│ │ │ │ └── styles.xml
│ │ │ │ └── values
│ │ │ │ └── styles.xml
│ │ │ └── profile
│ │ │ └── AndroidManifest.xml
│ ├── build.gradle
│ ├── gradle.properties
│ ├── gradle
│ │ └── wrapper
│ │ │ └── gradle-wrapper.properties
│ └── settings.gradle
├── assets
│ ├── doggo.jpeg
│ └── street.jpg
├── ios
│ ├── .gitignore
│ ├── Flutter
│ │ ├── AppFrameworkInfo.plist
│ │ ├── Debug.xcconfig
│ │ └── Release.xcconfig
│ ├── Podfile
│ ├── Podfile.lock
│ ├── Runner.xcodeproj
│ │ ├── project.pbxproj
│ │ ├── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata
│ │ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ │ └── WorkspaceSettings.xcsettings
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ └── Runner.xcscheme
│ ├── Runner.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ └── WorkspaceSettings.xcsettings
│ ├── Runner
│ │ ├── AppDelegate.swift
│ │ ├── Assets.xcassets
│ │ │ ├── AppIcon.appiconset
│ │ │ │ ├── Contents.json
│ │ │ │ ├── Icon-App-1024x1024@1x.png
│ │ │ │ ├── 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-83.5x83.5@2x.png
│ │ │ └── LaunchImage.imageset
│ │ │ │ ├── Contents.json
│ │ │ │ ├── LaunchImage.png
│ │ │ │ ├── LaunchImage@2x.png
│ │ │ │ ├── LaunchImage@3x.png
│ │ │ │ └── README.md
│ │ ├── Base.lproj
│ │ │ ├── LaunchScreen.storyboard
│ │ │ └── Main.storyboard
│ │ ├── Info.plist
│ │ └── Runner-Bridging-Header.h
│ └── RunnerTests
│ │ └── RunnerTests.swift
├── lib
│ └── main.dart
├── pubspec.lock
├── pubspec.yaml
└── test
│ └── widget_test.dart
├── ios
├── .gitignore
├── Assets
│ └── .gitkeep
├── Classes
│ ├── BitmapPlugin.h
│ ├── BitmapPlugin.m
│ ├── SwiftBitmapPlugin.swift
│ └── bitmap.cpp
└── bitmap.podspec
├── lib
├── bitmap_flutter.dart
└── src
│ ├── bitmap.dart
│ ├── ffi.dart
│ └── operation
│ ├── adjust_color.dart
│ ├── brightness.dart
│ ├── contrast.dart
│ ├── crop.dart
│ ├── flip.dart
│ ├── operation.dart
│ ├── resize.dart
│ ├── rgb_overlay.dart
│ └── rotation.dart
├── macos
├── Classes
│ └── BitmapPlugin.swift
└── bitmap.podspec
├── pubspec.lock
├── pubspec.yaml
├── test
└── bitmap_test.dart
└── transform.jpg
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 |
12 | # IntelliJ related
13 | *.iml
14 | *.ipr
15 | *.iws
16 | .idea/
17 |
18 | # Visual Studio Code related
19 | .vscode/
20 |
21 | # Flutter/Dart/Pub related
22 | **/doc/api/
23 | .dart_tool/
24 | .flutter-plugins
25 | .packages
26 | .pub-cache/
27 | .pub/
28 | build/
29 | ios/.generated/
30 | android/.cxx/
31 |
--------------------------------------------------------------------------------
/.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: "db7ef5bf9f59442b0e200a90587e8fa5e0c6336a"
8 | channel: "stable"
9 |
10 | project_type: plugin
11 |
12 | # Tracks metadata for the flutter migrate command
13 | migration:
14 | platforms:
15 | - platform: root
16 | create_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a
17 | base_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a
18 | - platform: android
19 | create_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a
20 | base_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a
21 | - platform: ios
22 | create_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a
23 | base_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a
24 |
25 | # User provided section
26 |
27 | # List of Local paths (relative to this file) that should be
28 | # ignored by the migrate tool.
29 | #
30 | # Files that are not part of the templates will be ignored by default.
31 | unmanaged_files:
32 | - 'lib/main.dart'
33 | - 'ios/Runner.xcodeproj/project.pbxproj'
34 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## 0.2.0
2 |
3 | * fix: Add support for android gradle version 8.1.3
4 | * feat: Implement RGB overlay operation
5 |
6 | ## 0.1.3
7 |
8 | * Bump ffi to 2.0.1
9 |
10 | ## 0.1.2
11 |
12 | * Fix wrong throw on resize image
13 |
14 | ## 0.1.1
15 |
16 | * Fix wrong assertion on resize image
17 |
18 | ## 0.1.0
19 |
20 | * Support FFI 1.0.0
21 | * Add crop operation
22 | * Add rotation operation
23 | * Change API to `bitmap.apply(Operation())`
24 | * Add batch operations
25 | * Update plugin to support Flutter 1.20.0
26 |
27 | ## 0.0.1
28 |
29 | * Initial release
30 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2019 Renan C. Araújo
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | 
3 |
4 | # Flutter Bitmap
5 |
6 | [](https://pub.dartlang.org/packages/bitmap)
7 |
8 | A minimalist [Flutter](https://flutter.dev/) package to perform fast bitmaps operations.
9 | The focus here is to provide a cool bitmap manipulation interface.
10 |
11 | The package standard format is [RGBA32](https://en.wikipedia.org/wiki/RGBA_color_space).
12 |
13 | Bitmap uses the Dart FFI to perform operations such as contrast, brightness, saturation, and exposure.
14 |
15 | For now, things like format encoding, EXIF and multi-frame images are not the concern of this package. If that is your need, check [`image`](https://pub.dartlang.org/packages/image).
16 | Some of the algorithms here are heavily inspired by this awesome lib.
17 |
18 | ## Why this exists?
19 |
20 | I started to use [dart image](https://pub.dartlang.org/packages/image) to create [LetsPicture](https://play.google.com/store/apps/details?id=app.letspicture.letspicture) (cool app, check it out) but since the beginning, I've noticed that the performance was really bad.
21 | [Dart image](https://pub.dartlang.org/packages/image) has its own Image format, so between decoding, putting some transformations and then displaying the result on the app you had to convert the image two times (at least).
22 |
23 | So this package is just this: We deal [bitmaps](https://en.wikipedia.org/wiki/BMP_file_format) (duh) and we focus only on Flutter use cases.
24 |
25 | `bitmap` takes some advantages from Flutter:
26 | - Every image is decoded to [RGBA32](https://en.wikipedia.org/wiki/RGBA_color_space) by the framework trough ImageStreamListener, so we can rely on Flutter to do the decoding job;
27 | - Dart FFI: we are porting some of our functions to C (or C++) making it blazing fast.
28 | - With this package, you can easily take advantage of stuff like [compute](https://api.flutter.dev/flutter/foundation/compute.html) ([Isolates](https://www.didierboelens.com/2019/01/futures---isolates---event-loop/)) on only the manipulations you want to free the UI thread of heavy computation.
29 |
30 | ## Alternatives
31 |
32 | #### Dart image
33 |
34 | As mentioned previously, [`check on pub`](https://pub.dartlang.org/packages/image).
35 |
36 | #### Flutter Built-in ColorFilter class
37 |
38 | Flutter has a powerful [ColorFilter](https://api.flutter.dev/flutter/dart-ui/ColorFilter-class.html) class (that came from [skia](https://skia.org/user/api/skpaint_overview#SkColorFilter)) which can be used to put some color corrections when painting stuff on canvas. You can use a matrix to correct color (Some matrix examples [here](https://docs.rainmeter.net/tips/colormatrix-guide/)).
39 | Not every color transformation can be done through the matrix, though.
40 |
41 | ## Basic usage
42 |
43 | ### 1. Image to Bitmap
44 |
45 | Everything is around the [Bitmap](https://pub.dev/documentation/bitmap/latest/bitmap/bitmap-library.html) class. You can get an instance of that from any [ImageProvider](https://api.flutter.dev/flutter/painting/ImageProvider-class.html).
46 |
47 | ```dart
48 | import 'package:bitmap/bitmap.dart';
49 |
50 | Bitmap bitmap = await Bitmap.fromProvider(NetworkImage("http://pudim.com.br/pudim.jpg")); // Notice this is an async operation
51 | ```
52 |
53 | ##### You can create from a headed [Uint8List](https://api.flutter.dev/flutter/dart-typed_data/Uint8List-class.html):
54 |
55 | ```dart
56 | import 'package:bitmap/bitmap.dart';
57 |
58 | Bitmap bitmap = Bitmap.fromHeadful(imageWidth, imageHeight, theListOfInts); // Not async
59 | ```
60 |
61 | ##### Or a headless:
62 |
63 | ```dart
64 | Bitmap bitmap = Bitmap.fromHeadless(imageWidth, imageHeight, theListOfInts); // Not async
65 | ```
66 | This is useful when you are dealing with the [Uint8List](https://api.flutter.dev/flutter/dart-typed_data/Uint8List-class.html) that [ByteData](https://api.flutter.dev/flutter/dart-typed_data/ByteData-class.html) generates.
67 |
68 | ##### You can even create a blank one
69 |
70 | ```dart
71 | Bitmap bitmap = Bitmap.blank(imageWidth, imageHeight);
72 | ```
73 | This creates a black, full transparent bitmap.
74 |
75 | ### 2. Applying some operations
76 |
77 | Let's put some contrast
78 | ```dart
79 | import 'package:bitmap/bitmap.dart';
80 |
81 | Bitmap contrastedBitmap = bitmap.apply(BitmapContrast(0.2));;
82 | ```
83 |
84 | It is possible to add several operations at once
85 | ```dart
86 | import 'package:bitmap/bitmap.dart';
87 | Bitmap brightBitmap = bitmap.applyBatch([
88 | BitmapBrightness(0.2),
89 | BitmapAdjustColor(
90 | saturation: 1.0
91 | ),
92 | ]);
93 | ```
94 |
95 | ### 3. Displaying/painting/saving the output
96 |
97 | You can create two outputs from a `Bitmap` instance:
98 | - A `Uint8List` with no header, only the content of the file (`.content` property).
99 | - A `Uint8List` with a bitmap header, which Flutter can parse (`.buildHeaded()` method).
100 |
101 | ##### Displaying
102 |
103 | To easiest way to display an image is to getting the bitmap with header and then passing it to the widget `Image.memory`:
104 | ```dart
105 | // ..
106 |
107 | Uint8List headedBitmap = bitmap.buildHeaded();
108 |
109 | // ..
110 | child: Image.memory(headedBitmap)
111 | // ..
112 | ```
113 |
114 | ##### Painting
115 |
116 | The `Bitmap` class has also a helper function `buildImage` that uses Flutter's `decodeImageFromList` to build a [`dart:ui Image`](https://api.flutter.dev/flutter/dart-ui/Image-class.html).
117 | With an `Image`, you can [paint it in a canvas](https://api.flutter.dev/flutter/dart-ui/Canvas/drawImage.html) (in a [CustomPainter](https://api.flutter.dev/flutter/rendering/CustomPainter-class.html), for example).
118 |
119 | ```dart
120 | import 'dart:ui' as ui;
121 | // ..
122 | ui.Image outputImage = await bitmap.buildImage();
123 | canvas.drawImage(outputImage, Offset.zero, ui.Paint());
124 | ```
125 |
126 | ##### Saving
127 |
128 | You can also save the image as a `.bmp` file (get the file content with the `.buildHeaded()` method).
129 | You can check also the [`image`](https://pub.dartlang.org/packages/image) lib where you can save the image in several formats.
130 |
131 | [How to save files with Flutter?](https://flutter.dev/docs/cookbook/persistence/reading-writing-files)
132 |
133 | ## Performance improvements and Dart FFI
134 |
135 | ### Dart FFI
136 |
137 | The capability of calling a `c` (or `c++`) function from dart can help us a lot in getter better performance times.
138 |
139 | ### Isolates
140 |
141 | Most of the manipulations on the bitmap take a long time to be completed. That's is because they have to iterate on every item of the bitmap.
142 | A picture with a 400px width and height sizes will generate a list of 640000 integers. This is a heavy computation.
143 | Those can be expensive. Sou you may use [Isolates](https://www.didierboelens.com/2019/01/futures---isolates---event-loop/) there to free the UI thread from all of this work.
144 |
145 | Check the [example app](https://github.com/renancaraujo/bitmap), where the transformations are applied through the compute function.
146 |
147 | **Important: it is noticed that the performance increases a lot when using release mode on your Flutter App**
148 |
149 | ## Apps using it (only one for now)
150 |
151 | - [Lets Picture](https://github.com/renancaraujo/letspicture) - [Play store](https://play.google.com/store/apps/details?id=app.letspicture.letspicture) and the [source code](https://github.com/renancaraujo/letspicture).
152 |
153 | ## Supported operations
154 |
155 | - Flip vertical
156 | - Flip horizontal
157 | - Rotation
158 | - Resize (nearest interpolation)
159 | - Contrast
160 | - Brightness
161 | - Saturation
162 | - Exposure
163 | - Crop
164 |
165 | ## Todo
166 |
167 | There is a lot of work to be done:
168 |
169 | - [ ] Resize with other interpolations
170 | - [ ] Set channel
171 | - [ ] White balance
172 | - [ ] Color blend
173 | - [ ] Noise
174 | - [ ] Tones
175 | - [ ] ??? The sky is the limit
176 |
--------------------------------------------------------------------------------
/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | analyzer:
2 | errors:
3 | mixin_inherits_from_not_object: ignore
4 | linter:
5 | rules:
6 | - always_declare_return_types
7 | - always_put_control_body_on_new_line
8 | - always_require_non_null_named_parameters
9 | - annotate_overrides
10 | - avoid_as
11 | - avoid_classes_with_only_static_members
12 | - avoid_empty_else
13 | - avoid_field_initializers_in_const_classes
14 | - avoid_function_literals_in_foreach_calls
15 | - avoid_init_to_null
16 | - avoid_null_checks_in_equality_operators
17 | - avoid_relative_lib_imports
18 | - avoid_renaming_method_parameters
19 | - avoid_return_types_on_setters
20 | - avoid_slow_async_io
21 | - await_only_futures
22 | - camel_case_types
23 | - cancel_subscriptions
24 | - control_flow_in_finally
25 | - directives_ordering
26 | - empty_catches
27 | - empty_constructor_bodies
28 | - empty_statements
29 | - hash_and_equals
30 | - implementation_imports
31 | - iterable_contains_unrelated_type
32 | - library_names
33 | - library_prefixes
34 | - list_remove_unrelated_type
35 | - no_adjacent_strings_in_list
36 | - no_duplicate_case_values
37 | - non_constant_identifier_names
38 | - overridden_fields
39 | - package_api_docs
40 | - package_names
41 | - package_prefixed_library_names
42 | - prefer_adjacent_string_concatenation
43 | - prefer_asserts_in_initializer_lists
44 | - prefer_collection_literals
45 | - prefer_conditional_assignment
46 | - prefer_const_constructors
47 | - prefer_const_declarations
48 | - prefer_const_literals_to_create_immutables
49 | - prefer_contains
50 | - prefer_equal_for_default_values
51 | - prefer_final_fields
52 | - prefer_final_locals
53 | - prefer_foreach
54 | - prefer_initializing_formals
55 | - prefer_is_empty
56 | - prefer_is_not_empty
57 | - prefer_typing_uninitialized_variables
58 | - recursive_getters
59 | - slash_for_doc_comments
60 | - sort_unnamed_constructors_first
61 | - test_types_in_equals
62 | - throw_in_finally
63 | - type_init_formals
64 | - unnecessary_brace_in_string_interps
65 | - unnecessary_getters_setters
66 | - unnecessary_null_aware_assignments
67 | - unnecessary_null_in_if_null_operators
68 | - unnecessary_overrides
69 | - unnecessary_parenthesis
70 | - unnecessary_this
71 | - unrelated_type_equality_checks
72 | - use_rethrow_when_possible
73 | - unnecessary_new
74 |
75 |
--------------------------------------------------------------------------------
/android/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 |
--------------------------------------------------------------------------------
/android/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.4.1)
2 |
3 | add_library( bitmap
4 |
5 | # Sets the library as a shared library.
6 | SHARED
7 |
8 | # Provides a relative path to your source file(s).
9 | ../ios/Classes/bitmap.cpp )
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | group 'com.example.bitmap'
2 | version '1.0-SNAPSHOT'
3 |
4 | buildscript {
5 | ext.kotlin_version = '1.9.0'
6 | repositories {
7 | google()
8 | mavenCentral()
9 | }
10 |
11 | dependencies {
12 | classpath 'com.android.tools.build:gradle:8.1.3'
13 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
14 | }
15 | }
16 |
17 | rootProject.allprojects {
18 | repositories {
19 | google()
20 | mavenCentral()
21 | }
22 | }
23 |
24 | apply plugin: 'com.android.library'
25 | apply plugin: 'kotlin-android'
26 |
27 | android {
28 | if (project.android.hasProperty("namespace")) {
29 | namespace "com.example.bitmap"
30 | }
31 |
32 | compileSdkVersion 33
33 |
34 | sourceSets {
35 | main.java.srcDirs += 'src/main/kotlin'
36 | }
37 | defaultConfig {
38 | minSdkVersion 16
39 | }
40 |
41 | compileOptions {
42 | sourceCompatibility = JavaVersion.VERSION_1_8
43 | targetCompatibility = JavaVersion.VERSION_1_8
44 | }
45 |
46 | kotlinOptions {
47 | jvmTarget = '1.8'
48 | }
49 |
50 | externalNativeBuild {
51 | cmake {
52 | path "CMakeLists.txt"
53 | }
54 | }
55 | }
56 |
57 | dependencies {
58 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
59 | }
60 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | zipStoreBase=GRADLE_USER_HOME
4 | zipStorePath=wrapper/dists
5 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-all.zip
6 |
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'bitmap'
2 |
--------------------------------------------------------------------------------
/android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/android/src/main/kotlin/com/example/bitmap/BitmapPlugin.kt:
--------------------------------------------------------------------------------
1 | package com.example.bitmap
2 |
3 | import androidx.annotation.NonNull
4 | import io.flutter.embedding.engine.plugins.FlutterPlugin
5 | import io.flutter.plugin.common.MethodCall
6 | import io.flutter.plugin.common.MethodChannel
7 | import io.flutter.plugin.common.MethodChannel.MethodCallHandler
8 | import io.flutter.plugin.common.MethodChannel.Result
9 |
10 | /** BitmapPlugin */
11 | class BitmapPlugin : FlutterPlugin, MethodCallHandler {
12 |
13 | private lateinit var channel: MethodChannel
14 |
15 | override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
16 | channel = MethodChannel(flutterPluginBinding.binaryMessenger, "bitmap")
17 | channel.setMethodCallHandler(this)
18 | }
19 |
20 | override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
21 | when (call.method) {
22 | "getPlatformVersion" -> result.success("Android ${android.os.Build.VERSION.RELEASE}")
23 | else -> result.notImplemented()
24 | }
25 | }
26 |
27 | override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
28 | channel.setMethodCallHandler(null)
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/android/src/test/kotlin/com/example/bitmap/BitmapPluginTest.kt:
--------------------------------------------------------------------------------
1 | package com.example.bitmap
2 |
3 | import io.flutter.plugin.common.MethodCall
4 | import io.flutter.plugin.common.MethodChannel
5 | import kotlin.test.Test
6 | import org.mockito.Mockito
7 |
8 | /*
9 | * This demonstrates a simple unit test of the Kotlin portion of this plugin's implementation.
10 | *
11 | * Once you have built the plugin's example app, you can run these tests from the command
12 | * line by running `./gradlew testDebugUnitTest` in the `example/android/` directory, or
13 | * you can run them directly from IDEs that support JUnit such as Android Studio.
14 | */
15 |
16 | internal class BitmapPluginTest {
17 | @Test
18 | fun onMethodCall_getPlatformVersion_returnsExpectedValue() {
19 | val plugin = BitmapPlugin()
20 |
21 | val call = MethodCall("getPlatformVersion", null)
22 | val mockResult: MethodChannel.Result = Mockito.mock(MethodChannel.Result::class.java)
23 | plugin.onMethodCall(call, mockResult)
24 |
25 | Mockito.verify(mockResult).success("Android " + android.os.Build.VERSION.RELEASE)
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/example/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 |
12 | # IntelliJ related
13 | *.iml
14 | *.ipr
15 | *.iws
16 | .idea/
17 |
18 | # The .vscode folder contains launch configuration and tasks you configure in
19 | # VS Code which you may wish to be included in version control, so this line
20 | # is commented out by default.
21 | #.vscode/
22 |
23 | # Flutter/Dart/Pub related
24 | **/doc/api/
25 | .dart_tool/
26 | .flutter-plugins
27 | .flutter-plugins-dependencies
28 | .packages
29 | .pub-cache/
30 | .pub/
31 | /build/
32 |
33 | # Web related
34 | lib/generated_plugin_registrant.dart
35 |
36 | # Exceptions to above rules.
37 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
38 |
39 |
--------------------------------------------------------------------------------
/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: "db7ef5bf9f59442b0e200a90587e8fa5e0c6336a"
8 | channel: "stable"
9 |
10 | project_type: app
11 |
12 | # Tracks metadata for the flutter migrate command
13 | migration:
14 | platforms:
15 | - platform: root
16 | create_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a
17 | base_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a
18 | - platform: android
19 | create_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a
20 | base_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a
21 | - platform: ios
22 | create_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a
23 | base_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a
24 | - platform: linux
25 | create_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a
26 | base_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a
27 | - platform: macos
28 | create_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a
29 | base_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a
30 | - platform: web
31 | create_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a
32 | base_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a
33 | - platform: windows
34 | create_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a
35 | base_revision: db7ef5bf9f59442b0e200a90587e8fa5e0c6336a
36 |
37 | # User provided section
38 |
39 | # List of Local paths (relative to this file) that should be
40 | # ignored by the migrate tool.
41 | #
42 | # Files that are not part of the templates will be ignored by default.
43 | unmanaged_files:
44 | - 'lib/main.dart'
45 | - 'ios/Runner.xcodeproj/project.pbxproj'
46 |
--------------------------------------------------------------------------------
/example/README.md:
--------------------------------------------------------------------------------
1 | # bitmap_example
2 |
3 | Demonstrates how to use the bitmap plugin.
4 |
5 | ## Getting Started
6 |
7 | This project is a starting point for a Flutter application.
8 |
9 | A few resources to get you started if this is your first Flutter project:
10 |
11 | - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
12 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
13 |
14 | For help getting started with Flutter, view our
15 | [online documentation](https://flutter.dev/docs), which offers tutorials,
16 | samples, guidance on mobile development, and a full API reference.
17 |
--------------------------------------------------------------------------------
/example/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
9 | # Remember to never publicly share your keystore.
10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
11 | key.properties
12 | **/*.keystore
13 | **/*.jks
14 |
--------------------------------------------------------------------------------
/example/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id "com.android.application"
3 | id "kotlin-android"
4 | id "dev.flutter.flutter-gradle-plugin"
5 | }
6 |
7 | def localProperties = new Properties()
8 | def localPropertiesFile = rootProject.file('local.properties')
9 | if (localPropertiesFile.exists()) {
10 | localPropertiesFile.withReader('UTF-8') { reader ->
11 | localProperties.load(reader)
12 | }
13 | }
14 |
15 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
16 | if (flutterVersionCode == null) {
17 | flutterVersionCode = '1'
18 | }
19 |
20 | def flutterVersionName = localProperties.getProperty('flutter.versionName')
21 | if (flutterVersionName == null) {
22 | flutterVersionName = '1.0'
23 | }
24 |
25 | android {
26 | namespace "com.example.example"
27 | compileSdkVersion flutter.compileSdkVersion
28 | ndkVersion flutter.ndkVersion
29 |
30 | compileOptions {
31 | sourceCompatibility JavaVersion.VERSION_1_8
32 | targetCompatibility JavaVersion.VERSION_1_8
33 | }
34 |
35 | kotlinOptions {
36 | jvmTarget = '1.8'
37 | }
38 |
39 | sourceSets {
40 | main.java.srcDirs += 'src/main/kotlin'
41 | }
42 |
43 | defaultConfig {
44 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
45 | applicationId "com.example.example"
46 | // You can update the following values to match your application needs.
47 | // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
48 | minSdkVersion flutter.minSdkVersion
49 | targetSdkVersion flutter.targetSdkVersion
50 | versionCode flutterVersionCode.toInteger()
51 | versionName flutterVersionName
52 | }
53 |
54 | buildTypes {
55 | release {
56 | // TODO: Add your own signing config for the release build.
57 | // Signing with the debug keys for now, so `flutter run --release` works.
58 | signingConfig signingConfigs.debug
59 | }
60 | }
61 | }
62 |
63 | flutter {
64 | source '../..'
65 | }
66 |
67 | dependencies {}
68 |
--------------------------------------------------------------------------------
/example/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
14 |
18 |
22 |
23 |
24 |
25 |
26 |
27 |
29 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.example.example
2 |
3 | import io.flutter.embedding.android.FlutterActivity
4 |
5 | class MainActivity: FlutterActivity() {
6 | }
7 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/drawable-v21/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bluefireteam/bitmap/6eb13d4980bd53a9b0de4eca178c60809bce3b5d/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/bluefireteam/bitmap/6eb13d4980bd53a9b0de4eca178c60809bce3b5d/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/bluefireteam/bitmap/6eb13d4980bd53a9b0de4eca178c60809bce3b5d/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/bluefireteam/bitmap/6eb13d4980bd53a9b0de4eca178c60809bce3b5d/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/bluefireteam/bitmap/6eb13d4980bd53a9b0de4eca178c60809bce3b5d/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values-night/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/example/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.9.0'
3 | repositories {
4 | google()
5 | mavenCentral()
6 | }
7 |
8 | dependencies {
9 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
10 | }
11 | }
12 |
13 | allprojects {
14 | repositories {
15 | google()
16 | mavenCentral()
17 | }
18 | }
19 |
20 | rootProject.buildDir = '../build'
21 | subprojects {
22 | project.buildDir = "${rootProject.buildDir}/${project.name}"
23 | }
24 | subprojects {
25 | project.evaluationDependsOn(':app')
26 | }
27 |
28 | tasks.register("clean", Delete) {
29 | delete rootProject.buildDir
30 | }
31 |
--------------------------------------------------------------------------------
/example/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx4G
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 |
--------------------------------------------------------------------------------
/example/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | zipStoreBase=GRADLE_USER_HOME
4 | zipStorePath=wrapper/dists
5 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip
6 |
--------------------------------------------------------------------------------
/example/android/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | def flutterSdkPath = {
3 | def properties = new Properties()
4 | file("local.properties").withInputStream { properties.load(it) }
5 | def flutterSdkPath = properties.getProperty("flutter.sdk")
6 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
7 | return flutterSdkPath
8 | }
9 | settings.ext.flutterSdkPath = flutterSdkPath()
10 |
11 | includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle")
12 |
13 | repositories {
14 | google()
15 | mavenCentral()
16 | gradlePluginPortal()
17 | }
18 |
19 | plugins {
20 | id "dev.flutter.flutter-gradle-plugin" version "1.0.0" apply false
21 | }
22 | }
23 |
24 | plugins {
25 | id "dev.flutter.flutter-plugin-loader" version "1.0.0"
26 | id "com.android.application" version "7.3.0" apply false
27 | }
28 |
29 | include ":app"
30 |
--------------------------------------------------------------------------------
/example/assets/doggo.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bluefireteam/bitmap/6eb13d4980bd53a9b0de4eca178c60809bce3b5d/example/assets/doggo.jpeg
--------------------------------------------------------------------------------
/example/assets/street.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bluefireteam/bitmap/6eb13d4980bd53a9b0de4eca178c60809bce3b5d/example/assets/street.jpg
--------------------------------------------------------------------------------
/example/ios/.gitignore:
--------------------------------------------------------------------------------
1 | *.mode1v3
2 | *.mode2v3
3 | *.moved-aside
4 | *.pbxuser
5 | *.perspectivev3
6 | **/*sync/
7 | .sconsign.dblite
8 | .tags*
9 | **/.vagrant/
10 | **/DerivedData/
11 | Icon?
12 | **/Pods/
13 | **/.symlinks/
14 | profile
15 | xcuserdata
16 | **/.generated/
17 | Flutter/App.framework
18 | Flutter/Flutter.framework
19 | Flutter/Flutter.podspec
20 | Flutter/Generated.xcconfig
21 | Flutter/ephemeral/
22 | Flutter/app.flx
23 | Flutter/app.zip
24 | Flutter/flutter_assets/
25 | Flutter/flutter_export_environment.sh
26 | ServiceDefinitions.json
27 | Runner/GeneratedPluginRegistrant.*
28 |
29 | # Exceptions to above rules.
30 | !default.mode1v3
31 | !default.mode2v3
32 | !default.pbxuser
33 | !default.perspectivev3
34 |
--------------------------------------------------------------------------------
/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 | 11.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/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/ios/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment this line to define a global platform for your project
2 | # platform :ios, '11.0'
3 |
4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true'
6 |
7 | project 'Runner', {
8 | 'Debug' => :debug,
9 | 'Profile' => :release,
10 | 'Release' => :release,
11 | }
12 |
13 | def flutter_root
14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
15 | unless File.exist?(generated_xcode_build_settings_path)
16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
17 | end
18 |
19 | File.foreach(generated_xcode_build_settings_path) do |line|
20 | matches = line.match(/FLUTTER_ROOT\=(.*)/)
21 | return matches[1].strip if matches
22 | end
23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
24 | end
25 |
26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
27 |
28 | flutter_ios_podfile_setup
29 |
30 | target 'Runner' do
31 | use_frameworks!
32 | use_modular_headers!
33 |
34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
35 | end
36 |
37 | post_install do |installer|
38 | installer.pods_project.targets.each do |target|
39 | flutter_additional_ios_build_settings(target)
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/example/ios/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - bitmap (0.0.1):
3 | - Flutter
4 | - Flutter (1.0.0)
5 |
6 | DEPENDENCIES:
7 | - bitmap (from `.symlinks/plugins/bitmap/ios`)
8 | - Flutter (from `Flutter`)
9 |
10 | EXTERNAL SOURCES:
11 | bitmap:
12 | :path: ".symlinks/plugins/bitmap/ios"
13 | Flutter:
14 | :path: Flutter
15 |
16 | SPEC CHECKSUMS:
17 | bitmap: 591b0556efe6e811a263b8dfdc511fe1faa72315
18 | Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
19 |
20 | PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3
21 |
22 | COCOAPODS: 1.12.1
23 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 54;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
11 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
12 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
13 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
14 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
15 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
16 | C79DF2D43ED612EBB7C3903C /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C9C63EE55E32E8A9F8219F0 /* Pods_Runner.framework */; };
17 | /* End PBXBuildFile section */
18 |
19 | /* Begin PBXCopyFilesBuildPhase section */
20 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = {
21 | isa = PBXCopyFilesBuildPhase;
22 | buildActionMask = 2147483647;
23 | dstPath = "";
24 | dstSubfolderSpec = 10;
25 | files = (
26 | );
27 | name = "Embed Frameworks";
28 | runOnlyForDeploymentPostprocessing = 0;
29 | };
30 | /* End PBXCopyFilesBuildPhase section */
31 |
32 | /* Begin PBXFileReference section */
33 | 0E09980A587ABB3C85121AAD /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; };
34 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; };
35 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
36 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
37 | 4AA7D1255AB78501A097F704 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; };
38 | 4C9C63EE55E32E8A9F8219F0 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
39 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; };
40 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
41 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; };
42 | 950A91CA40C20268F693704C /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; };
43 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; };
44 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; };
45 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
46 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
47 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
48 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
49 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
50 | /* End PBXFileReference section */
51 |
52 | /* Begin PBXFrameworksBuildPhase section */
53 | 97C146EB1CF9000F007C117D /* Frameworks */ = {
54 | isa = PBXFrameworksBuildPhase;
55 | buildActionMask = 2147483647;
56 | files = (
57 | C79DF2D43ED612EBB7C3903C /* Pods_Runner.framework in Frameworks */,
58 | );
59 | runOnlyForDeploymentPostprocessing = 0;
60 | };
61 | /* End PBXFrameworksBuildPhase section */
62 |
63 | /* Begin PBXGroup section */
64 | 30608FFB367171B4C72BF01C /* Frameworks */ = {
65 | isa = PBXGroup;
66 | children = (
67 | 4C9C63EE55E32E8A9F8219F0 /* Pods_Runner.framework */,
68 | );
69 | name = Frameworks;
70 | sourceTree = "";
71 | };
72 | 9740EEB11CF90186004384FC /* Flutter */ = {
73 | isa = PBXGroup;
74 | children = (
75 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
76 | 9740EEB21CF90195004384FC /* Debug.xcconfig */,
77 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
78 | 9740EEB31CF90195004384FC /* Generated.xcconfig */,
79 | );
80 | name = Flutter;
81 | sourceTree = "";
82 | };
83 | 97C146E51CF9000F007C117D = {
84 | isa = PBXGroup;
85 | children = (
86 | 9740EEB11CF90186004384FC /* Flutter */,
87 | 97C146F01CF9000F007C117D /* Runner */,
88 | 97C146EF1CF9000F007C117D /* Products */,
89 | D7E953E155436CCC5E91988E /* Pods */,
90 | 30608FFB367171B4C72BF01C /* Frameworks */,
91 | );
92 | sourceTree = "";
93 | };
94 | 97C146EF1CF9000F007C117D /* Products */ = {
95 | isa = PBXGroup;
96 | children = (
97 | 97C146EE1CF9000F007C117D /* Runner.app */,
98 | );
99 | name = Products;
100 | sourceTree = "";
101 | };
102 | 97C146F01CF9000F007C117D /* Runner */ = {
103 | isa = PBXGroup;
104 | children = (
105 | 97C146FA1CF9000F007C117D /* Main.storyboard */,
106 | 97C146FD1CF9000F007C117D /* Assets.xcassets */,
107 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
108 | 97C147021CF9000F007C117D /* Info.plist */,
109 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
110 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
111 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
112 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
113 | );
114 | path = Runner;
115 | sourceTree = "";
116 | };
117 | D7E953E155436CCC5E91988E /* Pods */ = {
118 | isa = PBXGroup;
119 | children = (
120 | 950A91CA40C20268F693704C /* Pods-Runner.debug.xcconfig */,
121 | 0E09980A587ABB3C85121AAD /* Pods-Runner.release.xcconfig */,
122 | 4AA7D1255AB78501A097F704 /* Pods-Runner.profile.xcconfig */,
123 | );
124 | name = Pods;
125 | path = Pods;
126 | sourceTree = "";
127 | };
128 | /* End PBXGroup section */
129 |
130 | /* Begin PBXNativeTarget section */
131 | 97C146ED1CF9000F007C117D /* Runner */ = {
132 | isa = PBXNativeTarget;
133 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
134 | buildPhases = (
135 | F3F12D9A66F64149ACC4CA8D /* [CP] Check Pods Manifest.lock */,
136 | 9740EEB61CF901F6004384FC /* Run Script */,
137 | 97C146EA1CF9000F007C117D /* Sources */,
138 | 97C146EB1CF9000F007C117D /* Frameworks */,
139 | 97C146EC1CF9000F007C117D /* Resources */,
140 | 9705A1C41CF9048500538489 /* Embed Frameworks */,
141 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
142 | 9336C0CFC86F60BF2BE900C0 /* [CP] Embed Pods Frameworks */,
143 | );
144 | buildRules = (
145 | );
146 | dependencies = (
147 | );
148 | name = Runner;
149 | productName = Runner;
150 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
151 | productType = "com.apple.product-type.application";
152 | };
153 | /* End PBXNativeTarget section */
154 |
155 | /* Begin PBXProject section */
156 | 97C146E61CF9000F007C117D /* Project object */ = {
157 | isa = PBXProject;
158 | attributes = {
159 | LastUpgradeCheck = 1430;
160 | ORGANIZATIONNAME = "";
161 | TargetAttributes = {
162 | 97C146ED1CF9000F007C117D = {
163 | CreatedOnToolsVersion = 7.3.1;
164 | LastSwiftMigration = 1100;
165 | };
166 | };
167 | };
168 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
169 | compatibilityVersion = "Xcode 9.3";
170 | developmentRegion = en;
171 | hasScannedForEncodings = 0;
172 | knownRegions = (
173 | en,
174 | Base,
175 | );
176 | mainGroup = 97C146E51CF9000F007C117D;
177 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
178 | projectDirPath = "";
179 | projectRoot = "";
180 | targets = (
181 | 97C146ED1CF9000F007C117D /* Runner */,
182 | );
183 | };
184 | /* End PBXProject section */
185 |
186 | /* Begin PBXResourcesBuildPhase section */
187 | 97C146EC1CF9000F007C117D /* Resources */ = {
188 | isa = PBXResourcesBuildPhase;
189 | buildActionMask = 2147483647;
190 | files = (
191 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
192 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
193 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
194 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
195 | );
196 | runOnlyForDeploymentPostprocessing = 0;
197 | };
198 | /* End PBXResourcesBuildPhase section */
199 |
200 | /* Begin PBXShellScriptBuildPhase section */
201 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
202 | isa = PBXShellScriptBuildPhase;
203 | alwaysOutOfDate = 1;
204 | buildActionMask = 2147483647;
205 | files = (
206 | );
207 | inputPaths = (
208 | "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
209 | );
210 | name = "Thin Binary";
211 | outputPaths = (
212 | );
213 | runOnlyForDeploymentPostprocessing = 0;
214 | shellPath = /bin/sh;
215 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
216 | };
217 | 9336C0CFC86F60BF2BE900C0 /* [CP] Embed Pods Frameworks */ = {
218 | isa = PBXShellScriptBuildPhase;
219 | buildActionMask = 2147483647;
220 | files = (
221 | );
222 | inputFileListPaths = (
223 | "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
224 | );
225 | name = "[CP] Embed Pods Frameworks";
226 | outputFileListPaths = (
227 | "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
228 | );
229 | runOnlyForDeploymentPostprocessing = 0;
230 | shellPath = /bin/sh;
231 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
232 | showEnvVarsInLog = 0;
233 | };
234 | 9740EEB61CF901F6004384FC /* Run Script */ = {
235 | isa = PBXShellScriptBuildPhase;
236 | alwaysOutOfDate = 1;
237 | buildActionMask = 2147483647;
238 | files = (
239 | );
240 | inputPaths = (
241 | );
242 | name = "Run Script";
243 | outputPaths = (
244 | );
245 | runOnlyForDeploymentPostprocessing = 0;
246 | shellPath = /bin/sh;
247 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
248 | };
249 | F3F12D9A66F64149ACC4CA8D /* [CP] Check Pods Manifest.lock */ = {
250 | isa = PBXShellScriptBuildPhase;
251 | buildActionMask = 2147483647;
252 | files = (
253 | );
254 | inputFileListPaths = (
255 | );
256 | inputPaths = (
257 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
258 | "${PODS_ROOT}/Manifest.lock",
259 | );
260 | name = "[CP] Check Pods Manifest.lock";
261 | outputFileListPaths = (
262 | );
263 | outputPaths = (
264 | "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
265 | );
266 | runOnlyForDeploymentPostprocessing = 0;
267 | shellPath = /bin/sh;
268 | 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";
269 | showEnvVarsInLog = 0;
270 | };
271 | /* End PBXShellScriptBuildPhase section */
272 |
273 | /* Begin PBXSourcesBuildPhase section */
274 | 97C146EA1CF9000F007C117D /* Sources */ = {
275 | isa = PBXSourcesBuildPhase;
276 | buildActionMask = 2147483647;
277 | files = (
278 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
279 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
280 | );
281 | runOnlyForDeploymentPostprocessing = 0;
282 | };
283 | /* End PBXSourcesBuildPhase section */
284 |
285 | /* Begin PBXVariantGroup section */
286 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = {
287 | isa = PBXVariantGroup;
288 | children = (
289 | 97C146FB1CF9000F007C117D /* Base */,
290 | );
291 | name = Main.storyboard;
292 | sourceTree = "";
293 | };
294 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
295 | isa = PBXVariantGroup;
296 | children = (
297 | 97C147001CF9000F007C117D /* Base */,
298 | );
299 | name = LaunchScreen.storyboard;
300 | sourceTree = "";
301 | };
302 | /* End PBXVariantGroup section */
303 |
304 | /* Begin XCBuildConfiguration section */
305 | 249021D3217E4FDB00AE95B9 /* Profile */ = {
306 | isa = XCBuildConfiguration;
307 | buildSettings = {
308 | ALWAYS_SEARCH_USER_PATHS = NO;
309 | CLANG_ANALYZER_NONNULL = YES;
310 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
311 | CLANG_CXX_LIBRARY = "libc++";
312 | CLANG_ENABLE_MODULES = YES;
313 | CLANG_ENABLE_OBJC_ARC = YES;
314 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
315 | CLANG_WARN_BOOL_CONVERSION = YES;
316 | CLANG_WARN_COMMA = YES;
317 | CLANG_WARN_CONSTANT_CONVERSION = YES;
318 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
319 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
320 | CLANG_WARN_EMPTY_BODY = YES;
321 | CLANG_WARN_ENUM_CONVERSION = YES;
322 | CLANG_WARN_INFINITE_RECURSION = YES;
323 | CLANG_WARN_INT_CONVERSION = YES;
324 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
325 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
326 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
327 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
328 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
329 | CLANG_WARN_STRICT_PROTOTYPES = YES;
330 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
331 | CLANG_WARN_UNREACHABLE_CODE = YES;
332 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
333 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
334 | COPY_PHASE_STRIP = NO;
335 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
336 | ENABLE_NS_ASSERTIONS = NO;
337 | ENABLE_STRICT_OBJC_MSGSEND = YES;
338 | GCC_C_LANGUAGE_STANDARD = gnu99;
339 | GCC_NO_COMMON_BLOCKS = YES;
340 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
341 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
342 | GCC_WARN_UNDECLARED_SELECTOR = YES;
343 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
344 | GCC_WARN_UNUSED_FUNCTION = YES;
345 | GCC_WARN_UNUSED_VARIABLE = YES;
346 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
347 | MTL_ENABLE_DEBUG_INFO = NO;
348 | SDKROOT = iphoneos;
349 | SUPPORTED_PLATFORMS = iphoneos;
350 | TARGETED_DEVICE_FAMILY = "1,2";
351 | VALIDATE_PRODUCT = YES;
352 | };
353 | name = Profile;
354 | };
355 | 249021D4217E4FDB00AE95B9 /* Profile */ = {
356 | isa = XCBuildConfiguration;
357 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
358 | buildSettings = {
359 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
360 | CLANG_ENABLE_MODULES = YES;
361 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
362 | ENABLE_BITCODE = NO;
363 | INFOPLIST_FILE = Runner/Info.plist;
364 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
365 | PRODUCT_BUNDLE_IDENTIFIER = com.example.bitmapExample;
366 | PRODUCT_NAME = "$(TARGET_NAME)";
367 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
368 | SWIFT_VERSION = 5.0;
369 | VERSIONING_SYSTEM = "apple-generic";
370 | };
371 | name = Profile;
372 | };
373 | 97C147031CF9000F007C117D /* Debug */ = {
374 | isa = XCBuildConfiguration;
375 | buildSettings = {
376 | ALWAYS_SEARCH_USER_PATHS = NO;
377 | CLANG_ANALYZER_NONNULL = YES;
378 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
379 | CLANG_CXX_LIBRARY = "libc++";
380 | CLANG_ENABLE_MODULES = YES;
381 | CLANG_ENABLE_OBJC_ARC = YES;
382 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
383 | CLANG_WARN_BOOL_CONVERSION = YES;
384 | CLANG_WARN_COMMA = YES;
385 | CLANG_WARN_CONSTANT_CONVERSION = YES;
386 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
387 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
388 | CLANG_WARN_EMPTY_BODY = YES;
389 | CLANG_WARN_ENUM_CONVERSION = YES;
390 | CLANG_WARN_INFINITE_RECURSION = YES;
391 | CLANG_WARN_INT_CONVERSION = YES;
392 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
393 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
394 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
395 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
396 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
397 | CLANG_WARN_STRICT_PROTOTYPES = YES;
398 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
399 | CLANG_WARN_UNREACHABLE_CODE = YES;
400 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
401 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
402 | COPY_PHASE_STRIP = NO;
403 | DEBUG_INFORMATION_FORMAT = dwarf;
404 | ENABLE_STRICT_OBJC_MSGSEND = YES;
405 | ENABLE_TESTABILITY = YES;
406 | GCC_C_LANGUAGE_STANDARD = gnu99;
407 | GCC_DYNAMIC_NO_PIC = NO;
408 | GCC_NO_COMMON_BLOCKS = YES;
409 | GCC_OPTIMIZATION_LEVEL = 0;
410 | GCC_PREPROCESSOR_DEFINITIONS = (
411 | "DEBUG=1",
412 | "$(inherited)",
413 | );
414 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
415 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
416 | GCC_WARN_UNDECLARED_SELECTOR = YES;
417 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
418 | GCC_WARN_UNUSED_FUNCTION = YES;
419 | GCC_WARN_UNUSED_VARIABLE = YES;
420 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
421 | MTL_ENABLE_DEBUG_INFO = YES;
422 | ONLY_ACTIVE_ARCH = YES;
423 | SDKROOT = iphoneos;
424 | TARGETED_DEVICE_FAMILY = "1,2";
425 | };
426 | name = Debug;
427 | };
428 | 97C147041CF9000F007C117D /* Release */ = {
429 | isa = XCBuildConfiguration;
430 | buildSettings = {
431 | ALWAYS_SEARCH_USER_PATHS = NO;
432 | CLANG_ANALYZER_NONNULL = YES;
433 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
434 | CLANG_CXX_LIBRARY = "libc++";
435 | CLANG_ENABLE_MODULES = YES;
436 | CLANG_ENABLE_OBJC_ARC = YES;
437 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
438 | CLANG_WARN_BOOL_CONVERSION = YES;
439 | CLANG_WARN_COMMA = YES;
440 | CLANG_WARN_CONSTANT_CONVERSION = YES;
441 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
442 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
443 | CLANG_WARN_EMPTY_BODY = YES;
444 | CLANG_WARN_ENUM_CONVERSION = YES;
445 | CLANG_WARN_INFINITE_RECURSION = YES;
446 | CLANG_WARN_INT_CONVERSION = YES;
447 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
448 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
449 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
450 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
451 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
452 | CLANG_WARN_STRICT_PROTOTYPES = YES;
453 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
454 | CLANG_WARN_UNREACHABLE_CODE = YES;
455 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
456 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
457 | COPY_PHASE_STRIP = NO;
458 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
459 | ENABLE_NS_ASSERTIONS = NO;
460 | ENABLE_STRICT_OBJC_MSGSEND = YES;
461 | GCC_C_LANGUAGE_STANDARD = gnu99;
462 | GCC_NO_COMMON_BLOCKS = YES;
463 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
464 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
465 | GCC_WARN_UNDECLARED_SELECTOR = YES;
466 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
467 | GCC_WARN_UNUSED_FUNCTION = YES;
468 | GCC_WARN_UNUSED_VARIABLE = YES;
469 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
470 | MTL_ENABLE_DEBUG_INFO = NO;
471 | SDKROOT = iphoneos;
472 | SUPPORTED_PLATFORMS = iphoneos;
473 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
474 | TARGETED_DEVICE_FAMILY = "1,2";
475 | VALIDATE_PRODUCT = YES;
476 | };
477 | name = Release;
478 | };
479 | 97C147061CF9000F007C117D /* Debug */ = {
480 | isa = XCBuildConfiguration;
481 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
482 | buildSettings = {
483 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
484 | CLANG_ENABLE_MODULES = YES;
485 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
486 | ENABLE_BITCODE = NO;
487 | INFOPLIST_FILE = Runner/Info.plist;
488 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
489 | PRODUCT_BUNDLE_IDENTIFIER = com.example.bitmapExample;
490 | PRODUCT_NAME = "$(TARGET_NAME)";
491 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
492 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
493 | SWIFT_VERSION = 5.0;
494 | VERSIONING_SYSTEM = "apple-generic";
495 | };
496 | name = Debug;
497 | };
498 | 97C147071CF9000F007C117D /* Release */ = {
499 | isa = XCBuildConfiguration;
500 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
501 | buildSettings = {
502 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
503 | CLANG_ENABLE_MODULES = YES;
504 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
505 | ENABLE_BITCODE = NO;
506 | INFOPLIST_FILE = Runner/Info.plist;
507 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
508 | PRODUCT_BUNDLE_IDENTIFIER = com.example.bitmapExample;
509 | PRODUCT_NAME = "$(TARGET_NAME)";
510 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
511 | SWIFT_VERSION = 5.0;
512 | VERSIONING_SYSTEM = "apple-generic";
513 | };
514 | name = Release;
515 | };
516 | /* End XCBuildConfiguration section */
517 |
518 | /* Begin XCConfigurationList section */
519 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
520 | isa = XCConfigurationList;
521 | buildConfigurations = (
522 | 97C147031CF9000F007C117D /* Debug */,
523 | 97C147041CF9000F007C117D /* Release */,
524 | 249021D3217E4FDB00AE95B9 /* Profile */,
525 | );
526 | defaultConfigurationIsVisible = 0;
527 | defaultConfigurationName = Release;
528 | };
529 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
530 | isa = XCConfigurationList;
531 | buildConfigurations = (
532 | 97C147061CF9000F007C117D /* Debug */,
533 | 97C147071CF9000F007C117D /* Release */,
534 | 249021D4217E4FDB00AE95B9 /* Profile */,
535 | );
536 | defaultConfigurationIsVisible = 0;
537 | defaultConfigurationName = Release;
538 | };
539 | /* End XCConfigurationList section */
540 | };
541 | rootObject = 97C146E61CF9000F007C117D /* Project object */;
542 | }
543 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Flutter
3 |
4 | @UIApplicationMain
5 | @objc class AppDelegate: FlutterAppDelegate {
6 | override func application(
7 | _ application: UIApplication,
8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
9 | ) -> Bool {
10 | GeneratedPluginRegistrant.register(with: self)
11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/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/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bluefireteam/bitmap/6eb13d4980bd53a9b0de4eca178c60809bce3b5d/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bluefireteam/bitmap/6eb13d4980bd53a9b0de4eca178c60809bce3b5d/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/bluefireteam/bitmap/6eb13d4980bd53a9b0de4eca178c60809bce3b5d/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/bluefireteam/bitmap/6eb13d4980bd53a9b0de4eca178c60809bce3b5d/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/bluefireteam/bitmap/6eb13d4980bd53a9b0de4eca178c60809bce3b5d/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/bluefireteam/bitmap/6eb13d4980bd53a9b0de4eca178c60809bce3b5d/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/bluefireteam/bitmap/6eb13d4980bd53a9b0de4eca178c60809bce3b5d/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/bluefireteam/bitmap/6eb13d4980bd53a9b0de4eca178c60809bce3b5d/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/bluefireteam/bitmap/6eb13d4980bd53a9b0de4eca178c60809bce3b5d/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/bluefireteam/bitmap/6eb13d4980bd53a9b0de4eca178c60809bce3b5d/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/bluefireteam/bitmap/6eb13d4980bd53a9b0de4eca178c60809bce3b5d/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/bluefireteam/bitmap/6eb13d4980bd53a9b0de4eca178c60809bce3b5d/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/bluefireteam/bitmap/6eb13d4980bd53a9b0de4eca178c60809bce3b5d/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/bluefireteam/bitmap/6eb13d4980bd53a9b0de4eca178c60809bce3b5d/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bluefireteam/bitmap/6eb13d4980bd53a9b0de4eca178c60809bce3b5d/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/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/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bluefireteam/bitmap/6eb13d4980bd53a9b0de4eca178c60809bce3b5d/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bluefireteam/bitmap/6eb13d4980bd53a9b0de4eca178c60809bce3b5d/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bluefireteam/bitmap/6eb13d4980bd53a9b0de4eca178c60809bce3b5d/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/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/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/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 |
--------------------------------------------------------------------------------
/example/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | bitmap_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 | CADisableMinimumFrameDurationOnPhone
45 |
46 | UIApplicationSupportsIndirectInputEvents
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/example/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/example/ios/RunnerTests/RunnerTests.swift:
--------------------------------------------------------------------------------
1 | import Flutter
2 | import UIKit
3 | import XCTest
4 |
5 | @testable import bitmap
6 |
7 | // This demonstrates a simple unit test of the Swift portion of this plugin's implementation.
8 | //
9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest.
10 |
11 | class RunnerTests: XCTestCase {
12 |
13 | func testGetPlatformVersion() {
14 | let plugin = BitmapPlugin()
15 |
16 | let call = FlutterMethodCall(methodName: "getPlatformVersion", arguments: [])
17 |
18 | let resultExpectation = expectation(description: "result block must be called.")
19 | plugin.handle(call) { result in
20 | XCTAssertEqual(result as! String, "iOS " + UIDevice.current.systemVersion)
21 | resultExpectation.fulfill()
22 | }
23 | waitForExpectations(timeout: 1)
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/example/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 |
3 | import 'package:bitmap/bitmap.dart';
4 | import 'package:flutter/foundation.dart';
5 | import 'package:flutter/material.dart';
6 |
7 | void main() => runApp(MyApp());
8 |
9 | class MyApp extends StatelessWidget {
10 | // This widget is the root of your application.
11 | @override
12 | Widget build(BuildContext context) {
13 | return MaterialApp(
14 | title: 'Image',
15 | theme: ThemeData(
16 | primarySwatch: Colors.orange,
17 | ),
18 | home: MyHomePage(
19 | title: "Pans",
20 | ),
21 | );
22 | }
23 | }
24 |
25 | class MyHomePage extends StatefulWidget {
26 | MyHomePage({
27 | Key? key,
28 | required this.title,
29 | }) : super(key: key);
30 |
31 | final String title;
32 |
33 | @override
34 | _MyHomePageState createState() => _MyHomePageState();
35 | }
36 |
37 | class _MyHomePageState extends State {
38 | ImageValueNotifier imageValueNotifier = ImageValueNotifier();
39 |
40 | @override
41 | void initState() {
42 | super.initState();
43 | imageValueNotifier.loadImage();
44 | }
45 |
46 | void flipHImage() {
47 | if (imageValueNotifier.value != null) {
48 | imageValueNotifier.flipHImage();
49 | }
50 | }
51 |
52 | void flipVImage() {
53 | if (imageValueNotifier.value != null) {
54 | imageValueNotifier.flipVImage();
55 | }
56 | }
57 |
58 | void rotateClockwiseImage() {
59 | if (imageValueNotifier.value != null) {
60 | imageValueNotifier.rotateClockwiseImage();
61 | }
62 | }
63 |
64 | void rotateCounterClockwiseImage() {
65 | if (imageValueNotifier.value != null) {
66 | imageValueNotifier.rotateCounterClockwiseImage();
67 | }
68 | }
69 |
70 | void rotate180Image() {
71 | if (imageValueNotifier.value != null) {
72 | imageValueNotifier.rotate180Image();
73 | }
74 | }
75 |
76 | void contrastImage() {
77 | if (imageValueNotifier.value != null) {
78 | imageValueNotifier.contrastImage();
79 | }
80 | }
81 |
82 | void brightnessImage() {
83 | if (imageValueNotifier.value != null) {
84 | imageValueNotifier.brightnessImage();
85 | }
86 | }
87 |
88 | void adjustColorImage() {
89 | if (imageValueNotifier.value != null) {
90 | imageValueNotifier.adjustColorImage();
91 | }
92 | }
93 |
94 | void batchOperations() {
95 | if (imageValueNotifier.value != null) {
96 | imageValueNotifier.batchOperations();
97 | }
98 | }
99 |
100 | @override
101 | Widget build(BuildContext context) {
102 | return Scaffold(
103 | body: GestureDetector(
104 | onTap: () {
105 | imageValueNotifier.reset();
106 | },
107 | child: Center(
108 | child: ValueListenableBuilder(
109 | valueListenable: imageValueNotifier,
110 | builder: (BuildContext context, Bitmap? bitmap, Widget? child) {
111 | if (bitmap == null) {
112 | return const CircularProgressIndicator();
113 | }
114 | return Column(
115 | children: [
116 | SafeArea(
117 | top: true,
118 | child: Image.memory(
119 | bitmap.buildHeaded(),
120 | ),
121 | ),
122 | const Text("Tap image to reset"),
123 | Text("ImageSize ${bitmap.width}"),
124 | ],
125 | );
126 | },
127 | ),
128 | ),
129 | ),
130 | floatingActionButton: Buttons(
131 | flipHImage: flipHImage,
132 | flipVImage: flipVImage,
133 | rotateClockwiseImage: rotateClockwiseImage,
134 | rotateCounterClockwiseImage: rotateCounterClockwiseImage,
135 | rotate180Image: rotate180Image,
136 | contrastImage: contrastImage,
137 | brightnessImage: brightnessImage,
138 | adjustColorImage: adjustColorImage,
139 | batchOperations: batchOperations,
140 | ), // This trailing comma makes auto-formatting nicer for build methods.
141 | );
142 | }
143 | }
144 |
145 | class Buttons extends StatelessWidget {
146 | const Buttons({
147 | Key? key,
148 | required this.flipHImage,
149 | required this.flipVImage,
150 | required this.rotateClockwiseImage,
151 | required this.rotateCounterClockwiseImage,
152 | required this.rotate180Image,
153 | required this.contrastImage,
154 | required this.brightnessImage,
155 | required this.adjustColorImage,
156 | required this.batchOperations,
157 | }) : super(key: key);
158 |
159 | final VoidCallback flipHImage;
160 | final VoidCallback flipVImage;
161 | final VoidCallback rotateClockwiseImage;
162 | final VoidCallback rotateCounterClockwiseImage;
163 | final VoidCallback rotate180Image;
164 | final VoidCallback contrastImage;
165 | final VoidCallback brightnessImage;
166 | final VoidCallback adjustColorImage;
167 | final VoidCallback batchOperations;
168 |
169 | @override
170 | Widget build(BuildContext context) {
171 | return Container(
172 | padding: const EdgeInsets.symmetric(horizontal: 20),
173 | child: Column(
174 | mainAxisAlignment: MainAxisAlignment.end,
175 | children: [
176 | Row(
177 | children: [
178 | TextButton(
179 | onPressed: flipHImage,
180 | child: const Text(
181 | "Flip horizontal",
182 | style: TextStyle(fontSize: 10),
183 | ),
184 | ),
185 | TextButton(
186 | onPressed: flipVImage,
187 | child: const Text(
188 | "Flip vertical",
189 | style: TextStyle(fontSize: 10),
190 | ),
191 | ),
192 | TextButton(
193 | onPressed: contrastImage,
194 | child: const Text(
195 | "Contrast +",
196 | style: TextStyle(fontSize: 10),
197 | ),
198 | ),
199 | ],
200 | ),
201 | Row(
202 | children: [
203 | TextButton(
204 | onPressed: brightnessImage,
205 | child: const Text(
206 | "Brightness +",
207 | style: TextStyle(fontSize: 10),
208 | ),
209 | ),
210 | TextButton(
211 | onPressed: adjustColorImage,
212 | child: const Text(
213 | "AdjustColor +",
214 | style: TextStyle(fontSize: 10),
215 | ),
216 | ),
217 | ],
218 | ),
219 | Row(
220 | children: [
221 | TextButton(
222 | onPressed: rotateClockwiseImage,
223 | child: const Text(
224 | "Rotate Clock +",
225 | style: TextStyle(fontSize: 10),
226 | ),
227 | ),
228 | TextButton(
229 | onPressed: rotateCounterClockwiseImage,
230 | child: const Text(
231 | "Rotate Clock -",
232 | style: TextStyle(fontSize: 10),
233 | ),
234 | ),
235 | TextButton(
236 | onPressed: rotate180Image,
237 | child: const Text(
238 | "Rotate 180",
239 | style: TextStyle(fontSize: 10),
240 | ),
241 | ),
242 | ],
243 | ),
244 | Row(
245 | children: [
246 | TextButton(
247 | onPressed: batchOperations,
248 | child: const Text(
249 | "Batch operations (saturation + crop)",
250 | style: TextStyle(fontSize: 10),
251 | ),
252 | ),
253 | ],
254 | ),
255 | ],
256 | ),
257 | );
258 | }
259 | }
260 |
261 | // stores headless contents
262 | class ImageValueNotifier extends ValueNotifier {
263 | ImageValueNotifier() : super(null);
264 |
265 | late Bitmap initial;
266 |
267 | void reset() {
268 | value = initial;
269 | }
270 |
271 | void loadImage() async {
272 | const ImageProvider imageProvider = const AssetImage("assets/street.jpg");
273 |
274 | value = await Bitmap.fromProvider(imageProvider);
275 | initial = value!;
276 | }
277 |
278 | void flipHImage() async {
279 | final temp = value!;
280 | value = null;
281 |
282 | final Uint8List converted = await compute(
283 | flipHImageIsolate,
284 | [temp.content, temp.width, temp.height],
285 | );
286 |
287 | value = Bitmap.fromHeadless(temp.width, temp.height, converted);
288 | }
289 |
290 | void flipVImage() async {
291 | final temp = value!;
292 | value = null;
293 |
294 | final converted = await compute(
295 | flipVImageIsolate,
296 | [temp.content, temp.width, temp.height],
297 | );
298 |
299 | value = Bitmap.fromHeadless(temp.width, temp.height, converted);
300 | }
301 |
302 | void rotateClockwiseImage() async {
303 | final temp = value!;
304 | value = null;
305 |
306 | final converted = await compute(
307 | rotateClockwiseImageIsolate,
308 | [temp.content, temp.width, temp.height],
309 | );
310 |
311 | value = Bitmap.fromHeadless(temp.height, temp.width, converted);
312 | }
313 |
314 | void rotateCounterClockwiseImage() async {
315 | final temp = value!;
316 | value = null;
317 |
318 | final converted = await compute(
319 | rotateCounterClockwiseImageIsolate,
320 | [temp.content, temp.width, temp.height],
321 | );
322 |
323 | value = Bitmap.fromHeadless(temp.height, temp.width, converted);
324 | }
325 |
326 | void rotate180Image() async {
327 | final temp = value!;
328 | value = null;
329 |
330 | final converted = await compute(
331 | rotate180ImageIsolate,
332 | [temp.content, temp.width, temp.height],
333 | );
334 |
335 | value = Bitmap.fromHeadless(temp.width, temp.height, converted);
336 | }
337 |
338 | void contrastImage() async {
339 | final temp = value!;
340 | value = null;
341 |
342 | final Uint8List converted = await compute(
343 | contrastImageIsolate,
344 | [temp.content, temp.width, temp.height],
345 | );
346 |
347 | value = Bitmap.fromHeadless(temp.width, temp.height, converted);
348 | }
349 |
350 | void brightnessImage() async {
351 | final temp = value!;
352 | value = null;
353 |
354 | final Uint8List converted = await compute(
355 | brightnessImageIsolate,
356 | [temp.content, temp.width, temp.height],
357 | );
358 |
359 | value = Bitmap.fromHeadless(temp.width, temp.height, converted);
360 | }
361 |
362 | void adjustColorImage() async {
363 | final temp = value!;
364 | value = null;
365 |
366 | final Uint8List converted = await compute(
367 | adjustColorsImageIsolate,
368 | [temp.content, temp.width, temp.height],
369 | );
370 |
371 | value = Bitmap.fromHeadless(temp.width, temp.height, converted);
372 | }
373 |
374 | void batchOperations() async {
375 | final temp = value!;
376 | value = null;
377 |
378 | final Uint8List converted = await compute(
379 | batchOperationsImageIsolate,
380 | [temp.content, temp.width, temp.height],
381 | );
382 |
383 | value = Bitmap.fromHeadless(temp.width - 20, temp.height - 20, converted);
384 | }
385 | }
386 |
387 | Future flipHImageIsolate(List imageData) async {
388 | final Uint8List byteData = imageData[0];
389 | final int width = imageData[1];
390 | final int height = imageData[2];
391 |
392 | final bigBitmap = Bitmap.fromHeadless(width, height, byteData);
393 | final returnBitmap = bigBitmap.apply(BitmapFlip.horizontal());
394 |
395 | return returnBitmap.content;
396 | }
397 |
398 | Future flipVImageIsolate(List imageData) async {
399 | final Uint8List byteData = imageData[0];
400 | final int width = imageData[1];
401 | final int height = imageData[2];
402 |
403 | final Bitmap bigBitmap = Bitmap.fromHeadless(width, height, byteData);
404 |
405 | final Bitmap returnBitmap = bigBitmap.apply(BitmapFlip.vertical());
406 |
407 | return returnBitmap.content;
408 | }
409 |
410 | Future rotateClockwiseImageIsolate(List imageData) async {
411 | final Uint8List byteData = imageData[0];
412 | final int width = imageData[1];
413 | final int height = imageData[2];
414 |
415 | final Bitmap bigBitmap = Bitmap.fromHeadless(width, height, byteData);
416 |
417 | final Bitmap returnBitmap = bigBitmap.apply(BitmapRotate.rotateClockwise());
418 |
419 | return returnBitmap.content;
420 | }
421 |
422 | Future rotateCounterClockwiseImageIsolate(List imageData) async {
423 | final Uint8List byteData = imageData[0];
424 | final int width = imageData[1];
425 | final int height = imageData[2];
426 |
427 | final Bitmap bigBitmap = Bitmap.fromHeadless(width, height, byteData);
428 |
429 | final Bitmap returnBitmap =
430 | bigBitmap.apply(BitmapRotate.rotateCounterClockwise());
431 |
432 | return returnBitmap.content;
433 | }
434 |
435 | Future rotate180ImageIsolate(List imageData) async {
436 | final Uint8List byteData = imageData[0];
437 | final int width = imageData[1];
438 | final int height = imageData[2];
439 |
440 | final Bitmap bigBitmap = Bitmap.fromHeadless(width, height, byteData);
441 |
442 | final Bitmap returnBitmap = bigBitmap.apply(BitmapRotate.rotate180());
443 |
444 | return returnBitmap.content;
445 | }
446 |
447 | Future contrastImageIsolate(List imageData) async {
448 | final Uint8List byteData = imageData[0];
449 | final int width = imageData[1];
450 | final int height = imageData[2];
451 |
452 | final Bitmap bigBitmap = Bitmap.fromHeadless(width, height, byteData);
453 |
454 | final returnBitmap = bigBitmap.apply(BitmapContrast(1.2));
455 |
456 | return returnBitmap.content;
457 | }
458 |
459 | Future brightnessImageIsolate(List imageData) async {
460 | final Uint8List byteData = imageData[0];
461 | final int width = imageData[1];
462 | final int height = imageData[2];
463 |
464 | final Bitmap bigBitmap = Bitmap.fromHeadless(width, height, byteData);
465 |
466 | final Bitmap returnBitmap = bigBitmap.apply(BitmapBrightness(0.1));
467 |
468 | return returnBitmap.content;
469 | }
470 |
471 | Future adjustColorsImageIsolate(List imageData) async {
472 | final Uint8List byteData = imageData[0];
473 | final int width = imageData[1];
474 | final int height = imageData[2];
475 |
476 | final Bitmap bigBitmap = Bitmap.fromHeadless(width, height, byteData);
477 |
478 | final Bitmap returnBitmap = bigBitmap.apply(
479 | BitmapAdjustColor(
480 | blacks: 0x00000000,
481 | saturation: 1.9, // 0 and 5 mid 1.0
482 | ),
483 | );
484 |
485 | return returnBitmap.content;
486 | }
487 |
488 | Future batchOperationsImageIsolate(List imageData) async {
489 | final Uint8List byteData = imageData[0];
490 | final int width = imageData[1];
491 | final int height = imageData[2];
492 |
493 | final Bitmap bigBitmap = Bitmap.fromHeadless(width, height, byteData);
494 |
495 | final Bitmap returnBitmap = bigBitmap.applyBatch([
496 | BitmapAdjustColor(
497 | saturation: 1.9,
498 | ),
499 | BitmapCrop.fromLTWH(
500 | left: 10,
501 | top: 10,
502 | width: width - 20,
503 | height: height - 20,
504 | ),
505 | ]);
506 |
507 | return returnBitmap.content;
508 | }
509 |
--------------------------------------------------------------------------------
/example/pubspec.lock:
--------------------------------------------------------------------------------
1 | # Generated by pub
2 | # See https://dart.dev/tools/pub/glossary#lockfile
3 | packages:
4 | async:
5 | dependency: transitive
6 | description:
7 | name: async
8 | sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
9 | url: "https://pub.dev"
10 | source: hosted
11 | version: "2.11.0"
12 | bitmap:
13 | dependency: "direct dev"
14 | description:
15 | path: ".."
16 | relative: true
17 | source: path
18 | version: "0.2.0"
19 | boolean_selector:
20 | dependency: transitive
21 | description:
22 | name: boolean_selector
23 | sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
24 | url: "https://pub.dev"
25 | source: hosted
26 | version: "2.1.1"
27 | characters:
28 | dependency: transitive
29 | description:
30 | name: characters
31 | sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
32 | url: "https://pub.dev"
33 | source: hosted
34 | version: "1.3.0"
35 | clock:
36 | dependency: transitive
37 | description:
38 | name: clock
39 | sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
40 | url: "https://pub.dev"
41 | source: hosted
42 | version: "1.1.1"
43 | collection:
44 | dependency: transitive
45 | description:
46 | name: collection
47 | sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
48 | url: "https://pub.dev"
49 | source: hosted
50 | version: "1.18.0"
51 | cupertino_icons:
52 | dependency: "direct main"
53 | description:
54 | name: cupertino_icons
55 | sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d
56 | url: "https://pub.dev"
57 | source: hosted
58 | version: "1.0.6"
59 | fake_async:
60 | dependency: transitive
61 | description:
62 | name: fake_async
63 | sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
64 | url: "https://pub.dev"
65 | source: hosted
66 | version: "1.3.1"
67 | ffi:
68 | dependency: transitive
69 | description:
70 | name: ffi
71 | sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878"
72 | url: "https://pub.dev"
73 | source: hosted
74 | version: "2.1.0"
75 | flutter:
76 | dependency: "direct main"
77 | description: flutter
78 | source: sdk
79 | version: "0.0.0"
80 | flutter_test:
81 | dependency: "direct dev"
82 | description: flutter
83 | source: sdk
84 | version: "0.0.0"
85 | matcher:
86 | dependency: transitive
87 | description:
88 | name: matcher
89 | sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
90 | url: "https://pub.dev"
91 | source: hosted
92 | version: "0.12.16"
93 | material_color_utilities:
94 | dependency: transitive
95 | description:
96 | name: material_color_utilities
97 | sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
98 | url: "https://pub.dev"
99 | source: hosted
100 | version: "0.5.0"
101 | meta:
102 | dependency: transitive
103 | description:
104 | name: meta
105 | sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e
106 | url: "https://pub.dev"
107 | source: hosted
108 | version: "1.10.0"
109 | path:
110 | dependency: transitive
111 | description:
112 | name: path
113 | sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
114 | url: "https://pub.dev"
115 | source: hosted
116 | version: "1.8.3"
117 | sky_engine:
118 | dependency: transitive
119 | description: flutter
120 | source: sdk
121 | version: "0.0.99"
122 | source_span:
123 | dependency: transitive
124 | description:
125 | name: source_span
126 | sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
127 | url: "https://pub.dev"
128 | source: hosted
129 | version: "1.10.0"
130 | stack_trace:
131 | dependency: transitive
132 | description:
133 | name: stack_trace
134 | sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
135 | url: "https://pub.dev"
136 | source: hosted
137 | version: "1.11.1"
138 | stream_channel:
139 | dependency: transitive
140 | description:
141 | name: stream_channel
142 | sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
143 | url: "https://pub.dev"
144 | source: hosted
145 | version: "2.1.2"
146 | string_scanner:
147 | dependency: transitive
148 | description:
149 | name: string_scanner
150 | sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
151 | url: "https://pub.dev"
152 | source: hosted
153 | version: "1.2.0"
154 | term_glyph:
155 | dependency: transitive
156 | description:
157 | name: term_glyph
158 | sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
159 | url: "https://pub.dev"
160 | source: hosted
161 | version: "1.2.1"
162 | test_api:
163 | dependency: transitive
164 | description:
165 | name: test_api
166 | sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
167 | url: "https://pub.dev"
168 | source: hosted
169 | version: "0.6.1"
170 | vector_math:
171 | dependency: transitive
172 | description:
173 | name: vector_math
174 | sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
175 | url: "https://pub.dev"
176 | source: hosted
177 | version: "2.1.4"
178 | web:
179 | dependency: transitive
180 | description:
181 | name: web
182 | sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152
183 | url: "https://pub.dev"
184 | source: hosted
185 | version: "0.3.0"
186 | sdks:
187 | dart: ">=3.2.0-194.0.dev <4.0.0"
188 | flutter: ">=3.13.9"
189 |
--------------------------------------------------------------------------------
/example/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: bitmap_example
2 | description: Demonstrates how to use the bitmap plugin.
3 | publish_to: 'none'
4 |
5 | environment:
6 | sdk: ">=3.0.3 <4.0.0"
7 | flutter: ">=3.13.9 <4.0.0"
8 |
9 | dependencies:
10 | flutter:
11 | sdk: flutter
12 |
13 | cupertino_icons: ^1.0.6
14 |
15 | dev_dependencies:
16 | flutter_test:
17 | sdk: flutter
18 | bitmap:
19 | path: ../
20 |
21 | flutter:
22 | uses-material-design: true
23 | assets:
24 | - assets/doggo.jpeg
25 | - assets/street.jpg
26 |
--------------------------------------------------------------------------------
/example/test/widget_test.dart:
--------------------------------------------------------------------------------
1 | // This is a basic Flutter widget test.
2 | //
3 | // To perform an interaction with a widget in your test, use the WidgetTester
4 | // utility that Flutter provides. For example, you can send tap and scroll
5 | // gestures. You can also use WidgetTester to find child widgets in the widget
6 | // tree, read text, and verify that the values of widget properties are correct.
7 |
8 | import 'package:flutter/material.dart';
9 | import 'package:flutter_test/flutter_test.dart';
10 |
11 | import 'package:bitmap_example/main.dart';
12 |
13 | void main() {
14 | testWidgets('Verify Platform version', (WidgetTester tester) async {
15 | // Build our app and trigger a frame.
16 | await tester.pumpWidget(MyApp());
17 |
18 | // Verify that platform version is retrieved.
19 | expect(
20 | find.byWidgetPredicate(
21 | (Widget widget) =>
22 | widget is Text && widget.data!.startsWith('Running on:'),
23 | ),
24 | findsOneWidget,
25 | );
26 | });
27 | }
28 |
--------------------------------------------------------------------------------
/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 | /Flutter/ephemeral/
38 | /Flutter/flutter_export_environment.sh
--------------------------------------------------------------------------------
/ios/Assets/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bluefireteam/bitmap/6eb13d4980bd53a9b0de4eca178c60809bce3b5d/ios/Assets/.gitkeep
--------------------------------------------------------------------------------
/ios/Classes/BitmapPlugin.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | @interface BitmapPlugin : NSObject
4 | @end
5 |
--------------------------------------------------------------------------------
/ios/Classes/BitmapPlugin.m:
--------------------------------------------------------------------------------
1 | #import "BitmapPlugin.h"
2 | #if __has_include()
3 | #import
4 | #else
5 | // Support project import fallback if the generated compatibility header
6 | // is not copied when this plugin is created as a library.
7 | // https://forums.swift.org/t/swift-static-libraries-dont-copy-generated-objective-c-header/19816
8 | #import "bitmap-Swift.h"
9 | #endif
10 |
11 | @implementation BitmapPlugin
12 | + (void)registerWithRegistrar:(NSObject*)registrar {
13 | [SwiftBitmapPlugin registerWithRegistrar:registrar];
14 | }
15 | @end
16 |
--------------------------------------------------------------------------------
/ios/Classes/SwiftBitmapPlugin.swift:
--------------------------------------------------------------------------------
1 | import Flutter
2 | import UIKit
3 |
4 | public class SwiftBitmapPlugin: NSObject, FlutterPlugin {
5 | public static func register(with registrar: FlutterPluginRegistrar) {
6 | let channel = FlutterMethodChannel(name: "bitmap", binaryMessenger: registrar.messenger())
7 | let instance = SwiftBitmapPlugin()
8 | registrar.addMethodCallDelegate(instance, channel: channel)
9 | }
10 |
11 | public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
12 | result("iOS " + UIDevice.current.systemVersion)
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/ios/Classes/bitmap.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | int get_red(uint64_t color) { return (color) & 0xff; }
6 | int get_green(uint64_t color) { return (color >> 8) & 0xff; }
7 | int get_blue(uint64_t color) { return (color >> 16) & 0xff; }
8 | int get_alpha(uint64_t color) { return (color >> 24) & 0xff; }
9 |
10 | int clamp255_0(int before) {
11 | if(before > 255) return 255;
12 | if(before < 0) return 0;
13 | return before;
14 | }
15 |
16 | int clamp255_n255(int before) {
17 | if(before > 255) return 255;
18 | if(before < -255) return -255;
19 | return before;
20 | }
21 |
22 | /**
23 | * Brightness
24 | * Receives a bitmap, its length and a brightness amount valuating between -255 and 255
25 | */
26 | extern "C" __attribute__((visibility("default"))) __attribute__((used))
27 | void brightness(uint8_t *starting_pointer, int bitmap_length, int brightness_amount) {
28 | for (int i = 0; i < bitmap_length; i += 4) {
29 | uint8_t *r = starting_pointer + i;
30 | uint8_t *g = starting_pointer + i + 1;
31 | uint8_t *b = starting_pointer + i + 2;
32 | uint8_t *a = starting_pointer + i + 3;
33 |
34 | *r = clamp255_0(*r + brightness_amount);
35 | *g = clamp255_0(*g + brightness_amount);
36 | *b = clamp255_0(*b + brightness_amount);
37 | }
38 | return;
39 | }
40 |
41 | /**
42 | * Contrast
43 | * Receives a bitmap, its length and a contrast rate greater than 0
44 | */
45 | extern "C" __attribute__((visibility("default"))) __attribute__((used))
46 | void contrast(uint8_t *starting_pointer, int bitmap_length, double contrast_rate) {
47 | double contrast_sqare = contrast_rate * contrast_rate;
48 | uint8_t contrast_applier[256];
49 | for (int i = 0; i < 256; ++i) {
50 | contrast_applier[i] = clamp255_0(floor(((((i / 255.0) - 0.5) * contrast_sqare) + 0.5) * 255.0));
51 | }
52 |
53 | for (int i = 0; i < bitmap_length; i += 4) {
54 | uint8_t *r = starting_pointer + i;
55 | uint8_t *g = starting_pointer + i + 1;
56 | uint8_t *b = starting_pointer + i + 2;
57 | uint8_t *a = starting_pointer + i + 3;
58 |
59 | *r = contrast_applier[*r];
60 | *g = contrast_applier[*g];
61 | *b = contrast_applier[*b];
62 | }
63 | return;
64 | }
65 |
66 | /**
67 | * Adjust color
68 | * Receives a lot of stuff
69 | */
70 | extern "C" __attribute__((visibility("default"))) __attribute__((used))
71 | void adjust_color(
72 | uint8_t *starting_pointer,
73 | int bitmap_length,
74 |
75 | uint64_t blacks,
76 | uint64_t whites,
77 | double saturation,
78 | double exposure,
79 |
80 | int compute_blacks,
81 | int compute_whites
82 | ) {
83 | // constants
84 | double DEG_TO_RAD = 0.0174532925;
85 |
86 | double LUM_COEFF_R = 0.2125;
87 | double LUM_COEFF_G = 0.7154;
88 | double LUM_COEFF_B = 0.0721;
89 |
90 | // prepare exposure
91 | if (exposure != 0.0) {
92 | exposure = pow(2, exposure);
93 | }
94 |
95 | // prepare saturation
96 | double inv_saturation = 1 - saturation;
97 |
98 | /// prepare whites and blacks
99 | double br, bg, bb;
100 | double wr, wg, wb;
101 | if (compute_blacks || compute_whites) {
102 | br = compute_blacks ? get_red(blacks) / 255.0 : 0.0;
103 | bg = compute_blacks ? get_green(blacks) / 255.0 : 0.0;
104 | bb = compute_blacks ? get_blue(blacks) / 255.0 : 0.0;
105 |
106 | wr = compute_whites ? get_red(whites) / 255.0 : 1.0;
107 | wg = compute_whites ? get_green(whites) / 255.0 : 1.0;
108 | wb = compute_whites ? get_blue(whites) / 255.0 : 1.0;
109 | }
110 |
111 | for (int i = 0; i < bitmap_length; i += 4) {
112 | uint8_t *r = starting_pointer + i;
113 | uint8_t *g = starting_pointer + i + 1;
114 | uint8_t *b = starting_pointer + i + 2;
115 |
116 |
117 | double r_rep = *r / 255.0;
118 | double g_rep = *g / 255.0;
119 | double b_rep = *b / 255.0;
120 |
121 | if (compute_blacks) {
122 | r_rep = (r_rep + br) * wr;
123 | g_rep = (g_rep + bg) * wg;
124 | b_rep = (b_rep + bb) * wb;
125 | }
126 |
127 | // saturation
128 | double lum = r_rep * LUM_COEFF_R + g_rep * LUM_COEFF_G + b_rep * LUM_COEFF_B;
129 |
130 | r_rep = lum * inv_saturation + r_rep * saturation;
131 | g_rep = lum * inv_saturation + g_rep * saturation;
132 | b_rep = lum * inv_saturation + b_rep * saturation;
133 |
134 | /// exposure
135 | if (exposure != 0.0) {
136 | r_rep = r_rep * exposure;
137 | g_rep = g_rep * exposure;
138 | b_rep = b_rep * exposure;
139 | }
140 |
141 | *r = clamp255_0(floor(r_rep * 255));
142 | *g = clamp255_0(floor(g_rep * 255));
143 | *b = clamp255_0(floor(b_rep * 255));
144 |
145 | }
146 | return;
147 | }
148 |
149 | /**
150 | * RGB overlay
151 | * Receives a RGB color and an overlay intensity (scale parameter)
152 | */
153 | extern "C" __attribute__((visibility("default"))) __attribute__((used))
154 | void rgb_overlay(
155 | uint8_t *starting_pointer,
156 | int bitmap_length,
157 | double red,
158 | double green,
159 | double blue,
160 | double scale
161 | ) {
162 | for(int i = 0; i < bitmap_length; i += 4) {
163 | uint8_t *r = starting_pointer + i;
164 | uint8_t *g = starting_pointer + i + 1;
165 | uint8_t *b = starting_pointer + i + 2;
166 |
167 | *r = clamp255_0(round((*r - (*r - red) * scale)));
168 | *g = clamp255_0(round((*g - (*g - green) * scale)));
169 | *b = clamp255_0(round((*b - (*b - blue) * scale)));
170 | }
171 |
172 | return;
173 | }
--------------------------------------------------------------------------------
/ios/bitmap.podspec:
--------------------------------------------------------------------------------
1 | #
2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
3 | # Run `pod lib lint bitmap.podspec` to validate before publishing.
4 | #
5 | Pod::Spec.new do |s|
6 | s.name = 'bitmap'
7 | s.version = '0.0.1'
8 | s.summary = 'A new flutter plugin project.'
9 | s.description = <<-DESC
10 | A new flutter plugin project.
11 | DESC
12 | s.homepage = 'http://example.com'
13 | s.license = { :file => '../LICENSE' }
14 | s.author = { 'Your Company' => 'email@example.com' }
15 | s.source = { :path => '.' }
16 | s.source_files = 'Classes/**/*'
17 | s.dependency 'Flutter'
18 | s.platform = :ios, '8.0'
19 |
20 | # Flutter.framework does not contain a i386 slice.
21 | s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }
22 | s.swift_version = '5.0'
23 | end
24 |
--------------------------------------------------------------------------------
/lib/bitmap_flutter.dart:
--------------------------------------------------------------------------------
1 | library bitmap;
2 |
3 | export 'src/bitmap.dart';
4 | export 'src/ffi.dart';
5 | export 'src/operation/operation.dart';
6 |
--------------------------------------------------------------------------------
/lib/src/bitmap.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 | import 'dart:typed_data';
3 | import 'dart:ui' as ui;
4 |
5 | import 'package:flutter/rendering.dart';
6 |
7 | import 'operation/operation.dart';
8 |
9 | class Bitmap {
10 | Bitmap.fromHeadless(this.width, this.height, this.content);
11 |
12 | Bitmap.fromHeadful(this.width, this.height, Uint8List headedIntList)
13 | : content = headedIntList.sublist(
14 | RGBA32BitmapHeader.RGBA32HeaderSize,
15 | headedIntList.length,
16 | );
17 |
18 | Bitmap.blank(
19 | this.width,
20 | this.height,
21 | ) : content = Uint8List.fromList(
22 | List.filled(width * height * RGBA32BitmapHeader.pixelLength, 0),
23 | );
24 |
25 | /// The width in pixels of the image.
26 | final int width;
27 |
28 | /// The width in pixels of the image.
29 | final int height;
30 |
31 | /// A [Uint8List] of bytes in a RGBA format.
32 | final Uint8List content;
33 |
34 | int get size => (width * height) * RGBA32BitmapHeader.pixelLength;
35 |
36 | // Creates a new instance of bitmap
37 | Bitmap cloneHeadless() {
38 | return Bitmap.fromHeadless(
39 | width,
40 | height,
41 | Uint8List.fromList(content),
42 | );
43 | }
44 |
45 | static Future fromProvider(ImageProvider provider) async {
46 | final Completer completer = Completer();
47 | final ImageStream stream = provider.resolve(const ImageConfiguration());
48 | final listener = ImageStreamListener(
49 | (ImageInfo info, bool synchronousCall) {
50 | if (!completer.isCompleted) {
51 | completer.complete(info);
52 | }
53 | },
54 | );
55 | stream.addListener(listener);
56 | final imageInfo = await completer.future;
57 | final ui.Image image = imageInfo.image;
58 | final ByteData? byteData = await image.toByteData();
59 | if (byteData == null) {
60 | throw StateError("Couldn't serialize image into bytes");
61 | }
62 |
63 | final Uint8List listInt = byteData.buffer.asUint8List();
64 |
65 | return Bitmap.fromHeadless(image.width, image.height, listInt);
66 | }
67 |
68 | Future buildImage() async {
69 | final Completer imageCompleter = Completer();
70 | final headedContent = buildHeaded();
71 | ui.decodeImageFromList(headedContent, (ui.Image img) {
72 | imageCompleter.complete(img);
73 | });
74 | return imageCompleter.future;
75 | }
76 |
77 | Uint8List buildHeaded() {
78 | final header = RGBA32BitmapHeader(size, width, height)
79 | ..applyContent(content);
80 | return header.headerIntList;
81 | }
82 |
83 | Bitmap apply(BitmapOperation operation) {
84 | return operation.applyTo(this);
85 | }
86 |
87 | Bitmap applyBatch(List operations) {
88 | Bitmap result = this;
89 | for (final operation in operations) {
90 | result = operation.applyTo(result);
91 | }
92 | return result;
93 | }
94 |
95 | @override
96 | bool operator ==(Object other) =>
97 | identical(this, other) ||
98 | other is Bitmap &&
99 | runtimeType == other.runtimeType &&
100 | width == other.width &&
101 | height == other.height &&
102 | content == other.content;
103 |
104 | @override
105 | int get hashCode => width.hashCode ^ height.hashCode ^ content.hashCode;
106 | }
107 |
108 | class RGBA32BitmapHeader {
109 | static const int pixelLength = 4;
110 | static const int RGBA32HeaderSize = 122;
111 |
112 | RGBA32BitmapHeader(this.contentSize, int width, int height) {
113 | headerIntList = Uint8List(fileLength);
114 |
115 | final ByteData bd = headerIntList.buffer.asByteData();
116 | bd.setUint8(0x0, 0x42);
117 | bd.setUint8(0x1, 0x4d);
118 | bd.setInt32(0x2, fileLength, Endian.little);
119 | bd.setInt32(0xa, RGBA32HeaderSize, Endian.little);
120 | bd.setUint32(0xe, 108, Endian.little);
121 | bd.setUint32(0x12, width, Endian.little);
122 | bd.setUint32(0x16, -height, Endian.little);
123 | bd.setUint16(0x1a, 1, Endian.little);
124 | bd.setUint32(0x1c, 32, Endian.little); // pixel size
125 | bd.setUint32(0x1e, 3, Endian.little); //BI_BITFIELDS
126 | bd.setUint32(0x22, contentSize, Endian.little);
127 | bd.setUint32(0x36, 0x000000ff, Endian.little);
128 | bd.setUint32(0x3a, 0x0000ff00, Endian.little);
129 | bd.setUint32(0x3e, 0x00ff0000, Endian.little);
130 | bd.setUint32(0x42, 0xff000000, Endian.little);
131 | }
132 |
133 | int contentSize;
134 |
135 | void applyContent(Uint8List contentIntList) {
136 | headerIntList.setRange(
137 | RGBA32HeaderSize,
138 | fileLength,
139 | contentIntList,
140 | );
141 | }
142 |
143 | late Uint8List headerIntList;
144 |
145 | int get fileLength => contentSize + RGBA32HeaderSize;
146 | }
147 |
--------------------------------------------------------------------------------
/lib/src/ffi.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ffi' as ffi;
2 |
3 | import 'dart:io';
4 |
5 | import 'dart:typed_data' as typed; // For Platform.isX
6 | import 'package:ffi/ffi.dart' as ext_ffi;
7 |
8 | final ffi.DynamicLibrary bitmapFFILib = Platform.isAndroid
9 | ? ffi.DynamicLibrary.open("libbitmap.so")
10 | : ffi.DynamicLibrary.process();
11 |
12 | typedef BitmapFFIExecution = void Function(
13 | ffi.Pointer startingPointer,
14 | typed.Uint8List pointerList,
15 | );
16 |
17 | class FFIImpl {
18 | FFIImpl(this.ffiExecution);
19 |
20 | final BitmapFFIExecution ffiExecution;
21 |
22 | void execute(typed.Uint8List sourceBmp) {
23 | final ffi.Pointer startingPointer = ext_ffi.calloc(
24 | sourceBmp.length,
25 | );
26 | final pointerList = startingPointer.asTypedList(sourceBmp.length);
27 | pointerList.setAll(0, sourceBmp);
28 | ffiExecution(startingPointer, pointerList);
29 | sourceBmp.setAll(0, pointerList);
30 |
31 | ext_ffi.calloc.free(startingPointer);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/lib/src/operation/adjust_color.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ffi' as ffi;
2 | import 'dart:typed_data';
3 |
4 | import '../bitmap.dart';
5 | import '../ffi.dart';
6 | import 'operation.dart';
7 |
8 | // *** FFi C++ bindings ***
9 | const _nativeFunctionName = "adjust_color";
10 |
11 | typedef _NativeSideFunction = ffi.Void Function(
12 | ffi.Pointer,
13 | ffi.Int32,
14 | ffi.Uint64,
15 | ffi.Uint64,
16 | ffi.Double,
17 | ffi.Double,
18 | ffi.Int32,
19 | ffi.Int32,
20 | );
21 |
22 | typedef _DartSideFunction = void Function(
23 | ffi.Pointer startingPointer,
24 | int bitmapLength,
25 | int blacks,
26 | int whites,
27 | double saturation,
28 | double exposure,
29 | int computeBlacks,
30 | int computeWhites,
31 | );
32 |
33 | _DartSideFunction _adjustColorFFIImpl = bitmapFFILib
34 | .lookup>(_nativeFunctionName)
35 | .asFunction();
36 |
37 | /// Adjusts a lot of stuff of color
38 | class BitmapAdjustColor implements BitmapOperation {
39 | BitmapAdjustColor({
40 | this.blacks,
41 | this.whites,
42 | this.exposure,
43 | this.saturation,
44 | });
45 |
46 | static const DEG_TO_RAD = 0.0174532925;
47 | static const lumCoeffR = 0.2125;
48 | static const lumCoeffG = 0.7154;
49 | static const lumCoeffB = 0.0721;
50 |
51 | /// Enhancement factor of the dark parts of an image
52 | int? blacks;
53 |
54 | /// Enhancement factor of the light parts of an image
55 | int? whites;
56 |
57 | /// Defines the saturation to be adjusted in an image
58 | double? saturation;
59 |
60 | /// Enhancement factor of the dark parts of an image
61 | double? exposure;
62 |
63 | @override
64 | Bitmap applyTo(Bitmap bitmap) {
65 | final Bitmap copy = bitmap.cloneHeadless();
66 | _adjustColorCore(
67 | copy.content,
68 | );
69 | return copy;
70 | }
71 |
72 | void _adjustColorCore(Uint8List sourceBmp) {
73 | if ((exposure == null || exposure == 0.0) &&
74 | (blacks == null || blacks == 0) &&
75 | (whites == null || whites == 0x00FFFFFF) &&
76 | saturation == null) {
77 | return;
78 | }
79 |
80 | final size = sourceBmp.length;
81 |
82 | final exposureNonNull = exposure ?? 0.0;
83 | final saturationNonNull = saturation ?? 1.0;
84 |
85 | final computeBlacks = (blacks != null && blacks != 0) ? 1 : 0;
86 | final computeWhites = (whites != null && whites != 0x00FFFFFF) ? 1 : 0;
87 |
88 | final blacksNonNull = blacks ?? 0;
89 | final whitesNonNull = whites ?? 0;
90 |
91 | // start native execution
92 | FFIImpl((startingPointer, pointerList) {
93 | _adjustColorFFIImpl(
94 | startingPointer,
95 | size,
96 | blacksNonNull,
97 | whitesNonNull,
98 | saturationNonNull,
99 | exposureNonNull,
100 | computeBlacks,
101 | computeWhites,
102 | );
103 | }).execute(sourceBmp);
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/lib/src/operation/brightness.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ffi' as ffi;
2 | import 'dart:typed_data';
3 |
4 | import '../bitmap.dart';
5 | import '../ffi.dart';
6 | import 'operation.dart';
7 |
8 | // *** FFi C++ bindings ***
9 | const _nativeFunctionName = "brightness";
10 |
11 | typedef _NativeSideFunction = ffi.Void Function(
12 | ffi.Pointer,
13 | ffi.Int32,
14 | ffi.Int32,
15 | );
16 |
17 | typedef _DartSideFunction = void Function(
18 | ffi.Pointer startingPointer,
19 | int bitmapLength,
20 | int brightnessAmount,
21 | );
22 |
23 | _DartSideFunction _brightnessFFIImpl = bitmapFFILib
24 | .lookup>(_nativeFunctionName)
25 | .asFunction();
26 |
27 | /// Changes brightness of [sourceBmp] accordingly to [brightnessRate] .
28 | ///
29 | /// [brightnessRate] Can be between -1.0 and 1.0. 0.0 does nothing;
30 | class BitmapBrightness implements BitmapOperation {
31 | BitmapBrightness(double brightnessFactor)
32 | : brightnessFactor = brightnessFactor.clamp(-1.0, 1.0);
33 |
34 | final double brightnessFactor;
35 |
36 | @override
37 | Bitmap applyTo(Bitmap bitmap) {
38 | final Bitmap copy = bitmap.cloneHeadless();
39 | _brightnessCore(copy.content, brightnessFactor);
40 | return copy;
41 | }
42 |
43 | void _brightnessCore(Uint8List sourceBmp, double brightnessRate) {
44 | assert(brightnessRate >= -1.0 && brightnessRate <= 1.0);
45 |
46 | if (brightnessRate == 0.0) {
47 | return;
48 | }
49 |
50 | final brightnessAmount = (brightnessRate * 255).floor();
51 | final size = sourceBmp.length;
52 |
53 | // start native execution
54 | FFIImpl((startingPointer, pointerList) {
55 | _brightnessFFIImpl(startingPointer, size, brightnessAmount);
56 | }).execute(sourceBmp);
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/lib/src/operation/contrast.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ffi' as ffi;
2 | import 'dart:typed_data';
3 |
4 | import '../bitmap.dart';
5 | import '../ffi.dart';
6 | import 'operation.dart';
7 |
8 | // *** FFi C++ bindings ***
9 | const _nativeFunctionName = "contrast";
10 |
11 | typedef _NativeSideFunction = ffi.Void Function(
12 | ffi.Pointer,
13 | ffi.Int32,
14 | ffi.Double,
15 | );
16 |
17 | typedef _DartSideFunction = void Function(
18 | ffi.Pointer startingPointer,
19 | int bitmapLength,
20 | double contrastRate,
21 | );
22 |
23 | _DartSideFunction _contrastFFIImpl = bitmapFFILib
24 | .lookup>(_nativeFunctionName)
25 | .asFunction();
26 |
27 | /// Sets a contrast of in image given [contrastFactor].
28 | class BitmapContrast implements BitmapOperation {
29 | BitmapContrast(this.contrastFactor) : assert(contrastFactor >= 0.0);
30 |
31 | double contrastFactor;
32 |
33 | @override
34 | Bitmap applyTo(Bitmap bitmap) {
35 | final Bitmap copy = bitmap.cloneHeadless();
36 | _contrastCore(copy.content, contrastFactor);
37 | return copy;
38 | }
39 |
40 | void _contrastCore(Uint8List sourceBmp, double contrastRate) {
41 | assert(contrastRate >= 0.0);
42 | final size = sourceBmp.length;
43 | FFIImpl((startingPointer, pointerList) {
44 | _contrastFFIImpl(startingPointer, size, contrastRate);
45 | }).execute(sourceBmp);
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/lib/src/operation/crop.dart:
--------------------------------------------------------------------------------
1 | import 'dart:typed_data';
2 |
3 | import '../bitmap.dart';
4 | import 'operation.dart';
5 |
6 | /// Crops the source bitmap to rectangle defined by [top], [left], [width] and [height].
7 | class BitmapCrop extends BitmapOperation {
8 | /// Crops the source bitmap to rectangle defined by top, left, width and height.
9 | BitmapCrop.fromLTWH({
10 | required this.left,
11 | required this.top,
12 | required this.width,
13 | required this.height,
14 | }) : assert(left >= 0),
15 | assert(top >= 0),
16 | assert(width > 0),
17 | assert(height > 0);
18 |
19 | BitmapCrop.fromLTRB({
20 | required this.left,
21 | required this.top,
22 | required int right,
23 | required int bottom,
24 | }) : width = right - left,
25 | height = bottom - top;
26 |
27 | int left;
28 | int top;
29 | int width;
30 | int height;
31 |
32 | @override
33 | Bitmap applyTo(Bitmap bitmap) {
34 | assert(left + width <= bitmap.width);
35 | assert(top + height <= bitmap.height);
36 |
37 | final int newBitmapSize = width * height * RGBA32BitmapHeader.pixelLength;
38 |
39 | final Bitmap cropped = Bitmap.fromHeadless(
40 | width,
41 | height,
42 | Uint8List(newBitmapSize),
43 | );
44 |
45 | _cropCore(
46 | bitmap.content,
47 | cropped.content,
48 | bitmap.width,
49 | // Height is not needed.
50 | left,
51 | top,
52 | width,
53 | height,
54 | );
55 |
56 | return cropped;
57 | }
58 |
59 | void _cropCore(
60 | Uint8List sourceBmp,
61 | Uint8List destBmp,
62 | int sourceWidth,
63 | int left,
64 | int top,
65 | int width,
66 | int height,
67 | ) {
68 | const pixelLength = RGBA32BitmapHeader.pixelLength;
69 |
70 | for (int x = left * pixelLength; x < (left + width) * pixelLength; x++) {
71 | for (int y = top; y < (top + height); y++) {
72 | destBmp[x - left * pixelLength + (y - top) * width * pixelLength] =
73 | sourceBmp[x + y * sourceWidth * pixelLength];
74 | }
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/lib/src/operation/flip.dart:
--------------------------------------------------------------------------------
1 | import 'dart:typed_data';
2 | import '../bitmap.dart';
3 | import 'operation.dart';
4 |
5 | class BitmapFlip implements BitmapOperation {
6 | final _Flip _flip;
7 |
8 | BitmapFlip.vertical() : _flip = _VerticalFlip();
9 |
10 | BitmapFlip.horizontal() : _flip = _HorizontalFlip();
11 |
12 | @override
13 | Bitmap applyTo(Bitmap bitmap) {
14 | return _flip.flip(bitmap);
15 | }
16 | }
17 |
18 | abstract class _Flip {
19 | Bitmap flip(Bitmap bitmap);
20 | }
21 |
22 | class _VerticalFlip implements _Flip {
23 | @override
24 | Bitmap flip(Bitmap bitmap) {
25 | final Bitmap copy = bitmap.cloneHeadless();
26 | final width = bitmap.width;
27 | final height = bitmap.height;
28 | final Uint8List copyContent = copy.content;
29 |
30 | _verticalFlipCore(copyContent, width, height);
31 |
32 | return copy;
33 | }
34 |
35 | void _verticalFlipCore(Uint8List bmp, int width, int height) {
36 | const pixelLength = RGBA32BitmapHeader.pixelLength;
37 |
38 | final int lineLength = width * pixelLength;
39 | final int halfHeight = height ~/ 2;
40 |
41 | for (int line = 0; line < halfHeight; line++) {
42 | final int startOfLine = line * lineLength;
43 | final int startOfOppositeLine = (height - 1 - line) * lineLength;
44 | for (int column = 0; column < width; column++) {
45 | final int pixelStart = startOfLine + column * pixelLength;
46 | final int pixelEnd = pixelStart + pixelLength;
47 |
48 | final int oppositePixelStart =
49 | startOfOppositeLine + column * pixelLength;
50 | final int oppositePixelEnd = oppositePixelStart + pixelLength;
51 |
52 | final Uint8List oppositePixel = bmp.sublist(
53 | oppositePixelStart,
54 | oppositePixelEnd,
55 | );
56 | final Uint8List targetPixel = bmp.sublist(pixelStart, pixelEnd);
57 |
58 | bmp.setRange(oppositePixelStart, oppositePixelEnd, targetPixel);
59 | bmp.setRange(pixelStart, pixelEnd, oppositePixel);
60 | }
61 | }
62 | }
63 | }
64 |
65 | class _HorizontalFlip implements _Flip {
66 | @override
67 | Bitmap flip(Bitmap bitmap) {
68 | final Bitmap copy = bitmap.cloneHeadless();
69 | final width = bitmap.width;
70 | final height = bitmap.height;
71 | final Uint8List copyContent = copy.content;
72 |
73 | _horizontalFlipCore(copyContent, width, height);
74 |
75 | return copy;
76 | }
77 |
78 | void _horizontalFlipCore(Uint8List bmp, int width, int height) {
79 | const pixelLength = RGBA32BitmapHeader.pixelLength;
80 |
81 | final int lineLength = width * pixelLength;
82 | final int halfLine = lineLength ~/ 2;
83 |
84 | for (int line = 0; line < height; line++) {
85 | final int startOfLine = line * lineLength;
86 | for (int relativeColumnStart = 0;
87 | relativeColumnStart < halfLine;
88 | relativeColumnStart += pixelLength) {
89 | final int pixelStart = startOfLine + relativeColumnStart;
90 | final int pixelEnd = pixelStart + pixelLength;
91 |
92 | final int relativeOppositePixelStart =
93 | lineLength - relativeColumnStart - pixelLength;
94 | final int oppositePixelStart = startOfLine + relativeOppositePixelStart;
95 | final int oppositePixelEnd = oppositePixelStart + pixelLength;
96 |
97 | final Uint8List oppositePixel = bmp.sublist(
98 | oppositePixelStart,
99 | oppositePixelEnd,
100 | );
101 | final Uint8List targetPixel = bmp.sublist(pixelStart, pixelEnd);
102 |
103 | bmp.setRange(oppositePixelStart, oppositePixelEnd, targetPixel);
104 | bmp.setRange(pixelStart, pixelEnd, oppositePixel);
105 | }
106 | }
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/lib/src/operation/operation.dart:
--------------------------------------------------------------------------------
1 | import '../bitmap.dart';
2 |
3 | export 'adjust_color.dart';
4 | export 'brightness.dart';
5 | export 'contrast.dart';
6 | export 'crop.dart';
7 | export 'flip.dart';
8 | export 'resize.dart';
9 | export 'rgb_overlay.dart';
10 | export 'rotation.dart';
11 |
12 | abstract class BitmapOperation {
13 | Bitmap applyTo(Bitmap bitmap);
14 | }
15 |
--------------------------------------------------------------------------------
/lib/src/operation/resize.dart:
--------------------------------------------------------------------------------
1 | import 'dart:typed_data';
2 | import '../bitmap.dart';
3 | import 'operation.dart';
4 |
5 | class BitmapResize implements BitmapOperation {
6 | BitmapResize.to({int? width, int? height})
7 | : resizeWidth = width,
8 | resizeHeight = height,
9 | assert(
10 | width != null || height != null,
11 | "You have to provide either width or height to resize an image",
12 | );
13 |
14 | final int? resizeHeight;
15 | final int? resizeWidth;
16 |
17 | @override
18 | Bitmap applyTo(Bitmap bitmap) {
19 | final width = bitmap.width;
20 | final height = bitmap.height;
21 |
22 | if (resizeWidth == null && resizeHeight == null) {
23 | throw UnsupportedError(
24 | "You have to provide either width or height to resize an image",
25 | );
26 | }
27 |
28 | // keep aspect ratio
29 | final toWidth = resizeWidth ?? (resizeHeight! * (width / height)).toInt();
30 | final toHeight = resizeHeight ?? (resizeWidth! * (height / width)).toInt();
31 |
32 | final int newBitmapBytesExtent =
33 | (toWidth * toHeight) * RGBA32BitmapHeader.pixelLength;
34 |
35 | final Bitmap resized = Bitmap.fromHeadless(
36 | toWidth,
37 | toHeight,
38 | Uint8List(newBitmapBytesExtent),
39 | );
40 |
41 | _resizeCore(
42 | bitmap.content,
43 | resized.content,
44 | width,
45 | height,
46 | toWidth,
47 | toHeight,
48 | );
49 |
50 | return resized;
51 | }
52 |
53 | void _resizeCore(
54 | Uint8List sourceBmp,
55 | Uint8List destBmp,
56 | int sourceWidth,
57 | int sourceHeight,
58 | int width, [
59 | int height = -1,
60 | ]) {
61 | assert(width > 0 && height > 0);
62 | const pixelLength = RGBA32BitmapHeader.pixelLength;
63 |
64 | final double proportionY = sourceHeight / height;
65 | final double proportionX = sourceWidth / width;
66 |
67 | final int lineLength = width * pixelLength;
68 | final int sourceLineLength = sourceWidth * pixelLength;
69 |
70 | // inspired by dart_image, interpolation: nearest
71 | final sourceColumns = Int32List(width);
72 |
73 | for (int column = 0; column < width; column++) {
74 | sourceColumns[column] = (column * proportionX).toInt();
75 | }
76 |
77 | for (int line = 0; line < height; line++) {
78 | final int startOfLine = line * lineLength;
79 |
80 | final int sourceLine = (line * proportionY).toInt();
81 | final int sourceStartOfLine = sourceLine * sourceLineLength;
82 |
83 | for (int column = 0; column < width; column++) {
84 | final int columnStart = column * pixelLength;
85 | final int pixelStart = startOfLine + columnStart;
86 | final int pixelEnd = pixelStart + pixelLength;
87 |
88 | final int sourceColumnStart = sourceColumns[column] * pixelLength;
89 | final int sourcePixelStart = sourceStartOfLine + sourceColumnStart;
90 | final int sourcePixelEnd = sourcePixelStart + pixelLength;
91 |
92 | final Uint8List sourcePixel =
93 | sourceBmp.sublist(sourcePixelStart, sourcePixelEnd);
94 |
95 | destBmp.setRange(pixelStart, pixelEnd, sourcePixel);
96 | }
97 | }
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/lib/src/operation/rgb_overlay.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ffi' as ffi;
2 | import 'dart:typed_data';
3 |
4 | import '../bitmap.dart';
5 | import '../ffi.dart';
6 | import 'operation.dart';
7 |
8 | // *** FFi C++ bindings ***
9 | const _nativeFunctionName = "rgb_overlay";
10 |
11 | typedef _NativeSideFunction = ffi.Void Function(ffi.Pointer,
12 | ffi.Int32, ffi.Double, ffi.Double, ffi.Double, ffi.Double);
13 |
14 | typedef _DartSideFunction = void Function(
15 | ffi.Pointer startingPointer,
16 | int bitmapLength,
17 | double red,
18 | double green,
19 | double blue,
20 | double scale);
21 |
22 | _DartSideFunction _rgbOverlayFFIImpl = bitmapFFILib
23 | .lookup>(_nativeFunctionName)
24 | .asFunction();
25 |
26 | class BitmapRgbOverlay implements BitmapOperation {
27 | BitmapRgbOverlay(this.red, this.green, this.blue, this.scale);
28 |
29 | final double red;
30 | final double green;
31 | final double blue;
32 | final double scale;
33 |
34 | @override
35 | Bitmap applyTo(Bitmap bitmap) {
36 | final Bitmap copy = bitmap.cloneHeadless();
37 | _rgbOverlayCore(copy.content, red, green, blue, scale);
38 | return copy;
39 | }
40 |
41 | void _rgbOverlayCore(Uint8List sourceBmp, double red, double green,
42 | double blue, double scale) {
43 | final size = sourceBmp.length;
44 |
45 | // start native execution
46 | FFIImpl((startingPointer, pointerList) {
47 | _rgbOverlayFFIImpl(startingPointer, size, red, green, blue, scale);
48 | }).execute(sourceBmp);
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/lib/src/operation/rotation.dart:
--------------------------------------------------------------------------------
1 | import 'dart:typed_data';
2 |
3 | import '../bitmap.dart';
4 | import 'operation.dart';
5 |
6 | class BitmapRotate implements BitmapOperation {
7 | final _Rotate _rotate;
8 |
9 | BitmapRotate.rotateClockwise() : _rotate = _RotateClockwise();
10 |
11 | BitmapRotate.rotate180() : _rotate = _Rotate180();
12 |
13 | BitmapRotate.rotateCounterClockwise() : _rotate = _RotateCounterClockwise();
14 |
15 | @override
16 | Bitmap applyTo(Bitmap bitmap) {
17 | return _rotate.doRotate(bitmap);
18 | }
19 | }
20 |
21 | abstract class _Rotate {
22 | Bitmap doRotate(Bitmap bitmap);
23 | }
24 |
25 | class _RotateClockwise implements _Rotate {
26 | @override
27 | Bitmap doRotate(Bitmap bitmap) {
28 | final Bitmap rotated = Bitmap.fromHeadless(
29 | bitmap.height,
30 | bitmap.width,
31 | Uint8List(bitmap.width * bitmap.height * RGBA32BitmapHeader.pixelLength),
32 | );
33 |
34 | _rotateClockwiseCore(
35 | bitmap.content,
36 | rotated.content,
37 | bitmap.width,
38 | bitmap.height,
39 | );
40 |
41 | return rotated;
42 | }
43 |
44 | void _rotateClockwiseCore(
45 | Uint8List sourceBmp,
46 | Uint8List destBmp,
47 | int width,
48 | int height,
49 | ) {
50 | assert(width > 0 && height > 0);
51 |
52 | const pixelLength = RGBA32BitmapHeader.pixelLength;
53 |
54 | final int lineLength = width * pixelLength;
55 | for (int line = 0; line < height; line++) {
56 | final startOfLine = line * lineLength;
57 | for (int column = 0; column < width; column++) {
58 | final int columnStart = column * pixelLength;
59 | final int pixelStart = startOfLine + columnStart;
60 | final int pixelEnd = pixelStart + pixelLength;
61 |
62 | final int rotatedStart =
63 | (height * column) * pixelLength + (height - line - 1) * pixelLength;
64 | final int rotatedEnd = rotatedStart + pixelLength;
65 |
66 | final Uint8List sourcePixel = sourceBmp.sublist(pixelStart, pixelEnd);
67 |
68 | destBmp.setRange(rotatedStart, rotatedEnd, sourcePixel);
69 | }
70 | }
71 | }
72 | }
73 |
74 | class _RotateCounterClockwise implements _Rotate {
75 | @override
76 | Bitmap doRotate(Bitmap bitmap) {
77 | final Bitmap rotated = Bitmap.fromHeadless(
78 | bitmap.height,
79 | bitmap.width,
80 | Uint8List(bitmap.width * bitmap.height * RGBA32BitmapHeader.pixelLength),
81 | );
82 |
83 | _rotateCounterClockwiseCore(
84 | bitmap.content,
85 | rotated.content,
86 | bitmap.width,
87 | bitmap.height,
88 | );
89 |
90 | return rotated;
91 | }
92 |
93 | void _rotateCounterClockwiseCore(
94 | Uint8List sourceBmp,
95 | Uint8List destBmp,
96 | int width,
97 | int height,
98 | ) {
99 | assert(width > 0 && height > 0);
100 | const pixelLength = RGBA32BitmapHeader.pixelLength;
101 |
102 | final int lineLength = width * pixelLength;
103 | for (int line = 0; line < height; line++) {
104 | final startOfLine = line * lineLength;
105 | for (int column = 0; column < width; column++) {
106 | final int columnStart = column * pixelLength;
107 | final int pixelStart = startOfLine + columnStart;
108 | final int pixelEnd = pixelStart + pixelLength;
109 |
110 | final int rotatedStart =
111 | (height * (width - column - 1)) * pixelLength + line * pixelLength;
112 | final int rotatedEnd = rotatedStart + pixelLength;
113 |
114 | final Uint8List sourcePixel = sourceBmp.sublist(pixelStart, pixelEnd);
115 |
116 | destBmp.setRange(rotatedStart, rotatedEnd, sourcePixel);
117 | }
118 | }
119 | }
120 | }
121 |
122 | class _Rotate180 implements _Rotate {
123 | @override
124 | Bitmap doRotate(Bitmap bitmap) {
125 | final Bitmap rotated = Bitmap.fromHeadless(
126 | bitmap.height,
127 | bitmap.width,
128 | Uint8List(bitmap.width * bitmap.height * RGBA32BitmapHeader.pixelLength),
129 | );
130 |
131 | _rotate180Core(
132 | bitmap.content,
133 | rotated.content,
134 | bitmap.width,
135 | bitmap.height,
136 | );
137 |
138 | return rotated;
139 | }
140 |
141 | void _rotate180Core(
142 | Uint8List sourceBmp,
143 | Uint8List destBmp,
144 | int width,
145 | int height,
146 | ) {
147 | assert(width > 0 && height > 0);
148 | const pixelLength = RGBA32BitmapHeader.pixelLength;
149 |
150 | final int lineLength = width * pixelLength;
151 | for (int line = 0; line < height; line++) {
152 | final startOfLine = line * lineLength;
153 | for (int column = 0; column < width; column++) {
154 | final int columnStart = column * pixelLength;
155 | final int pixelStart = startOfLine + columnStart;
156 | final int pixelEnd = pixelStart + pixelLength;
157 |
158 | final int rotatedStart = width * (height - line - 1) * pixelLength +
159 | (width - column - 1) * pixelLength;
160 | final int rotatedEnd = rotatedStart + pixelLength;
161 |
162 | final Uint8List sourcePixel = sourceBmp.sublist(pixelStart, pixelEnd);
163 |
164 | destBmp.setRange(rotatedStart, rotatedEnd, sourcePixel);
165 | }
166 | }
167 | }
168 | }
169 |
--------------------------------------------------------------------------------
/macos/Classes/BitmapPlugin.swift:
--------------------------------------------------------------------------------
1 | import Cocoa
2 | import FlutterMacOS
3 |
4 | public class BitmapPlugin: NSObject, FlutterPlugin {
5 | public static func register(with registrar: FlutterPluginRegistrar) {
6 | let channel = FlutterMethodChannel(name: "bitmap", binaryMessenger: registrar.messenger)
7 | let instance = BitmapPlugin()
8 | registrar.addMethodCallDelegate(instance, channel: channel)
9 | }
10 |
11 | public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
12 | switch call.method {
13 | case "getPlatformVersion":
14 | result("macOS " + ProcessInfo.processInfo.operatingSystemVersionString)
15 | default:
16 | result(FlutterMethodNotImplemented)
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/macos/bitmap.podspec:
--------------------------------------------------------------------------------
1 | #
2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
3 | # Run `pod lib lint bitmap.podspec` to validate before publishing.
4 | #
5 | Pod::Spec.new do |s|
6 | s.name = 'bitmap'
7 | s.version = '0.0.1'
8 | s.summary = 'A new flutter plugin project.'
9 | s.description = <<-DESC
10 | A new flutter plugin project.
11 | DESC
12 | s.homepage = 'http://example.com'
13 | s.license = { :file => '../LICENSE' }
14 | s.author = { 'Your Company' => 'email@example.com' }
15 | s.source = { :path => '.' }
16 | s.source_files = 'Classes/**/*'
17 | s.dependency 'FlutterMacOS'
18 |
19 | s.platform = :osx, '10.11'
20 | s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' }
21 | s.swift_version = '5.0'
22 | end
23 |
--------------------------------------------------------------------------------
/pubspec.lock:
--------------------------------------------------------------------------------
1 | # Generated by pub
2 | # See https://dart.dev/tools/pub/glossary#lockfile
3 | packages:
4 | async:
5 | dependency: transitive
6 | description:
7 | name: async
8 | sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
9 | url: "https://pub.dev"
10 | source: hosted
11 | version: "2.11.0"
12 | boolean_selector:
13 | dependency: transitive
14 | description:
15 | name: boolean_selector
16 | sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
17 | url: "https://pub.dev"
18 | source: hosted
19 | version: "2.1.1"
20 | characters:
21 | dependency: transitive
22 | description:
23 | name: characters
24 | sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
25 | url: "https://pub.dev"
26 | source: hosted
27 | version: "1.3.0"
28 | clock:
29 | dependency: transitive
30 | description:
31 | name: clock
32 | sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
33 | url: "https://pub.dev"
34 | source: hosted
35 | version: "1.1.1"
36 | collection:
37 | dependency: transitive
38 | description:
39 | name: collection
40 | sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
41 | url: "https://pub.dev"
42 | source: hosted
43 | version: "1.18.0"
44 | fake_async:
45 | dependency: transitive
46 | description:
47 | name: fake_async
48 | sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
49 | url: "https://pub.dev"
50 | source: hosted
51 | version: "1.3.1"
52 | ffi:
53 | dependency: "direct main"
54 | description:
55 | name: ffi
56 | sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878"
57 | url: "https://pub.dev"
58 | source: hosted
59 | version: "2.1.0"
60 | flutter:
61 | dependency: "direct main"
62 | description: flutter
63 | source: sdk
64 | version: "0.0.0"
65 | flutter_test:
66 | dependency: "direct dev"
67 | description: flutter
68 | source: sdk
69 | version: "0.0.0"
70 | matcher:
71 | dependency: transitive
72 | description:
73 | name: matcher
74 | sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
75 | url: "https://pub.dev"
76 | source: hosted
77 | version: "0.12.16"
78 | material_color_utilities:
79 | dependency: transitive
80 | description:
81 | name: material_color_utilities
82 | sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
83 | url: "https://pub.dev"
84 | source: hosted
85 | version: "0.5.0"
86 | meta:
87 | dependency: transitive
88 | description:
89 | name: meta
90 | sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e
91 | url: "https://pub.dev"
92 | source: hosted
93 | version: "1.10.0"
94 | path:
95 | dependency: transitive
96 | description:
97 | name: path
98 | sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
99 | url: "https://pub.dev"
100 | source: hosted
101 | version: "1.8.3"
102 | sky_engine:
103 | dependency: transitive
104 | description: flutter
105 | source: sdk
106 | version: "0.0.99"
107 | source_span:
108 | dependency: transitive
109 | description:
110 | name: source_span
111 | sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
112 | url: "https://pub.dev"
113 | source: hosted
114 | version: "1.10.0"
115 | stack_trace:
116 | dependency: transitive
117 | description:
118 | name: stack_trace
119 | sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
120 | url: "https://pub.dev"
121 | source: hosted
122 | version: "1.11.1"
123 | stream_channel:
124 | dependency: transitive
125 | description:
126 | name: stream_channel
127 | sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
128 | url: "https://pub.dev"
129 | source: hosted
130 | version: "2.1.2"
131 | string_scanner:
132 | dependency: transitive
133 | description:
134 | name: string_scanner
135 | sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
136 | url: "https://pub.dev"
137 | source: hosted
138 | version: "1.2.0"
139 | term_glyph:
140 | dependency: transitive
141 | description:
142 | name: term_glyph
143 | sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
144 | url: "https://pub.dev"
145 | source: hosted
146 | version: "1.2.1"
147 | test_api:
148 | dependency: transitive
149 | description:
150 | name: test_api
151 | sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
152 | url: "https://pub.dev"
153 | source: hosted
154 | version: "0.6.1"
155 | vector_math:
156 | dependency: transitive
157 | description:
158 | name: vector_math
159 | sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
160 | url: "https://pub.dev"
161 | source: hosted
162 | version: "2.1.4"
163 | web:
164 | dependency: transitive
165 | description:
166 | name: web
167 | sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152
168 | url: "https://pub.dev"
169 | source: hosted
170 | version: "0.3.0"
171 | sdks:
172 | dart: ">=3.2.0-194.0.dev <4.0.0"
173 | flutter: ">=3.13.9"
174 |
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: bitmap_flutter
2 | description: Bitmap is a fast and minimalistic lib that heelps you to manipulate image on Flutter apps.
3 | version: 1.0.0
4 | homepage: https://github.com/guptan404/bitmap
5 | topics: [image, image-processing, ffi]
6 |
7 | environment:
8 | sdk: ">=3.1.0 <4.0.0"
9 | flutter: ">=3.13.9"
10 |
11 | dependencies:
12 | flutter:
13 | sdk: flutter
14 | ffi: ^2.1.0
15 |
16 | dev_dependencies:
17 | flutter_test:
18 | sdk: flutter
19 |
20 | flutter:
21 | plugin:
22 | platforms:
23 | android:
24 | package: com.example.bitmap
25 | pluginClass: BitmapPlugin
26 | ios:
27 | pluginClass: BitmapPlugin
28 |
--------------------------------------------------------------------------------
/test/bitmap_test.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter_test/flutter_test.dart';
2 |
3 | void main() {
4 | test('Figure out a way to test this with FFI', () {});
5 | }
6 |
--------------------------------------------------------------------------------
/transform.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bluefireteam/bitmap/6eb13d4980bd53a9b0de4eca178c60809bce3b5d/transform.jpg
--------------------------------------------------------------------------------