Home > Enterprise >  Encoding QR data as PNG using C and stb_image_write
Encoding QR data as PNG using C and stb_image_write

Time:07-15

im trying to render QR to image (png, svg) using QR-Code-generator-1.8.0 and stb_image_write, i follow the example on demo example and generate the QR correctly but very small and i dont know how to scale it, i suppose must be at image writing, but how to add pixel image information to generate the image in whichever size we pass as argument to the function?, the real question is how to create the QR as image in any size that i want it.

the full code is next:

#include "qrcodegen.h"

#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"

#define Border    4

void qr_make_image_data(const uint8_t *data, uint8_t **result) {
  int size = qrcodegen_getSize(data);
  int border = Border;
  *result = calloc(1, (size   border*2)*(size   border*2)*2);
  int count = 0;
  for (int y = -border; y < size   border; y  )
    for (int x = -border; x < size   border; x  ) 
      (*result)[count  ] = qrcodegen_getModule(data, x, y) ? 0xff : 0x00;
}

int qr_make(char *text, char *file_out) {
  uint8_t qrcode[qrcodegen_BUFFER_LEN_MAX];
  uint8_t temp_buf[qrcodegen_BUFFER_LEN_MAX];
  bool ok = qrcodegen_encodeText(text, temp_buf, qrcode,
      qrcodegen_Ecc_MEDIUM, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX,
      qrcodegen_Mask_AUTO, true);
  if (!ok) return -1;
  int size = qrcodegen_getSize(qrcode);
  uint8_t *data = NULL;
  qr_make_image_data(qrcode, &data);

  int image_side = size   Border * 2;
  int result = stbi_write_png(file_out, image_side, image_side, 1, data, 0);
  free(data);
  return result;
}

int main(void) {
  char *sample_text_1 = "Donec diam neque, vestibulum eget, "
    "vulputate ut, ultrices vel, augue. Donec posuere metus "
    "vitae ipsum. Mauris sit amet eros. Vestibulum ac est "
    "lacinia nisi venenatis tristique. Integer pede justo, "
    "lacinia eget, tincidunt eget, tempus vel, pede.";

  char *sample_text_2 = "www.stackoverflow.com";

  qr_make(sample_text_1, "qr1.png");
  qr_make(sample_text_2, "qr2.png");
}

That's the solution, and also fix the pixel data on qr_make() function, that was my error, i put it inverted, the code next fix that and resize the output image:

#include "qrcodegen.h"

#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"
#define STB_IMAGE_RESIZE_IMPLEMENTATION
#include "stb_image_resize.h"

#define Border    4

void qr_make_image_data(const uint8_t *data, uint8_t **result) {
  int size = qrcodegen_getSize(data);
  int border = Border;
  uint8_t datablock;
  *result = calloc(1, (size   border*2)*(size   border*2));
  int count = 0;
  for (int y = -border; y < size   border; y  )
    for (int x = -border; x < size   border; x  ) {
      (*result)[count  ] = qrcodegen_getModule(data, x, y) ? 0x00 : 0xff;
    }
}

int qr_make(char *text, char *file_out, int resize_factor) {
  uint8_t qrcode[qrcodegen_BUFFER_LEN_MAX];
  uint8_t temp_buf[qrcodegen_BUFFER_LEN_MAX];

  // encode text as QR code
  bool ok = qrcodegen_encodeText(text, temp_buf, qrcode,
      qrcodegen_Ecc_QUARTILE, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX,
      qrcodegen_Mask_AUTO, false);

  if (!ok) return -1;
  int size = qrcodegen_getSize(qrcode);
  uint8_t *data = NULL;
  qr_make_image_data(qrcode, &data);

  // calculate width and height
  int image_side = size   Border * 2;
  int image_side_resized = image_side * resize_factor;

  // memory buffer for resized data
  uint8_t *resized_data = malloc(image_side_resized * image_side_resized * 1);

  stbir_resize(data, image_side, image_side, 0, resized_data, image_side_resized, image_side_resized, 0,
      STBIR_TYPE_UINT8, 1, STBIR_ALPHA_CHANNEL_NONE, 0, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP,
      STBIR_FILTER_BOX, STBIR_FILTER_BOX, STBIR_COLORSPACE_SRGB, NULL);

  // encode data as PNG image file
  int result = stbi_write_png(file_out, image_side_resized, image_side_resized, 1, resized_data, 0);
  free(data);
  free(resized_data);

  return result;
}

int main(void) {
  char *sample_text_1 = "Donec diam neque, vestibulum eget, "
    "vulputate ut, ultrices vel, augue. Donec posuere metus "
    "vitae ipsum. Mauris sit amet eros. Vestibulum ac est "
    "lacinia nisi venenatis tristique. Integer pede justo, "
    "lacinia eget, tincidunt eget, tempus vel, pede.";


  char *sample_text_2 = "www.stackoverflow.com";

  qr_make(sample_text_1, "QR1.png", 4);
  qr_make(sample_text_2, "QR2.png", 4);
}

CodePudding user response:

It seems you could resize the bitmap generated by qr_make_image_data to a greater size using stb_image_resize.h with a box filter, ie: using the default simple API.

If your goal is to insert the png file on a web page, you could achieve the same result with less bandwidth by specifying the bitmap display size with width and height attributes in the IMG tag, or in the style sheet.

  • Related