DataMatrix-кодирование с zxing генерирует только растровое изображение 14px
Я использую zxing для генерации штрих-кодов с разными типами (EAN, 2of5 и DataMatrix). Генерация в целом работает нормально. Единственная проблема, с которой я сейчас сталкиваюсь, заключается в том, что zxing генерирует только растровое изображение 14x14 пикселей, которое слишком мало. Но только при использовании матрицы! EAN13, 2of5 / ITF и QR-коды отлично работают с одним и тем же кодом.
мой код:
BitMatrix bitMatrix = new DataMatrixWriter().encode(message, BarcodeFormat.DATA_MATRIX, 1080, 1080, null);
int height = bitMatrix.getHeight(); //height is always 14, it doesn't matter what value I pass to the encoder
как вы можете себе представить, это выглядит довольно дерьмово на экране 1080p, как nexus 5. Я что-то не так понял? Нужно ли делать специальные настройки для DataMatrix?
Google и Stackoverflow не смогли мне помочь, поскольку я не могу найти примеров использования DataMatrix
обновление Вот как я преобразую bitmatrix в bitmap
int width = bitMatrix.getWidth();
int height = bitMatrix.getHeight();
int[] pixels = new int[width * height];
// All are 0, or black, by default
for (int y = 0; y < height; y++) {
int offset = y * width;
for (int x = 0; x < width; x++) {
pixels[offset + x] = bitMatrix.get(x, y) ? BLACK : WHITE;
}
}
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
если я использую любые другие значения для высоты, я получаю OutOfBoundsException, которое довольно очевидно (я ничего другого не ожидал)...
когда я пытаюсь масштабировать imageview и установить фиксированную ширину и высоту, штрих-код можно сканировать, но выглядит как дерьмо. Это слишком очевидно, как bitmatrix только 14х14, а не размер, который я указала.
есть ли простой способ каким-то образом масштабировать bitmatrix? Потому что он состоит только из точек, поэтому это должно быть возможно, но я не хочу вычислять его сам. Я не мог найти никакой документации для bitmatrix, кроме stackoverflow, и это мне совсем не помогло.
Если Я передайте MinWidth или MaxWidth кодировщику через HintMap, приложение всегда аварийно завершает работу за исключением. HintMap (mWidth-ширина дисплея устройства, но я попробовал несколько значений): Hashtable hintMap = новый хеш();
hintMap.put(EncodeHintType.MIN_SIZE, new Dimension(mWidth, mWidth));
hintMap.put(EncodeHintType.MAX_SIZE, new Dimension(mWidth, mWidth));
hintMap.put(EncodeHintType.DATA_MATRIX_SHAPE, SymbolShapeHint.FORCE_SQUARE);
исключения:
java.lang.IllegalArgumentException: Can't find a symbol arrangement that matches the message. Data codewords: 7
эта последняя проблема кажется мне ошибкой в zxing. Я не понимаю, почему генерация не работает, если я изменить размер.
4 ответов
вот небольшой пример того, как вы можете изменить свой метод преобразования из BitMatrix в Bitmap. Метод масштабирования BitMatrix.
int BLACK = 0xFF000000;
int WHITE = 0xFFFFFFFF;
// change the values to your needs
int requestedWidth = 300;
int requestedHeight = 300;
int width = bitMatrix.getWidth();
int height = bitMatrix.getHeight();
// calculating the scaling factor
int pixelsize = requestedWidth/width;
if (pixelsize > requestedHeight/height)
{
pixelsize = requestedHeight/height;
}
int[] pixels = new int[requestedWidth * requestedHeight];
// All are 0, or black, by default
for (int y = 0; y < height; y++) {
int offset = y * requestedWidth * pixelsize;
// scaling pixel height
for (int pixelsizeHeight = 0; pixelsizeHeight < pixelsize; pixelsizeHeight++, offset+=requestedWidth) {
for (int x = 0; x < width; x++) {
int color = bitMatrix.get(x, y) ? BLACK : WHITE;
// scaling pixel width
for (int pixelsizeWidth = 0; pixelsizeWidth < pixelsize; pixelsizeWidth++) {
pixels[offset + x * pixelsize + pixelsizeWidth] = color;
}
}
}
}
Bitmap bitmap = Bitmap.createBitmap(requestedWidth, requestedHeight, Bitmap.Config.ARGB_8888);
bitmap.setPixels(pixels, 0, requestedWidth, 0, 0, requestedWidth, requestedHeight);
// I could only test it with BufferedImage and a modified version of the zxing J2SE client
// BufferedImage bitmap = new BufferedImage(requestedWidth, requestedHeight, BufferedImage.TYPE_INT_ARGB);
// bitmap.getRaster().setDataElements(0, 0, requestedWidth, requestedHeight, pixels);
Как я помню, кодировщик матрицы данных является своего рода нечетным человеком, так как код пришел из другого места (barcode4j). Он будет использовать минимальные соответствующие размеры и предполагает, что вызывающий будет масштабировать графику по желанию.
Вы можете сделать это здесь-просто установить ImageView
для масштабирования его содержимого. Это не должно повредить для любого из закодированных штрих-кодов, если вы не включаете сглаживание.
также EncodeHintType.MIN_SIZE
подсказка, которая установит минимум размер, только для матрицы данных.
Я знаю, что этот вопрос касается Android, но я думаю, что может быть классифицирован как общий.
Я работаю с Swift и оберткой ZXingObjC. Я получаю эту ошибку, используя кодировку DataMatrix:
' не удается найти расположение символов, соответствующее сообщению. Данные кодовые слова: 5'
Итак, отладочный код, я прибыл в класс ZXDataMatrixSymbolInfo, по методу:
+ (ZXDataMatrixSymbolInfo *)lookup:(int)dataCodewords shape:(ZXDataMatrixSymbolShapeHint)shape minSize:(ZXDimension *)minSize
когда происходит?
Я пишу пользовательский swift обертка (CoderEncoder) для моего проекта, с помощью этого метода:
static func encode(string code: String, encoding: CoderEncorderType, size: CGSize = CGSizeMake(200, 200)) -> UIImage? {
let writer: ZXWriter = ZXMultiFormatWriter.writer() as! ZXWriter
do {
let format = CodeEncoder.getEncoding(type: encoding)
let result = try writer.encode(code, format: format, width: Int32(size.width), height: Int32(size.height))
let cgImage = ZXImage(matrix: result, onColor: UIColor.blackColor().CGColor, offColor: UIColor.clearColor().CGColor).cgimage
return UIImage(CGImage: cgImage)
} catch let error as NSError {
ERLog(what: error)
}
return nil
}
Итак, когда я звоню:
CoderEncoder.encode("foo", .DataMatrix)
ошибка.
В основном, в zxdatamatrixwriter maxSize равен нулю, поэтому вам нужно указать измерение от 10 до 144.
или!! или укажите форму:
ZXDataMatrixSymbolShapeHintForcesquare
ZXDataMatrixSymbolShapeHintForcerectangle
есть ли простой способ каким-то образом масштабировать bitmatrix?
Да, есть. Проблема в том, что использование автоматического масштабирования Android вызывает некоторые проблемы:
- Android использует билинейную фильтрацию при масштабировании
- двухлинейная фильтрация не может быть отключена при использовании аппаратного ускорения
подход, который я принял, заключается в масштабировании вручную целочисленным фактором растрового изображения. Вот как преобразовать a BitMatrix для неразбавленного растрового изображения:
/**
* Create an unscaled bitmap (1 square = 1 pixel) from a bitmatrix
*
* @param bitMatrix the bitmatrix to convert
* @return a unscaled bitmap
*/
public Bitmap drawUnscaledBitmap(BitMatrix bitMatrix) {
final int bmWidth = bitMatrix.getWidth();
final int bmHeight = bitMatrix.getHeight();
final Bitmap bitmap = Bitmap.createBitmap(bmWidth, bmHeight, Bitmap.Config.ARGB_8888);
int[] pixels = new int[bmWidth * bmHeight];
for (int y = 0; y < bmHeight; y++) {
int offset = y * bmWidth;
for (int x = 0; x < bmWidth; x++) {
pixels[offset + x] = bitMatrix.get(x, y) ? Color.BLACK : Color.WHITE;
}
}
bitmap.setPixels(pixels, 0, bmWidth, 0, 0, bmWidth, bmHeight);
return bitmap;
}
и вот как масштабировать растровое изображение ,чтобы (почти) соответствовать желаемому размеру прямоугольника:
/**
* Upscale a bitmap (maintaining ratio) by the biggest integer scaling factor that allows the bitmap to still fit in the given size
*
* @param bitmap the bitmap to upscale
* @param size the size that the output scaled bitmap needs to fit in
* @return the scaled bitmap if the integer scaling factor is > 1; the original bitmap otherwise
*/
public Bitmap drawScaledBitmap(Bitmap bitmap, Size size) {
final int bmWidth = bitmap.getWidth();
final int bmHeight = bitmap.getHeight();
final int wScalingFactor = size.getWidth() / bmWidth;
final int hScalingFactor = size.getHeight() / bmHeight;
final int scalingFactor = Math.min(wScalingFactor, hScalingFactor);
return scalingFactor > 1 ? Bitmap.createScaledBitmap(bitmap, bmWidth * scalingFactor, bmHeight * scalingFactor, false) : bitmap;
}