Closed lanceschi closed 10 years ago
zbarimg
links against ImageMagick to handle image conversions; it's not a feature of the underlying library. The zbar library itself only handles a few formats, and I think the only reason JPEG made the cut is because zbar can decompress JPEG more efficiently than if you provided it a 24/32-bit RGB surface.
There are lots of options for image conversion in Ruby, and I didn't want to pick one and make it a ruby-zbar
dependency, so as a result ruby-zbar
handles only a few formats as well.
@willglynn: thanks for you reply. Since I've already ImageMagick on my VM how I'm a supposed then to initialize accordingly ZBar module and Image class after I manage to load the picture? Here's the code:
require 'RMagick'
require 'zbar'
img = Magick::Image.read('barcode01.png').first
...
Thanks, Luca
I don't have RMagick immediately handy, but probably something like:
pgm = img.to_blob { |attrs| attrs.format = 'PGM' }
zbar_image = ZBar::Image.from_pgm(pgm)
symbols = zbar_image.process
@willglynn: yep, it did the trick! Thanks! Just to recap:
require 'RMagick'
require 'zbar'
img = Magick::Image.read('barcode01.png').first
pgm = img.to_blob { |attrs| attrs.format = 'PGM' }
zbar_image = ZBar::Image.from_pgm(pgm)
symbols = zbar_image.process
There's also ZBar::Symbol @location which holds an array of arrays, can you further comment this? Here the decoding results:
1.9.3-p429 :019 > puts symbols.inspect [#<ZBar::Symbol:0x8d954ec @symbology="EAN-8", @data="80050643", @addon="", @quality=255, @location=[[1302, 1835], [1302, 2399], [1304, 1833], [1305, 1785], [1305, 1206], [1306, 1835], [1306, 2403], [1307, 1787], [1308, 1833], [1308, 2402], [1309, 1787], [1310, 1833], [1311, 1783], [1311, 1207], [1313, 1785], [1314, 1836], [1314, 2401], [1315, 1784], [1315, 1208], [1316, 2398], [1317, 1785], [1317, 1209], [1318, 1838], [1318, 2403], [1319, 1781], [1319, 1207], [1320, 1838], [1320, 2398], [1321, 1786], [1321, 1209], [1322, 2399], [1324, 2399], [1325, 1785], [1325, 1209], [1326, 1833], [1326, 2401], [1327, 1785], [1327, 1209], [1330, 2403], [1331, 1785], [1331, 1210], [1332, 1835], [1332, 2398], [1334, 2400], [1335, 1785], [1335, 1212], [1337, 1785], [1337, 1211], [1338, 2399], [1339, 1786], [1339, 1209], [1340, 1836], [1340, 2400], [1341, 1784], [1341, 1210], [1342, 1838], [1342, 2400], [1345, 1785], [1345, 1212], [1346, 1836], [1346, 2399], [1347, 1785], [1347, 1212], [1348, 2398], [1349, 1785], [1349, 1210], [1350, 1834], [1350, 2398], [1351, 1786], [1351, 1212], [1352, 2400], [1353, 1786], [1353, 1211], [1354, 1834], [1354, 2398], [1355, 1786], [1355, 1211], [1356, 1842], [1356, 2400], [1357, 1786], [1357, 1210], [1358, 2398], [1359, 1785], [1359, 1214], [1360, 1835], [1360, 2397], [1361, 1788], [1361, 1212], [1362, 1835], [1362, 2398], [1363, 1784], [1363, 1212], [1364, 1834], [1364, 2397], [1365, 1784], [1366, 1835], [1367, 1785], [1367, 1213], [1368, 1837], [1368, 2398], [1369, 1783], [1369, 1212], [1370, 2399], [1371, 1785], [1371, 1214], [1372, 2396], [1373, 1785], [1373, 1214], [1374, 2400], [1375, 1786], [1375, 1215], [1376, 2398], [1377, 1784], [1377, 1215], [1378, 1836], [1378, 2398], [1379, 1787], [1379, 1213], [1380, 1836], [1380, 2397], [1381, 1786], [1381, 1213], [1382, 2397], [1383, 1784], [1383, 1215], [1384, 2397], [1385, 1785], [1385, 1214], [1386, 2394], [1387, 1788], [1387, 1214], [1388, 1842], [1388, 2394], [1389, 1786], [1389, 1217], [1390, 1838], [1390, 2394], [1391, 1786], [1391, 1218], [1392, 2397], [1393, 1786], [1393, 1216], [1394, 1838], [1394, 2398], [1395, 1786], [1395, 1216], [1396, 1840], [1396, 2395], [1397, 1786], [1397, 1216], [1398, 2394], [1399, 1789], [1399, 1215], [1400, 1837], [1401, 1786], [1401, 1216], [1402, 1839], [1402, 2398], [1403, 1786], [1403, 1216], [1404, 2393], [1405, 1789], [1405, 1218], [1406, 2396], [1407, 1787], [1407, 1214], [1408, 2393], [1410, 2394], [1411, 1785], [1411, 1214], [1412, 1839], [1412, 2397], [1414, 2394], [1415, 1787], [1415, 1220], [1416, 1836], [1416, 2395], [1417, 1791], [1417, 1218], [1418, 2395], [1419, 1786], [1419, 1218], [1420, 1840], [1421, 1788], [1421, 1218], [1422, 1840], [1422, 2399], [1423, 1786], [1423, 1219], [1424, 2394], [1425, 1788], [1425, 1219], [1426, 1837], [1426, 2394], [1427, 1788], [1427, 1219], [1428, 1840], [1428, 2395], [1429, 1788], [1429, 1218], [1430, 1838], [1430, 2392], [1431, 1789], [1431, 1218], [1432, 2393], [1433, 1788], [1433, 1221], [1434, 1838], [1434, 2395], [1435, 1787], [1435, 1221], [1436, 2392], [1437, 1787], [1437, 1221], [1438, 1840], [1438, 2394], [1439, 1787], [1439, 1218], [1440, 1837], [1441, 1788], [1441, 1222], [1442, 1838], [1443, 1788], [1443, 1222], [1444, 2392], [1445, 1788], [1445, 1220], [1446, 1837], [1446, 2392], [1447, 1788], [1447, 1222], [1448, 2390], [1449, 1789], [1449, 1223], [1450, 1838], [1450, 2392], [1451, 1788], [1451, 1223], [1452, 1840], [1452, 2394], [1453, 1786], [1453, 1220], [1455, 1789], [1455, 1220], [1456, 1837], [1456, 2392], [1464, 1840], [1466, 1840], [1470, 1838], [1472, 1838], [1473, 1224], [1475, 1224], [1476, 1841], [1477, 1226], [1478, 1839]]>] => nil
Thanks again!
Symbol quality is somewhat ill-defined:
Returns: an unscaled, relative quantity: larger values are better than smaller values, where "large" and "small" are application dependent. Note: expect the exact definition of this quantity to change as the metric is refined. currently, only the ordered relationship between two values is defined and will remain stable in the future
I wouldn't use that value for anything terribly important.
Any MPixels limitations that you're aware of?
No, but you'll probably have memory issues at some point if you process a lot of images, especially if you're using RMagick to handle conversions. Learning about the Ruby GC is most of the solution; RMagick::Image#destroy!
is another part.
There's also ZBar::Symbol @location which holds an array of arrays, can you further comment this? Here the decoding results:
Locations are a bunch of [x,y]
pairs describing the polygon in which ZBar found a barcode.
No, but you'll probably have memory issues at some point if you process a lot of images, especially if you're using RMagick to handle conversions. Learning about the Ruby GC is most of the solution.
Good point. I was thinking of scaling pictures to speed up the raw pgm conversion. Do you suggest to force a GC after the decoding process has come to an end? Any better approach?
Thanks, Luca
I've found the most reliable way to control memory consumption in a Ruby process is to do image work out-of-process. MiniMagick can help: it lets you do things like crop and convert with a simple Ruby API, but it delegates the actual processing to command-line ImageMagick/GraphicsMagick tools. This isn't necessarily the ideal solution, but it's less likely to give you grief.
@willglynn: I gave MiniMagick a try:
require 'mini_magick'
require 'zbar'
img = MiniMagick::Image.open('barcode01.jpg')
img.format('PGM')
pgm = img.to_blob
zbar_image = ZBar::Image.from_pgm(pgm)
symbols = zbar_image.process
It seems to me that MiniMagick with the first line create an img
object pointing to a tmp file onto which directing further processing (a good thing!).
1.9.3-p484 :003 > img = MiniMagick::Image.open('barcode01.jpg')
=> #<MiniMagick::Image:0x000000015889e0 @path="/tmp
/mini_magick20140129-2325-1toyrgc.jpg", @tempfile=#<File:/tmp
/mini_magick20140129-2325-1toyrgc.jpg (closed)>>
On the other hand pgm
object or better String still resides in memory after creation. Any way to force object destruction and the memory release after ZBar processing has terminated? Or should I wait for Ruby GC?
Thanks, L.
On the other hand
pgm
object or better String still resides in memory after creation. Any way to force object destruction and the memory release after ZBar processing has terminated? Or should I wait for Ruby GC?
I wouldn't worry about it as long as you let it go out of scope before processing another image. Back of the napkin: PGM is 8 bits per pixel, so a 5000 * 5000 image weighs 25 MB. Even assuming there's an extra copy or two held temporarily, that's readily affordable as long as you go one at a time.
The primary way that RMagick can bite you is because Ruby doesn't "see" the memory used by ImageMagick. This means you can burn hundreds of MB and run out of RAM before the GC ever gets invoked. Passing image data around as a Ruby string isn't ideally efficient, but it avoids that problem since it's Ruby-allocated memory. Ruby will run its garbage collector automatically as you use more RAM, and it'll clean up the bits you don't need any more.
Hi @willglynn, was wondering if you had any insight into an issue I'm having. I am using the Grim gem to strip a multi-page PDF into one PNG per page. Then I am trying to read a barcode on each page using the process outlined above. I am getting an error I've never seen before and did a little source diving into the gem code but can't figure out where max_value is being set. I am attaching here a screenshot of the error I am getting as well as the PNG file I am trying to read. Thanks!
Error:
PNG I am trying to read:
Source code: Where does $4 come from?
$4
is the fourth capture from that regex, P5
being the first. 255 is expected, since that corresponds to an 8-bit PGM, which encodes image data identically to zbar's Y800
format. What is the value in your blob?
@willglynn I got 65535. Does that seem crazy?
That's a 16-bit image, which zbar doesn't support. Convert it to 8-bit before turning into a PGM.
This worked -- thanks @willglynn !
Hi,
I was just trying in IRB your nice binding albeit I wasn't able to decode and process PNG images. I took a look at the source code and I cound't find any references to PNG file format. I'm a correct? Are there any workarounds, since command line 'zbarimg' can handle those?
Thanks, Luca