Repository: flutter
Issue: Image generated from repaintboundary.toImage() does not exceeds from fix resolution on different devices
Labels: framework,a: images,has reproducible steps,P2,found in release: 3.3,found in release: 3.7,team-framework,triaged-framework

I am trying to convert widget to image but when widget is very big then repaintBoundary.toImage() scaled down and image does not exceed above specific resolution.

ui.Image? image = await repaintBoundary?.toImage(pixelRatio: pixelRatio);

**RepaintBoundary Size before repaintBoundary.toImage()** 
![Inkedrepaintboundary](https://user-images.githubusercontent.com/25194088/210725518-14723e01-e845-4013-be16-6c32e4e986f1.jpg)

**Image size after repaintBoundary.toImage()**
![Inkedimage](https://user-images.githubusercontent.com/25194088/210725670-616744c8-c25d-46e7-8483-7fcbb6857dfc.jpg)


```
[√] Flutter (Channel stable, 3.3.10, on Microsoft Windows [Version 10.0.19044.2364], locale en-US)
    • Flutter version 3.3.10 on channel stable at C:\Users\Office1\Downloads\Compressed\flutter_windows_3.3.5-stable\flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 135454af32 (3 weeks ago), 2022-12-15 07:36:55 -0800
    • Engine revision 3316dd8728
    • Dart version 2.18.6
    • DevTools version 2.15.0

[!] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
    • Android SDK at C:\Users\Office1\AppData\Local\Android\Sdk
    • Platform android-33, build-tools 33.0.0
    • ANDROID_HOME = C:\Users\Office1\AppData\Local\Android\Sdk
    • Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java
    • Java version openjdk version "11.0.13" 2021-10-19
    X Android license status unknown.
      Run `flutter doctor --android-licenses` to accept the SDK licenses.
      See https://flutter.dev/docs/get-started/install/windows#android-setup for more details.

[√] Chrome - develop for the web
    • Chrome at C:\Program Files\Google\Chrome\Application\chrome.exe

[X] Visual Studio - develop for Windows
    X Visual Studio not installed; this is necessary for Windows development.
      Download at https://visualstudio.microsoft.com/downloads/.
      Please install the "Desktop development with C++" workload, including all of its default components

[√] Android Studio (version 2021.3)
    • Android Studio at C:\Program Files\Android\Android Studio
    • Flutter plugin can be installed from:
       https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
       https://plugins.jetbrains.com/plugin/6351-dart
    • Java version openjdk version "11.0.13" 2021-10-19

[√] VS Code (version 1.73.1)
    • VS Code at C:\Users\Office1\AppData\Local\Programs\Microsoft VS Code
    • Flutter extension can be installed from:
       https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter
[√] Connected device (3 available)
    • Windows (desktop) • windows • windows-x64    • Microsoft Windows [Version 10.0.19044.2364]
    • Chrome (web)      • chrome  • web-javascript • Google Chrome 108.0.5359.125
    • Edge (web)        • edge    • web-javascript • Microsoft Edge 108.0.1462.54

[√] HTTP Host Availability
    • All required HTTP hosts are available

```

```
import 'package:capture_image/capture_controller.dart';
import 'package:capture_image/capture_widget.dart';
import 'package:capture_image/test_widget.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
final navigatorKey = GlobalKey<NavigatorState>();

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  MyApp({super.key});


  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      title: 'Flutter Demo',
      navigatorKey: navigatorKey,
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or simply save your changes to "hot reload" in a Flutter IDE).
        // Notice that the counter didn't reset back to zero; the application
        // is not restarted.
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  // This widget is the home page of your application. It is stateful, meaning
  // that it has a State object (defined below) that contains fields that affect
  // how it looks.

  // This class is the configuration for the state. It holds the values (in this
  // case the title) provided by the parent (in this case the App widget) and
  // used by the build method of the State. Fields in a Widget subclass are
  // always marked "final".

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  CaptureController captureController = Get.put(CaptureController());


  Future _incrementCounter() async {
    captureController.updatePrintingWidet(TestWidget().obs);
    List<CaptureResult>? list = await captureController.showAndCaptureDialog();
    print(list);
  }

  @override
  Widget build(BuildContext context) {
    // This method is rerun every time setState is called, for instance as done
    // by the _incrementCounter method above.
    //
    // The Flutter framework has been optimized to make rerunning build methods
    // fast, so that you can just rebuild anything that needs updating rather
    // than having to individually change instances of widgets.
    return Scaffold(
      appBar: AppBar(
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        title: Text(widget.title),
      ),
      body: Center(
        // Center is a layout widget. It takes a single child and positions it
        // in the middle of the parent.
        child: Column(
          // Column is also a layout widget. It takes a list of children and
          // arranges them vertically. By default, it sizes itself to fit its
          // children horizontally, and tries to be as tall as its parent.
          //
          // Invoke "debug painting" (press "p" in the console, choose the
          // "Toggle Debug Paint" action from the Flutter Inspector in Android
          // Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
          // to see the wireframe for each widget.
          //
          // Column has various properties to control how it sizes itself and
          // how it positions its children. Here we use mainAxisAlignment to
          // center the children vertically; the main axis here is the vertical
          // axis because Columns are vertical (the cross axis would be
          // horizontal).
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}


```

```
import 'package:flutter/material.dart';

class TestWidget extends StatefulWidget {
  const TestWidget({Key? key}) : super(key: key);

  @override
  State<TestWidget> createState() => _TestWidgetState();
}

class _TestWidgetState extends State<TestWidget> {
  @override
  Widget build(BuildContext context) {
    return Column(
      children:getitemList()
    );
  }

  List<Widget> getitemList()
  {
    List<Widget> list = [];
    for(int i = 0 ;i< 2000; i++)
      {
        list.add(Text("Number $i"));
      }
    return list;
  }
}


```

```
import 'package:capture_image/capture_widget.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';


import 'main.dart';

class CaptureController extends GetxController {
  RxInt captureSize = 384.obs;
  Rx<GlobalKey<CaptureWidgetState>>? captureKey;
  Rx<Widget> printingWidget = Container().obs;

  updatePrintingWidet(Rx<Widget> widget) {
    printingWidget = widget;
    this.update();
  }

  Future<List<CaptureResult>?> showAndCaptureDialog() async {
    bool isBuild = false;
    List<CaptureResult>? list=[];
    captureKey = GlobalKey<CaptureWidgetState>().obs;

    /*await showDialog(context: Get.context!,
        barrierDismissible: false,
        builder: (_){
          return Material(child: SingleChildScrollView(child: Container(width: 384,child: printingWidget.value),),);
        });*/

    await Future.delayed(Duration(milliseconds: 500));
    await showDialog(
        barrierColor: Colors.white.withOpacity(0),
        barrierDismissible: false,
        context:navigatorKey.currentContext!,
        builder: (_) {
          return CaptureWidget(
            key: captureKey!.value,
            child: Container(),
            capture: printingWidget.value,
            callBack: (isBuildComplete) async {
              isBuild = isBuildComplete;
             await Future.delayed(Duration(milliseconds: 50));
              list= await captureKey!.value.currentState?.captureImage();
              Navigator.of(navigatorKey.currentContext!).pop();
            },
          );
        });
    return list;
  }
}

```

```
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'dart:ui';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:get/get.dart';

import 'package:flutter/foundation.dart';

class CaptureWidget extends StatefulWidget {
  final Widget? child;
  final Widget? capture;
  final TextDirection textDirection;
  final Function(bool)? callBack;

  const CaptureWidget({Key? key, this.capture, this.child, this.textDirection = ui.TextDirection.ltr, this.callBack}) : super(key: key);

  @override
  CaptureWidgetState createState() => CaptureWidgetState();
}

enum ReceipSize
{
  TWO_INCH,
  THREE_INCH,
  FOUR_INCH
}

class CaptureWidgetState extends State<CaptureWidget> {

  final GlobalKey<CaptureWidgetState> _printReceiptBoundaryKey= GlobalKey<CaptureWidgetState>();
/*  final GlobalKey<CaptureWidgetState> _boundaryKey3= GlobalKey<CaptureWidgetState>();
  final GlobalKey<CaptureWidgetState> _boundaryKey4= GlobalKey<CaptureWidgetState>();*/


  RxDouble preProcessReceiptSize = 0.0.obs;


  Future<CaptureResult> repaintBoundaryToImage(GlobalKey key, {double pixelRatio = 1.0}) {
    return new Future.delayed(const Duration(milliseconds: 20), () async {
      RenderRepaintBoundary? repaintBoundary;

      if (key.currentContext != null) {
        repaintBoundary = (key.currentContext?.findRenderObject()) as RenderRepaintBoundary;
      }

      if (kDebugMode && repaintBoundary != null) {
        if (repaintBoundary.debugNeedsPaint) {
          print("Waiting for boundary to be painted.");
          await Future.delayed(const Duration(milliseconds: 500));
          return repaintBoundaryToImage(key);
        }
      }
      ui.Image? image = await repaintBoundary?.toImage(pixelRatio: pixelRatio);

      ByteData? byteData = await image?.toByteData(format: ui.ImageByteFormat.png);

      return CaptureResult(byteData?.buffer?.asUint8List(), image?.width, image?.height);
    });
  }

/*  Uint8List resizeImage(Uint8List data,Size size) {
    Uint8List resizedData = data;
    IMG.Image img = IMG.decodeImage(data);
    IMG.Image resized = IMG.copyResize(img, width: size.width.ceil(), height: size.height.ceil());
    resizedData = IMG.encodeJpg(resized);
    return resizedData;
  }*/

  Future<List<CaptureResult>> captureImage() async {
    List<CaptureResult> list = <CaptureResult>[];
    preProcessReceiptSize.value = 384;
    await Future.delayed(const Duration(milliseconds: 100));
    final captureResult2 = await repaintBoundaryToImage(_printReceiptBoundaryKey);
    preProcessReceiptSize.value = 576;
    await Future.delayed(const Duration(milliseconds: 100));
    final captureResult3 = await repaintBoundaryToImage(_printReceiptBoundaryKey);
    preProcessReceiptSize.value = 832;
    await Future.delayed(const Duration(milliseconds: 100));
    final captureResult4 = await repaintBoundaryToImage(_printReceiptBoundaryKey);
    list.add(captureResult2);
    list.add(captureResult3);
    list.add(captureResult4);
    return list;
  }

  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
      await Future.delayed(const Duration(milliseconds: 800));
      widget.callBack!(true);
    });
  }

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(builder: (context, constraint) {
      print(constraint.maxHeight);
      print(constraint.maxWidth);
      return Stack(
        fit: StackFit.expand,
        children: <Widget>[
          widget.child!,
          Positioned(
              left: 0,
              right: 0,
              top: MediaQuery.of(context).size.height * 2,
              child: Center(
                  child: SingleChildScrollView(
                child: SingleChildScrollView(
                  scrollDirection: Axis.horizontal,
                  child: RepaintBoundary(
                    key: _printReceiptBoundaryKey,
                    child: Obx(()=> SizedBox(
                          width: preProcessReceiptSize.value,
                          child: Material(
                            color: Colors.white,
                            child: widget.capture,
                          )),
                    ),
                  ),
                ),
              ))),
          /*Positioned(
              left: 0,
              right: 0,
              top: MediaQuery.of(context).size.height * 2,
              child: Center(
                  child: SingleChildScrollView(
                child: SingleChildScrollView(
                  scrollDirection: Axis.horizontal,
                  child: RepaintBoundary(
                    key: _boundaryKey3,
                    child: SizedBox(
                        width: double.parse(PrinterSizeEnum.PRINTABLE_AREA_3_INCH.toString()),
                        child: Material(
                          color: Colors.white,
                          child: widget.capture,
                        )),
                  ),
                ),
              ))),*/
          /*Positioned(
              left: 0,
              right: 0,
              top: MediaQuery.of(context).size.height * 2,
              child: Center(
                  child: SingleChildScrollView(
                child: SingleChildScrollView(
                  scrollDirection: Axis.horizontal,
                  child: RepaintBoundary(
                      key: _boundaryKey4,
                      child: SizedBox(
                          width: double.parse(PrinterSizeEnum.PRINTABLE_AREA_4_INCH.toString()),
                          child: Material(color: Colors.white, child: widget.capture))),
                ),
              ))),*/
        ],
      );
    });
  }
}

class CaptureResult {
  final Uint8List? data;
  final int? width;
  final int? height;

  const CaptureResult(this.data, this.width, this.height);
}

```