Skip to content

Commit

Permalink
Merge pull request #4 from SumiMakito/develop
Browse files Browse the repository at this point in the history
Ver 1.0.1 released
  • Loading branch information
sumimakito authored May 2, 2017
2 parents 051e94d + 9c79afe commit bca53a3
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 40 deletions.
7 changes: 7 additions & 0 deletions .idea/dictionaries/makito.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

41 changes: 25 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,6 @@ An awesome<del>(simple)</del> QR code generator for Android.

一个优雅的<del>(不起眼的)</del> QR 二维码生成器

### Introducing EFQRCode written in Swift

EFQRCode is a tool to generate QRCode image or recognize QRCode from image, in Swift.

AwesomeQRCode is inspired by [EFQRCode by EyreFree](https://github.com/EyreFree/EFQRCode).

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

Redirect to [Awesome-qr.js](https://github.com/SumiMakito/Awesome-qr.js)

### Get sample APK, 下载演示 APK

<a href="https://play.google.com/store/apps/details?id=com.github.sumimakito.awesomeqrsample" target="_blank"><img src="art/play_store_badge.png" alt="Google Play Store" width="200"></a>
Expand Down Expand Up @@ -67,16 +53,39 @@ public static Bitmap create(
int colorLight, // Color of empty space. Will be OVERRIDE by autoColor. (BYTE_EPT) 空白点的颜色
Bitmap backgroundImage, // The background image to embed in the QR code. If null, no background image will be embedded. 欲嵌入的背景图
boolean whiteMargin, // If true, background image will not be drawn on the margin area. Default is true. 若为 true, 则背景图将不会绘制到外边距区域
boolean autoColor // If true, colorDark will be set to the dominant color of backgroundImage. Default is true. 若为 true, 则将从背景图取主要颜色作为实点颜色
boolean autoColor, // If true, colorDark will be set to the dominant color of backgroundImage. Default is true. 若为 true, 则将从背景图取主要颜色作为实点颜色
boolean binarize, // If true, background images will be binarized. Default is false. 若为 true, 背景图像将被二值化处理
int binarizeThreshold // Threshold value used while binarizing background images. Default is 128. 0 < threshold < 255. 控制背景图像二值化的阈值
) throws IllegalArgumentException { ... }
```

### Changelog, 更新日志

#### 1.0.1
Now background images can be binarized as you like.

#### 1.0.0
Initial release.

### Alternatives on other platforms/in other languages. 其他平台或语言下的对等项目

#### EFQRCode written in Swift

EFQRCode is a tool to generate QRCode image or recognize QRCode from image, in Swift.

AwesomeQRCode is inspired by [EFQRCode by EyreFree](https://github.com/EyreFree/EFQRCode).

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

Redirect to [Awesome-qr.js](https://github.com/SumiMakito/Awesome-qr.js)

### 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 &amp; License, 版权信息与授权协议

Copyright &copy; 2017 Sumi Makito
Expand Down
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ android {
applicationId "com.github.sumimakito.awesomeqrsample"
minSdkVersion 19
targetSdkVersion 25
versionCode 3
versionName "1.2"
versionCode 4
versionName "1.3"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ public class MainActivity extends AppCompatActivity {
private ScrollView scrollView;
private EditText etDotScale;
private TextView tvJSHint;
private CheckBox ckbBinarize;
private EditText etBinarizeThreshold;

@Override
protected void onCreate(Bundle savedInstanceState) {
Expand All @@ -61,6 +63,8 @@ protected void onCreate(Bundle savedInstanceState) {
btGenerate = (Button) findViewById(R.id.generate);
ckbWhiteMargin = (CheckBox) findViewById(R.id.whiteMargin);
ckbAutoColor = (CheckBox) findViewById(R.id.autoColor);
ckbBinarize= (CheckBox) findViewById(R.id.binarize);
etBinarizeThreshold = (EditText) findViewById(R.id.binarizeThreshold);

ckbAutoColor.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
Expand All @@ -70,6 +74,13 @@ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
}
});

ckbBinarize.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
etBinarizeThreshold.setEnabled(isChecked);
}
});

btSelectBG.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Expand Down Expand Up @@ -99,8 +110,12 @@ public void onClick(View v) {
etDotScale.getText().length() == 0 ? 0.3f : Float.parseFloat(etDotScale.getText().toString()),
ckbAutoColor.isChecked() ? Color.BLACK : Color.parseColor(etColorDark.getText().toString()),
ckbAutoColor.isChecked() ? Color.WHITE : Color.parseColor(etColorLight.getText().toString()),
backgroundImage, ckbWhiteMargin.isChecked(),
ckbAutoColor.isChecked());
backgroundImage,
ckbWhiteMargin.isChecked(),
ckbAutoColor.isChecked(),
ckbBinarize.isChecked(),
etBinarizeThreshold.getText().length() == 0 ? 128 : Integer.parseInt(etBinarizeThreshold.getText().toString())
);
} catch (Exception e) {
Toast.makeText(MainActivity.this, "Error occurred, please check your configs.", Toast.LENGTH_LONG).show();
}
Expand Down Expand Up @@ -166,7 +181,9 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}

private void generate(final String contents, final int size, final int margin, final float dotScale, final int colorDark, final int colorLight, final Bitmap background, final boolean whiteMargin, final boolean autoColor) {
private void generate(final String contents, final int size, final int margin, final float dotScale,
final int colorDark, final int colorLight, final Bitmap background, final boolean whiteMargin,
final boolean autoColor, final boolean binarize, final int binarizeThreshold) {
if (generating) return;
generating = true;
progressDialog = new ProgressDialog.Builder(this).setMessage("Generating...").setCancelable(false).create();
Expand All @@ -175,7 +192,7 @@ private void generate(final String contents, final int size, final int margin, f
@Override
public void run() {
try {
final Bitmap b = AwesomeQRCode.create(contents, size, margin, dotScale, colorDark, colorLight, background, whiteMargin, autoColor);
final Bitmap b = AwesomeQRCode.create(contents, size, margin, dotScale, colorDark, colorLight, background, whiteMargin, autoColor, binarize, binarizeThreshold);
runOnUiThread(new Runnable() {
@Override
public void run() {
Expand Down
27 changes: 26 additions & 1 deletion app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -170,10 +170,10 @@
android:id="@+id/colorDark"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:enabled="false"
android:hint="colorDark"
android:lines="1"
android:maxLines="1"
android:enabled="false"
android:singleLine="true" />


Expand Down Expand Up @@ -213,6 +213,31 @@
android:layout_height="wrap_content"
android:text="White margin on background image" />

<CheckBox
android:id="@+id/binarize"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Binarize background image" />

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:paddingLeft="4dp"
android:paddingRight="4dp"
android:text="binarizeThreshold (0 &lt; threshold &lt; 255)" />

<EditText
android:id="@+id/binarizeThreshold"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:enabled="false"
android:hint="128"
android:lines="1"
android:maxLines="1"
android:inputType="number"
android:singleLine="true" />

<Button
android:id="@+id/generate"
android:layout_width="match_parent"
Expand Down
4 changes: 2 additions & 2 deletions library/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ android {
defaultConfig {
minSdkVersion 9
targetSdkVersion 25
versionCode 1
versionName "1.0.0"
versionCode 2
versionName "1.0.1"

testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public class AwesomeQRCode {
* This default value makes data blocks appear smaller.
*/
private static float DEFAULT_DTA_DOT_SCALE = 0.3f;
private static int DEFAULT_BINARIZING_THRESHOLD = 128;

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, true);
Expand All @@ -52,25 +53,41 @@ public static Bitmap create(String contents, int size, int margin, int colorDark
}

public static Bitmap create(String contents, int size, int margin, float dataDotScale, int colorDark, int colorLight, Bitmap backgroundImage, boolean whiteMargin) throws IllegalArgumentException {
return create(contents, size, margin, dataDotScale, colorDark, colorLight, backgroundImage, whiteMargin, true);
return create(contents, size, margin, dataDotScale, colorDark, colorLight, backgroundImage, whiteMargin, false);
}

public static Bitmap create(String contents, int size, int margin, float dataDotScale, Bitmap backgroundImage, boolean whiteMargin, boolean binarize) throws IllegalArgumentException {
return create(contents, size, margin, dataDotScale, Color.BLACK, Color.WHITE, backgroundImage, whiteMargin, true, binarize, DEFAULT_BINARIZING_THRESHOLD);
}

public static Bitmap create(String contents, int size, int margin, float dataDotScale, Bitmap backgroundImage, boolean whiteMargin, boolean binarize, int binarizeThreshold) throws IllegalArgumentException {
return create(contents, size, margin, dataDotScale, Color.BLACK, Color.WHITE, backgroundImage, whiteMargin, true, binarize, binarizeThreshold);
}

public static Bitmap create(String contents, int size, int margin, float dataDotScale, int colorDark, int colorLight, Bitmap backgroundImage, boolean whiteMargin, boolean autoColor) throws IllegalArgumentException {
return create(contents, size, margin, dataDotScale, colorDark, colorLight, backgroundImage, whiteMargin, autoColor, false, DEFAULT_BINARIZING_THRESHOLD);
}

public static Bitmap create(String contents, int size, int margin, float dataDotScale, int colorDark, int colorLight, Bitmap backgroundImage, boolean whiteMargin, boolean autoColor, boolean binarize) throws IllegalArgumentException {
return create(contents, size, margin, dataDotScale, colorDark, colorLight, backgroundImage, whiteMargin, autoColor, binarize, DEFAULT_BINARIZING_THRESHOLD);
}

/**
* Create a QR matrix and render it use given configs.
*
* @param contents Contents to encode.
* @param size Width as well as the height of the output QR code, includes margin.
* @param margin Margin to add around the QR code.
* @param dataDotScale Scale the data blocks and makes them appear smaller.
* @param colorDark Color of blocks. Will be OVERRIDE by autoColor. (BYTE_DTA, BYTE_POS, BYTE_AGN, BYTE_TMG)
* @param colorLight Color of empty space. Will be OVERRIDE by autoColor. (BYTE_EPT)
* @param contents Contents to encode.
* @param size Width as well as the height of the output QR code, includes margin.
* @param margin Margin to add around the QR code.
* @param dataDotScale Scale the data blocks and makes them appear smaller.
* @param colorDark Color of blocks. Will be OVERRIDE by autoColor. (BYTE_DTA, BYTE_POS, BYTE_AGN, BYTE_TMG)
* @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 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.
* @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) throws IllegalArgumentException {
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 {
if (contents.isEmpty()) {
throw new IllegalArgumentException("Error: contents is empty. (contents.isEmpty())");
}
Expand All @@ -90,10 +107,10 @@ public static Bitmap create(String contents, int size, int margin, float dataDot
if (dataDotScale < 0 || dataDotScale > 1) {
throw new IllegalArgumentException("Error: an illegal data dot scale is given. (dataDotScale < 0 || dataDotScale > 1)");
}
return render(byteMatrix, size - 2 * margin, margin, dataDotScale, colorDark, colorLight, backgroundImage, whiteMargin, autoColor);
return render(byteMatrix, size - 2 * margin, margin, dataDotScale, colorDark, colorLight, backgroundImage, whiteMargin, autoColor, binarize, binarizeThreshold);
}

private static Bitmap render(ByteMatrix byteMatrix, int innerRenderedSize, int margin, float dataDotScale, int colorDark, int colorLight, Bitmap backgroundImage, boolean whiteMargin, boolean autoColor) {
private static Bitmap render(ByteMatrix byteMatrix, int innerRenderedSize, int margin, float dataDotScale, int colorDark, int colorLight, Bitmap backgroundImage, boolean whiteMargin, boolean autoColor, boolean binarize, int binarizeThreshold) {
int nCount = byteMatrix.getWidth();
float nWidth = (float) innerRenderedSize / nCount;
float nHeight = (float) innerRenderedSize / nCount;
Expand All @@ -112,6 +129,16 @@ private static Bitmap render(ByteMatrix byteMatrix, int innerRenderedSize, int m
colorDark = getDominantColor(backgroundImage);
}

if (binarize && backgroundImage != null) {
int threshold = DEFAULT_BINARIZING_THRESHOLD;
if (binarizeThreshold > 0 && binarizeThreshold < 255) {
threshold = binarizeThreshold;
}
colorDark = Color.BLACK;
colorLight = Color.WHITE;
binarize(backgroundImageScaled, threshold);
}

Paint paint = new Paint();
Paint paintDark = new Paint();
paintDark.setColor(colorDark);
Expand All @@ -126,6 +153,8 @@ private static Bitmap render(ByteMatrix byteMatrix, int innerRenderedSize, int m
Canvas canvas = new Canvas(renderedBitmap);
canvas.drawColor(Color.WHITE);
canvas.drawBitmap(backgroundImageScaled, whiteMargin ? margin : 0, whiteMargin ? margin : 0, paint);


for (int row = 0; row < byteMatrix.getHeight(); row++) {
String s = "";
for (int col = 0; col < byteMatrix.getWidth(); col++) {
Expand Down Expand Up @@ -223,9 +252,8 @@ private static ByteMatrix getBitMatrix(String contents) {
}

/**
*
* @param contents Contents to encode.
* @param errorCorrectionLevel ErrorCorrectionLevel
* @param contents Contents to encode.
* @param errorCorrectionLevel ErrorCorrectionLevel
* @return QR code object.
* @throws WriterException Refer to the messages below.
*/
Expand Down Expand Up @@ -308,5 +336,19 @@ private static int getDominantColor(Bitmap bitmap) {
blue = Math.max(0, Math.min(0xFF, blue / c));
return (0xFF << 24) | (red << 16) | (green << 8) | blue;
}

private static void binarize(Bitmap bitmap, int threshold) {
int r, g, b;
for (int y = 0; y < bitmap.getHeight(); y++) {
for (int x = 0; x < bitmap.getHeight(); x++) {
int color = bitmap.getPixel(x, y);
r = (color >> 16) & 0xFF;
g = (color >> 8) & 0xFF;
b = color & 0xFF;
float sum = 0.30f * r + 0.59f * g + 0.11f * b;
bitmap.setPixel(x, y, sum > threshold ? Color.WHITE : Color.BLACK);
}
}
}
}

0 comments on commit bca53a3

Please sign in to comment.