{"id":13670563,"url":"https://github.com/alibaba/power_image","last_synced_at":"2025-10-14T08:46:36.109Z","repository":{"id":37726372,"uuid":"493561541","full_name":"alibaba/power_image","owner":"alibaba","description":"A powerful plugin that fully uses the native image library's ability to display images on the flutter side.","archived":false,"fork":false,"pushed_at":"2023-10-16T10:36:22.000Z","size":2573,"stargazers_count":514,"open_issues_count":25,"forks_count":55,"subscribers_count":12,"default_branch":"main","last_synced_at":"2025-04-27T13:37:26.593Z","etag":null,"topics":["flutter","image"],"latest_commit_sha":null,"homepage":"","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alibaba.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2022-05-18T07:47:34.000Z","updated_at":"2025-04-24T16:56:09.000Z","dependencies_parsed_at":"2024-01-14T16:16:31.314Z","dependency_job_id":"4c2737ea-1445-4b81-8c75-1aa51eddb007","html_url":"https://github.com/alibaba/power_image","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/alibaba/power_image","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alibaba%2Fpower_image","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alibaba%2Fpower_image/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alibaba%2Fpower_image/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alibaba%2Fpower_image/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alibaba","download_url":"https://codeload.github.com/alibaba/power_image/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alibaba%2Fpower_image/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279018299,"owners_count":26086345,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-14T02:00:06.444Z","response_time":60,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["flutter","image"],"created_at":"2024-08-02T09:00:45.498Z","updated_at":"2025-10-14T08:46:31.087Z","avatar_url":"https://github.com/alibaba.png","language":"Dart","funding_links":[],"categories":["UI库"],"sub_categories":[],"readme":"# PowerImage\n\nA powerful plugin that fully uses the native image library's ability to display images on the flutter side.\n\n[中文文档](https://github.com/alibaba/power_image/blob/main/README_CN.md)\n\n**Features:**\n\n- Supports the ability to load ui.Image. In the solution based on external texture, the user could not get the real ui.Image to use, which made the image library powerless in this special usage scenario.\n\n- Support image preloading capability. Just like flutter precacheImage. This is very useful in some scenarios that require high image display speed.\n\n- Added texture cache to connect with flutter's imageCache! Unified image cache to avoid memory problems caused by mixing native images.\n\n- Emulators are supported. Before flutter-1.23.0-18.1.pre, the emulator could not display Texture Widget.\n\n- Improve the custom image type channel. Solve the demand for business custom image acquisition.\n\n- Perfect exception capture and collection.\n\n- Support animation. (PR from LiteTao)\n\n\n# Usage\n\n## Installation\n\n- power_image：It is recommended to use the latest version, [power_image pub versions](https://pub.dev/packages/power_image/versions)\n- power_image_ext：You need to choose the version based on the flutter version you are using.  Go to [power_image_ext](https://github.com/alibaba/power_image_ext) for details！[power_image_ext pub versions](https://pub.dev/packages/power_image_ext/versions)\n\nAdd the following to your `pubspec.yaml` file:\n```yaml\ndependencies:\n  power_image: 0.1.0-pre.2\n      \ndependency_overrides:\n  power_image_ext: 2.5.3\n```\n\nor use code in github directly:\n\n```yaml\ndependencies:\n  power_image:\n    git:\n      url: 'git@github.com:alibaba/power_image.git'\n      ref: '0.1.0-pre.2'\n      \ndependency_overrides:\n  power_image_ext:\n    git:\n      url: 'git@github.com:alibaba/power_image_ext.git'\n      ref: '2.5.3'\n```\n\n## Setup\n\n### Flutter\n#### 1. Replace `ImageCache` with `ImageCacheExt`.\n\n```dart\n/// call before runApp()\nPowerImageBinding();\n```\nor\n```dart\n/// return ImageCacheExt in createImageCache(), \n/// if you have extends with WidgetsFlutterBinding\nclass XXX extends WidgetsFlutterBinding {\n  @override\n  ImageCache createImageCache() {\n    return ImageCacheExt();\n  }\n}\n```\n\n\n\n#### 2. Setup PowerImageLoader\nInitialize and set the global default rendering mode, renderingTypeTexture is texture mode, renderingTypeExternal is ffi mode\nIn addition, there are exception reports in PowerImageSetupOptions, and the sampling rate of exception reports can be set.\n```dart\n    PowerImageLoader.instance.setup(PowerImageSetupOptions(renderingTypeTexture,\n        errorCallbackSamplingRate: 1.0,\n        errorCallback: (PowerImageLoadException exception) {\n\n    }));\n```\n\n\n\n### iOS\n\nPowerImage provides basic image types, including network, file, nativeAsset, and flutter assets. Users need to customize their corresponding loaders.\n\n#### OC\n\n```objectivec\n    [[PowerImageLoader sharedInstance] registerImageLoader:[PowerImageNetworkImageLoader new] forType:kPowerImageImageTypeNetwork];\n    [[PowerImageLoader sharedInstance] registerImageLoader:[PowerImageAssetsImageLoader new] forType:kPowerImageImageTypeNativeAsset];\n    [[PowerImageLoader sharedInstance] registerImageLoader:[PowerImageFlutterAssertImageLoader new] forType:kPowerImageImageTypeAsset];\n    [[PowerImageLoader sharedInstance] registerImageLoader:[PowerImageFileImageLoader new] forType:kPowerImageImageTypeFile];\n```\n\n#### Swift\n\n```swift\n        PowerImageLoader.sharedInstance().register(PowerImageNetworkImageLoader.init(), forType: kPowerImageImageTypeNetwork)\n        PowerImageLoader.sharedInstance().register(PowerImageAssetsImageLoader.init(), forType: kPowerImageImageTypeNativeAsset)\n        PowerImageLoader.sharedInstance().register(PowerImageFlutterAssertImageLoader.init(), forType: kPowerImageImageTypeAsset)\n        PowerImageLoader.sharedInstance().register(PowerImageFileImageLoader.init(), forType: kPowerImageImageTypeFile)\n```\n\n\nThe loader needs to follow the PowerImageLoaderProtocol protocol:\n\n```objectivec\ntypedef void(^PowerImageLoaderCompletionBlock)(BOOL success, PowerImageResult *imageResult);\n\n@protocol PowerImageLoaderProtocol \u003cNSObject\u003e\n@required\n- (void)handleRequest:(PowerImageRequestConfig *)requestConfig completed:(PowerImageLoaderCompletionBlock)completedBlock;\n@end\n```\n\n\n\nNetwork image loader example:\n\n#### OC\n\n```objectivec\n- (void)handleRequest:(PowerImageRequestConfig *)requestConfig completed:(PowerImageLoaderCompletionBlock)completedBlock {\n    \n    /// CDN optimization, you need transfer reqSize to native image loader!\n    /// CDN optimization, you need transfer reqSize to native image loader!\n    /// like this: [[SDWebImageManager sharedManager] downloadImageWithURL:[NSURL URLWithString:requestConfig.srcString] viewSize:reqSize completed:\n    CGSize reqSize = requestConfig.originSize;\n    /// attention.\n\n    \n    [[SDWebImageManager sharedManager] loadImageWithURL:[NSURL URLWithString:requestConfig.srcString] options:nil progress:^(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL) {\n\n        } completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {\n            if (image != nil) {\n                completedBlock([PowerImageResult successWithImage:image]);\n            }else {\n                completedBlock([PowerImageResult failWithMessage:error.localizedDescription]);\n            }\n    }];\n\n}\n```\n\n#### Swift\n\n```swift\n\nfunc handleRequest(_ requestConfig: PowerImageRequestConfig!, completed completedBlock: PowerImageLoaderCompletionBlock!) {\n        let reqSize:CGSize = requestConfig.originSize\n        let url = URL(string: requestConfig.srcString())\n        SDWebImageManager.shared.loadImage(with: url, progress: nil) { image, data, error, cacheType, finished, url in\n            \n            if let image = image {\n                if (image.sd_isAnimated) {\n                    let frames:[SDImageFrame] = SDImageCoderHelper.frames(from: image)!\n                    if frames.count \u003e 0 {\n                        var arr:[PowerImageFrame] = []\n                        for index in 0..\u003cframes.count {\n                            let frame:SDImageFrame = frames[index]\n                            arr.append(PowerImageFrame(image: frame.image, duration: frame.duration))\n                        }\n                        let flutterImage = PowerFlutterMultiFrameImage(image: image, frames: arr)\n                        completedBlock(PowerImageResult.success(with: flutterImage))\n                        return\n                    }\n                }\n                \n                completedBlock(PowerImageResult.success(with: image))\n                \n            }else{\n                completedBlock(PowerImageResult.fail(withMessage: error?.localizedDescription ?? \"PowerImageNetworkLoaderError!\"))\n            }   \n       }\n}\n```\n\nnative asset loader example:\n#### OC\n```objectivec\n- (void)handleRequest:(PowerImageRequestConfig *)requestConfig completed:(PowerImageLoaderCompletionBlock)completedBlock {\n    UIImage *image = [UIImage imageNamed:requestConfig.srcString];\n    if (image) {\n        completedBlock([PowerImageResult successWithImage:image]);\n    }else {\n        completedBlock([PowerImageResult failWithMessage:@\"MyAssetsImageLoader UIImage imageNamed: nil\"]);\n    }\n}\n```\n#### Swift\n```swift\n\nfunc handleRequest(_ requestConfig: PowerImageRequestConfig!, completed completedBlock: PowerImageLoaderCompletionBlock!) {\n        \n        let image = UIImage(named: requestConfig.srcString())\n        \n        if let image = image {\n            completedBlock(PowerImageResult.success(with: image))\n        }else{\n            completedBlock(PowerImageResult.fail(withMessage: \"PowerImageAssetsImageLoaderError!\"))\n        }\n    }\n\n```\n\nflutter asset loader example:\n#### OC\n```objectivec\n- (void)handleRequest:(PowerImageRequestConfig *)requestConfig completed:(PowerImageLoaderCompletionBlock)completedBlock {\n    UIImage *image = [self flutterImageWithName:requestConfig];\n    if (image) {\n        completedBlock([PowerImageResult successWithImage:image]);\n    } else {\n        completedBlock([PowerImageResult failWithMessage:@\"flutterImageWithName nil\"]);\n    }\n}\n\n- (UIImage*)flutterImageWithName:(PowerImageRequestConfig *)requestConfig {\n    NSString *name = requestConfig.srcString;\n    NSString *package = requestConfig.src[@\"package\"];\n    NSString *filename = [name lastPathComponent];\n    NSString *path = [name stringByDeletingLastPathComponent];\n    for (int screenScale = [UIScreen mainScreen].scale; screenScale \u003e 1; --screenScale) {\n        NSString *key = [self lookupKeyForAsset:[NSString stringWithFormat:@\"%@/%d.0x/%@\", path, screenScale, filename] fromPackage:package];\n        UIImage *image = [UIImage imageNamed:key inBundle:[NSBundle mainBundle] compatibleWithTraitCollection:nil];\n        if (image) {\n            return image;\n        }\n    }\n    NSString *key = [self lookupKeyForAsset:name fromPackage:package];\n\n    /// webp iOS \u003c 14 not support \n    if ([name hasSuffix:@\".webp\"] \u0026\u0026 !(@available(ios 14.0, *))) {\n        NSString *mPath = [[NSBundle mainBundle] pathForResource:key ofType:nil];\n        NSData *webpData = [NSData dataWithContentsOfFile:mPath];\n        return [UIImage sd_imageWithWebPData:webpData];\n    }\n    return [UIImage imageNamed:key inBundle:[NSBundle mainBundle] compatibleWithTraitCollection:nil];\n}\n\n- (NSString *)lookupKeyForAsset:(NSString *)asset fromPackage:(NSString *)package {\n    if (package \u0026\u0026 [package isKindOfClass:[NSString class]] \u0026\u0026 ![package isEqualToString:@\"\"]) {\n        return [FlutterDartProject lookupKeyForAsset:asset fromPackage:package];\n    }else {\n        return [FlutterDartProject lookupKeyForAsset:asset];\n    }\n}\n\n```\n\n#### Swift\n\n```swift\n\nfunc handleRequest(_ requestConfig: PowerImageRequestConfig!, completed completedBlock: PowerImageLoaderCompletionBlock!) {\n        let image = self.flutterImage(requestConfig: requestConfig)\n        if let image = image {\n            completedBlock(PowerImageResult.success(with: image))\n        }else {\n            completedBlock(PowerImageResult.fail(withMessage: \"PowerImageFlutterAssertImageLoaderError\"))\n        }\n    }\n    \n    \n    private func flutterImage(requestConfig:PowerImageRequestConfig) -\u003e UIImage? {\n        \n        let name:String = requestConfig.srcString()!\n        let package:String? = requestConfig.src[\"package\"] as? String\n        let fileName:String = NSString(string: name).lastPathComponent\n        let path:String = NSString(string: name).deletingLastPathComponent\n        \n        \n        let scaleArr:[Int] = (2...Int(UIScreen.main.scale)).reversed()\n        \n        for scale in scaleArr {\n            let key:String = self.lookupKeyForAsset(asset: String(format: \"%s/%d.0x/%s\", path,scale,fileName), package: package)\n            let image = UIImage(named: key,in: Bundle.main,compatibleWith: nil)\n            if image != nil {\n                return image!\n            }\n        }\n        \n        let key = self.lookupKeyForAsset(asset: name, package: package)\n        return UIImage(named: key,in: Bundle.main,compatibleWith: nil)\n    }\n    \n    private func lookupKeyForAsset(asset:String,package:String?) -\u003e String {\n        if let package = package, package != \"\" {\n            return FlutterDartProject.lookupKey(forAsset: asset,fromPackage: package)\n        }else{\n            return FlutterDartProject.lookupKey(forAsset: asset)\n        }\n    }\n\n```\n\nfile loader example:\n#### OC\n```objectivec\n- (void)handleRequest:(PowerImageRequestConfig *)requestConfig completed:(PowerImageLoaderCompletionBlock)completedBlock {\n    \n    UIImage *image = [[UIImage alloc] initWithContentsOfFile:requestConfig.srcString];\n\n    if (image) {\n        completedBlock([PowerImageResult successWithImage:image]);\n    } else {\n        completedBlock([PowerImageResult failWithMessage:@\"UIImage initWithContentsOfFile nil\"]);\n    }\n}\n```\n\n#### Swift\n\n```swift\n\nfunc handleRequest(_ requestConfig: PowerImageRequestConfig!, completed completedBlock: PowerImageLoaderCompletionBlock!) {\n        \n        let image = UIImage(contentsOfFile: requestConfig.srcString())\n        \n        if let image = image {\n            completedBlock(PowerImageResult.success(with: image))\n        }else{\n            completedBlock(PowerImageResult.fail(withMessage: \"PowerImageFileImageLoaderError!\"))\n        }\n    }\n\n```\n\n\n### Android\nPowerImage provides basic image types, including network, file, nativeAsset, and flutter assets. Users need to customize their corresponding loaders.\n\n#### Java\n\n```java\nPowerImageLoader.getInstance().registerImageLoader(\n                new PowerImageNetworkLoader(this.getApplicationContext()), \"network\");\nPowerImageLoader.getInstance().registerImageLoader(\n                new PowerImageNativeAssetLoader(this.getApplicationContext()), \"nativeAsset\");\nPowerImageLoader.getInstance().registerImageLoader(\n                new PowerImageFlutterAssetLoader(this.getApplicationContext()), \"asset\");\nPowerImageLoader.getInstance().registerImageLoader(\n                new PowerImageFileLoader(this.getApplicationContext()), \"file\");\n```\n\n#### Kotlin\n\n```kotlin\nPowerImageLoader.getInstance().registerImageLoader(\n            PowerImageNetworkLoader(this.applicationContext), \"network\"\n)\nPowerImageLoader.getInstance().registerImageLoader(\n            PowerImageNativeAssetLoader(this.applicationContext), \"nativeAsset\"\n)\nPowerImageLoader.getInstance().registerImageLoader(\n            PowerImageFlutterAssetLoader(this.applicationContext), \"asset\"\n)\nPowerImageLoader.getInstance().registerImageLoader(\n            PowerImageFileLoader(this.applicationContext), \"file\"\n)\n```\n\nThe loader needs to follow the PowerImageLoaderProtocol protocol:\n\n```java\npublic interface PowerImageLoaderProtocol {\n    void handleRequest(PowerImageRequestConfig request, PowerImageResult result);\n}\n```\n\n\nNetwork image loader example:\n\n#### Java\n\n```java\npublic class PowerImageNetworkLoader implements PowerImageLoaderProtocol {\n\n    private Context context;\n\n    public PowerImageNetworkLoader(Context context) {\n        this.context = context;\n    }\n\n    @Override\n    public void handleRequest(PowerImageRequestConfig request, PowerImageResponse response) {\n        Glide.with(context).asDrawable().load(request.srcString()).listener(new RequestListener\u003cDrawable\u003e() {\n            @Override\n            public boolean onLoadFailed(@Nullable GlideException e, Object model, Target\u003cDrawable\u003e target, boolean isFirstResource) {\n                response.onResult(PowerImageResult.genFailRet(\"Native加载失败: \" + (e != null ? e.getMessage() : \"null\")));\n                return true;\n            }\n\n            @Override\n            public boolean onResourceReady(Drawable resource, Object model, Target\u003cDrawable\u003e target, DataSource dataSource, boolean isFirstResource) {\n                if (resource instanceof GifDrawable) {\n                    response.onResult(PowerImageResult.genSucRet(new GlideMultiFrameImage((GifDrawable) resource, false)));\n                } else {\n                    if (resource instanceof BitmapDrawable) {\n                        response.onResult(PowerImageResult.genSucRet(new FlutterSingleFrameImage((BitmapDrawable) resource)));\n                    } else {\n                        response.onResult(PowerImageResult.genFailRet(\"Native加载失败:  resource : \" + String.valueOf(resource)));\n                    }\n                }\n                return true;\n            }\n        }).submit(request.width \u003c= 0 ? Target.SIZE_ORIGINAL : request.width,\n                request.height \u003c= 0 ? Target.SIZE_ORIGINAL : request.height);\n    }\n}\n```\n\n#### Kotlin\n\n```kotlin\nclass PowerImageNetworkLoader(private val context: Context) : PowerImageLoaderProtocol {\n    override fun handleRequest(request: PowerImageRequestConfig, response: PowerImageResponse) {\n        Glide.with(context).asDrawable().load(request.srcString())\n            .listener(object : RequestListener\u003cDrawable\u003e {\n                override fun onLoadFailed(\n                    e: GlideException?,\n                    model: Any,\n                    target: Target\u003cDrawable\u003e,\n                    isFirstResource: Boolean\n                ): Boolean {\n                    response.onResult(PowerImageResult.genFailRet(\"Native加载失败: \" + if (e != null) e.message else \"null\"))\n                    return true\n                }\n\n                override fun onResourceReady(\n                    resource: Drawable,\n                    model: Any,\n                    target: Target\u003cDrawable\u003e,\n                    dataSource: DataSource,\n                    isFirstResource: Boolean\n                ): Boolean {\n                    if (resource is GifDrawable) {\n                        response.onResult(\n                            PowerImageResult.genSucRet(\n                                GlideMultiFrameImage(\n                                    resource as GifDrawable,\n                                    false\n                                )\n                            )\n                        )\n                    } else {\n                        if (resource is BitmapDrawable) {\n                            response.onResult(\n                                PowerImageResult.genSucRet(\n                                    FlutterSingleFrameImage(\n                                        resource as BitmapDrawable\n                                    )\n                                )\n                            )\n                        } else {\n                            response.onResult(PowerImageResult.genFailRet(\"Native加载失败:  resource : $resource\"))\n                        }\n                    }\n                    return true\n                }\n            }).submit(\n                if (request.width \u003c= 0) Target.SIZE_ORIGINAL else request.width,\n                if (request.height \u003c= 0) Target.SIZE_ORIGINAL else request.height\n            )\n    }\n}\n```\n\nnative asset loader example:\n\n#### Java\n\n```java\npublic class PowerImageNativeAssetLoader implements PowerImageLoaderProtocol {\n\n    private Context context;\n\n    public PowerImageNativeAssetLoader(Context context) {\n        this.context = context;\n    }\n\n    @Override\n    public void handleRequest(PowerImageRequestConfig request, PowerImageResponse response) {\n        Resources resources = context.getResources();\n        int resourceId = 0;\n        try {\n            resourceId = resources.getIdentifier(request.srcString(),\n                    \"drawable\", context.getPackageName());\n        } catch (Resources.NotFoundException e) {\n            // 资源未找到\n            e.printStackTrace();\n        }\n        if (resourceId == 0) {\n            response.onResult(PowerImageResult.genFailRet(\"资源未找到\"));\n            return;\n        }\n        Glide.with(context).asBitmap().load(resourceId).listener(new RequestListener\u003cBitmap\u003e() {\n            @Override\n            public boolean onLoadFailed(@Nullable GlideException e, Object model, Target\u003cBitmap\u003e target, boolean isFirstResource) {\n                response.onResult(PowerImageResult.genFailRet(\"Native加载失败: \" + (e != null ? e.getMessage() : \"null\")));\n                return true;\n            }\n\n            @Override\n            public boolean onResourceReady(Bitmap resource, Object model, Target\u003cBitmap\u003e target, DataSource dataSource, boolean isFirstResource) {\n                response.onResult(PowerImageResult.genSucRet(resource));\n                return true;\n            }\n        }).submit(request.width \u003c= 0 ? Target.SIZE_ORIGINAL : request.width,\n                request.height \u003c= 0 ? Target.SIZE_ORIGINAL : request.height);\n    }\n}\n```\n\n#### Kotlin\n\n```kotlin\nclass PowerImageNativeAssetLoader(private val context: Context) : PowerImageLoaderProtocol {\n    override fun handleRequest(request: PowerImageRequestConfig, response: PowerImageResponse) {\n        val resources = context.resources\n        var resourceId = 0\n        try {\n            resourceId = resources.getIdentifier(\n                request.srcString(),\n                \"drawable\", context.packageName\n            )\n        } catch (e: Resources.NotFoundException) {\n            // 资源未找到\n            e.printStackTrace()\n        }\n        if (resourceId == 0) {\n            response.onResult(PowerImageResult.genFailRet(\"资源未找到\"))\n            return\n        }\n        Glide.with(context).asBitmap().load(resourceId).listener(object : RequestListener\u003cBitmap?\u003e {\n            override fun onLoadFailed(\n                e: GlideException?,\n                model: Any,\n                target: Target\u003cBitmap?\u003e,\n                isFirstResource: Boolean\n            ): Boolean {\n                response.onResult(PowerImageResult.genFailRet(\"Native加载失败: \" + if (e != null) e.message else \"null\"))\n                return true\n            }\n\n            override fun onResourceReady(\n                resource: Bitmap?,\n                model: Any,\n                target: Target\u003cBitmap?\u003e,\n                dataSource: DataSource,\n                isFirstResource: Boolean\n            ): Boolean {\n                response.onResult(PowerImageResult.genSucRet(resource))\n                return true\n            }\n        }).submit(\n            if (request.width \u003c= 0) Target.SIZE_ORIGINAL else request.width,\n            if (request.height \u003c= 0) Target.SIZE_ORIGINAL else request.height\n        )\n    }\n}\n\n```\n\nflutter asset loader example:\n\n#### Java\n\n```java\npublic class PowerImageFlutterAssetLoader implements PowerImageLoaderProtocol {\n\n    private Context context;\n\n    public PowerImageFlutterAssetLoader(Context context) {\n        this.context = context;\n    }\n\n    @Override\n    public void handleRequest(PowerImageRequestConfig request, PowerImageResponse response) {\n        String name = request.srcString();\n        if (name == null || name.length() \u003c= 0) {\n            response.onResult(PowerImageResult.genFailRet(\"src 为空\"));\n            return;\n        }\n        String assetPackage = \"\";\n        if (request.src != null) {\n            assetPackage = (String) request.src.get(\"package\");\n        }\n        String path;\n        if (assetPackage != null \u0026\u0026 assetPackage.length() \u003e 0) {\n            path = FlutterMain.getLookupKeyForAsset(name, assetPackage);\n        } else {\n            path = FlutterMain.getLookupKeyForAsset(name);\n        }\n        if (path == null || path.length() \u003c= 0) {\n            response.onResult(PowerImageResult.genFailRet(\"path 为空\"));\n            return;\n        }\n        Uri asset = Uri.parse(\"file:///android_asset/\" + path);\n        Glide.with(context).asBitmap().load(asset).listener(new RequestListener\u003cBitmap\u003e() {\n            @Override\n            public boolean onLoadFailed(@Nullable GlideException e, Object model, Target\u003cBitmap\u003e target, boolean isFirstResource) {\n                response.onResult(PowerImageResult.genFailRet(\"Native加载失败: \" + (e != null ? e.getMessage() : \"null\")));\n                return true;\n            }\n\n            @Override\n            public boolean onResourceReady(Bitmap resource, Object model, Target\u003cBitmap\u003e target, DataSource dataSource, boolean isFirstResource) {\n                response.onResult(PowerImageResult.genSucRet(resource));\n                return true;\n            }\n        }).submit(request.width \u003c= 0 ? Target.SIZE_ORIGINAL : request.width,\n                request.height \u003c= 0 ? Target.SIZE_ORIGINAL : request.height);\n    }\n\n}\n```\n\n#### Kotlin\n\n```kotlin\nclass PowerImageFlutterAssetLoader(private val context: Context) : PowerImageLoaderProtocol {\n    override fun handleRequest(request: PowerImageRequestConfig, response: PowerImageResponse) {\n        val name = request.srcString()\n        if (name == null || name.length \u003c= 0) {\n            response.onResult(PowerImageResult.genFailRet(\"src 为空\"))\n            return\n        }\n        var assetPackage: String? = \"\"\n        if (request.src != null) {\n            assetPackage = request.src[\"package\"] as String?\n        }\n        val path: String = if (assetPackage != null \u0026\u0026 assetPackage.length \u003e 0) {\n            FlutterMain.getLookupKeyForAsset(name, assetPackage)\n        } else {\n            FlutterMain.getLookupKeyForAsset(name)\n        }\n        if (path.isEmpty()) {\n            response.onResult(PowerImageResult.genFailRet(\"path 为空\"))\n            return\n        }\n        val asset = Uri.parse(\"file:///android_asset/$path\")\n        Glide.with(context).asBitmap().load(asset).listener(object : RequestListener\u003cBitmap?\u003e {\n            override fun onLoadFailed(\n                e: GlideException?,\n                model: Any,\n                target: Target\u003cBitmap?\u003e,\n                isFirstResource: Boolean\n            ): Boolean {\n                response.onResult(PowerImageResult.genFailRet(\"Native加载失败: \" + if (e != null) e.message else \"null\"))\n                return true\n            }\n\n            override fun onResourceReady(\n                resource: Bitmap?,\n                model: Any,\n                target: Target\u003cBitmap?\u003e,\n                dataSource: DataSource,\n                isFirstResource: Boolean\n            ): Boolean {\n                response.onResult(PowerImageResult.genSucRet(resource))\n                return true\n            }\n        }).submit(\n            if (request.width \u003c= 0) Target.SIZE_ORIGINAL else request.width,\n            if (request.height \u003c= 0) Target.SIZE_ORIGINAL else request.height\n        )\n    }\n}\n```\n\nfile loader example:\n\n#### Java\n\n```java\npublic class PowerImageFileLoader implements PowerImageLoaderProtocol {\n\n    private final Context context;\n\n    public PowerImageFileLoader(Context context) {\n        this.context = context;\n    }\n\n    @Override\n    public void handleRequest(PowerImageRequestConfig request, PowerImageResponse response) {\n        String name = request.srcString();\n        if (name == null || name.length() \u003c= 0) {\n            response.onResult(PowerImageResult.genFailRet(\"src 为空\"));\n            return;\n        }\n        Uri asset = Uri.parse(\"file://\" + name);\n        Glide.with(context).asBitmap().load(asset).listener(new RequestListener\u003cBitmap\u003e() {\n            @Override\n            public boolean onLoadFailed(@Nullable GlideException e, Object model, Target\u003cBitmap\u003e target, boolean isFirstResource) {\n                response.onResult(PowerImageResult.genFailRet(\"Native加载失败: \" + (e != null ? e.getMessage() : \"null\")));\n                return true;\n            }\n\n            @Override\n            public boolean onResourceReady(Bitmap resource, Object model, Target\u003cBitmap\u003e target, DataSource dataSource, boolean isFirstResource) {\n                response.onResult(PowerImageResult.genSucRet(resource));\n                return true;\n            }\n        }).submit(request.width \u003c= 0 ? Target.SIZE_ORIGINAL : request.width,\n                request.height \u003c= 0 ? Target.SIZE_ORIGINAL : request.height);\n    }\n}\n```\n\n#### Kotlin\n\n```kotlin\nclass PowerImageFileLoader(private val context: Context) : PowerImageLoaderProtocol {\n    override fun handleRequest(request: PowerImageRequestConfig, response: PowerImageResponse) {\n        val name = request.srcString()\n        if (name == null || name.length \u003c= 0) {\n            response.onResult(PowerImageResult.genFailRet(\"src 为空\"))\n            return\n        }\n        val asset = Uri.parse(\"file://$name\")\n        Glide.with(context).asBitmap().load(asset).listener(object : RequestListener\u003cBitmap?\u003e {\n            override fun onLoadFailed(\n                e: GlideException?,\n                model: Any,\n                target: Target\u003cBitmap?\u003e,\n                isFirstResource: Boolean\n            ): Boolean {\n                response.onResult(PowerImageResult.genFailRet(\"Native加载失败: \" + if (e != null) e.message else \"null\"))\n                return true\n            }\n\n            override fun onResourceReady(\n                resource: Bitmap?,\n                model: Any,\n                target: Target\u003cBitmap?\u003e,\n                dataSource: DataSource,\n                isFirstResource: Boolean\n            ): Boolean {\n                response.onResult(PowerImageResult.genSucRet(resource))\n                return true\n            }\n        }).submit(\n            if (request.width \u003c= 0) Target.SIZE_ORIGINAL else request.width,\n            if (request.height \u003c= 0) Target.SIZE_ORIGINAL else request.height\n        )\n    }\n}\n```\n\n\n## API\nnetwork image:\n```dart\n  PowerImage.network(\n    String src, {\n    Key? key,\n    String? renderingType,\n    double? imageWidth,\n    double? imageHeight,\n    this.width,\n    this.height,\n    this.frameBuilder,\n    this.errorBuilder,\n    this.fit = BoxFit.cover,\n    this.alignment = Alignment.center,\n    this.semanticLabel,\n    this.excludeFromSemantics = false,\n  })\n```\n\nnativeAsset:\n\n```dart\nPowerImage.nativeAsset(\n    String src, {\n    Key? key,\n    String? renderingType,\n    double? imageWidth,\n    double? imageHeight,\n    this.width,\n    this.height,\n    this.frameBuilder,\n    this.errorBuilder,\n    this.fit = BoxFit.cover,\n    this.alignment = Alignment.center,\n    this.semanticLabel,\n    this.excludeFromSemantics = false,\n  })\n```\n\nFlutter asset:\n\n```dart\n  PowerImage.asset(\n    String src, {\n    Key? key,\n    String? renderingType,\n    double? imageWidth,\n    double? imageHeight,\n    String? package,\n    this.width,\n    this.height,\n    this.frameBuilder,\n    this.errorBuilder,\n    this.fit = BoxFit.cover,\n    this.alignment = Alignment.center,\n    this.semanticLabel,\n    this.excludeFromSemantics = false,\n  })\n```\n\nFile:\n\n```dart\n  PowerImage.file(String src,\n      {Key key,\n      this.width,\n      this.height,\n      this.frameBuilder,\n      this.errorBuilder,\n      this.fit = BoxFit.cover,\n      this.alignment = Alignment.center,\n      String renderingType,\n      double imageWidth,\n      double imageHeight})\n```\n\nCustom Image Type:\n\n1.Define custom ImageType like \"album\".\n\n2.Define custom PowerImageRequestOptionsSrc to  pass argument to Native loader.\n\n3.Register custom loader in Android and iOS for \"album\" to receive argument and return Bitmap or UIImage.\n\n4.Flutter Side will display Image successfully.\n\n```dart\n  /// 自定义 imageType\\src\n  /// 效果：将src encode 后，完成地传递给 native 对应 imageType 注册的 loader\n  /// 使用场景：\n  /// 例如，自定义加载相册照片，通过自定义 imageType 为 \"album\"，\n  /// native 侧注册 \"album\" 类型的 loader 自定义图片的加载。  \nPowerImage.type(\n    String imageType, {\n    required PowerImageRequestOptionsSrc src,\n    Key? key,\n    String? renderingType,\n    double? imageWidth,\n    double? imageHeight,\n    this.width,\n    this.height,\n    this.frameBuilder,\n    this.errorBuilder,\n    this.fit = BoxFit.cover,\n    this.alignment = Alignment.center,\n    this.semanticLabel,\n    this.excludeFromSemantics = false,\n  })\n```\n\n.options\n\n```dart\n  /// 更加灵活的方式，通过自定义options来展示图片\n  ///\n  /// PowerImageRequestOptions({\n  ///   @required this.src,   //资源\n  ///   @required this.imageType, //资源类型，如网络图，本地图或者自定义等\n  ///   this.renderingType, //渲染方式，默认全局\n  ///   this.imageWidth,  //图片的渲染的宽度\n  ///   this.imageHeight, //图片渲染的高度\n  /// });\n  ///\n  /// PowerExternalImageProvider（FFI[bitmap]方案）\n  /// PowerTextureImageProvider（texture方案）\n  ///\n  /// 使用场景：\n  /// 例如，自定义加载相册照片，通过自定义 imageType 为 \"album\"，\n  /// native 侧注册 \"album\" 类型的 loader 自定义图片的加载。\n  ///\nPowerImage.options(\n    PowerImageRequestOptions options, {\n    Key? key,\n    this.width,\n    this.height,\n    this.frameBuilder,\n    this.errorBuilder,\n    this.fit = BoxFit.cover,\n    this.alignment = Alignment.center,\n    this.semanticLabel,\n    this.excludeFromSemantics = false,\n  })\n```\n\n\n#### Android\n\n```java\nPowerImageLoader.getInstance().registerImageLoader(\n  new PowerImageAlbumLoader(application.getApplicationContext()), \"album\");\n```\n\n```java\npublic class PowerImageAlbumLoader implements PowerImageLoaderProtocol {\n\n    private final Context context;\n\n    public PowerImageAlbumLoader(Context context) {\n        this.context = context;\n    }\n\n    @Override\n    public void handleRequest(PowerImageRequestConfig request, final PowerImageResponse response) {\n        Map\u003cString, Object\u003e src = request.src;\n        if (src == null || src.get(Const.Argument.ASSET_ID) == null || src.get(Const.Argument.ASSET_TYPE) == null) {\n            PowerImageResult result = PowerImageResult.genFailRet(\"asset id or assetType == null\");\n            response.onResult(result);\n            return;\n        }\n        AssetQuality quality = AssetQuality.values()[(int) src.get(Const.Argument.QUALITY)];\n        boolean highQuality = quality == AssetQuality.fullScreen;\n        final LocalMedia media = new LocalMedia();\n        media.fromMap(src);\n        final ThumbnailLoader thumbnailLoader = new ThumbnailLoader(context);\n        thumbnailLoader.load(media, highQuality, new ThumbnailLoader.ThumbnailLoadListener() {\n            @Override\n            public void onThumbnailLoaded(final Bitmap bitmap) {\n                PowerImageResult result;\n                if (bitmap == null) {\n                    result = PowerImageResult.genFailRet(\"bitmap == null\");\n                } else {\n                    result = PowerImageResult.genSucRet(bitmap);\n                }\n                response.onResult(result);\n            }\n        });\n    }\n\n}\n```\n\n#### iOS\n\n```objective-c\n[[PowerImageLoader sharedInstance] registerImageLoader:[AlbumAssetsImageLoader new] forType:@\"album\"];\n```\n\n```objective-c\n- (void)handleRequest:(PowerImageRequestConfig *)requestConfig completed:(PowerImageLoaderCompletionBlock)completedBlock {\n    NSString *assetId = requestConfig.src[@\"assetId\"];\n    NSNumber *imageWidth = requestConfig.src[@\"imageWidth\"];\n    NSNumber *imageHeight = requestConfig.src[@\"imageHeight\"];\n    if (assetId) {\n        if (imageWidth \u0026\u0026 imageHeight) {\n            [[MPAssetManager sharedInstance] getImageWithAssetId:assetId\n                                                       imageSize:CGSizeMake(imageWidth.doubleValue, imageHeight.doubleValue)\n                                                  successHandler:^(UIImage *image) {\n                completedBlock([PowerImageResult successWithImage:image]);\n            } failureHandler:^(NSError *error) {\n                completedBlock([PowerImageResult failWithMessage:error.localizedDescription]);\n            }];\n        } else {\n            [[MPAssetManager sharedInstance] getThumbnail:assetId\n                                           successHandler:^(UIImage *image) {\n                completedBlock([PowerImageResult successWithImage:image]);\n            } failureHandler:^(NSError *error) {\n                completedBlock([PowerImageResult failWithMessage:error.localizedDescription]);\n            }];\n        }\n    } else {\n        completedBlock([PowerImageResult failWithMessage:@\"assetId is nil\"]);\n    }\n}\n```\n\n# Example\n\nNetwork\n\n```dart\n          return PowerImage.network(\n            'https://flutter.github.io/assets-for-api-docs/assets/widgets/owl.jpg',\n            width: 100,\n            height: 100,\n          );\n```\n\n\n\n# Best practice\n\n[Best practice](BESTPRACTICE.md)\n\n\n\n# How it works\n\nhttps://mp.weixin.qq.com/s/TdTGK21S-Yd3aD-yZDoYyQ\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falibaba%2Fpower_image","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falibaba%2Fpower_image","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falibaba%2Fpower_image/lists"}