Giter Site home page Giter Site logo

hm21 / pro_image_editor Goto Github PK

View Code? Open in Web Editor NEW
81.0 81.0 56.0 175.11 MB

The pro_image_editor is a Flutter widget designed for image editing within your application. It provides a flexible and convenient way to integrate image editing capabilities into your Flutter project.

Home Page: https://hm21.github.io/pro_image_editor/

License: BSD 3-Clause "New" or "Revised" License

Kotlin 0.01% Swift 0.18% Objective-C 0.01% Dart 96.74% CMake 1.22% C++ 1.61% C 0.09% HTML 0.10% JavaScript 0.04%
crop editor filter image image-editor painting pro-image-editor widget

pro_image_editor's Introduction

Typing SVG

About Me

Hey, I'm Alex, a passionate software developer based in the beautiful country of Switzerland πŸ‡¨πŸ‡­. I thrive on turning ideas into elegant and functional software solutions. Whether it's web development, mobile apps, or tinkering with the latest tech gadgets, I'm always eager to learn and create.

What I Do

  • 🌐 I specialize in web development, with expertise in technologies like Angular, TypeScript, JavaScript, HTML, and CSS.

  • πŸ“± Flutter has been my go-to framework for crafting stunning cross-platform mobile applications.

  • πŸ’» I have a knack for backend development, working with technologies like Firebase, Supabase and .NET.

  • ☁️ In the cloud computing realm, I'm well-versed in GCP (Google Cloud Platform) and Azure.

  • 🌟 I enjoy hardware tinkering, especially with Raspberry Pi projects, where I leverage the power of .NET IoT to create innovative solutions.

  • πŸ› οΈ My favorite coding companions are Visual Studio Code and Visual Studio.


My Skills

Get in Touch

I'm always open to collaboration and connecting with fellow developers. If you have any questions, ideas, or just want to say hello, don't hesitate to reach out:

Let's code, learn, and build amazing things together! πŸš€


hm21

pro_image_editor's People

Contributors

adamkoch avatar diegotori avatar heropolisda2ny avatar hm21 avatar hoyaaaa avatar lvsecoto avatar yfming93 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

pro_image_editor's Issues

Build error due to unconfigured namespace in image_editor dependency

When attempting to build a project that includes the pro_image_editor package, the build fails with a configuration error related to its dependency, image_editor version 1.3.0. The error is as follows:
`1: Task failed with an exception.

  • What went wrong:
    A problem occurred configuring project ':image_editor_common'.

Could not create an instance of type com.android.build.api.variant.impl.LibraryVariantBuilderImpl.
Namespace not specified. Specify a namespace in the module's build file. See https://d.android.com/r/tools/upgrade-assistant/set-namespace for information about setting the namespace.

 If you've specified the package attribute in the source AndroidManifest.xml, you can use the AGP Upgrade Assistant to migrate to the namespace value in the build file. Refer to https://d.android.com/r/tools/upgrade-assistant/agp-upgrade-assistant for general information about using the AGP Upgrade Assistant.

`
This suggests that the image_editor package has not been configured with a namespace, a requirement introduced in recent versions of the Android Gradle Plugin (AGP).

Steps to Reproduce
Include pro_image_editor in a Flutter project's dependencies.
Attempt to build the project for Android.
Observe the build failure with the above error message.

Expected Behavior
The project builds successfully without any configuration errors related to namespaces in dependencies.

Actual Behavior
The build fails due to a missing namespace configuration in the image_editor package.

Suggested Fix
According to the provided error message and the AGP documentation, it is necessary to specify a namespace in the module's build file for image_editor. This can be achieved by following the instructions provided in the AGP Upgrade Assistant documentation: . The necessary changes should be applied to the image_editor package to ensure compatibility with recent AGP versions and to avoid build failures due to unconfigured namespaces.

Additional Context
Flutter version: 3.19.0
pro_image_editor version: ^2.5.7
image_editor version: 1.3.0
Android Gradle Plugin version: [include the version you are using]
Gradle version: 8.2
Please let me know if you need any more information or if there's anything else I can do to help resolve this issue.

[Feature request] Can we add ready templates (like predefined text or image on some position

Platforms

Android, iOS, Web, Windows, macOS, Linux

Description

I think it will be good to have some predefined templates. As, example in Photoshop we have psd format, which we can save as template and then reuse/change/export it. Imagine I have t-shirt with name/surname on top and big sized number in center on back side of t-shirt, like football players wears. And we can load this template change name/surname and number without any other actions. Thank you
Screenshot_2

Why

It is must to have feature I think and also it will save time to desing.

Feature Request: Landscape support

Is your feature request related to a problem? Please describe.
Currently landsscape mode is not supported and the widget will always fallback to portrait mode

Describe the solution you'd like
For tablet users that mainly use our app in landscape mode this change in orientation can be confusing and in addition to that we navigate from differently oriented dynamic screens to pro_image_editor and that makes it kind of tricky to restore the orientation of the previous screen correctly.

Describe alternatives you've considered
I guess one way would be to wrap your widget into a rotation widget but i don't think this is a viable solution to the problem

Additional context
At the moment i don't really see a problem with allowing other device orientations. Only the implemented color slider might overflow on some devices. I want the user to decide in which orientation he uses the phone and maybe the color slider should be rotated horizontally in landscape mode. Most phone users will not use landscape mode in the app anyway or manually lock their screens to their prefrered orientation.

What are your thoughts on that?

[Feature request] OnEditComplete/Done should have a

Platforms

Android, iOS, Web, Windows, macOS, Linux

Description

Now OnEditImageCompleted works only if I interact with the image(add/edit anything). But I want OnEditImageCompleted callback or similar mechanism when the user doesn't need any editing and click on "done" icon , and it should have a callback/void function that catches the Uint8List bytes, I want to get the Uint8List bytes image data when no user edit is performed and the user click on the 'done' icon
image

Why

No response

[Question] Dramatic increase in file size after editing

Platforms

iOS

Your question

Hi developers,
Thanks for developing this fantastic plugin, it is nice and good to use. Just one thing that I would like to confirm if that's expected behavior.
I downloaded the source and try out with the example, just adding minimal code to print the image size before and after edit, and found the size increase dramatically (from 321KB to 2.9M). The editing is minimal too, just drawing a circle.
image

Thanks again for looking into this. Cheers.

[Feature request] Open editor on a specific page

Platforms

Android, iOS

Description

Hey there, great package!

I would like to have the editor start on a specific page (i.e in the painting editor), but I haven't found a way to do so. Would it be possible to have a config like:

paintEditorConfigs: PaintEditorConfigs(
  initialPage: true,
),

Or to expose a controller so that I can explicitly trigger the page change as soon as I open the editor?

Why

Our users use the painting feature way more than the other sorts of edition, so it would be easier for them if we had the editor open in that particular mode

[bug] Bottom Overflow

Hello, I tried the package in an app on my physical device (Samsung Galaxy 10e), and got a bottom overflow warning :

Screenshot_20240212_153130

Feature Request: Configure only selected crop aspect ratio

Need such options to Configure/control only selected crop aspect ratio like only 16:9 or 4:3

I mean there needs have the control-availity to disable some aspect ratio.

Also need the control to change the editing options' position as wish

[Feature request] Helper lines for aligning items with each other

Platforms

Android, iOS, Web

Description

First of all - awesome library, thanks for creating and sharing it.

Feature request - the helper lines for aligning with center or with certain rotation angles are great.

Helper lines for aligning items with each other would also be really helpful. For example, if you position some text somewhere and then add another item, if a helper line would appear to make sure they are both lined up with each other.

Example:
Simulator Screenshot - iPhone 15 Pro - 2024-06-07 at 21 23 56

Thanks again!

Why

Keeping items aligned with each other easily is helpful and looks a lot better!

[Question] WhatsApp mode with paint editor

Placeholder

Hello friend, a suggestion, I know that WhatsApp doesn't include circle, rectangular and other shapes, but it would be very interesting to have them, people loved the shapes, it would be very complicated, or there would be a way to customize this, I tried but it didn't work. I achieved

Crashes when saving edited image[bug]

Hello thanks for a wonderful package. I just added the package and it comes up but after editing the following happens

  1. load an image
  2. edit the image
  3. click on the good symbol in the upper right corner, it pops up a alert says " applying changes" the crashes with an error. " failed assertion !deburgluck is not true." I am using a vivo android 7 phone for testing
    θΆ…ηΊ§ζˆͺ屏_20240320_142008

[bug] 'Null' is not a subtype of type 'String' in type cast

Describe the bug
An error appears when trying to pass emoji set as below per example documentation:

'Null' is not a subtype of type 'String' in type cast

emojiSet: [
  CategoryEmoji(
  Category.ANIMALS,
    [Emoji.fromJson({})],
   )
 ],

Steps to Reproduce

  1. Open Camera
  2. Navigate to ProImageEditor

Expected Behavior
To work as expected and open up the emoji tab

setState() called after dispose(): ProImageEditorState#ba168(lifecycle state: defunct, not mounted)

Package Version

2.7.9

Flutter Version

3.19

Platforms

Android

How to reproduce?

when i open texteditor enter text and click on done icon then the exception is throw

Logs (optional)

The following assertion was thrown while notifying status listeners for ProxyAnimation: setState() called after dispose(): ProImageEditorState#ba168(lifecycle state: defunct, not mounted) This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback. The preferred solution is to cancel the timer or stop listening to the animation in the dispose() callback. Another solution is to check the "mounted" property of this object before calling setState() to ensure the object is still in the tree. This error might indicate a memory leak if setState() is being called because another object is retaining a reference to this State object after it has been removed from the tree. To avoid memory leaks, consider breaking the reference to this object during dispose().

Example code (optional)

final _editorKey = GlobalKey<ProImageEditorState>();
  StreamController _updateUIStream = StreamController.broadcast();
  @override
  Widget build(BuildContext context) {
    return SafeArea(
        child: BlocBuilder<AddNewBloc, AddNewState>(builder: (context, state) {
      return Scaffold(
        appBar: _buildAppBar(context),
        body: Stack(children: [
          ProImageEditor.network(
            key: _editorKey,
            onUpdateUI: () => _updateUIStream.add(null),
            allowCompleteWithEmptyEditing: true,
            // configs: const ProImageEditorConfigs(
            //   customWidgets: ImageEditorCustomWidgets(
            //       // bottomNavigationBar: SizedBox(),
            //       ),
            // ),
            'https://picsum.photos/id/237/2000',
            onImageEditingComplete: (Uint8List bytes) async {
              /*
                 `Your code for handling the edited image. Upload it to your server as an example.`
          
                 You can choose whether you want to use await, so that the loading-dialog remains visible until your code is also ready,
                 or without async, so that the loading-dialog closes immediately.
                */
            },
          ),
          state.showbottomContainer
              ? _buildColumnBookmark(context, _editorKey, state)
              : const SizedBox(),
          state.showbottomContainer
              ? CustomImageView(
                  imagePath: ImageConstant.imgPolygon1,
                  height: 47.v,
                  width: 103.h,
                  alignment: Alignment.bottomLeft,
                  margin: EdgeInsets.only(left: 26.h),
                  fit: BoxFit.cover,
                )
              : const SizedBox(),
);
}
  Widget _buildColumnBookmark(BuildContext context,
      GlobalKey<ProImageEditorState> key, AddNewState state) {
    return Align(
      alignment: Alignment.bottomCenter,
      child: Container(
        margin: EdgeInsets.only(bottom: 46.v),
        padding: EdgeInsets.symmetric(
          horizontal: 26.h,
          vertical: 20.v,
        ),
        decoration: AppDecoration.fillPrimary.copyWith(
          borderRadius: BorderRadiusStyle.roundedBorder33,
        ),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            SizedBox(height: 25.v),
            Padding(
              padding: EdgeInsets.only(right: 1.h),
              child: BlocSelector<AddNewBloc, AddNewState, AddNewModel?>(
                selector: (state) => state.screen3AddNewModelObj,
                builder: (context, screen3AddNewModelObj) {
                  return GridView.builder(
                    shrinkWrap: true,
                    gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                      mainAxisExtent: 93.v,
                      crossAxisCount: 3,
                      mainAxisSpacing: 15.h,
                      crossAxisSpacing: 15.h,
                    ),
                    physics: const NeverScrollableScrollPhysics(),
                    itemCount:
                        screen3AddNewModelObj?.gridgalleryPicItemList.length ??
                            0,
                    itemBuilder: (context, index) {
                      GridgalleryPicItemModel model = screen3AddNewModelObj
                              ?.gridgalleryPicItemList[index] ??
                          GridgalleryPicItemModel();
                      return GridgalleryPicItemWidget(
                        model,
                        onTapColumngallery: () {
                          if (index == 1) {
                            BlocProvider.of<AddNewBloc>(context).add(
                                ShowContainerEvent(
                                    ishow: state.showbottomContainer
                                        ? false
                                        : true));
                            key.currentState?.openTextEditor();
                          } else {}
                        },
                      );
                    },
                  );
                },
              ),
            )
          ],
        ),
      ),
    );
  }

Device Model (optional)

No response

when i click on blur and filter buttons my previous changes were disappear and when i complete the operation the changes were reappear again

Describe the bug
A clear and concise description of what the bug is.

Steps to Reproduce

  1. Go to '...'
  2. Click on '....'
  3. Scroll down to '....'
  4. See error

Expected Behavior
A clear and concise description of what you expected to happen.

Screenshots
If applicable, add screenshots to help explain your problem.

Additional Context
Add any other context about the problem here.

[Bug]: screenshot package needs update for flutter 3.22

Package Version

22

Flutter Version

3.22

Platforms

Web

How to reproduce?

install flutter 3.22, try to compile

Target dart2js failed: ProcessException: Process exited abnormally with exit code 1:
../../../../../.pub-cache/hosted/pub.dev/screenshot-2.3.0/lib/screenshot.dart:164:9:
Error: No named parameter with the name 'size'.
        size: logicalSize,
        ^^^^

Logs (optional)

https://github.com/SachinGanesh/screenshot/issues/169

Example code (optional)

No response

Device Model (optional)

No response

[Feature request] More text options (bold, italic, underline, lists)

Platforms

Android, iOS, Web

Description

It would be great to add more text formatting options, the main ones being:

  • common formatting - bold, italic, underline
  • lists - numbered and and bullets

There are probably more :-)

Thanks!

Why

Adds more flexibility to the existing text tool which already has sizing and rotate ability (and font changing which is awesome!).

Allow custom color of image editor icon

Platforms

Android, iOS

Description

Currently, ImageEditorIcons only support custom image editor icons. It would be even better if we could customize the color of the image editor icons as well

Change the color of the appBar and bottom nav bar in main screen [Feature request]

Platforms

Android, iOS, Web

Description

This package is very useful and thank you for the great job.
I've been checked all documents and there was some features that doesn't exist now! e.g. WhatsApp mode and change the color of the appBar (appBarBackgroundColor in imageEditorTheme) and bottom nav bar (bottomBarBackgroundColor in imageEditorTheme) in main edit screen. It would be great to implement these feature again.

Why

No response

[Bug]: Removing bottom navigation bar via ImageEditorCustomWidgets causes layout to skip when moving items

Package Version

3.0.4

Flutter Version

3.22.2

Platforms

Android, iOS

How to reproduce?

Not sure if this is the right way to remove the bottom navigation bar, but I am doing:

ProImageEditorConfigs(
  customWidgets: ImageEditorCustomWidgets(
    bottomNavigationBar: const SizedBox(),
  ),
),

This seems to work fine. However, when dragging items around after that. The layout shifts back to having the space for the bottom navigation bar (so everything shifts upward). The preview moves up and shrinks. And the "delete" drop target stays in the right place but the actual drop target itself seems to be offset upward as well.

Video demonstrating:

Simulator.Screen.Recording.-.iPhone.15.Pro.-.2024-06-08.at.22.33.51.mp4

Logs (optional)

No response

Example code (optional)

No response

Device Model (optional)

No response

[Bug]: Loader doesn't stop after apply edit

Package Version

2.7.3

Flutter Version

3.19.6

Platforms

Android

How to reproduce?

I found this issue after applying changes

Logs (optional)

No response

Example code (optional)

mixin ExampleHelperState<T extends StatefulWidget> on State<T> {

  Uint8List? editedBytes;

  Future<void> onImageEditingComplete(bytes) async {
    editedBytes = bytes;
    pop(context);
  }

  Future<void> onCloseEditor() async {
    if (editedBytes != null) {
      navigationPush(context: context, to: ImageEditPage(imageByte: editedBytes!)).whenComplete(() {
        editedBytes = null;
      });
    } else {
      pop(context);
    }
  }
}

ProImageEditor.memory(
      widget.imageByte!,
      onImageEditingComplete: onImageEditingComplete,
      onCloseEditor: onCloseEditor,
      allowCompleteWithEmptyEditing: true,
      configs: proImageEditorConfigs(context)
    )

Device Model (optional)

No response

[Bug]: WEB: Unsupported operation: Platform._operatingSystem

Package Version

2.7.2

Flutter Version

3.19

Platforms

Web

How to reproduce?

make an emoji and drag it around. Drag is also kind of broken.

Logs (optional)

══║ EXCEPTION CAUGHT BY GESTURE β•žβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
The following UnsupportedError was thrown while handling a gesture:
Unsupported operation: Platform._operatingSystem

Example code (optional)

mouse is not visible, but it's on the right side
bug

Also, adding text makes a full screen barrier, but the image isn't maximized like drawing.
Screenshot-20240504193010-2917x1794

Device Model (optional)

linux

Issue with Not Getting Edited Image Back from ProImageEditor

I'm working on a FlutterFlow project that utilizes ProImageEditor to allow users to edit images within the app. I've encountered an issue where the edited image is not being returned correctly after the editing process.

Here is an overview of what I'm attempting to do:

The user selects an image to edit, which is then passed to ProImageEditor for editing.
After editing, I expect the edited image bytes to be returned so I can save them on the user's device and display them in the app.
The relevant code for this process is:

// Start of image editing
var editedBytes = await Navigator.of(context).push(
  MaterialPageRoute(
    builder: (context) => ProImageEditor.memory(
      widget.uploadedFile.bytes!,
      onImageEditingComplete: (Uint8List bytes) async {
        Navigator.pop(context, bytes); // Expected to return edited bytes
      },
      configs: ProImageEditorConfigs(
        // Editor configurations
      ),
    ),
  ),
);

// Save and display the edited image
if (editedBytes != null) {
  String? imagePath = await saveImageToDevice(editedBytes);
  if (imagePath != null) {
    setState(() {
      FFAppState().imagemEditadaPath = imagePath;
    });
  }
}

The issue is that the bytes of the edited image do not seem to be returned after editing, resulting in an inability to save and display the edited image. The onImageEditingComplete method does not seem to be functioning as expected, or perhaps I am missing a step in the process.

Full code:

// Automatic FlutterFlow imports
import '/backend/backend.dart';
import '/flutter_flow/flutter_flow_theme.dart';
import '/flutter_flow/flutter_flow_util.dart';
import '/custom_code/widgets/index.dart'; // Imports other custom widgets
import '/custom_code/actions/index.dart'; // Imports custom actions
import '/flutter_flow/custom_functions.dart'; // Imports custom functions
import 'package:flutter/material.dart';
// Begin custom widget code
// DO NOT REMOVE OR MODIFY THE CODE ABOVE!

import 'package:extended_image/extended_image.dart';
import 'package:pro_image_editor/pro_image_editor.dart';
import 'package:image_editor/image_editor.dart';
import 'package:emoji_picker_flutter/emoji_picker_flutter.dart';
import 'package:colorfilter_generator/colorfilter_generator.dart';
import 'package:rounded_background_text/rounded_background_text.dart';
import 'package:screenshot/screenshot.dart';
import 'package:vibration/vibration.dart';
import 'dart:async';
import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/foundation.dart' hide Category;
import 'package:flutter/services.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:pro_image_editor/widgets/loading_dialog.dart';
import 'package:image/image.dart' as img;
import 'package:http/http.dart';
import 'package:path_provider/path_provider.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:firebase_core/firebase_core.dart';

class MyHomePage extends StatefulWidget {
  const MyHomePage({
    super.key,
    this.width,
    this.height,
    required this.uploadedFile,
  });

  final double? width; // Largura opcional para o widget
  final double? height; // Altura opcional para o widget
  final FFUploadedFile uploadedFile; // O arquivo enviado pelo usuΓ‘rio

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  Uint8List? editedImageBytes; // Armazena os bytes da imagem editada
  // Define uma variΓ‘vel para armazenar os bytes da imagem a serem exibidos
  Uint8List? imageToShow;

  // Salva os bytes da imagem editada no dispositivo e retorna o caminho do arquivo
  Future<String?> saveImageToDevice(Uint8List imageBytes) async {
    try {
      // ObtΓ©m o diretΓ³rio de documentos do aplicativo
      final directory = await getApplicationDocumentsDirectory();
      // Cria um caminho de arquivo ΓΊnico
      String fileName =
          "edited_image_${DateTime.now().millisecondsSinceEpoch}.png";
      File imageFile = File('${directory.path}/$fileName');
      // Escreve os bytes da imagem no arquivo
      await imageFile.writeAsBytes(imageBytes);
      // Retorna o caminho do arquivo onde a imagem foi salva
      return imageFile.path;
    } catch (e) {
      print("Erro ao salvar a imagem no dispositivo: $e");
      return null;
    }
  }

  // Local onde vocΓͺ deseja decidir qual imagem mostrar
  Future<Uint8List?> getImageToShow() async {
    if (FFAppState().imagemEditadaPath != null &&
        FFAppState().imagemEditadaPath.isNotEmpty) {
      // Tenta carregar a imagem editada do caminho do arquivo de forma assΓ­ncrona
      try {
        final file = File(FFAppState().imagemEditadaPath);
        return await file.readAsBytes();
      } catch (e) {
        print("Erro ao ler a imagem editada: $e");
        return null;
      }
    } else if (widget.uploadedFile.bytes != null) {
      // Retorna os bytes da imagem original enviada
      return widget.uploadedFile.bytes;
    }
    return null;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.start,
          children: [
            // Botão para iniciar a edição de imagem
            OutlinedButton.icon(
              onPressed: () async {
                if (widget.uploadedFile.bytes != null) {
                  // Edita a imagem usando ProImageEditor.memory com os bytes do arquivo enviado
                  var editedBytes = await Navigator.of(context).push(
                    MaterialPageRoute(
                      builder: (context) => ProImageEditor.memory(
                        widget.uploadedFile.bytes!,
                        onImageEditingComplete: (Uint8List bytes) async {
                          Navigator.pop(context,
                              bytes); // Retorna os bytes editados para a tela anterior
                        },
                        configs: ProImageEditorConfigs(
                          // Configuraçáes para o ProImageEditor
                          // Inclui localização, personalizaçáes de UI e alternÒncias de recursos
                          // Consulte a documentação do ProImageEditor para detalhes
                          i18n: const I18n(
                            various: I18nVarious(
                              loadingDialogMsg: 'Por favor, aguarde...',
                              closeEditorWarningTitle:
                                  'Fechar o Editor de Imagens?',
                              closeEditorWarningMessage:
                                  'Tem certeza de que deseja fechar o Editor de imagens? Suas alteraçáes não serão salvas.',
                              closeEditorWarningConfirmBtn: 'Ok',
                              closeEditorWarningCancelBtn: 'Cancelar',
                            ),
                            paintEditor: I18nPaintingEditor(
                              bottomNavigationBarText: 'Desenhar',
                              freestyle: 'Livre',
                              arrow: 'Seta',
                              line: 'Linha',
                              rectangle: 'RetΓ’ngulo',
                              circle: 'CΓ­rculo',
                              dashLine: 'Linha Tracejada',
                              lineWidth: 'Espessura da linha',
                              toggleFill: 'Alternar Preenchimento',
                              undo: 'Desfazer',
                              redo: 'Refazer',
                              done: 'Feito',
                              back: 'Voltar',
                              smallScreenMoreTooltip: 'Mais',
                            ),
                            textEditor: I18nTextEditor(
                              inputHintText: 'Insira o texto',
                              bottomNavigationBarText: 'Texto',
                              back: 'Voltar',
                              done: 'Feito',
                              textAlign: 'Alinhar texto',
                              backgroundMode: 'Modo de fundo',
                              smallScreenMoreTooltip: 'Mais',
                            ),
                            cropRotateEditor: I18nCropRotateEditor(
                              bottomNavigationBarText: 'Cortar/Girar',
                              rotate: 'Girar',
                              ratio: 'Recortes',
                              back: 'Voltar',
                              done: 'Feito',
                              prepareImageDialogMsg: 'Por favor, aguarde...',
                              applyChangesDialogMsg: 'Por favor, aguarde...',
                              smallScreenMoreTooltip: 'Mais',
                            ),
                            cancel: 'Cancelar',
                            undo: 'Desfazer',
                            redo: 'Refazer',
                            done: 'Feito',
                            remove: 'Remover',
                            doneLoadingMsg:
                                'As alteraçáes estão sendo aplicadas',
                          ),
                          helperLines: const HelperLines(
                            showVerticalLine: true,
                            showHorizontalLine: true,
                            showRotateLine: true,
                            hitVibration: true,
                          ),
                          customWidgets: const ImageEditorCustomWidgets(),
                          imageEditorTheme: const ImageEditorTheme(
                            layerHoverCursor: SystemMouseCursors.move,
                            helperLine: HelperLineTheme(
                              horizontalColor: Color(0XFF4C68FC),
                              verticalColor: Color(0XFF4C68FC),
                              rotateColor: Color(0xFFE91E63),
                            ),
                            paintingEditor: PaintingEditorTheme(
                              appBarBackgroundColor: Color(0xFF000000),
                              lineWidthBottomSheetColor: Color(0xFF252728),
                              appBarForegroundColor: Color(0xFFE1E1E1),
                              background: Color.fromARGB(255, 22, 22, 22),
                              bottomBarColor: Color(0xFF000000),
                              bottomBarActiveItemColor: Color(0XFF4C68FC),
                              bottomBarInactiveItemColor: Color(0xFFEEEEEE),
                            ),
                            textEditor: TextEditorTheme(
                              appBarBackgroundColor: Color(0xFF000000),
                              appBarForegroundColor: Color(0xFFE1E1E1),
                              background: Color.fromARGB(155, 0, 0, 0),
                              inputHintColor: Color(0xFFBDBDBD),
                              inputCursorColor: Color(0XFF4C68FC),
                            ),
                            cropRotateEditor: CropRotateEditorTheme(
                              appBarBackgroundColor: Color(0xFF000000),
                              appBarForegroundColor: Color(0xFFE1E1E1),
                              background: Color.fromARGB(255, 22, 22, 22),
                              cropCornerColor: Color(0XFF4C68FC),
                            ),
                            filterEditor: FilterEditorTheme(
                              appBarBackgroundColor: Color(0xFF000000),
                              appBarForegroundColor: Color(0xFFE1E1E1),
                              previewTextColor: Color(0xFFE1E1E1),
                              background: Color.fromARGB(255, 22, 22, 22),
                            ),
                            blurEditor: BlurEditorTheme(
                              appBarBackgroundColor: Color(0xFF000000),
                              appBarForegroundColor: Color(0xFFE1E1E1),
                              background: Color.fromARGB(255, 22, 22, 22),
                            ),
                            emojiEditor: EmojiEditorTheme(),
                            stickerEditor: StickerEditorTheme(),
                            background: Color.fromARGB(255, 22, 22, 22),
                            loadingDialogTheme: LoadingDialogTheme(
                              textColor: Color(0xFFE1E1E1),
                            ),
                            uiOverlayStyle: SystemUiOverlayStyle(
                              statusBarColor: Color(0x42000000),
                              statusBarIconBrightness: Brightness.light,
                              systemNavigationBarIconBrightness:
                                  Brightness.light,
                              statusBarBrightness: Brightness.dark,
                              systemNavigationBarColor: Color(0xFF000000),
                            ),
                          ),
                          icons: const ImageEditorIcons(
                            paintingEditor: IconsPaintingEditor(
                              bottomNavBar: Icons.edit_rounded,
                              lineWeight: Icons.line_weight_rounded,
                              freeStyle: Icons.edit,
                              arrow: Icons.arrow_right_alt_outlined,
                              line: Icons.horizontal_rule,
                              fill: Icons.format_color_fill,
                              noFill: Icons.format_color_reset,
                              rectangle: Icons.crop_free,
                              circle: Icons.lens_outlined,
                              dashLine: Icons.power_input,
                            ),
                            textEditor: IconsTextEditor(
                              bottomNavBar: Icons.text_fields,
                              alignLeft: Icons.align_horizontal_left_rounded,
                              alignCenter:
                                  Icons.align_horizontal_center_rounded,
                              alignRight: Icons.align_horizontal_right_rounded,
                              backgroundMode: Icons.layers_rounded,
                            ),
                            cropRotateEditor: IconsCropRotateEditor(
                              bottomNavBar: Icons.crop_rotate_rounded,
                              rotate: Icons.rotate_90_degrees_ccw_outlined,
                              aspectRatio: Icons.crop,
                            ),
                            filterEditor: IconsFilterEditor(
                              bottomNavBar: Icons.filter,
                            ),
                            emojiEditor: IconsEmojiEditor(
                              bottomNavBar:
                                  Icons.sentiment_satisfied_alt_rounded,
                            ),
                            stickerEditor: IconsStickerEditor(
                              bottomNavBar: Icons.layers_outlined,
                            ),
                            closeEditor: Icons.clear,
                            doneIcon: Icons.done,
                            applyChanges: Icons.done,
                            backButton: Icons.arrow_back,
                            undoAction: Icons.undo,
                            redoAction: Icons.redo,
                            removeElementZone: Icons.delete_outline_rounded,
                          ),
                          paintEditorConfigs: const PaintEditorConfigs(
                            enabled: true,
                            hasOptionFreeStyle: true,
                            hasOptionArrow: true,
                            hasOptionLine: true,
                            hasOptionRect: true,
                            hasOptionCircle: true,
                            hasOptionDashLine: true,
                            canToggleFill: true,
                            canChangeLineWidth: true,
                            initialFill: false,
                            showColorPicker: true,
                            freeStyleHighPerformanceScaling: true,
                            initialStrokeWidth: 10.0,
                            initialColor: Color(0xffff0000),
                            initialPaintMode: PaintModeE.freeStyle,
                          ),
                          textEditorConfigs: const TextEditorConfigs(
                            enabled: true,
                            canToggleTextAlign: true,
                            canToggleBackgroundMode: true,
                            initFontSize: 24.0,
                            initialTextAlign: TextAlign.center,
                            initialBackgroundColorMode:
                                LayerBackgroundColorModeE.backgroundAndColor,
                          ),
                          cropRotateEditorConfigs: CropRotateEditorConfigs(
                            initAspectRatio: 3.0 /
                                4.0, // Exemplo de como definir um valor inicial
                            aspectRatios: const [
                              AspectRatioItem(
                                  text: 'Personalizado', value: null),
                              AspectRatioItem(
                                  text: 'Original',
                                  value:
                                      0.0), // Supondo que 0.0 representa a proporção original
                              AspectRatioItem(text: '1x1', value: 1.0 / 1.0),
                              AspectRatioItem(text: '4x3', value: 4.0 / 3.0),
                              AspectRatioItem(text: '3x4', value: 3.0 / 4.0),
                              AspectRatioItem(text: '16x9', value: 16.0 / 9.0),
                              AspectRatioItem(text: '9x16', value: 9.0 / 16.0),
                            ],
                            enabled: true,
                            canRotate: true,
                            canChangeAspectRatio: true,
                          ),
                          filterEditorConfigs:
                              FilterEditorConfigs(enabled: false),
                          blurEditorConfigs: const BlurEditorConfigs(
                            enabled: false,
                          ),
                          emojiEditorConfigs: const EmojiEditorConfigs(
                            enabled: false,
                          ),
                          designMode: ImageEditorDesignModeE.material,
                          heroTag: 'hero',
                          theme: ThemeData(
                            useMaterial3: true,
                            colorScheme: ColorScheme.fromSeed(
                              seedColor: Colors.blue.shade800,
                              brightness: Brightness.dark,
                            ),
                          ),
                        ),
                      ),
                    ),
                  );
                  if (editedBytes != null) {
                    // Salva a imagem editada no dispositivo e obtΓ©m o caminho do arquivo
                    String? imagePath = await saveImageToDevice(editedBytes);
                    if (imagePath != null) {
                      setState(() {
                        FFAppState().imagemEditadaPath =
                            imagePath; // Atualiza o estado com o novo caminho da imagem
                      });
                    }
                  }
                }
              },
              icon: const Icon(Icons.edit), // Ícone para o botão de edição
              label: const Text('Editar imagem'), // RΓ³tulo do botΓ£o
              // Personalizando a aparΓͺncia do botΓ£o
              style: OutlinedButton.styleFrom(
                side: BorderSide(
                    color: Color(0XFF4C68FC),
                    width: 1), // Cor e espessura da borda
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(12), // Raio da borda
                ),
                foregroundColor: Color(0XFF4C68FC), // Cor do texto e Γ­cone
              ),
            ),
            const SizedBox(height: 15), // Espaçamento entre widgets
            // Usa um FutureBuilder para esperar pela determinação assíncrona da imagem a mostrar
            Flexible(
              child: FutureBuilder<Uint8List?>(
                future: getImageToShow(),
                builder: (context, snapshot) {
                  if (snapshot.connectionState == ConnectionState.done &&
                      snapshot.hasData) {
                    // A imagem Γ© exibida dentro de um SizedBox para definir suas dimensΓ΅es mΓ‘ximas.
                    // O widget de imagem em si irÑ se adaptar para manter sua proporção dentro deste espaço.
                    return SizedBox(
                      width: double.infinity, // Usa toda a largura disponΓ­vel
                      height: 500, // Altura mΓ‘xima
                      child: Image.memory(
                        snapshot.data!,
                        fit: BoxFit
                            .contain, // Mantém a proporção da imagem sem cortÑ-la
                      ),
                    );
                  } else {
                    // Exibe um placeholder ou um widget de carregamento enquanto a imagem estΓ‘ sendo preparada
                    return SizedBox(
                      width: double.infinity,
                      height: 500,
                      child: Center(child: CircularProgressIndicator()),
                    );
                  }
                },
              ),
            ),
          ],
        ),
      ),
    );
  }
}

[Bug]: Close editor is not working properly

Package Version

2.7.0

Flutter Version

3.19.6

Platforms

Android, iOS

How to reproduce?

After clicking the 'Ok' button on the 'Close Image Editor' popup, it doesn't navigate back. it still displays the 'Result' screen with below code. In your sample code, you called Navigator.pop(context) method to exit 'MainEditor' screen but I want the user to be able to edit when they return from the 'Result' screen then I comment out Navigator.pop(context); in onImageEditingComplete() method.
Better we should have an option for user can custom closeWarning() method (Popup called on PopScope) then they can handle their logic.

  Future<void> onImageEditingComplete(bytes) async {
    editedBytes = bytes;
    // I want the user to be able to edit when they return from the 'Result' screen. That's why I didn't call the Navigator.pop(context) method.
    // Navigator.pop(context);
  }

  void onCloseEditor() {
    if (editedBytes != null) {
      Navigator.push(
        context,
        MaterialPageRoute(
          builder: (context) {
            return PreviewImgPage(imgBytes: editedBytes!);
          },
        ),
      );
    } else {
      Navigator.pop(context);
    }
  }
  1. Open Editor screen and edit something such as add text/emoji
  2. On 'Main Editor' screen, click on 'Done' button. It will be go to 'Result' screen
  3. On 'Result' screen, click on 'Back' button on appbar
  4. On 'Main Editor' screen, click on 'Cancel/Close' button
  5. On 'Close Image Editor' popup, click on 'OK' button.

Actually: Display 'Result' screen
Expected: Pop back, not display the 'Result' screen

Bug on iOS

Describe the bug
There is a bug on iOS with version 2.6.2, but it works fine on Android. I was using version 2.4.3, with this version, I closed the page myself after editing by adding "Navigator.pop(context);" in the "onImageEditingComplete" function. With version 2.6.2, I had to remove the "Navigator.pop(context);" because the package already closed the page with editing on its own, and the bug seems to be caused by that. After an "onImageEditingComplete", there is this error:

======== Exception caught by animation library =====================================================
The following assertion was thrown while notifying status listeners for AnimationController:
setState() or markNeedsBuild() called during build.

This Overlay widget cannot be marked as needing to build because the framework is already in the process of building widgets. A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was: Overlay-[LabeledGlobalKey#e965e]
state: OverlayState#71528(tickers: tracking 0 tickers, entries: [OverlayEntry#ec0b1(opaque: false; maintainState: false), OverlayEntry#d9b02(opaque: false; maintainState: true), OverlayEntry#04268(opaque: false; maintainState: false), OverlayEntry#3731c(opaque: false; maintainState: true), OverlayEntry#19f89(opaque: false; maintainState: false), OverlayEntry#998d6(opaque: false; maintainState: true), OverlayEntry#0aac6(opaque: false; maintainState: false), OverlayEntry#acddb(opaque: false; maintainState: true)])
The widget which was currently being built when the offending call was made was: Builder
dirty
When the exception was thrown, this was the stack:
#0 Element.markNeedsBuild. (package:flutter/src/widgets/framework.dart:5042:9)
#1 Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:5054:6)
#2 State.setState (package:flutter/src/widgets/framework.dart:1223:15)
#3 OverlayState._didChangeEntryOpacity (package:flutter/src/widgets/overlay.dart:792:5)
#4 OverlayEntry.opaque= (package:flutter/src/widgets/overlay.dart:113:15)
#5 TransitionRoute._handleStatusChanged (package:flutter/src/widgets/routes.dart:241:32)
#6 AnimationLocalStatusListenersMixin.notifyStatusListeners (package:flutter/src/animation/listener_helpers.dart:240:19)
#7 AnimationController._checkStatusChanged (package:flutter/src/animation/animation_controller.dart:850:7)
#8 AnimationController._startSimulation (package:flutter/src/animation/animation_controller.dart:781:5)
#9 AnimationController._animateToInternal (package:flutter/src/animation/animation_controller.dart:644:12)
#10 AnimationController.reverse (package:flutter/src/animation/animation_controller.dart:527:12)
#11 TransitionRoute.didPop (package:flutter/src/widgets/routes.dart:305:18)
#12 LocalHistoryRoute.didPop (package:flutter/src/widgets/routes.dart:757:18)
#13 _RouteEntry.handlePop (package:flutter/src/widgets/navigator.dart:3076:16)
#14 NavigatorState._flushHistoryUpdates (package:flutter/src/widgets/navigator.dart:4270:22)
#15 NavigatorState.pop (package:flutter/src/widgets/navigator.dart:5294:7)
#16 LoadingDialog.show. (package:pro_image_editor/widgets/loading_dialog.dart:99:48)
#17 new CupertinoDialogRoute. (package:flutter/src/cupertino/route.dart:1349:25)
#18 RawDialogRoute.buildPage (package:flutter/src/widgets/routes.dart:2160:28)
#19 _ModalScopeState.build.. (package:flutter/src/widgets/routes.dart:973:53)
#20 Builder.build (package:flutter/src/widgets/basic.dart:7698:48)
#21 StatelessElement.build (package:flutter/src/widgets/framework.dart:5550:49)
#22 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5480:15)
#23 Element.rebuild (package:flutter/src/widgets/framework.dart:5196:7)
#24 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2904:19)
#25 WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:989:21)
#26 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:448:5)
#27 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1386:15)
#28 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1311:9)
#29 SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1169:5)
#30 _invoke (dart:ui/hooks.dart:312:13)
#31 PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:399:5)
#32 _drawFrame (dart:ui/hooks.dart:283:31)
The AnimationController notifying status listeners was: AnimationController#15184(β—€ 1.000; for MyPageRoute(null))

I would like to point out that on an iOS simulator, this bug poses no problem, it is just reported and the application continues to work, but when the update of my app was validated on the app store and I tried, I I realized that this was causing the application to crash.

[bug] Unable to load asset 'path to file'

Describe the bug
Unable to load asset error with the following example:

void _openEditor(path) async {
    File file = File(path);
    bool fileExists = await file.exists();
    if (fileExists) {
      print('File exists at: $path');
    } else {
      print('File does not exist at: $path');
    }
    imagePath = path;
    if (!context.mounted) return;
    await Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => ProImageEditor.asset(
          path,
          onImageEditingComplete: (byte) async {
            Directory appDocDir = await getApplicationDocumentsDirectory();
            File file = File('${appDocDir.path}/${DateTime.now().millisecondsSinceEpoch}.jpg');
            await file.writeAsBytes(byte);
            if (!context.mounted) return;
            imagePath = file.path;
            Navigator.pop(context);
          },
        ),
      ),
    );
  }

Knowing that passing and checking if fileExists returns true.

Steps to Reproduce

  1. Take Picture
  2. Call Editor Function
  3. Error appears with exception in editor.

Expected Behavior
To load the image as expected.

[Question] Is it a must to have the ProImageEditor as only component on screen ?

Platforms

No response

Your question

Hi Developer,

I tried to embed the editor into our existing application, where we have the editor in a popup dialog, and some input components on the side :
image

When click the paint, it will enter edit mode (become full screen automatically), can we not go into full screen but stick with the container size and only edit within the container?
image

After edit, it shows correctly in the component,
image
but if we click the paint icon again, you'll see the painting has shifted to left.
image

If we click OK and go back, it still shows correctly outside.

May I know is it a bug or limitation ? That we can only use the editor in full screen without other components?

And, is it possible to have control on the Cancel and OK button to hide them? Because we want to have our own control on the dialog level to save / cancel the image editing.

Thanks!

[Bug]: Example doesn't run on Linux

Package Version

22

Flutter Version

22

Platforms

Linux

How to reproduce?

run exampled

Logs (optional)

Launching lib/main.dart on Linux in debug mode...
CMake Error at CMakeLists.txt:51 (add_subdirectory):
  The source directory

    /home/steve/expr/pro_image_editor/example/linux/flutter

  does not contain a CMakeLists.txt file.


CMake Error at CMakeLists.txt:114 (install):
  install FILES given directory "" to install.


CMake Error at CMakeLists.txt:117 (install):
  install FILES given directory "" to install.


Error: Unable to generate build files

Exited (1).

Example code (optional)

sdfdddd

Device Model (optional)

linux

[bug] Navigator.of(context).pop() from onImageEditingComplete can't return data

Describe the bug
When calling Navigator.of(context).pop('page2'); from inside the onImageEditingComplete event no data is returned.
i expect the string 'page2' to be retuned but the return value remains null. I also tried to use a explicit context that is consitend over the navigation but this still results in null being returned.

I made a simple app to reproduce the issue. Page1 returns 'page1' successfully while Page2 containing the ProImageEditor does not return 'page2'.

main.dart

import 'package:flutter/material.dart';
import 'package:poptest/page1.dart';
import 'package:poptest/page2.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            TextButton(
                onPressed: () => _goToPage1(), child: Text('Go to Page1')),
            TextButton(
                onPressed: () => _goToPage2(), child: Text('Go to Page2')),
          ],
        ),
      ),
    );
  }

  void _goToPage1() async {
    final result = await Navigator.of(context)
        .push(MaterialPageRoute(builder: (context) => Page1()));
    print(result);
  }

  void _goToPage2() async {
    final result = await Navigator.of(context)
        .push(MaterialPageRoute(builder: (context) => Page2()));
    print(result);
  }
}

page1.dart

import 'package:flutter/material.dart';

class Page1 extends StatefulWidget {
  const Page1({super.key});

  @override
  State<Page1> createState() => _Page1State();
}

class _Page1State extends State<Page1> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: TextButton(
          onPressed: () => Navigator.of(context).pop('page1'),
          child: Text('Close page1'),
        ),
      ),
    );
  }
}

page2.dart

import 'package:flutter/material.dart';
import 'package:pro_image_editor/pro_image_editor.dart';

class Page2 extends StatefulWidget {
  const Page2({super.key});

  @override
  State<Page2> createState() => _Page1State();
}

class _Page1State extends State<Page2> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ProImageEditor.network(
        'https://picsum.photos/id/237/2000',
        onImageEditingComplete: (byte) async {
          Navigator.of(context).pop('page2');
        },
      ),
    );
  }
}

Feature Request: Saving/Loading Editor State

Is your feature request related to a problem? Please describe.
It would be great to save and load editor state, e.g. state can be saved as a json file which than can be loaded. My used case would be a server generating elements like text content, etc. and then sending a pre-built state to the app which then loads it.

Describe the solution you'd like
serializable state, something like a json file which contains the layout of elements, as well as information about the transformations applied to the base image (although I expect this second part to be more difficult, the most important thing would be loading elements onto the picture)

Describe alternatives you've considered
The alternative I've considered is well...using a different editor package, but I can't find a suitable one.

Additional context
If I recall correctly, https://github.com/imgly/pesdk-flutter has state serialization/deserialization, but the api is outdated (I can't even build it on android)

Checklist

  • I have searched the existing issues to ensure that this feature has not already been requested or implemented.
  • I understand that feature requests are subject to review and may not be implemented immediately.

Add configuration for output image size

Platforms

Android, iOS

Description

Hi @hm21. Could you help me add an output configuration for image size? For example, if I configure the output image size to be 400x400, then regardless of whether the user edits an image with a larger size, after successful editing, the image will always fit within the 400x400 dimensions. I think it would be better to add padding of 8px or 16px, so the actual content of the image should be 392x392 with 8px padding or 384x384 with 16px padding.
Thank you!

Why

No response

[Bug]: Web: Image shrinks when editted

Package Version

2.7.3

Flutter Version

3.19

Platforms

Web

How to reproduce?

I edit an image and the result is smaller
Screenshot-20240506155433-809x995

Logs (optional)

See the image size on right, every save the image gets smaller and smaller

Example code (optional)

No response

Device Model (optional)

linux

Transparent background and multi layer issues

Firstly, I really appreciate your repository.

During usage, I encountered several issues and am looking forward to your answers:

When I load a PNG image with a transparent background, I cannot achieve pixel-transparent background like Photoshop. I tried setting a transparent background color for the theme, but it seems the transparency effect doesn't work, only solid colors.
imageEditorTheme: const ImageEditorTheme( background: Colors.transparent, )

I also want to implement a multi-layer feature similar to Photoshop. For instance, I first load a PNG image. How can I add a background layer beneath this image to achieve a background change effect? I attempted to use the following code, but it seems calling addLayer multiple times will directly overwrite other layers.
Layer layer = Layer(); _editorKey.currentState?.addLayer(layer, image: ei);
Looking forward to your response. Thank you!

[Bug]: Closing dialog that contains image editor without saving first has exception

Package Version

2.7.9

Flutter Version

3.22

Platforms

Web

How to reproduce?

Put image editor in a dialog. Add an emoji and close the parent dialog without saving first. Seems the warning dialog about saving unsaved changes doesn't work in this case.

Error: Assertion failed: file:///home/steve/development/flutter/packages/flutter/lib/src/widgets/navigator.dart:4817:12
!_debugLocked
is not true
dart-sdk/lib/internal/js_dev_runtime/private/ddc_runtime/errors.dart 296:3 throw
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 29:3 assertFailed
packages/flutter/src/widgets/navigator.dart 4817:13 [_pushEntry]
packages/flutter/src/widgets/navigator.dart 4774:5 push
packages/flutter/src/material/dialog.dart 1436:63 showDialog
packages/flutter/src/material/dialog.dart 1476:14 showAdaptiveDialog
packages/pro_image_editor/modules/main_editor/main_editor.dart 1397:13 closeWarning

Logs (optional)

Error: Assertion failed: file:///home/steve/development/flutter/packages/flutter/lib/src/widgets/navigator.dart:4817:12
!_debugLocked
is not true
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 296:3       throw_
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 29:3        assertFailed
packages/flutter/src/widgets/navigator.dart 4817:13                               [_pushEntry]
packages/flutter/src/widgets/navigator.dart 4774:5                                push
packages/flutter/src/material/dialog.dart 1436:63                                 showDialog
packages/flutter/src/material/dialog.dart 1476:14                                 showAdaptiveDialog
packages/pro_image_editor/modules/main_editor/main_editor.dart 1397:13            closeWarning
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 84:54                runBody
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 127:5                _async
packages/pro_image_editor/modules/main_editor/main_editor.dart 1389:20            closeWarning
packages/pro_image_editor/modules/main_editor/main_editor.dart 1543:15            <fn>
packages/flutter/src/widgets/routes.dart 1739:30                                  onPopInvoked
packages/flutter/src/widgets/navigator.dart 3112:5                                pop
packages/flutter/src/widgets/navigator.dart 5287:12                               pop
packages/shared_ui/src/dialogs/dialog_base.dart 126:29                            <fn>
packages/flutter/src/material/ink_well.dart 1171:21                               handleTap
packages/flutter/src/gestures/recognizer.dart 344:24                              invokeCallback
packages/flutter/src/gestures/tap.dart 652:11                                     handleTapUp
packages/flutter/src/gestures/tap.dart 309:5                                      [_checkUp]
packages/flutter/src/gestures/tap.dart 242:7                                      handlePrimaryPointer

Example code (optional)

No response

Device Model (optional)

No response

stickers should can be selected and drag to rotate

Platforms

Android, iOS

Description

stickers should can be selected and drag to rotate, when click to a sticker or text or anything, it should be seen selected (may be have a border), and can drag or rotate

Why

it is very common and important to a image editor

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.