How to convert images from the jpg format to ppm(P3) - jpeg

I have recently learned how to read ppm3(P3) images in C++. I just read RGB pixels written in a plain format. I want to convert some certain jpg pictures to ppm3 and then experiment with different things, like identifying numbers there, the circled answers in exam papers, etc.
I have tried this website: https://convertio.co/pdf-ppm/, but it transformed a photo in the P6 format. Could anyone help?

You can use ImageMagick in the Terminal/shell:
magick INPUT.JPG -compress none OUTPUT.PPM
If you omit -compress none you'll get binary (i.e. P6) PPM output.
If using old v6 ImageMagick, that becomes:
convert INPUT.JPG -compress none OUTPUT.PPM
All the options, switches, operators and settings for ImageMagick are documented here.
If you want to convert PPM to JPEG, or to PNG, you can just use:
magick INPUT.PPM OUTPUT.JPG
or
magick INPUT.PPM OUTPUT.PNG
You can also programmatically create a random PPM file like this:
#!/bin/bash
W=5; H=4
echo "P3\n${W} ${H}\n255" > image.ppm
for ((i=0;i<$((W*H*3));i++)) ; do
echo $((RANDOM%255))
done >> image.ppm
Then enlarge for easy viewing and make into a PNG:
magick image.ppm -scale 200x result.png
Or, the same thing again, nut maybe slightly more elegantly and without creating an intermediate file:
#!/bin/bash
W=5; H=4
{
printf "P3\n${W} ${H}\n255\n"
for ((i=0;i<$((W*H*3));i++)) ; do
echo $((RANDOM%255))
done
} | magick ppm:- -scale 200x result.png
If you prefer to use the lighter weight, but far less capable NetPBM tools, it would be:
jpegtopnm -plain INPUT.JPG > OUTPUT.PPM

For parsing pixels P6 is probably more useful for binary apps like C
P3 is about 4 times bigger than P6
both P3 and P6 are uncompressed format 1 entry = one pixel component
normally 3 components = 1 pixel (rgb) here is a white cow in a snowfield
each 255 on the Ascii =ÿ in the binary thus faster to count one byte text ÿ than 4 byte 255 the main advantage for P3 is when using an ascii editor to fettle the values as number key inputs (modify lower order numbers as 000 - 031 control code values becomes a problem in text editors)
SAFE binary bytes were used for Ansi Art as here this is a binary.ppm (just using safe non control codes.
The binary version (P6 uncompressed) is most easily generated For PDF users by xpdf or poppler pdftoppm (one single executable no real need for more than that).
http://www.xpdfreader.com/download.html
For Jpeg you can use jpegtopnm as described in other answer by Mark
https://sourceforge.net/projects/netpbm/files/
for docs and other info see https://netpbm.sourceforge.net/doc/
for binaries on windows the Cygwin / GNUwin32 ports may be useful but older 2005 https://gnuwin32.sourceforge.net/packages/netpbm.htm One exe & 4 dlls
for better description see https://en.wikipedia.org/wiki/Netpbm#File_formats
for windows related viewing see https://github.com/vbaderks/netpbm-wic-codec and also possibly conversion https://github.com/peirick/ZackViewer

Related

How to get a Hex Color Code from a solid-color image for a script?

I was writing a script to change my background on my Linux Machine to a random image from a set of images that contain only solid colors. What I would like to do is expand this script to also theme certain applications (mostly terminal ones) accordingly, at the very least to change the text color, possibly switch from dark to light background, etc. I was wondering what options I have to get the Hex Code for the color in the image. Is there something in bash I can do this with? Would I need to write a program in a more robust language and have the hex-code be the output? Is there a better way of doing this entirely? My searching thus far has been a bit inconclusive.
I would highly recommend to use ImageMagick for this task. The documentation mentions how to extract data from an image.
From "Extracting the average colour":
The average color of an image can be found very quickly by using "-scale" to reduce an image to a single pixel. Here for example is the average color of the built-in "rose:" image. I output the color using the FX Escape Format which
returns a color string that can be used directly IM without change.
user#laptop:~$ convert rose: -scale 1x1\! -format '%[pixel:s]\n' info:-
Will output: srgb(146,89,80)
In your case, replace rose: with an image file of yours, like foo.png.
If you want the output directly in hex notation, use this:
convert rose: -scale 1x1\! -format '%[pixel:s]\n' info:- | awk -F '[(,)]' '{printf("#%x%x%x\n",$2,$3,$4)}'

Extracting Text from a PDF file with embedded font

I have a PDF file containing some tabular data.
http://dl.dropbox.com/u/44235928/sample_rotate-0.pdf
I have to extract the tabular data from it. I have tried following with no success :
Select the text and paste it to notepad/excel-sheet. (I am getting junk characters)
Used save as text from Acrobat Reader. It is also giving junk characters and not the actual text.
Tried ApachePDFBox command line utility to extract text from PDF. It is also giving junk characters instead of real texts.
Finally I am trying a OCR solution. I am converting the pdf file into .tif images using ImageMagick and getting those images processed by tesseract OCR.
The OCR solution is not very accurate though( about 80% words matched ).
I tried changing density and geometry of the image created from PDF to get better results from tesseract OCR.
convert -rotate 90 -geometry 10000 -depth 8 -density 800 sample.pdf img_800_10000.tif;
tesseract img_800_10000.tif img_800_10000.tif nobatch letters;
I am not sure for what kind of image( density, geometry, monochromatic, sharpen boundary etc) would be best suited for the OCR.
Please suggest what could be the best possible parameters(density,geometry,depth etc) for generating images from a PDF file, so that the tesseract accuracy will increase.
I am open to other( non-ocr ) solutions as well.
In this case I recommend to NOT use ImageMagick for the PDF -> TIFF conversion. Instead, use Ghostscript. Two reasons:
Using Ghostscript directly will give you more control over individual parameters of the conversion.
ImageMagick cannot do that particular conversion itself -- it will call Ghostscript as its 'delegate' anyway, but will not allow you to give all the same fine-grained control that your own Ghostscript command will give you.
Most of the text in the table of your sample PDF is extremely small (I guess, only 4 or 5 pt high). This makes it rather difficult to run a successful OCR unless you increase the resolution considerably.
Ghostscript uses -r72 by default for image format output (such as TIFF). Tesseract works best with r=300 or r=400 -- but only for a font size from 10-12 pt or higher. Therefor, to compensate for the small text size you should make Ghostscript using a resolution of at least 1200 DPI when it renders the PDF to the image.
Also, you'll have to rotate the image so the text displays in the normal reading direction (not bottom -> top).
This is the command which I would try first:
gs \
-o sample.tif \
-sDEVICE=tiffg4 \
-r1200 \
-dAutoRotatePages=/PageByPage \
sample_rotate-0.pdf
You may need to play with variations of the -r1200 parameter (higher or lower) for best results.
Since a comment asked "How to define the geometry of an image when using Ghostscript as we do in convert?", here is an answer:
It does not make sense to define geometry (that is image dimensions) and resolution for a raster image created by Ghostscript at the same time.
Once you convert a vector based page of a given dimension (such as PDF) into a raster image (such as the TIFF G4 format) giving a desired resolution (as done in the other answer), you already indirectly and implicitly also did set the dimension:
The original PDF dimension of your sample file sample_rotate-0.pdf is 1008x612 points.
At a resolution of 72 DPI (the default Ghostscript uses if not given directly, or -r72 in the Ghostscript command if given directly) the image dimensions will be 1008x612 pixels.
At a resolution of 720 DPI (-r720 in the Ghostscript command) the image dimensions will be 10080x6120 pixels.
At a resolution of 1440 DPI (-r1440 in the Ghostscript command of my other answer) the image dimensions will be 20160x12240 pixels.
At a resolution of 1200 DPI (-r1200 in the Ghostscript command) the image dimensions will be 16800x10200 pixels.
At resolution of 1000 DPI (-r1000 in the Ghostscript command) the image dimensions will be 14000x8500 pixels.
At a resolution of 120 DPI (-r120 in the Ghostscript command) the image dimensions will be 1680x1020 pixels.
At resolution of 100 DPI (-r100 in the Ghostscript command) the image dimensions will be 1400x850 pixels.
If you absolutely insist to specify the dimension/geometry for the output image on the Ghostscript commandline (rather than the resolution), you can do so by adding -gNNNNxMMMM -dPDFFitPage to the commandline.
There you can find decoded content of your file: https://docs.google.com/open?id=0B1YEM-11PerqSHpnb1RQcnJ4cFk
A absolutely sure the OCR is the best way to read pdf file, but you can try REGEX-ing the native content. It going to be be the hard and long way.

Convert image to indexed color with custom palette through console

I have image.png in truecolor,
palette.png (N colors, where N>256) or text file, where list RGB color palette.
How to get a picture with this palette?
If I use imagemagick:
convert image.png -remap palette.png remap_image.png
It does not work.
convert image.png -map palette.png remap_image.png
Gives a very bad quality. The image is very noisy. File size is bigger than before.
GIMP gives best quality:
Сonvert image to indexed color > use custom palette
But GIMP is GUI. I need to convert a lot images in the console without running the gimp and X.org.
Using a shared palette across multiple images requires a carefully crafted palette. If you don't take great care when using the palette of a single image across many images, the result will be poor.
This needn't be complicated though. If you have accesss to the GIMP (or other tool) which supports truecolor graphics, you can create a large image and fit all of the smaller images into it, then quantize the image to N colors, then use that palette as the source.
you should be able to closely mimic GIMP's behavior in the console using ImageMagick
Once you've got a truecolor image with all the colors you want to quantize,
# Create an 8-bit png from our source, with a 235-color palette as an example.
convert truecolor_source.png -colors 235 palette.png
# Create an 8-bit png from an arbitrary image and use the palette in palette.png
convert sample.png -map palette.png output.png
There are a number of options for down-sampling colors, like dithering. See the ImageMagickv6 example page for an excellent overview with example pictures and code.
Although I still don't exactly understand what you want to do, your currently most recent comment ("Yes, from RGB to palette will set independently. Need set correct quantity of colors"), it sounds like all you want to do is set a strict limit on the amount of colors of a bunch of images, but they don't need to use the same palette.
In that case, the solution is very simple:
convert sample.png -colors 135 output.png
Try playing with the quantization options if the result isn't to your satisfaction.
If the output image is too large for your liking, you can experiment with the -quality option.
If this still isn't satisfactory, please try to explain your goal in a more detailed manner.
Good luck!
cat photo.png | pngnq -s 1 > photoindexed.png
I tend to get good results with the "-remap" (single imge) or "+remap" (multiple images) functions in combination with "-colors". Read up on those functions here. Note that "with "-remap" you provide IM with the final set of colors you want to use for the image, whether you plan to dither those colors, or just replace the ones with their nearest neighbours.", meaning just remapping/replacing might not look good enough, as colors from the input image are simply replaced by those from the palette image. Some form of dithering will be necessary to distribute pixel color conversion errors throughout the output image, because not all colors in the palette match those of the input image.
I'd suggest you use the "-colors N" option for that. This will reduce your output image color count to a maximum of N. By default ImageMagick uses "-dither Riemersma" for this implicitly when you specify "-colors N". The are also other dithering options available.

How to write a bash script that cuts images into pieces using image magick?

I have a number of input images that contain multiple smaller images, all of them in a single row. All the contained images are the same size. So, for example, the image input.png may be 480x48 and contain 10 48x48 images, all in one row.
Using the imagemagick convert tool (or any other tool supplied with the defaul imagemagick suite), I want to write a bash script that takes an input image, the number of images to cut, and then cuts them all into individual images.
The user interaction i can do, but I've not been able to get convert to do the actual cutting. Can anyone suggest something? From reading the manual pages, i think this should work:
convert 'input.png[0x0+48+48]' output.png
but I get an error:
convert: no pixels defined in cache
tb_icons_l.png' #
magick/cache.c/OpenCache/3572.
convert: No IDATs written into file
1.png' #
coders/png.c/PNGErrorHandler/1391.
Any ideas?
I would do it like that:
convert input.png -crop 48x48 +repage +adjoin output_%02d.gif
Read more at Tile Cropping, in ImageMagick documentation.
I believe you've got the position and size swapped. Try:
convert 'input.png[48x48+0+0]' output.png
The third image would be:
convert 'input.png[48x48+96+0]' output.png
Or
convert 'input.png[48x48+0+96]' output.png

Compose multiple JPEG files without re-compression

How can I compose (adjoin) multiple JPEG files without re-compression?
I know there is jpegtran that can losslessly crop and resize JPEG images, so I wonder if there is similar tool to adjoin images lossless?
Their size is a multiple 1 MCU block (16 pixels in both directions).
Newer versions of jpegtran include lossless "crop 'n' drop" (or "cut & paste") features. Via the command line, you can use -crop to create a larger image based on one of the pieces, and -drop to paste subsequent images into the combined image. Unfortunately, multiple -drop options aren't currently supported, so jpegtran needs to be invoked once for every part.
jpegtran -outfile combined.jpg -copy all -crop ${totalWidth}x${totalHeight} part-0.jpg
jpegtran -outfile combined-tmp.jpg -copy all -drop +${xOff[1]}+${yOff[1]} part-1.jpg combined.jpg && mv combined-tmp.jpg combined.jpg
...
jpegtran -outfile combined-tmp.jpg -copy all -drop +${xOff[$n]}+${yOff[$n]} part-$n.jpg combined.jpg && mv combined-tmp.jpg combined.jpg
Your mileage may vary depending on the exact properties of the image parts.
What you want to do is certainly possible, but in order for it to be truly lossless, both images must use the same quantization tables and color subsampling option. If, for example, the 2 images come from the same source (e.g. camera), then you can be pretty sure that it would be possible. You would need to entropy-decode each MCU in both images, rearrange them the way you want and then re-entropy code them and output the JPEG bitstream. If you want to overlay one on the other or crop/merge them on non-MCU boundaries, then you hit the same problem as above and must do a full decode and re-encode.
I've used ImageMagick's composite binary to watermark a JPG with a PNG image.
Like this:
composite -tile -dissolve 15 targetimage.jpg watermark.png
You can obviously use two JPEGs to achieve what you're looking for.
Using the -quality and -sampling-factor arguments will help retain quality. There is also a -compress <type> argument, where type can by Lossless. However, ImageMagick does not recommend the use of this value as the JPEG library must be patched to support this.
It's worth investigating though if it will achieve a genuine lossless image, and you're not happy with the quality of the compress and sampling-factor arguments.

Resources