imcodec_native 0.1.4 copy "imcodec_native: ^0.1.4" to clipboard
imcodec_native: ^0.1.4 copied to clipboard

Optional AVIF, HEIF/HEIC, JPEG XL and WebP codecs for Imcodec, with bundled native and WebAssembly engines on all Flutter platforms.

example/lib/main.dart

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:imcodec_native/imcodec_native.dart' as codec;

/// Initializes optional codecs before launching the cross-platform demo.
Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await codec.ImcodecNative.initialize();
  runApp(const CodecExample());
}

/// Demonstrates runner-based encoding and generic format detection.
class CodecExample extends StatefulWidget {
  /// Creates the demo application.
  const CodecExample({super.key});

  @override
  State<CodecExample> createState() => _CodecExampleState();
}

/// Owns only the ephemeral status and preview of the latest conversion.
class _CodecExampleState extends State<CodecExample> {
  /// PNG preview of the last decoded result.
  Uint8List? _preview;

  /// Conversion result or user-visible failure.
  String _status = 'Select a format to encode a synthetic RGBA image.';

  /// Prevents overlapping button actions.
  bool _busy = false;

  /// Runs native encoding through Imcodec's platform-appropriate runner.
  Future<void> _convert(codec.ImageFormat format) async {
    setState(() => _busy = true);
    try {
      final codec.Image source = codec.Image(width: 192, height: 128);
      for (int y = 0; y < source.height; y++) {
        for (int x = 0; x < source.width; x++) {
          source.setPixelRgba(x, y, x * 255 ~/ 191, y * 255 ~/ 127, 180, (x + y) % 32 < 16 ? 255 : 128);
        }
      }
      const codec.ParallelRunner runner = kIsWeb ? codec.runSequentially : codec.onBoundedIsolates;
      final Uint8List bytes = switch (format) {
        codec.NativeImageFormat.avif => await codec.encodeAvifWith(
          runner,
          source,
          options: const codec.AvifEncodeOptions(speed: 9),
        ),
        codec.NativeImageFormat.heif => await codec.encodeHeifWith(runner, source),
        codec.ImageFormat.jpegXl => await codec.encodeJpegXlWith(
          runner,
          source,
          options: const codec.JpegXlEncodeOptions(
            effort: codec.JpegXlEffort.fast,
          ),
        ),
        codec.ImageFormat.webp => await codec.encodeWebPWith(runner, source),
        _ => throw UnsupportedError('Unsupported demo format'),
      };
      final codec.Image decoded = switch (format) {
        codec.NativeImageFormat.avif => await codec.decodeAvifAsync(bytes),
        codec.NativeImageFormat.heif => await codec.decodeHeifAsync(bytes),
        codec.ImageFormat.jpegXl => await codec.decodeJpegXlAsync(bytes),
        codec.ImageFormat.webp => await codec.decodeWebPAsync(bytes),
        _ => throw UnsupportedError('Unsupported demo format'),
      };
      if (!mounted) {
        return;
      }
      setState(() {
        _preview = codec.encodePng(decoded);
        _status = '${codec.ImageFormat.sniff(bytes)?.name}: ${bytes.length} bytes, ${decoded.width} × ${decoded.height}';
      });
    } on Object catch (error) {
      if (mounted) {
        setState(() => _status = error.toString());
      }
    } finally {
      if (mounted) {
        setState(() => _busy = false);
      }
    }
  }

  @override
  Widget build(BuildContext context) => MaterialApp(
    home: Scaffold(
      appBar: AppBar(title: const Text('ImcodecNative')),
      body: Center(
        child: Padding(
          padding: const EdgeInsets.all(24),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              SelectableText(codec.ImcodecNative.backendVersion),
              const SizedBox(height: 24),
              Wrap(
                spacing: 12,
                runSpacing: 12,
                children: [
                  for (final codec.ImageFormat format in [codec.NativeImageFormat.avif, codec.NativeImageFormat.heif, codec.ImageFormat.jpegXl, codec.ImageFormat.webp])
                    FilledButton(onPressed: _busy ? null : () => _convert(format), child: Text(format.name)),
                ],
              ),
              const SizedBox(height: 24),
              if (_busy) const CircularProgressIndicator(),
              if (_preview case final Uint8List bytes) Image.memory(bytes, width: 384, gaplessPlayback: true),
              const SizedBox(height: 12),
              Text(_status),
            ],
          ),
        ),
      ),
    ),
  );
}
0
likes
150
points
126
downloads
screenshot

Documentation

API reference

Publisher

verified publisherfocale-editor.app

Weekly Downloads

Optional AVIF, HEIF/HEIC, JPEG XL and WebP codecs for Imcodec, with bundled native and WebAssembly engines on all Flutter platforms.

Repository (GitHub)
View/report issues
Contributing

Topics

#image #codec #native-assets #webassembly #flutter

License

MIT (license)

Dependencies

code_assets, crypto, ffi, flutter, hooks, imcodec, web

More

Packages that depend on imcodec_native