@@ -54,21 +54,37 @@ import com.aspose.barcode.cloud.api.GenerateApi
5454import com.aspose.barcode.cloud.api.ScanApi
5555import com.aspose.barcode.cloud.model.BarcodeImageFormat
5656import com.aspose.barcode.cloud.model.BarcodeImageParams
57+ import com.aspose.barcode.cloud.model.Code128EncodeMode
58+ import com.aspose.barcode.cloud.model.Code128Params
59+ import com.aspose.barcode.cloud.model.ECIEncodings
5760import com.aspose.barcode.cloud.model.EncodeBarcodeType
61+ import com.aspose.barcode.cloud.model.MicroQRVersion
62+ import com.aspose.barcode.cloud.model.Pdf417EncodeMode
63+ import com.aspose.barcode.cloud.model.Pdf417ErrorLevel
64+ import com.aspose.barcode.cloud.model.Pdf417Params
5865import com.aspose.barcode.cloud.model.QREncodeMode
5966import com.aspose.barcode.cloud.model.QRErrorLevel
6067import com.aspose.barcode.cloud.model.QRVersion
6168import com.aspose.barcode.cloud.model.QrParams
69+ import com.aspose.barcode.cloud.model.RectMicroQRVersion
6270import com.aspose.barcode.cloud.requests.GenerateRequestWrapper
6371import com.aspose.barcode.cloud.requests.ScanMultipartRequestWrapper
6472import com.google.android.material.snackbar.Snackbar
6573import java.io.File
6674import java.io.FileOutputStream
6775import kotlin.math.floor
76+ import kotlin.math.min
6877import androidx.core.graphics.scale
6978
7079class MainActivity : AppCompatActivity () {
7180 companion object {
81+ /* * Barcode types whose modules are square and get distorted by a non-square image. */
82+ private val SQUARE_BARCODE_TYPES = setOf (
83+ EncodeBarcodeType .QR ,
84+ EncodeBarcodeType .GS1_QR ,
85+ EncodeBarcodeType .MICRO_QR ,
86+ )
87+
7288 private fun imageSize (width : Int , height : Int , maxSize : Int = 384): Size {
7389 val ratio = width.toFloat() / height
7490 if (ratio > 1 ) {
@@ -194,7 +210,7 @@ class MainActivity : AppCompatActivity() {
194210 val smallerBmp = reduceBitmapSize(image)
195211
196212 barcodeImgView.setImageBitmap(smallerBmp)
197- startRecognizeAnimation ()
213+ startProgressAnimation ()
198214
199215 val tmpFile = File .createTempFile(" barcode" , null )
200216
@@ -209,7 +225,7 @@ class MainActivity : AppCompatActivity() {
209225 val recognized = scanApi.scanMultipart(apiRequest)
210226
211227 runOnUiThread {
212- stopRecognizeAnimation ()
228+ stopProgressAnimation ()
213229 if (recognized.barcodes.isEmpty()) {
214230 barcodeTextEdit.setText(" " )
215231 showErrorMessage(" No barcode detected" )
@@ -222,7 +238,7 @@ class MainActivity : AppCompatActivity() {
222238 }
223239 } catch (e: ApiException ) {
224240 runOnUiThread {
225- stopRecognizeAnimation ()
241+ stopProgressAnimation ()
226242
227243 var message = e.message + " : " + e.details
228244 if (e.httpCode == 0 ) {
@@ -232,7 +248,7 @@ class MainActivity : AppCompatActivity() {
232248 }
233249 } catch (e: Exception ) {
234250 runOnUiThread {
235- stopRecognizeAnimation ()
251+ stopProgressAnimation ()
236252 showErrorMessage(" Exception: " + e.message)
237253 }
238254 }
@@ -242,44 +258,38 @@ class MainActivity : AppCompatActivity() {
242258 }
243259 }
244260
245- private fun startRecognizeAnimation () {
261+ private fun startProgressAnimation () {
246262 val rotation = AnimationUtils .loadAnimation(this , R .anim.rotate)
247263 rotation.fillAfter = true
248264 barcodeImgView.startAnimation(rotation)
249265 }
250266
251- private fun stopRecognizeAnimation () {
267+ private fun stopProgressAnimation () {
252268 barcodeImgView.clearAnimation()
253269 }
254270
255271 fun onBtnGenerateClick (@Suppress(" UNUSED_PARAMETER" ) view : View ) {
256272 val type = EncodeBarcodeType .fromValue(barcodeTypeSpinner.selectedItem.toString())
257273
258274 val genRequest = GenerateRequestWrapper (type, barcodeTextEdit.text.toString())
259- genRequest.barcodeImageParams = BarcodeImageParams ().apply {
260- imageFormat = BarcodeImageFormat .PNG
261- imageHeight = barcodeImgView.measuredHeight.toFloat()
262- imageWidth = barcodeImgView.measuredWidth.toFloat()
263- }
275+ genRequest.barcodeImageParams = imageParams(type)
264276
265- if (type == EncodeBarcodeType .QR ) {
266- genRequest.qrParams = QrParams ().apply {
267- qrEncodeMode = QREncodeMode .AUTO
268- qrErrorLevel = QRErrorLevel .LEVEL_M
269- qrVersion = QRVersion .AUTO
270- qrAspectRatio = 0.75f
271- }
272- }
277+ applyEncodeParams(genRequest, type)
278+
279+ startProgressAnimation()
273280
274281 Thread {
275282 try {
276283 val generated = generateApi.generate(genRequest)
277284 runOnUiThread {
285+ stopProgressAnimation()
278286 val bitmap = BitmapFactory .decodeFile(generated!! .absolutePath)
279287 barcodeImgView.setImageBitmap(bitmap)
280288 }
281289 } catch (e: ApiException ) {
282290 runOnUiThread {
291+ stopProgressAnimation()
292+
283293 var message = e.message + " : " + e.details
284294 if (e.httpCode == 0 ) {
285295 message = " Check ClientId and ClientSecret in ApiClient $message "
@@ -288,12 +298,85 @@ class MainActivity : AppCompatActivity() {
288298 }
289299 } catch (e: Exception ) {
290300 runOnUiThread {
301+ stopProgressAnimation()
291302 showErrorMessage(" Exception: " + e.message)
292303 }
293304 }
294305 }.start()
295306 }
296307
308+ /* *
309+ * The API stretches the barcode to fill the requested image, so a square symbology
310+ * has to be rendered into a square image to keep its modules square.
311+ */
312+ private fun imageParams (type : EncodeBarcodeType ) = BarcodeImageParams ().apply {
313+ imageFormat = BarcodeImageFormat .PNG
314+
315+ if (type in SQUARE_BARCODE_TYPES ) {
316+ val side = min(barcodeImgView.measuredWidth, barcodeImgView.measuredHeight).toFloat()
317+ imageHeight = side
318+ imageWidth = side
319+ } else {
320+ imageHeight = barcodeImgView.measuredHeight.toFloat()
321+ imageWidth = barcodeImgView.measuredWidth.toFloat()
322+ }
323+ }
324+
325+ /* *
326+ * Attaches the optional parameter groups supported by [GenerateRequestWrapper].
327+ * Each group applies to its own family of barcode types.
328+ */
329+ private fun applyEncodeParams (request : GenerateRequestWrapper , type : EncodeBarcodeType ) {
330+ when (type) {
331+ EncodeBarcodeType .QR ,
332+ EncodeBarcodeType .GS1_QR -> request.qrParams = qrParams()
333+
334+ EncodeBarcodeType .MICRO_QR -> request.qrParams = qrParams().apply {
335+ microQRVersion = MicroQRVersion .AUTO
336+ }
337+
338+ EncodeBarcodeType .RECT_MICRO_QR -> request.qrParams = qrParams().apply {
339+ rectMicroQrVersion = RectMicroQRVersion .AUTO
340+ }
341+
342+ EncodeBarcodeType .CODE128 ,
343+ EncodeBarcodeType .GS1_CODE128 -> request.code128Params = Code128Params ().apply {
344+ code128EncodeMode = Code128EncodeMode .AUTO
345+ }
346+
347+ EncodeBarcodeType .PDF417 ,
348+ EncodeBarcodeType .MACRO_PDF417 -> request.pdf417Params = pdf417Params(3.0f )
349+
350+ EncodeBarcodeType .MICRO_PDF417 ,
351+ EncodeBarcodeType .GS1_MICRO_PDF417 -> request.pdf417Params = pdf417Params(2.0f )
352+
353+ else -> Unit
354+ }
355+ }
356+
357+ private fun qrParams () = QrParams ().apply {
358+ qrEncodeMode = QREncodeMode .AUTO
359+ qrErrorLevel = QRErrorLevel .LEVEL_M
360+ qrVersion = QRVersion .AUTO
361+ qrECIEncoding = ECIEncodings .UTF8
362+ // 1.0 keeps the modules square, lower values flatten the barcode.
363+ qrAspectRatio = 1.0f
364+ }
365+
366+ /* *
367+ * @param aspectRatio defined by the standard: 3 to 5 for Pdf417 and MacroPdf417,
368+ * 2 to 5 for MicroPdf417.
369+ */
370+ private fun pdf417Params (aspectRatio : Float ) = Pdf417Params ().apply {
371+ pdf417EncodeMode = Pdf417EncodeMode .AUTO
372+ pdf417ErrorLevel = Pdf417ErrorLevel .LEVEL2
373+ pdf417ECIEncoding = ECIEncodings .UTF8
374+ pdf417AspectRatio = aspectRatio
375+ // 0 selects the column and row count automatically.
376+ pdf417Columns = 0
377+ pdf417Rows = 0
378+ }
379+
297380 fun onBtnTakePhotoClick (@Suppress(" UNUSED_PARAMETER" ) view : View ) {
298381 val takePictureIntent = Intent (MediaStore .ACTION_IMAGE_CAPTURE )
299382 if (takePictureIntent.resolveActivity(packageManager) != null ) {
0 commit comments