diff --git a/.idea/misc.xml b/.idea/misc.xml index 5d19981..fbb6828 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -37,7 +37,7 @@ - + diff --git a/README-zh_CN.md b/README-zh_CN.md new file mode 100644 index 0000000..2cbfe0d --- /dev/null +++ b/README-zh_CN.md @@ -0,0 +1,177 @@ +# AwesomeQRCode +[![](https://jitpack.io/v/SumiMakito/AwesomeQRCode.svg)](https://jitpack.io/#SumiMakito/AwesomeQRCode) +[![license](https://img.shields.io/github/license/SumiMakito/AwesomeQRCode.svg)](https://github.com/SumiMakito/AwesomeQRCode/blob/master/LICENSE) +[![release](https://img.shields.io/github/release/SumiMakito/AwesomeQRCode.svg)](https://github.com/SumiMakito/AwesomeQRCode/releases/latest) + +一个优雅的(不起眼的) QR 二维码生成器 + +[Swithc to English Version?](README.md) + +Special, thus awesome. + +### 好耶! 演示应用! + +Google Play Store + +### 样例 + +> 拿起你的手机扫描下面的二维码试试吧! + +样例 1 | 样例 2 | 样例 3 +------------ | ------------- | ------------- + | | + + +使用圆点做数据点 | 二值化处理 | 带有 Logo +------------ | ------------- | ------------- + | | + +### 添加依赖项 + +> 万事开头难, 补全就好啦! + +在项目根目录下的 build.gradle 中补充以下内容: +``` +allprojects { + repositories { + ... + maven { url 'https://jitpack.io' } + } +} +``` + +在应用模块层级下的 build.gradle 中补充以下内容: +``` +dependencies { + compile 'com.github.SumiMakito:AwesomeQRCode:1.0.5' +} +``` + +### 快速上手 + +#### "人家只想要 Bitmap 嘛": + +> 原来乃只想要 Bitmap 撒... 满足你!! + + +> 这种情况下,二维码将同步(synchronously)生成,这有可能阻塞 UI 线程,引起应用无响应(ANR)问题。因此建议在非 UI 线程中使用。 + +```java +new Thread() { + @Override + public void run() { + super.run(); + Bitmap qrCode = new AwesomeQRCode.Renderer() + .contents("Makito loves Kafuu Chino.") + .size(800).margin(20) + .render(); + }.start(); +``` + +#### 异步生成二维码并在 ImageView 中显示: + +```java +new AwesomeQRCode.Renderer() + .contents("Makito loves Kafuu Chino.") + .size(800).margin(20) + .renderAsync(new AwesomeQRCode.Callback() { + @Override + public void onRendered(AwesomeQRCode.Renderer renderer, final Bitmap bitmap) { + runOnUiThread(new Runnable() { + @Override + public void run() { + // 提示: 这里使用 runOnUiThread(...) 来规避从非 UI 线程操作 UI 控件时产生的问题。 + imageView.setImageBitmap(bitmap); + } + }); + } + + @Override + public void onError(AwesomeQRCode.Renderer renderer, Exception e) { + e.printStackTrace(); + } + }); +``` + +### 参数说明 + +参数名 | 类型 | 说明 | 默认值 | 备注 +:----:|:------:|----|:--:|:-----: +contents | String | 欲编码的内容 | null | 必需 +size | int-px | 尺寸, 长宽一致, 包含外边距 | 800 | 必需 +margin | int-px | 二维码图像的外边距 | 20 | 必需 +dataDotScale | float | 数据点缩小比例 | 0.3f | (0, 1.0f) +colorDark | int-color | 非空白区域的颜色 | Color.BLACK | +colorLight | int-color | 空白区域的颜色 | Color.WHITE | +background | Bitmap | 欲嵌入的背景图, 设为 null 以禁用 | null | +whiteMargin | int-px | 若设为 true, 背景图外将绘制白色边框 | true | +autoColor | boolean | 若为 true, 背景图的主要颜色将作为实点的颜色, 即 colorDark | true | +binarize | boolean | 若为 true, 图像将被二值化处理, 未指定阈值则使用默认值 | fasle | +binarizeThreshold | int | 二值化处理的阈值 | 128 | (0, 255) +roundedDataDots | boolean | 若为 true, 数据点将以圆点绘制 | false | +logo | Bitmap | 欲嵌入至二维码中心的 Logo, 设为 null 以禁用 | null | +logoMargin | int-px | Logo 周围的空白边框, 设为 0 以禁用 | 10 | +logoCornerRadius | int-px | Logo 及其边框的圆角半径, 设为 0 以禁用 | 8 | +logoScale | float | 用于计算 Logo 大小, 过大将覆盖过多数据点而导致解码失败 | 0.2f | (0, 1.0f) + + + +### 更新日志 + +#### 1.0.5 版本 +- 使用 AwesomeQRCode 的方式变的更优雅 + +#### 1.0.4 版本 +- 可以在二维码中选择嵌入 Logo +- 演示应用更新 + +#### 1.0.3 版本 +- 在二维码中的 Hints 中加入 CHARACTER_SET => UTF-8 +- 修复 [#7](https://github.com/SumiMakito/AwesomeQRCode/issues/7) 中提到的编码问题 + +#### 1.0.2 版本 +- 加入使用圆点绘制二维码数据点的选项 + +#### 1.0.1 版本 +- 加入背景二值化的支持 + +#### 1.0.0 版本 +- 初次发布 + +### 相关项目 + +#### Swift 下的 EFQRCode + +AwesomeQRCode 受 [由 EyreFree 创造的 EFQRCode](https://github.com/EyreFree/EFQRCode) 所启发而生,它是一个轻量级的、用来生成和识别二维码的纯 Swift 库,可根据输入的水印图和图标产生艺术二维码,基于 CoreImage 进行开发。受 qrcode 启发。EFQRCode 为你提供了一种更好的在你的 App 中操作二维码的方式。 + + +#### 可在网页使用的 JavaScript 版: Awesome-qr.js + +详情请至 [Awesome-qr.js](https://github.com/SumiMakito/Awesome-qr.js) + +### 可以请我喝一杯卡布奇诺吗? +PayPal | 支付宝 +----|---- +[PayPal](https://www.paypal.me/makito) | [支付宝](https://qr.alipay.com/a6x02021re1jk4ftcymlw79) + +### 版权信息与授权协议 + +Copyright © 2017 Sumi Makito + +Licensed under Apache License 2.0 License. + +``` +Copyright 2017 Sumi Makito + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +``` diff --git a/README.md b/README.md index 6d403d4..0096af3 100644 --- a/README.md +++ b/README.md @@ -5,15 +5,15 @@ An awesome(simple) QR code generator for Android. -一个优雅的(不起眼的) QR 二维码生成器 +[切换至中文(简体)版本?](README-zh_CN.md) Special, thus awesome. -### Get sample APK, 下载演示 APK +### Yay! Demo Available! Google Play Store -### Examples, 样例 +### Examples > Try to scan these QR codes below with your smart phone. @@ -26,7 +26,7 @@ Solid dots instead of blocks|Binarized|With logo at the center ------------ | ------------- | ------------- | | -### Add dependency into your project, 添加依赖项 +### Add dependency into your project Add below lines in build.gradle of your project: ``` @@ -41,86 +41,99 @@ allprojects { Then, add below lines in build.gradle of your app module: ``` dependencies { - compile 'com.github.SumiMakito:AwesomeQRCode:1.0.4' + compile 'com.github.SumiMakito:AwesomeQRCode:1.0.5' } ``` -### Quick start, 快速上手 +### Quick start -```java -Bitmap qrCode = AwesomeQRCode.create("Makito loves Kafuu Chino.", 800, 20); -Bitmap qrCodeWithBackground = AwesomeQRCode.create("Makito loves Kafuu Chino.", 800, 20, backgroundBitmap); -Bitmap qrCodeWithLogo = AwesomeQRCode.create("Makito loves Kafuu Chino.", 800, 20, null, logoBitmap); -Bitmap qrCodeWithBackgroundAndLogo = AwesomeQRCode.create("Makito loves Kafuu Chino.", 800, 20, backgroundBitmap, logoBitmap); -``` -### Parameters, 参数 +#### "I just wanna get a Bitmap": -> Here's a full list of all parameters, but some of them are optional. You can view all the possible simplified methods at the end of AwesomeQRCode.java. +> In this case, QR code will be generated synchronously. Thus it means you may take a risk blocking the UI thread, which would lead to Application Not Responding (ANR). I strongly recommend you to use it in a non-UI thread. + +```java +new Thread() { + @Override + public void run() { + super.run(); + Bitmap qrCode = new AwesomeQRCode.Renderer() + .contents("Makito loves Kafuu Chino.") + .size(800).margin(20) + .render(); + }.start(); +``` -> (Translation) 以下列出全部参数,但其中部分参数是可选的。关于简化的调用方法,请查看 AwesomeQRCode.java 的结尾部分。 +#### Generate a QR code asynchronously and show the QR code in an ImageView: ```java -public static Bitmap create( - String contents, - int size, - int margin, - float dataDotScale, - int colorDark, - int colorLight, - Bitmap backgroundImage, - boolean whiteMargin, - boolean autoColor, - boolean binarize, - int binarizeThreshold, - boolean roundedDataDots, - Bitmap logoImage, - int logoMargin, - int logoCornerRadius, - float logoScale -) throws IllegalArgumentException { ... } +new AwesomeQRCode.Renderer() + .contents("Makito loves Kafuu Chino.") + .size(800).margin(20) + .renderAsync(new AwesomeQRCode.Callback() { + @Override + public void onRendered(AwesomeQRCode.Renderer renderer, final Bitmap bitmap) { + runOnUiThread(new Runnable() { + @Override + public void run() { + // Tip: here we use runOnUiThread(...) to avoid the problems caused by operating UI elements from a non-UI thread. + imageView.setImageBitmap(bitmap); + } + }); + } + + @Override + public void onError(AwesomeQRCode.Renderer renderer, Exception e) { + e.printStackTrace(); + } + }); ``` -Parameter | Explanation -----|---- -contents (String) | Contents to encode. 欲编码的内容 -size (int-px) | Width as well as the height of the output QR code, includes margin. 尺寸, 长宽一致, 包含外边距 -margin (int-px) | Margin to add around the QR code. 二维码图像的外边距, 默认 20px -dataDotScale (float) | Value used to scale down the data dots' size. (0 < scale < 1.0f) 数据区域点缩小比例 -colorDark (int-color) | Color of "true" blocks. Works only when both colorDark and colorLight are set. (BYTE_DTA, BYTE_POS, BYTE_AGN, BYTE_TMG) 实点的颜色 -colorLight (int-color) | Color of empty space, or "false" blocks. Works only when both colorDark and colorLight are set. (BYTE_EPT) 空白区的颜色 -backgroundImage (Bitmap) | Background image to embed in the QR code. Leave null to disable. 欲嵌入的背景图, 设为 null 以禁用 -whiteMargin (int-px) | If set to true, a white border will appear around the background image. Default is true. 若设为 true, 背景图外将绘制白色边框 -autoColor (boolean) | If set to true, the dominant color of backgroundImage will be used as colorDark. Default is true. 若为 true, 背景图的主要颜色将作为实点的颜色, 即 colorDark -binarize (boolean) | If set to true, the whole image will be binarized with the given threshold, or default threshold if not specified. Default is false. 若为 true, 图像将被二值化处理, 未指定阈值则使用默认值 -binarizeThreshold (int) | Threshold used to binarize the whole image. Default is 128. (0 < threshold < 255) 二值化处理的阈值 -roundedDataDots (boolean) | If set to true, data dots will appear as solid dots instead of blocks. Default is false. 若为 true, 数据点将以圆点绘制, 取代默认的小方块 -logoImage (Bitmap) | Logo image to embed at the center of generated QR code. Leave null to disable. 欲嵌入至二维码中心的 LOGO 标识, 设为 null 以禁用 -logoMargin (int-px) | White margin that appears around the logo image. Leave 0 to disable. LOGO 标识周围的空白边框, 设为 0 以禁用 -logoCornerRadius (int-px) | Radius of the logo's corners. Leave 0 to disable. LOGO 标识及其边框的圆角半径, 设为 0 以禁用 -logoScale (float) | Value used to scale the logo image. Larger value may result in decode failure. Size of the logo equals to `logoScale*(size-2*margin)`. Default is 0.2f. 用于计算 LOGO 大小的值, 过大将导致解码失败, LOGO 尺寸计算公式 `logoScale*(size-2*margin)`, 默认 0.2f +### Parameters + +Parameter | Type | Explanation | Default Value | Misc. +:----:|:------:|----|:--:|:--: +contents | String | Contents to encode. | null | Required +size | int-px | Width as well as the height of the output QR code, includes margin. | 800 | Required +margin | int-px | Margin to add around the QR code. | 20 | Required +dataDotScale | float | Value used to scale down the data dots' size. | 0.3f | (0, 1.0f) +colorDark | int-color | Color of "true" blocks. Works only when both colorDark and colorLight are set. | Color.BLACK | +colorLight | int-color | Color of empty space, or "false" blocks. Works only when both colorDark and colorLight are set. | Color.WHITE | +background | Bitmap | Background image to embed in the QR code. Leave null to disable. | null | +whiteMargin | int-px | If set to true, a white border will appear around the background image. | true | +autoColor | boolean | If set to true, the dominant color of backgroundImage will be used as colorDark. | true | +binarize | boolean | If set to true, the whole image will be binarized with the given threshold, or default threshold if not specified. | fasle | +binarizeThreshold | int | Threshold used to binarize the whole image. | 128 | (0, 255) +roundedDataDots | boolean | If set to true, data dots will appear as solid dots instead of blocks. | false | +logo | Bitmap | Logo image to embed at the center of generated QR code. Leave null to disable. | null | +logoMargin | int-px | White margin that appears around the logo image. Leave 0 to disable. LOGO | 10 | +logoCornerRadius | int-px | Radius of the logo's corners. Leave 0 to disable. | 8 | +logoScale | float | Value used to scale the logo image. Larger value may result in decode failure. | 0.2f | (0, 1.0f) + +### Changelog -### Changelog, 更新日志 +#### Version 1.0.5 +- The way to use AwesomeQRCode is more elegant. -#### 1.0.4 -New feature: Embedding a logo image in the QR code. -Sample/Demo application updated. +#### Version 1.0.4 +- New feature: Embedding a logo image in the QR code. +- Sample/Demo application updated. -#### 1.0.3 -Added CHARACTER_SET => UTF-8 to QR code's hints before encoding. -Fixed an encoding issue mentioned in [#7](https://github.com/SumiMakito/AwesomeQRCode/issues/7). +#### Version 1.0.3 +- Added CHARACTER_SET => UTF-8 to QR code's hints before encoding. +- Fixed an encoding issue mentioned in [#7](https://github.com/SumiMakito/AwesomeQRCode/issues/7). -#### 1.0.2 -Added an optional parameter which enables the data dots to appear as filled circles. +#### Version 1.0.2 +- Added an optional parameter which enables the data dots to appear as filled circles. -#### 1.0.1 -Now background images can be binarized as you like. +#### Version 1.0.1 +- Now background images can be binarized as you like. -#### 1.0.0 -Initial release. +#### Version 1.0.0 +- Initial release. -### Alternatives on other platforms/in other languages. 其他平台或语言下的对等项目 +### Alternatives #### EFQRCode written in Swift @@ -130,16 +143,16 @@ AwesomeQRCode is inspired by [EFQRCode by EyreFree](https://github.com/EyreFree/ If your application is in need of generating pretty QR codes in Swift, take a look at EFQRCode. It should help. -#### Awesome-qr.js written in JavaScript, 支持 JavaScript 的 Awesome-qr.js +#### Awesome-qr.js written in JavaScript Redirect to [Awesome-qr.js](https://github.com/SumiMakito/Awesome-qr.js) -### Would you like to buy me a cup of cappuccino? 要请我喝一杯卡布奇诺吗? +### Would you like to buy me a cup of cappuccino? PayPal | Alipay ----|---- [PayPal](https://www.paypal.me/makito) | [Alipay](https://qr.alipay.com/a6x02021re1jk4ftcymlw79) -### Copyright & License, 版权信息与授权协议 +### Copyright & License Copyright © 2017 Sumi Makito diff --git a/app/build.gradle b/app/build.gradle index 6396886..d50b7ee 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -7,8 +7,8 @@ android { applicationId "com.github.sumimakito.awesomeqrsample" minSdkVersion 19 targetSdkVersion 25 - versionCode 9 - versionName "1.8" + versionCode 10 + versionName "1.9" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { diff --git a/app/src/main/java/com/github/sumimakito/awesomeqrsample/MainActivity.java b/app/src/main/java/com/github/sumimakito/awesomeqrsample/MainActivity.java index d6ecbde..3e04eb8 100644 --- a/app/src/main/java/com/github/sumimakito/awesomeqrsample/MainActivity.java +++ b/app/src/main/java/com/github/sumimakito/awesomeqrsample/MainActivity.java @@ -269,37 +269,43 @@ private void generate(final String contents, final int size, final int margin, f generating = true; progressDialog = new ProgressDialog.Builder(this).setMessage("Generating...").setCancelable(false).create(); progressDialog.show(); - new Thread(new Runnable() { - @Override - public void run() { - try { - qrBitmap = AwesomeQRCode.create(contents, size, margin, dotScale, colorDark, - colorLight, background, whiteMargin, autoColor, binarize, binarizeThreshold, - roundedDD, logoImage, logoMargin, logoCornerRadius, logoScale); - runOnUiThread(new Runnable() { - @Override - public void run() { - qrCodeImageView.setImageBitmap(qrBitmap); - configViewContainer.setVisibility(View.GONE); - resultViewContainer.setVisibility(View.VISIBLE); - if (progressDialog != null) progressDialog.dismiss(); - generating = false; - } - }); - } catch (Exception e) { - e.printStackTrace(); - runOnUiThread(new Runnable() { - @Override - public void run() { - if (progressDialog != null) progressDialog.dismiss(); - configViewContainer.setVisibility(View.VISIBLE); - resultViewContainer.setVisibility(View.GONE); - generating = false; - } - }); - } - } - }).start(); + new AwesomeQRCode.Renderer().contents(contents) + .size(size).margin(margin).dotScale(dotScale) + .colorDark(colorDark).colorLight(colorLight) + .background(background).whiteMargin(whiteMargin) + .autoColor(autoColor).roundedDots(roundedDD) + .binarize(binarize).binarizeThreshold(binarizeThreshold) + .logo(logoImage).logoMargin(logoMargin) + .logoRadius(logoCornerRadius).logoScale(logoScale) + .renderAsync(new AwesomeQRCode.Callback() { + @Override + public void onRendered(AwesomeQRCode.Renderer renderer, final Bitmap bitmap) { + runOnUiThread(new Runnable() { + @Override + public void run() { + qrCodeImageView.setImageBitmap(bitmap); + configViewContainer.setVisibility(View.GONE); + resultViewContainer.setVisibility(View.VISIBLE); + if (progressDialog != null) progressDialog.dismiss(); + generating = false; + } + }); + } + + @Override + public void onError(AwesomeQRCode.Renderer renderer, Exception e) { + e.printStackTrace(); + runOnUiThread(new Runnable() { + @Override + public void run() { + if (progressDialog != null) progressDialog.dismiss(); + configViewContainer.setVisibility(View.VISIBLE); + resultViewContainer.setVisibility(View.GONE); + generating = false; + } + }); + } + }); } private void saveBitmap(Bitmap bitmap) { diff --git a/library/build.gradle b/library/build.gradle index 013aef6..4e83bd3 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -6,8 +6,8 @@ android { defaultConfig { minSdkVersion 9 targetSdkVersion 25 - versionCode 5 - versionName "1.0.4" + versionCode 6 + versionName "1.0.5" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" @@ -25,7 +25,6 @@ dependencies { androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) - compile 'com.android.support:appcompat-v7:25.3.1' compile 'com.google.zxing:core:3.2.0' testCompile 'junit:junit:4.12' } diff --git a/library/src/main/java/com/github/sumimakito/awesomeqr/AwesomeQRCode.java b/library/src/main/java/com/github/sumimakito/awesomeqr/AwesomeQRCode.java index 4ab6dae..007c166 100644 --- a/library/src/main/java/com/github/sumimakito/awesomeqr/AwesomeQRCode.java +++ b/library/src/main/java/com/github/sumimakito/awesomeqr/AwesomeQRCode.java @@ -9,7 +9,6 @@ import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.RectF; -import android.util.Log; import com.google.zxing.EncodeHintType; import com.google.zxing.WriterException; @@ -18,9 +17,7 @@ import com.google.zxing.qrcode.encoder.Encoder; import com.google.zxing.qrcode.encoder.QRCode; -import java.util.HashMap; import java.util.Hashtable; -import java.util.Map; public class AwesomeQRCode { /** @@ -41,6 +38,7 @@ public class AwesomeQRCode { private static float DEFAULT_DTA_DOT_SCALE = 0.3f; private static float DEFAULT_LOGO_SCALE = 0.2f; + private static int DEFAULT_SIZE = 800; private static int DEFAULT_MARGIN = 20; private static int DEFAULT_LOGO_MARGIN = 10; private static int DEFAULT_LOGO_RADIUS = 8; @@ -57,7 +55,7 @@ public class AwesomeQRCode { * @param colorLight Color of empty space. Will be OVERRIDE by autoColor. (BYTE_EPT) * @param backgroundImage The background image to embed in the QR code. If null, no background image will be embedded. * @param whiteMargin If true, background image will not be drawn on the margin area. - * @param autoColor If true, colorDark will be set to the dominant color of backgroundImage. + * @param autoColor If true, colorDark will be set to the dominant color of background. * @param binarize If true, all images will be binarized while rendering. Default is false. * @param binarizeThreshold Threshold value used while binarizing. Default is 128. 0 < threshold < 255. * @param roundedDataDots If true, data blocks will appear as filled circles. Default is false. @@ -68,10 +66,10 @@ public class AwesomeQRCode { * @return Bitmap of QR code * @throws IllegalArgumentException Refer to the messages below. */ - public static Bitmap create(String contents, int size, int margin, float dataDotScale, int colorDark, - int colorLight, Bitmap backgroundImage, boolean whiteMargin, boolean autoColor, - boolean binarize, int binarizeThreshold, boolean roundedDataDots, - Bitmap logoImage, int logoMargin, int logoCornerRadius, float logoScale) throws IllegalArgumentException { + private static Bitmap create(String contents, int size, int margin, float dataDotScale, int colorDark, + int colorLight, Bitmap backgroundImage, boolean whiteMargin, boolean autoColor, + boolean binarize, int binarizeThreshold, boolean roundedDataDots, + Bitmap logoImage, int logoMargin, int logoCornerRadius, float logoScale) throws IllegalArgumentException { if (contents.isEmpty()) { throw new IllegalArgumentException("Error: contents is empty. (contents.isEmpty())"); } @@ -396,82 +394,153 @@ private static void binarize(Bitmap bitmap, int threshold) { } } - /* TONS OF SHORTENED METHODS */ + public static class Renderer { + private String contents; + private int size; + private int margin; + private float dataDotScale; + private int colorDark; + private int colorLight; + private Bitmap backgroundImage; + private boolean whiteMargin; + private boolean autoColor; + private boolean binarize; + private int binarizeThreshold; + private boolean roundedDataDots; + private Bitmap logoImage; + private int logoMargin; + private int logoCornerRadius; + private float logoScale; + + public Renderer() { + size = DEFAULT_SIZE; + margin = DEFAULT_MARGIN; + dataDotScale = DEFAULT_DTA_DOT_SCALE; + colorDark = Color.BLACK; + colorLight = Color.WHITE; + colorDark = Color.BLACK; + whiteMargin = true; + autoColor = true; + binarize = false; + binarizeThreshold = DEFAULT_BINARIZING_THRESHOLD; + roundedDataDots = false; + logoMargin = DEFAULT_LOGO_MARGIN; + logoCornerRadius = DEFAULT_LOGO_RADIUS; + logoScale = DEFAULT_LOGO_SCALE; + } - public static Bitmap create(String contents, int size, int margin) throws IllegalArgumentException { - return create(contents, size, margin, DEFAULT_DTA_DOT_SCALE, 0, 0, null, true, true, false, 0, false, null, 0, 0, 0); - } + public Renderer autoColor(boolean autoColor) { + this.autoColor = autoColor; + return this; + } - public static Bitmap create(String contents, int size, int margin, int colorDark, int colorLight) throws IllegalArgumentException { - return create(contents, size, margin, DEFAULT_DTA_DOT_SCALE, colorDark, colorLight, null, true, false, false, 0, false, null, 0, 0, 0); - } + public Renderer background(Bitmap backgroundImage) { + this.backgroundImage = backgroundImage; + return this; + } - public static Bitmap create(String contents, int size, Bitmap backgroundImage) throws IllegalArgumentException { - return create(contents, size, DEFAULT_MARGIN, DEFAULT_DTA_DOT_SCALE, 0, 0, backgroundImage, true, true, false, 0, false, null, 0, 0, 0); - } + public Renderer binarize(boolean binarize) { + this.binarize = binarize; + return this; + } - public static Bitmap create(String contents, int size, Bitmap backgroundImage, Bitmap logoImage) throws IllegalArgumentException { - return create(contents, size, DEFAULT_MARGIN, DEFAULT_DTA_DOT_SCALE, 0, 0, backgroundImage, true, true, false, 0, false, logoImage, DEFAULT_LOGO_MARGIN, DEFAULT_LOGO_RADIUS, DEFAULT_LOGO_SCALE); - } + public Renderer binarizeThreshold(int binarizeThreshold) { + this.binarizeThreshold = binarizeThreshold; + return this; + } - public static Bitmap create(String contents, int size, int margin, int colorDark, - int colorLight, Bitmap backgroundImage) throws IllegalArgumentException { - return create(contents, size, margin, DEFAULT_DTA_DOT_SCALE, colorDark, colorLight, backgroundImage, - true, false, false, 0, false, null, 0, 0, 0); - } + public Renderer colorDark(int colorDark) { + this.colorDark = colorDark; + return this; + } - public static Bitmap create(String contents, int size, int colorDark, - int colorLight, Bitmap backgroundImage, Bitmap logoImage) throws IllegalArgumentException { - return create(contents, size, DEFAULT_MARGIN, DEFAULT_DTA_DOT_SCALE, colorDark, colorLight, backgroundImage, true, false, false, 0, - false, logoImage, DEFAULT_LOGO_MARGIN, DEFAULT_LOGO_RADIUS, DEFAULT_LOGO_SCALE); - } + public Renderer colorLight(int colorLight) { + this.colorLight = colorLight; + return this; + } - public static Bitmap create(String contents, int size, int margin, int colorDark, - int colorLight, Bitmap backgroundImage, Bitmap logoImage) throws IllegalArgumentException { - return create(contents, size, margin, DEFAULT_DTA_DOT_SCALE, colorDark, colorLight, backgroundImage, true, false, false, 0, - false, logoImage, DEFAULT_LOGO_MARGIN, DEFAULT_LOGO_RADIUS, DEFAULT_LOGO_SCALE); - } + public Renderer contents(String contents) { + this.contents = contents; + return this; + } - public static Bitmap create(String contents, int size, int margin, Bitmap backgroundImage) throws IllegalArgumentException { - return create(contents, size, margin, DEFAULT_DTA_DOT_SCALE, 0, 0, backgroundImage, - true, true, false, 0, false, null, 0, 0, 0); - } + public Renderer dotScale(float dataDotScale) { + this.dataDotScale = dataDotScale; + return this; + } - public static Bitmap create(String contents, int size, int margin, Bitmap backgroundImage, boolean whiteMargin) throws IllegalArgumentException { - return create(contents, size, margin, DEFAULT_DTA_DOT_SCALE, 0, 0, backgroundImage, - whiteMargin, true, false, 0, false, null, 0, 0, 0); - } + public Renderer logo(Bitmap logoImage) { + this.logoImage = logoImage; + return this; + } - public static Bitmap create(String contents, int size, int margin, Bitmap backgroundImage, boolean whiteMargin, boolean roundedDataDots) throws IllegalArgumentException { - return create(contents, size, margin, DEFAULT_DTA_DOT_SCALE, 0, 0, backgroundImage, - whiteMargin, true, false, 0, roundedDataDots, null, 0, 0, 0); - } + public Renderer logoRadius(int logoCornerRadius) { + this.logoCornerRadius = logoCornerRadius; + return this; + } - public static Bitmap create(String contents, int size, int margin, int colorDark, int colorLight, Bitmap backgroundImage, boolean whiteMargin) - throws IllegalArgumentException { - return create(contents, size, margin, DEFAULT_DTA_DOT_SCALE, colorDark, colorLight, backgroundImage, - whiteMargin, false, false, 0, false, null, 0, 0, 0); - } + public Renderer logoMargin(int logoMargin) { + this.logoMargin = logoMargin; + return this; + } - public static Bitmap create(String contents, int size, int margin, float dataDotScale, int colorDark, - int colorLight, Bitmap backgroundImage, boolean whiteMargin, boolean autoColor, - boolean roundedDataDots) throws IllegalArgumentException { - return create(contents, size, margin, dataDotScale, colorDark, colorLight, backgroundImage, - whiteMargin, autoColor, false, 0, roundedDataDots, null, 0, 0, 0); - } + public Renderer logoScale(float logoScale) { + this.logoScale = logoScale; + return this; + } - public static Bitmap create(String contents, int size, int margin, float dataDotScale, int colorDark, - int colorLight, Bitmap backgroundImage, boolean whiteMargin, boolean autoColor, - boolean binarize, int binarizeThreshold) throws IllegalArgumentException { - return create(contents, size, margin, dataDotScale, colorDark, colorLight, backgroundImage, - whiteMargin, autoColor, binarize, binarizeThreshold, false, null, 0, 0, 0); + public Renderer margin(int margin) { + this.margin = margin; + return this; + } + + public Renderer roundedDots(boolean roundedDataDots) { + this.roundedDataDots = roundedDataDots; + return this; + } + + public Renderer size(int size) { + this.size = size; + return this; + } + + public Renderer whiteMargin(boolean whiteMargin) { + this.whiteMargin = whiteMargin; + return this; + } + + public Bitmap render() throws IllegalArgumentException { + return create( + contents, size, margin, dataDotScale, colorDark, colorLight, + backgroundImage, whiteMargin, autoColor, binarize, binarizeThreshold, + roundedDataDots, logoImage, logoMargin, logoCornerRadius, logoScale + ); + } + + public void renderAsync(final Callback callback) throws IllegalArgumentException { + new Thread() { + @Override + public void run() { + super.run(); + try { + Bitmap bitmap = create( + contents, size, margin, dataDotScale, colorDark, colorLight, + backgroundImage, whiteMargin, autoColor, binarize, binarizeThreshold, + roundedDataDots, logoImage, logoMargin, logoCornerRadius, logoScale + ); + if (callback != null) callback.onRendered(Renderer.this, bitmap); + } catch (Exception e) { + if (callback != null) callback.onError(Renderer.this, e); + } + } + }.start(); + } } - public static Bitmap create(String contents, int size, int margin, float dataDotScale, int colorDark, - int colorLight, Bitmap backgroundImage, boolean whiteMargin, boolean autoColor, - boolean binarize, int binarizeThreshold, boolean roundedDataDots) throws IllegalArgumentException { - return create(contents, size, margin, dataDotScale, colorDark, colorLight, backgroundImage, - whiteMargin, autoColor, binarize, binarizeThreshold, roundedDataDots, null, 0, 0, 0); + public interface Callback { + void onRendered(Renderer renderer, Bitmap bitmap); + + void onError(Renderer renderer, Exception e); } }