Software/tool to generate R-G-B values of every pixel from an image and vice-versa - image-processing

Is there a software/tool that can generate me a matrix of RGB values from a simple raw 8-bit RGB image?
Also, is there a software/tool that can generate an image from a given matrix of RGB values?
Thank you.
PS:
i) I am aware that this can be done using Matlab. I am looking for a tool that can do it that is not Matlab.
ii) I am aware of existing question about doing similar stuff programmatically. I need a software tool, if there is any, that can do this task.

I would suggest you use the venerable NetPBM which is available for Linux, macOS and Windows. Alternatively, you could use ImageMagick but that is much heavier weight, see later.
NetPBM Method - see Wikipedia NetPBM entry
So, let's start with a raw, 8-bit RGB file that contains a red, a green and a blue pixel:
-rw-r--r-- 1 mark staff 9 10 Oct 07:47 rgb888.bin
As you can see, it has 9 bytes. Let's look at them:
xxd -g3 rgb888.bin
00000000: ff0000 00ff00 0000ff
Now, if we want that image as a matrix of legible values:
rawtoppm -plain 3 1 rgb888.bin
Sample Output
P3
3 1
255
255 0 0 0 255 0 0 0 255
where:
-plain means to display in ASCII rather than binary
P3 tells us it is colour and ASCII
3 1 tells us its dimension are 3 pixels wide by 1 pixel high
255 essentially tells us it is 8-bit (65536 would mean 16-bit)
the last row is the pixels
Converting back to binary is a little harder, let's assume we start with a PPM file created like this:
rawtoppm -plain 3 1 rgb888.bin > image.ppm
So, we can get the binary version like this:
ppmtoppm < image.ppm | tail -c 9 > rgb888.bin
and look at it with:
xxd -g3 rgb888.bin
00000000: ff00 0000 ff00 0000 ff
ImageMagick Method
# Convert binary RGB888 to text
convert -depth 8 -size 3x1 RGB:rgb888.bin txt:
Sample Output
# ImageMagick pixel enumeration: 3,1,65535,srgb
0,0: (65535,0,0) #FF0000 red
1,0: (0,65535,0) #00FF00 lime
2,0: (0,0,65535) #0000FF blue
Or, slightly different appearance:
# Convert binary RGB888 to matrix
convert -depth 8 -size 3x1 RGB:rgb888.bin -compress none ppm:
Sample Output
P3
3 1
255
255 0 0 0 255 0 0 0 255
And now going the other way, PPM to binary
# Convert PPM image to binary
convert image.ppm rgb:image.bin
# Check how the binary looks
xxd -g 3 image.bin
00000000: ff0000 00ff00 0000ff .........
Plain dump method
Maybe you are happy with a plain dump from od:
od -An -t u1 rgb888.bin
Sample Output
255 0 0 0 255 0 0 0 255

Related

ImageMagick `-duplicate` but to beginning of sequence

-duplicate
convert img*.png -duplicate 3 out.gif
makes
0 1 2 2 2 2
where 0 is img0.png, and 1 is img1.png, etc, making a GIF. But can I make below?
0 0 0 0 1 2 2 2 2
that is, append to end and start? I get I can use indexing to make
0 1 2 2 2 2 0 0 0
which is identical in a loop, but I need the 0s at start in context.
TL;DR for 0 0 0 1 2 3 ... 20 21 21 21 (any number of images) do
convert img*.png -write mpr:imgs -delete 0--1 mpr:imgs[0,0,0,1--1,-1,-1] out.gif
Using ImageMagick v6 on Windows command line, this command will let you arrange the order and number of images in any way you need.
convert img*.png -write mpr:imgs -delete 0--1 mpr:imgs[0,1,2,2,2,2,0,0,0] out.gif
That reads the 3 input images, copies them all into a memory register named "mpr:imgs", deletes the input images from the command, then reads the images from that memory register as you specify in the square brackets. The image index 0 is the first image read into the command, 1 is the second, etc.
Also, using -duplicate you can specify which image in the list you want to use according to their order in the list. This command will give the same result as the one above...
convert img*.png -duplicate 3 -duplicate 3,0 out.gif
The command reads the three images, then -duplicate 3 makes 3 more of the last image in the list, then -duplicate 3,0 makes 3 more of the first image in the list, index 0.
Another approach would be to use ( -clone ... ) inside parentheses to create the number of duplicates in the order you want.
convert img*.png ( -clone 2,2,2 -clone 0,0,0 ) out.gif
That reads the 3 input images, clones the third image 3 times, then clones the first image 3 times, giving the same result as the commands above.
These commands are in Windows syntax. For a *nix OS you'd have to escape the parentheses with backslashes "\(...\)".
Also helpful are -swap, -reverse, -insert, and -delete to manipulate the order of images in the list.
You should be able to load your first image, make any duplicates you need, then load the second and make duplicates and load the third and make any duplicates:
convert img0.png -duplicate 3 img1.png img2.png -duplicate 3 ...
will give your desired image sequence:
0 0 0 0 1 2 2 2 2

padding algorithm more than 512 bits in sha256

if anyone answered my quesion i would be very much grateful,
my question is in sha256 , if we have 512 bits message length how can i do padding , because in sha256 l+1+k=448mod512, it will overflow 512 bit block, i mean to say that for hashing computation we need to divide 512 bit block into 16 x 32 blocks , and the process is the message bit length (l) + k number of '0' + binary representation of l(length of message). my point is 512 bit after k number 0f '0' and bit representation of l(length of message) we will get more than 512 bits , how ae we going to divide into 16 x 32 bit blocks.
You don't need to pad your data to be a certain length in order to get a sha256 checksum value; the algorithm will handle a few bytes as well as megabytes of data:
Linux> echo 'hey' | sha256sum
4e955fea0268518cbaa500409dfbec88f0ecebad28d84ecbe250baed97dba889 -
Linux> echo '' | sha256sum
01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b -
Linux> ls -oh L0_2018_08_28_Disk1_8mtbno4o_3_1.bkp
-rw-r-----. 1 nfsnobody 348M Aug 28 23:48 L0_2018_08_28_Disk1_8mtbno4o_3_1.bkp
Linux> sha256sum L0_2018_08_28_Disk1_8mtbno4o_3_1.bkp
34438a1bc45f613b7be8797b1139aaa66a60d73844f2d7554184b17c621b4576 L0_2018_08_28_Disk1_8mtbno4o_3_1.bkp
If you want to learn about the actual algorithm, one open-source implementation says
Algorithm specification can be found here:
http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf

When reading 4-channel tif file, value different from SKIMAGE, TIFFFILE and so on

I know the opencv got a BGR order, but in my experiment, not only the order but also the values are totally messed
import cv2 as cv
import tifffile as tiff
import skimage.io
img_path = r"C:\test\pics\t100r50s16_1_19.tif"
c = cv.imread(img_path,cv.IMREAD_UNCHANGED)
t = tiff.imread(img_path)
s = skimage.io.imread(img_path)
print("c:", c.shape, "t:", t.shape, "s:", s.shape)
print("c:", c.dtype, "t:", t.dtype, "s:", s.dtype)
print(c[0, 0], c[1023, 0], c[0, 1023], c[1023, 1023])
print(t[0, 0], t[1023, 0], t[0, 1023], t[1023, 1023])
print(s[0, 0], s[1023, 0], s[0, 1023], s[1023, 1023])
print(c.sum())
print(t.sum())
print(s.sum())
And the outputs like this:
c: (1024, 1024, 4) t: (1024, 1024, 4) s: (1024, 1024, 4)
c: uint8 t: uint8 s: uint8
[ 50 63 56 182] [131 137 140 193] [29 28 27 94] [123 130 134 190]
[ 79 88 70 182] [185 181 173 193] [74 77 80 94] [180 174 165 190]
[ 79 88 70 182] [185 181 173 193] [74 77 80 94] [180 174 165 190]
# Here seems that opencv only read the alpha channel right,
# the values of first three channels are much different than other package
539623146
659997127
659997127
The image i use can be download here. So, here is my question, how open cv handle 4 channel tiff file? Because when i test on 3-channel image, everything looks alright.
I don't buy it for a minute that there is a rounding error or some error related to JPEG decoding like the linked article suggests.
Firstly because your image is integer, specifically uint8 so there is no rounding of floats, and secondly because the compression of your TIF image is not JPEG - in fact there is no compression. You can see that for yourself if you use ImageMagick and do:
identify -verbose a.tif
or if you use tiffinfo that ships with libtiff, like this:
tiffinfo -v a.tif
So, I did some experiments by generating sample images with ImageMagick like this:
# Make 8x8 pixel TIF full of RGBA(64,128,192) with full opacity
convert -depth 8 -size 8x8 xc:"rgba(64,128,192,1)" a.tif
# Make 8x8 pixel TIFF with 4 rows per strip
convert -depth 8 -define tiff:rows-per-strip=4 -size 8x8 xc:"rgba(64,128,192,1)" a.tif
And OpenCV was able to read all those correctly, however, when I did the following it went wrong.
# Make 8x8 pixel TIFF with RGB(64,128,192) with 50% opacity
convert -depth 8 -define tiff:rows-per-strip=1 -size 8x8 xc:"rgba(64,128,192,0.5)" a.tif
And the values came out in OpenCV as 32, 64, 96 - yes, exactly HALF the correct values - like OpenCV is pre-multiplying the alpha. So I tried with an opacity of 25% and the values came out at 1/4 of the correct ones. So, I suspect there is a bug in OpenCV that premultiplies the alpha.
If you look at your values, you will see that tifffile and skimage read the first pixel as:
[ 79 88 70 182 ]
if you look at the alpha of that pixel, it is 0.713725 (182/255), and if you multiply each of those values by that, you will get:
[ 50 63 56 182 ]
which is exactly what OpenCV did.
As a workaround, I guess you could divide by the alpha to scale correctly.
In case the argument is that OpenCV intentionally pre-multiplies the alpha, then that begs the question why it does that for TIFF files but NOT for PNG files:
# Create 8x8 PNG image full of rgb(64,128,192) with alpha=0.5
convert -depth 8 size 8x8 xc:"rgba(64,128,192,0.5)" a.png
Check with OpenCV:
import cv2
c = cv2.imread('a.png',cv2.IMREAD_UNCHANGED)
In [4]: c.shape
Out[4]: (8, 8, 4)
In [5]: c
Out[5]:
array([[[192, 128, 64, 128],
[192, 128, 64, 128],
...
...
In case anyone thinks that the values in the TIF file are as OpenCV reports them, I can only say that I wrote rgb(64,128,192) at 50% opacity and I tested each of the following and found that they all agree, with the sole exception of OpenCV that that is exactly what the file contains:
ImageMagick v7
libvips v8
Adobe Photoshop CC 2017
PIL/Pillow v5.2.0
GIMP v2.8
scikit-image v0.14

24 bit bmp to RGB565 file conversion

I want to convert 24 bit bmp files to RGB565 format to write to a serial TFT colour display.
The size of the 24bit bmp will always be 320x240 pixels as my TFT display is 320x240
Has anyone any experience of doing this? It could be C/C++, Shell, Python, Java Script and so on...
I would use either NetPBM (much smaller and lighter-weight) or ImageMagick (much bigger installation) to convert the BMP into a format that is simple to parse and then use Perl to convert that to RGB565 format.
I assume you are planning to write the RGB565 data to a frame buffer, so you would do something like:
./bmp2rgb565 image.bmp > /dev/fb1
So, save the following as bmp2rgb565:
#!/bin/bash
################################################################################
# bmp2rgb565
# Mark Setchell
################################################################################
if [ $# -ne 1 ]; then
echo Usage: $0 image.bmp
exit 1
fi
file=$1
# Use NetPBM's "bmptopnm" to convert BMP to PNM for easy reading
# You could use ImageMagick: convert "$file" PNM: | perl ...
bmptopnm "$file" 2> /dev/null |
perl -e '
my $debug=0; # Change to 1 for debugging
# Discard first 3 lines of PNM header:
# P3
# 320 240
# 255
my $line=<STDIN>; $line=<STDIN>; $line=<STDIN>;
# Read file, 3 RGB bytes at a time
{
local $/ = \3;
while(my $pixel=<STDIN>){
# Extract 8-bit R,G and B from pixel
my ($r,$g,$b)=unpack("CCC",$pixel);
printf("R/G/B: %d/%d/%d\n",$r,$g,$b) if $debug;
# Convert to RGB565
my $r5=$r>>3;
my $g6=$g>>2;
my $b5=$b>>3;
my $rgb565 = ($r5<<11) | ($g6<<5) | $b5;
# Convert to little-endian 16-bit (VAX order) and write 2 bytes
my $v=pack("v",$rgb565);
syswrite(STDOUT,$v,2);
}
}
'
I don't have a frame buffer handy to test, but it should be pretty close.
Note that you could make the code more robust by starting off with:
convert "$file" -depth 8 -resize 320x240\! PNM: | perl ...
which would make sure the image always matches the framebuffer size, and that it is 8-bit and not 16-bit. You may also want a -flip or -flop in there if the BMP image is upside-down or back-to-front.
Note that if you use ImageMagick convert, the code will work for GIFs, TIFFs, JPEGs, PNGs and around 150 other formats as well as BMP.
Note that if you want to test the code, you can generate a black image with ImageMagick like this:
convert -size 320x240 xc:black BMP3:black.bmp
and then look for a bunch of zeroes in the output if you run:
./bmp2rgb565 black.bmp | xxd -g2
Likewise, you can generate a white image and look for a bunch of ffs:
convert -size 320x240 xc:red BMP3:white.bmp
And so on with red, green and blue:
convert -size 320x240 xc:red BMP3:red.bmp
convert -size 320x240 xc:lime BMP3:green.bmp
convert -size 320x240 xc:blue BMP3:blue.bmp
# Or make a cyan-magenta gradient image
convert -size 320x240 gradient:cyan-magenta cyan-magenta-gradient.bmp
Example:
./RGB565 red.bmp | xxd -g2 | more
00000000: 00f8 00f8 00f8 00f8 00f8 00f8 00f8 00f8 ................
00000010: 00f8 00f8 00f8 00f8 00f8 00f8 00f8 00f8 ................
Example:
./RGB565 blue.bmp | xxd -g2 | more
00000000: 1f00 1f00 1f00 1f00 1f00 1f00 1f00 1f00 ................
00000010: 1f00 1f00 1f00 1f00 1f00 1f00 1f00 1f00 ................
Keywords: RGB565, rgb565, framebuffer, frame-buffer, pack, unpack, Perl, BMP, PGM, image, Raspberry Pi, RASPI
To convert to RGB565 you can use ImageMagick:
convert test.png -resize 320x200 -ordered-dither threshold,32,64,32 test2.png
In what format do you need the output to be?
I'm assuming you simply want to stream out the pixel data without any headers or additional data.
The core of the problem has already been described here.
If you want to implement it for yourself, the following approach will probably help:
After opening the file, yout need to skip the BMP header by reading the bfOffBits value (see this BMP format description), the easiest way would probably be to implement it in C by reading into a struct that matches the BMP header.
(Note: This only works because the dimensions of the image are divisible by 4! Check the format description for more details)
Then seek forward by bfOffBits and while the file has not ended, transform three consecutive bytes (uint8_t) to one 16 bit value (uint16_t) by using the approach from the question I mentioned above. The basic C file operations you would need are fopen, fclose, fread, fwrite, fgetc/fgetwc, fputc/fputwc and fseek

ImageMagick convert crop with formatted filenames

I am working with the ImageMagick convert program via command line. I am using it to split an image into 16x16 images. This work well with the crop command. I do as such:
convert.exe "C:\Users\Matt\Desktop\tiles\maps\shrine_source\shadow_light.png" -crop 16x16 "C:\Users\Matt\Desktop\tiles\maps\shadow_light_input\shadow_light_%02d.png"
The problem is I would like to format the part after the underscore starting from an index. For instance, starting from "shadow_light_2048.png" and so forth. Looking at some examples I was thinking it could be done with bracket notations like "shadow_light_%[2048-3071].png", but it seems to ignore this.
Could someone help point me in the right direction on how to properly format to filename? Ideally in a way to where I only have to specify the starting index.
Use the -scene option to set the scene number which is what gets put where you use %d:
convert input.png -crop ... -scene 2048 result-%04d.png
So, for example, let's create a 20x20 black image and chop it up into tiles each 10x10:
convert xc:black[20x20] -crop 10x10 -scene 2048 tile-%d.png
-rw-r--r-- 1 mark staff 301 21 Jul 09:18 tile-2051.png
-rw-r--r-- 1 mark staff 301 21 Jul 09:18 tile-2050.png
-rw-r--r-- 1 mark staff 301 21 Jul 09:18 tile-2049.png
-rw-r--r-- 1 mark staff 280 21 Jul 09:18 tile-2048.png

Resources