Close

Returning a JPG thumbnail as a JSON array

A project log for ESP32 WiFi instant Camera

The FS32 is a digital Polaroid that uploads the photo instantly to the cloud

Martin FasaniMartin Fasani 01/06/2019 at 12:260 Comments

The limit I hit with this is that anything more than 10Kb of Json and Arduino JSON cannot parse it. So I didn't found time to check why it is, I just though about debugging it with PlatformIO with a board that supports debbuging and ordered one.

https://github.com/martinberlin/php-gallery/blob/master/upload-xbm.php The lines to do this in PHP are not very complicated, we will first reduce the thumbnail using imagemagic to about 60px height (Proportional) and then just read byte by byte and converting it to an integer. The image method does not really care if it's an hexa like "0xFF" or 255. So I prefer to sent 255 since it will generate a smaller Json response.

<?php
switch ($returnType) {
        // JPG bytes
        case 3:
            $im->setImageFormat('jpg');
            $jpg = $im->getImageBlob();
            $cleanPixels = array();
            foreach(str_split($jpg) as $char){
                array_push($cleanPixels, ord($char)); // For HEX image: "0x".strtoupper(bin2hex($char))
            }
            //header("Content-Type: image/jpeg");exit($jpg); // Check JPEG
            $imageObj['jpg']    = $cleanPixels;
}
$imageObj['url'] = "http://".$_SERVER['HTTP_HOST']."/".$directoryBase.$directoryDate.$uploadedName;
$imageObj['hash']= md5_file($uploadedFile);
$imageObj['folder'] = $getFolder;
echo json_encode($imageObj);

That will return a JSON like this (leaving only 5 bytes to avoid pasting an endless sucker here):

{"jpg":[255,216,0,0,0],
"url":,
"hash":"0c3d3224de90d57f32fbef43116eec14",
"folder":"Tests"}

 This is how will parse this incoming bytes in C++

// After successful upload and discarding response headers
// https://github.com/martinberlin/FS32/blob/tft-7735/src/FasarekFS2.ino#L380
 DynamicJsonBuffer jsonBuffer;
  JsonObject& json = jsonBuffer.parseObject(response);
  total_time = millis() - total_time;
  cameraOff();
  if (!json.success()) {
    tft.setTextColor(TFT_RED);
    printMessage("JSON parse failed", true, true);
    server.send(200, "text/html", "<div id='m'>JSON parse error. Debug:<br>"+response+"</div><br>");
    return;
  }
  
  char imageUrl[300];
  char hash[33];
  char folder[33];
  // WARNING If the json does not contain any of this properties then ESP will reboot
  strcpy(imageUrl, json["url"]);
  strcpy(hash, json["hash"]);
  strcpy(folder, json["folder"]);

  // serverCaptureWifi()
  if (json.containsKey("jpg")) {
    JsonArray& arr = json["jpg"];
    int c = 0;
    const char* tempx;
    for (auto value : arr) {
      image[c] = value.as<unsigned int>();
      c++;
    }
    // Draw thumbnail coming from json:
drawArrayJpeg(image, sizeof(image), 0, 11);

I hope that explains a bit more how is the JPG thumbnail rendering in this project.

NOTE : If anyone has an advice regarding my 10Kb max JSON String please comment. I also found out that when the response coming from the API is two long, strange numbers appear in the beginning and the end, so I had to clean it up like this:

// DEBUG: Do some ugly parsing since a big JSON comes with garbage at the beginning like 398f {"jpg":1,2} 0 (And an appended zero?)
int jsonStart = response.indexOf('{');
int jsonEnd = response.indexOf('}');
response = response.substring(jsonStart, jsonEnd+1);

 That is really sub-optimal and I still do not understand why. Is because String has a limit in characters ?

Discussions