mirror of
https://github.com/CatimaLoyalty/Android.git
synced 2026-04-09 18:07:54 -04:00
Merge pull request #43 from brarcher/datamatrix-scaling
Datamatrix scaling
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
package protect.card_locker;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.AsyncTask;
|
||||
import android.util.Log;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.MultiFormatWriter;
|
||||
import com.google.zxing.WriterException;
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/**
|
||||
* This task will generate a barcode and load it into an ImageView.
|
||||
* Only a weak reference of the ImageView is kept, so this class will not
|
||||
* prevent the ImageView from being garbage collected.
|
||||
*/
|
||||
class BarcodeImageWriterTask extends AsyncTask<Void, Void, Bitmap>
|
||||
{
|
||||
private static final String TAG = "LoyaltyCardLocker";
|
||||
|
||||
private final WeakReference<ImageView> imageViewReference;
|
||||
private final String cardId;
|
||||
private final BarcodeFormat format;
|
||||
private final int imageHeight;
|
||||
private final int imageWidth;
|
||||
|
||||
public BarcodeImageWriterTask(ImageView imageView, String cardIdString,
|
||||
BarcodeFormat barcodeFormat)
|
||||
{
|
||||
// Use a WeakReference to ensure the ImageView can be garbage collected
|
||||
imageViewReference = new WeakReference<>(imageView);
|
||||
|
||||
cardId = cardIdString;
|
||||
format = barcodeFormat;
|
||||
imageHeight = imageView.getHeight();
|
||||
imageWidth = imageView.getWidth();
|
||||
}
|
||||
|
||||
public Bitmap doInBackground(Void... params)
|
||||
{
|
||||
MultiFormatWriter writer = new MultiFormatWriter();
|
||||
BitMatrix bitMatrix;
|
||||
try
|
||||
{
|
||||
bitMatrix = writer.encode(cardId, format, imageWidth, imageHeight, null);
|
||||
|
||||
final int WHITE = 0xFFFFFFFF;
|
||||
final int BLACK = 0xFF000000;
|
||||
|
||||
int bitMatrixWidth = bitMatrix.getWidth();
|
||||
int bitMatrixHeight = bitMatrix.getHeight();
|
||||
|
||||
int[] pixels = new int[bitMatrixWidth * bitMatrixHeight];
|
||||
|
||||
for (int y = 0; y < bitMatrixHeight; y++)
|
||||
{
|
||||
int offset = y * bitMatrixWidth;
|
||||
for (int x = 0; x < bitMatrixWidth; x++)
|
||||
{
|
||||
int color = bitMatrix.get(x, y) ? BLACK : WHITE;
|
||||
pixels[offset + x] = color;
|
||||
}
|
||||
}
|
||||
Bitmap bitmap = Bitmap.createBitmap(bitMatrixWidth, bitMatrixHeight,
|
||||
Bitmap.Config.ARGB_8888);
|
||||
bitmap.setPixels(pixels, 0, bitMatrixWidth, 0, 0, bitMatrixWidth, bitMatrixHeight);
|
||||
|
||||
// Determine if the image needs to be scaled.
|
||||
// This is necessary because the datamatrix barcode generator
|
||||
// ignores the requested size and returns the smallest image necessary
|
||||
// to represent the barcode. If we let the ImageView scale the image
|
||||
// it will use bi-linear filtering, which results in a blurry barcode.
|
||||
// To avoid this, if scaling is needed do so without filtering.
|
||||
|
||||
int heightScale = imageHeight / bitMatrixHeight;
|
||||
int widthScale = imageWidth / bitMatrixHeight;
|
||||
int scalingFactor = Math.min(heightScale, widthScale);
|
||||
|
||||
if(scalingFactor > 1)
|
||||
{
|
||||
bitmap = Bitmap.createScaledBitmap(bitmap, bitMatrixWidth * scalingFactor, bitMatrixHeight * scalingFactor, false);
|
||||
}
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
catch (WriterException | IllegalArgumentException e)
|
||||
{
|
||||
Log.e(TAG, "Failed to generate barcode", e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void onPostExecute(Bitmap result)
|
||||
{
|
||||
ImageView imageView = imageViewReference.get();
|
||||
if(imageView == null)
|
||||
{
|
||||
// The ImageView no longer exists, nothing to do
|
||||
return;
|
||||
}
|
||||
|
||||
imageView.setImageBitmap(result);
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@ package protect.card_locker;
|
||||
|
||||
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Bundle;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v7.app.ActionBar;
|
||||
@@ -12,14 +11,12 @@ import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.MultiFormatWriter;
|
||||
import com.google.zxing.WriterException;
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
import com.google.zxing.integration.android.IntentIntegrator;
|
||||
import com.google.zxing.integration.android.IntentResult;
|
||||
|
||||
@@ -149,52 +146,34 @@ public class LoyaltyCardViewActivity extends AppCompatActivity
|
||||
|
||||
if(cardIdField.getText().length() > 0 && barcodeTypeField.getText().length() > 0)
|
||||
{
|
||||
MultiFormatWriter writer = new MultiFormatWriter();
|
||||
BitMatrix result;
|
||||
try
|
||||
String formatString = barcodeTypeField.getText().toString();
|
||||
final BarcodeFormat format = BarcodeFormat.valueOf(formatString);
|
||||
final String cardIdString = cardIdField.getText().toString();
|
||||
|
||||
if(barcodeImage.getHeight() == 0)
|
||||
{
|
||||
String formatString = barcodeTypeField.getText().toString();
|
||||
BarcodeFormat format = BarcodeFormat.valueOf(formatString);
|
||||
if(format == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Unrecognized barcode format: " + formatString);
|
||||
}
|
||||
|
||||
int generateWidth = 100;
|
||||
int generateHeight = 100;
|
||||
|
||||
String cardIdString = cardIdField.getText().toString();
|
||||
|
||||
Log.i(TAG, "Card: " + cardIdString);
|
||||
|
||||
result = writer.encode(cardIdString, format, generateWidth, generateHeight, null);
|
||||
|
||||
final int WHITE = 0xFFFFFFFF;
|
||||
final int BLACK = 0xFF000000;
|
||||
|
||||
int width = result.getWidth();
|
||||
int height = result.getHeight();
|
||||
int[] pixels = new int[width * height];
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
int offset = y * width;
|
||||
for (int x = 0; x < width; x++)
|
||||
Log.d(TAG, "ImageView size is not known known at start, waiting for load");
|
||||
// The size of the ImageView is not yet available as it has not
|
||||
// yet been drawn. Wait for it to be drawn so the size is available.
|
||||
barcodeImage.getViewTreeObserver().addOnGlobalLayoutListener(
|
||||
new ViewTreeObserver.OnGlobalLayoutListener()
|
||||
{
|
||||
pixels[offset + x] = result.get(x, y) ? BLACK : WHITE;
|
||||
}
|
||||
}
|
||||
Bitmap bitmap = Bitmap.createBitmap(width, height,
|
||||
Bitmap.Config.ARGB_8888);
|
||||
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
|
||||
barcodeImage.setImageBitmap(bitmap);
|
||||
|
||||
barcodeIdLayout.setVisibility(View.VISIBLE);
|
||||
barcodeImageLayout.setVisibility(View.VISIBLE);
|
||||
@Override
|
||||
public void onGlobalLayout()
|
||||
{
|
||||
Log.d(TAG, "ImageView size now known");
|
||||
new BarcodeImageWriterTask(barcodeImage, cardIdString, format).execute();
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (WriterException | IllegalArgumentException e)
|
||||
else
|
||||
{
|
||||
Log.e(TAG, "Failed to generate barcode", e);
|
||||
Log.d(TAG, "ImageView size known known, creating barcode");
|
||||
new BarcodeImageWriterTask(barcodeImage, cardIdString, format).execute();
|
||||
}
|
||||
|
||||
barcodeIdLayout.setVisibility(View.VISIBLE);
|
||||
barcodeImageLayout.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
View.OnClickListener captureCallback = new View.OnClickListener()
|
||||
@@ -332,4 +311,4 @@ public class LoyaltyCardViewActivity extends AppCompatActivity
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,10 +5,6 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||
android:paddingTop="@dimen/activity_vertical_margin"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
tools:context="protect.card_locker.MainActivity"
|
||||
tools:showIn="@layout/main_activity">
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout android:orientation="vertical"
|
||||
android:padding="5.0dip"
|
||||
android:padding="10.0dp"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<LinearLayout android:orientation="horizontal"
|
||||
android:padding="5.0dip"
|
||||
android:padding="5.0dp"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:baselineAligned="true">
|
||||
@@ -18,7 +18,7 @@
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout android:orientation="horizontal"
|
||||
android:padding="5.0dip"
|
||||
android:padding="5.0dp"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:baselineAligned="true">
|
||||
|
||||
Reference in New Issue
Block a user