Jump to content

API/Write: Difference between revisions

11,910 bytes removed ,  30 March 2018
no edit summary
No edit summary
No edit summary
Line 32: Line 32:


=== Manipulating photos for a product ===
=== Manipulating photos for a product ===
==== Understanding products and photos ====
[[API/Write/Photos]]
* Photos are the primary source of Open Food Facts.
* We need good photos of the '''product''', of its '''ingredients''' and '''nutrition table'''. (and for each language present on the packaging)
* Please encourage your users to add as many photos as possible, even if the product is already complete (in that case, don't set them as default photos for  front, ingredients, and nutrition)


==== Upload behaviour ====
If you upload an image (eg for front), the first one will be shown, the others will be saved but not displayed. Useful if you want to let your users take additional images that are neither front, ingredients or nutrition (eg: recycling instructions, labels…)
==== Understanding photos for multilingual products ====
Multilingual products have several photos based on languages present on the packaging. Just suffix the lang code to our examples to get or add the relevant language(s).
==== Adding photos for a product ====
* Use the POST method on:
<pre>Test server: https://world.openfoodfacts.net/cgi/product_image_upload.pl</pre>
<pre>Live server: https://world.openfoodfacts.org/cgi/product_image_upload.pl</pre>
<sup>(remember to do tests on world.openfoodfacts.net - login and password: off )</sup>
===== Parameters =====
* code: the barcode
* imagefield: (front | ingredients | nutrition)
* imgupload_front : your image file if imagefield:front
* imgupload_ingredients: your image file if imagefield:ingredients
* imgupload_nutrition: your image file if imagefield:nutrition
===== Example =====
<pre>
curl --user off:off --form "imgupload_front=@Tacitus.jpg" --form code=1212121212 --form imagefield=front --form user_id=tacite  --form password=mypassword https://fr.openfoodfacts.net/cgi/product_image_upload.pl</pre>
=====Important=====
*  Content-Disposition: form-data; name=“imgupload_front”; filename=“front.png”
* There must be a HTTP header "Content-Type: multipart/form-data" in the HTTP POST request.
* The imageupload_(front|ingredients|nutrition) name, size and data needs to be encoded in the multipart/form-data format, usually your HTTP request library will do that for you.
* All parameters need to be passed as POST parameters, do not put some in the URL.
* 0048151623426 is a random barcode used only for demonstration purposes.
==== Getting a list of all available photos ====
You get a list of all available photos in the product JSON (both selected photos for all languages, and Raw photos (source images for the selected images and images that are not used)
===== Properties of a photo =====
* id = 5
* uploaded_t = 1474912158 (UNIX timestamp format)
* uploader = tacinte (contributor slug)
* sizes
100
"h":100,
"w":75
* 400
"h":400,
"w":300
* full
"w":3120,
"h":4160
===== Properties of a selected photo =====
* nutrition_fr
* y1 = 151.8125
* normalize":"true",
* x2":"169.75",
* rev":"13",
* geometry":"1238x1238-527-1578"
* sizes
*100
"h":100,
"w":75
* 200
* 400
"h":400,
"w":300
* full
"w":3120,
"h":4160
* y2 = 270.8125
*  x1 = 50.75
*  angle = 0
* white_magic = false
*  imgid = 4
<pre>
      "images":{ 
        "front_fr":{ 
            "y2":"340.8125",
            "x1":"67.75",
            "angle":"0",
            "imgid":"5",
            "white_magic":"false",
            "x2":"245.75",
            "normalize":"true",
            "y1":"13.8125",
            "rev":"10",
            "geometry":"1851x3401-704-143",
            "sizes":{ 
              "400":{ 
                  "w":218,
                  "h":400
              },
              "full":{ 
                  "h":3401,
                  "w":1851
              },
              "100":{ 
                  "w":54,
                  "h":100
              },
              "200":{ 
                  "h":200,
                  "w":109
              }
            }
        },
        "2":{ 
            "sizes":{ 
              "400":{ 
                  "h":400,
                  "w":300
              },
              "full":{ 
                  "h":4160,
                  "w":3120
              },
              "100":{ 
                  "w":75,
                  "h":100
              }
            },
            "uploaded_t":"1474912149",
            "uploader":"tacinte"
        },
        "5":{ 
            "uploaded_t":"1474912158",
            "uploader":"tacinte",
            "sizes":{ 
              "100":{ 
                  "h":100,
                  "w":75
              },
              "400":{ 
                  "h":400,
                  "w":300
              },
              "full":{ 
                  "w":3120,
                  "h":4160
              }
            }
        },
        "3":{ 
            "uploaded_t":"1474912152",
            "uploader":"tacinte",
            "sizes":{ 
              "full":{ 
                  "w":3120,
                  "h":4160
              },
              "400":{ 
                  "h":400,
                  "w":300
              },
              "100":{ 
                  "h":100,
                  "w":75
              }
            }
        },
        "nutrition_fr":{ 
            "y1":"151.8125",
            "normalize":"true",
            "x2":"169.75",
            "rev":"13",
            "geometry":"1238x1238-527-1578",
            "sizes":{ 
              "full":{ 
                  "w":1238,
                  "h":1238
              },
              "400":{ 
                  "h":400,
                  "w":400
              },
              "100":{ 
                  "w":100,
                  "h":100
              },
              "200":{ 
                  "w":200,
                  "h":200
              }
            },
            "y2":"270.8125",
            "x1":"50.75",
            "angle":"0",
            "white_magic":"false",
            "imgid":"4"
        },
        "4":{ 
            "sizes":{ 
              "400":{ 
                  "w":300,
                  "h":400
              },
              "full":{ 
                  "h":4160,
                  "w":3120
              },
              "100":{ 
                  "h":100,
                  "w":75
              }
            },
            "uploader":"tacinte",
            "uploaded_t":"1474912154"
        },
        "ingredients_fr":{ 
            "y2":"248.8125",
            "x1":"82.75",
            "angle":"0",
            "white_magic":"false",
            "imgid":"3",
            "normalize":"true",
            "y1":"158.8125",
            "x2":"257.75",
            "rev":"12",
            "sizes":{ 
              "full":{ 
                  "w":1820,
                  "h":936
              },
              "400":{ 
                  "h":206,
                  "w":400
              },
              "100":{ 
                  "h":51,
                  "w":100
              },
              "200":{ 
                  "h":103,
                  "w":200
              }
            },
            "geometry":"1820x936-860-1651"
        },
        "1":{ 
            "sizes":{ 
              "full":{ 
                  "w":3120,
                  "h":4160
              },
              "400":{ 
                  "h":400,
                  "w":300
              },
              "100":{ 
                  "w":75,
                  "h":100
              }
            },
            "uploaded_t":"1474912148",
            "uploader":"tacinte"
        }
      },
</pre>
==== Adding a photo to the list of all available photos ====
==== Getting the current global photo ====
==== Setting a new current global photo ====
==== Getting the current ingredients photo ====
==== Setting a new current ingredients photo ====
==== Getting the current nutrition photo ====
==== Setting a new current nutrition photo ====
==== Choosing the product by barcode ====
<pre>code=</pre>
Values:
==== Selecting a photo ====
<pre>imgid=</pre>
Values:
==== Rotating a photo ====
<pre>Test server: https://world.openfoodfacts.net/cgi/product_image_rotate.pl</pre>
<pre>Live server: https://world.openfoodfacts.org/cgi/product_image_rotate.pl</pre>
===== Values and output =====
Parameters:
<pre>
imgid =
code = BARCODE
angle = Angle of the rotation - 90° increments
normalize = whether the source image should be normalized
white_magic = whether the source image should be "white magic"'d ( background removal)
</pre>
<pre>function update_image(imagefield) {
$('#crop_' + imagefield).attr("src","/cgi/product_image_rotate.pl?code=" + code + "&imgid=" + imagefield_imgid[imagefield]
+ "&angle=" + angles[imagefield] + "&normalize=" + $("#normalize_" + imagefield).prop('checked')
+ "&white_magic=" + $("#white_magic_" + imagefield).prop('checked') );
$('div[id="cropbuttonmsg_' + imagefield +'"]').hide();
}
</pre>
==== Removing background on a photo ("White magic") ====
This will work best on photos with a white background. Best use case is to let user try it and give up if the result is not satisfying.
<pre>white_magic=</pre>
Values:
==== Color correction on a photo ("Normalize")====
<pre>normalize=</pre>
Values:
==== Cropping a photo ====
This implies applying operations to a source image (not only cropping, but all the others if applicable). We start from a source image (defined by a barcode and incremental id), apply cropping parameters (x1, y1, x2, y2), additional operations (white_magic, normalize)
<br>
<pre>Test server: https://world.openfoodfacts.net/cgi/product_image_crop.pl</pre>
<pre>Live server: https://world.openfoodfacts.org/cgi/product_image_crop.pl</pre>
=====Values=====
<pre>
code=BARCODE
id=
angle= Angle of the rotation
normalize = whether the source image should be normalized
white_magic = whether the source image should be white magiced ( background removal)
type = add
action = display
imgid =
x1= the X origin of the crop
y1=the Y origin of the crop
x2=the X end of the crop
y2=the Y end of the crop
</pre>
===== Ignore me =====
<pre>$.post('/cgi/product_image_crop.pl',
{code: code, id: imagefield , imgid: imgid,
x1:selection.x, y1:selection.y, x2:selection.x + selection.width, y2:selection.y + selection.height,
angle:angles[imagefield], normalize:$("#normalize_" + imagefield).prop('checked'),
white_magic:$("#white_magic_" + imagefield).prop('checked') }, function(data) {
imagefield_url[imagefield] = data.image.display_url;
update_display(imagefield, false);
$('div[id="cropbutton_' + imagefield +'"]').show();
$('div[id="cropbuttonmsg_' + imagefield +'"]').html(Lang.image_saved);
$(document).foundation('equalizer', 'reflow');
}, 'json');
}); </pre>
==== Performing OCR on a photo ====
We start from a source image (defined by barcode and id) as selected for ingredients. We ask Product Opener to process it (process_image=1). Product Opener returns a JSON. Processing is done using Tesseract (3 on preprod). The result is often cripped with errors. Take steps to avoid direct copy pasting into the ingredients field by your users.
<pre>Test server: https://world.openfoodfacts.net/cgi/ingredients.pl</pre>
<pre>Live server: https://world.openfoodfacts.net/cgi/ingredients.pl</pre>
===== Values and output =====
<pre>
code=code
id=imagefield
process_image=1
</pre>
This will return JSON
===== Ignore me =====
<pre>
$.post('/cgi/ingredients.pl',
{ }, function(data) {
if (data.status == 0) {
$('div[id="ocrbuttondiv_' + imagefield +'"]').html(Lang.extracted_ingredients_ok);
var ingredients_text_id = imagefield.replace("ingredients","ingredients_text");
$("#" + ingredients_text_id).val(data.ingredients_text_from_image);
}
else {
$('div[id="ocrbuttondiv_' + imagefield +'"]').html(Lang.extracted_ingredients_nok);
}
$(document).foundation('equalizer', 'reflow');
}, 'json');
</pre>


=== Posting a new product ===
=== Posting a new product ===