Repository: flutter
Issue: RawImage Leaks when the image is changed
Labels: framework,P2,team-framework,triaged-framework

### Steps to reproduce

Use RawImage, change the image it references every frame, it will leak the images and run flutter out of memory (flutter web).


A while back I looked into RawImage to see why it was leaking. Looks like it clones your image handle before it passes it to RenderImage:

https://github.com/flutter/flutter/blob/1fb077118d0a4d576fa7eb82c05f07f4748e4bf3/packages/flutter/lib/src/widgets/basic.dart#L6131

But then RenderImage only disposes the image when it changes if it's a clone of the image that it currently has:

https://github.com/flutter/flutter/blob/1fb077118d0a4d576fa7eb82c05f07f4748e4bf3/packages/flutter/lib/src/rendering/image.dart#L92


### Expected results

Don't crash flutter

### Actual results

Flutter runs out of memory in canvaskit heap

### Code sample

```dart
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'dart:ui' as ui;
import 'dart:math';
import 'dart:async';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Center(
          child: RandomImageWidget()
        ),
      ),
    );
  }
}



class RandomImageWidget extends StatefulWidget {
  @override
  _RandomImageWidgetState createState() => _RandomImageWidgetState();
}

class _RandomImageWidgetState extends State<RandomImageWidget> with SingleTickerProviderStateMixin {
  ui.Image? _image;
  late Ticker _ticker;
  final _random = Random();

  @override
  void initState() {
    super.initState();
    _ticker = createTicker((_) {
      // Generate a new random image each frame.
      _generateRandomImage();
    });
    _ticker.start();
  }

  @override
  void dispose() {
    _ticker.dispose();
    super.dispose();
  }

  Future<void> _generateRandomImage() async {
    final width =1000;
    final height = 1000;

    // Create a PictureRecorder and Canvas to draw on.
    final recorder = ui.PictureRecorder();
    final canvas = Canvas(recorder);

    final paint = Paint()..style = PaintingStyle.fill;
    
    // Draw a random color for each pixel.
    for (int y = 0; y < height; y++) {
      for (int x = 0; x < width; x++) {
        paint.color = Color.fromARGB(
          255,
          _random.nextInt(256),
          _random.nextInt(256),
          _random.nextInt(256),
        );
        canvas.drawRect(Rect.fromLTWH(x.toDouble(), y.toDouble(), 1, 1), paint);
      }
    }

    // Finalize drawing and create an image.
    final picture = recorder.endRecording();
    final image = await picture.toImage(width, height);

    // Update the state with the newly generated image.
    setState(() {
      _image?.dispose();
      _image = image;
    });
  }

  @override
  Widget build(BuildContext context) {
    return RawImage(
      image: _image,
      width: 200,
      height: 200,
    );
  }
}
```
### Screenshots or Video

<details open>
<summary>Screenshots / Video demonstration</summary>

[Upload media here]

</details>


### Logs

<details open><summary>Logs</summary>

```console
[Paste your logs here]
```

</details>


### Flutter Doctor output

<details open><summary>Doctor output</summary>

```console
[Paste your output here]
```

</details>