API/Write/Photos
<Back to API/Write(Required reading) The new version of the documentation is available here:
- API V2 - Comprehensive but not OpenAPI compliant - It contains uses cases for displaying a product, and letting your users add the data required to get the Nutri-Score, the NOVA classification, additives, and the Eco-Score.
- API V2 - new OpenAPI documentation - Work in Progress
- API V3 - new OpenAPI documentation - Work in Progress
Manipulating photos for a product
Understanding products and 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)
- Good photos means a minimal allowed size: 640 x 160.
- 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:
Test server: https://world.openfoodfacts.net/cgi/product_image_upload.pl
Live server: https://world.openfoodfacts.org/cgi/product_image_upload.pl
(remember to do tests on world.openfoodfacts.net - login and password: off )
Parameters
- code: the barcode of the product
- imagefield: (can be either: front | ingredients | nutrition)
- imgupload_front : your image file if imagefield=front
- imgupload_ingredients: your image file if imagefield=ngredients
- imgupload_nutrition: your image file if imagefield=nutrition
Example
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
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
"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" } },
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
code=
Values:
Selecting a photo
product_image_crop.pl?code=3266110700910&id=nutrition_fr&imgid=1
id: the field you want to attribute the image to code: the barcode of the product imgid: the image id you want to select into the field
id can be: front_fr nutrition_fr ingredients_fr front_nl nutrition_nl ingredients_nl …
You retrieve the photo id when you upload it
Rotating a photo
Test server: https://world.openfoodfacts.net/cgi/product_image_rotate.pl
Parameters:
Getting the preview
Parameters:
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)
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(); }
Actually rotating the photo
Removing background on a photo
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.
white_magic=
Values:
Perform color correction on a photo
normalize=
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)
Test server: https://world.openfoodfacts.net/cgi/product_image_crop.pl
https://world.openfoodfacts.org/cgi/product_image_crop.pl?code=1&imgid=2&id=front_en&x1=0&y1=0&x2=145&y2=145
Values
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 = the id of the source image 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
Ignore me
$.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'); });
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 or Google Cloud Vision. The result is often cripped with errors with Tesseract, less with Google Cloud Vision. Take steps to ensure your users correct the output. Do send the corrected output using the ingredients WRITE API. If possible, please use your own OCR, this costs us money, and we're a non-profit with no budget.
Test server: https://world.openfoodfacts.net/cgi/ingredients.pl
Values and output
code=code id=imagefield process_image=1
Example:
ingredients.pl?code=13333560&id=ingredients_en&process_image=1&ocr_engine=tesseract
This will return JSON