Problems in reading 12 bits image saved as 16 bits

Hello.

I still have problems to read a 12 bits image. It was saved as 16 bits by python (because 12 bits is not a standard) and when I try to print out the pixel values I get a lot of 0 and 1.
Could anyone give a look, please?

The image is at https://drive.google.com/open?id=18a2EZIggHhKHAGHIN9G3Th9bI9MnsDTy
The corresponding txt file given by python start as

sec;[1519830179.6817112, 1519830180.68179]
val;[array([[ 89, 0, 30, 65, 34, 37, 75, 32, 126, 107, 267,
132, 120, 95, 58, 129, 124, 85, 207, 239, 137, 140,
174, 181, 125, 150, 159, 152, 101, 164, 186, 189, 276,
98, 308, 279, 195, 222, 197, 229, 184, 239, 111, 184,
178, 287, 109, 206, 289, 190, 232, 204, 221, 180, 245,
214, 245, 288, 154, 186, 310, 292, 122, 260, 192, 239,
207, 280, 344, 224, 175, 255, 380, 244, 262, 276, 241,
228, 262, 251, 216, 198, 270, 309, 214, 344, 261, 194,
282, 321, 198, 303, 231, 287, 299, 281, 152, 180, 280,
330, 327, 240, 281, 250, 259, 293, 268, 328, 244, 271,
342, 362, 229, 282, 234, 273, 316, 285, 235, 192, 228,

And my routine is in attachment.

Could anyone tell me why with my routine I get a lot of 0 and 1, please?
And could anyone tell me how to fix it, please?

Thanks,
regards,
franciuska

Replot.C (4.2 KB)

your image is a WebP image.
not sure TImage::Open has support for that codec.
From https://root.cern.ch/doc/master/classTImage.html#a25969786f61a927763a4c00ebc3fbd6a, it doesn’t look like so.

here is some Go code to convert it to a regular PNG file:

package main

import (
	"flag"
	"image"
	"image/png"
	"log"
	"os"

	_ "golang.org/x/image/webp"
)

func main() {

	flag.Parse()
	if flag.NArg() < 1 {
		log.Fatalf("please give a path to a file to analyze")
	}
	if flag.NArg() < 2 {
		log.Fatalf("please give a path to a file to convert to PNG")
	}

	f, err := os.Open(flag.Arg(0))
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()

	img, format, err := image.Decode(f)
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("decoded image from %q: %v", f.Name(), format)

	log.Printf("image: %v", img.Bounds())

	o, err := os.Create(flag.Arg(1))
	if err != nil {
		log.Fatal(err)
	}
	defer o.Close()

	err = png.Encode(o, img)
	if err != nil {
		log.Fatalf("error converting to PNG: %v", err)
	}

	err = o.Close()
	if err != nil {
		log.Fatalf("error closing output file: %v", err)
	}
}

and here is the Linux binary:

$> curl -O -L https://cern.ch/binet/root-discourse/webp-cnv-png
$> chmod +x ./webp-cnv-png
$> ./webp-cnv-png img-root-discourse.webp img-root-discourse.png
2018/03/05 11:58:42 decoded image from "img-root-discourse.webp": webp
2018/03/05 11:58:42 image: (0,0)-(1226,1028)

hth,
-s

Thanks a lot.
Isn’t any way to do the same in python, pls?
Sorry, I have been using always only root…

And how did you see that it was a WebP, please?

Thanks,
franciuska

I ran the file utility on it:

$> file ./img-root-discourse.webp 
./img-root-discourse.webp: RIFF (little-endian) data, Web/P image

also:

$> hexdump -C ./img-root-discourse.webp | head
00000000  52 49 46 46 ca 99 00 00  57 45 42 50 56 50 38 4c  |RIFF....WEBPVP8L|
00000010  be 99 00 00 2f c9 c4 00  01 7f 20 10 48 da 1f 7c  |..../..... .H..||
00000020  85 09 98 80 f9 4f 6c c7  9b 80 88 08 9f d3 b6 6d  |.....Ol........m|
00000030  9b dc 36 92 ee f0 2f 88  37 d4 bd 77 44 b2 7e 80  |..6.../.7..wD.~.|
00000040  32 92 9e ed 1c cc 04 bd  2f 22 41 ef 4d 00 74 af  |2......./"A.M.t.|
00000050  45 00 f4 ba 4d 00 f4 6c  47 04 20 cf ba 08 50 9e  |E...M..lG. ...P.|
00000060  d9 5a 20 55 b3 2e 91 aa  da b7 3e 6a 3f 25 4a 3f  |.Z U......>j?%J?|
00000070  60 ca e4 f1 3c f7 fd bc  11 19 48 52 01 da dd 47  |`...<.....HR...G|
00000080  44 ff 1d 4a 92 54 35 a9  c4 28 02 ee 1d 7b cb cb  |D..J.T5..(...{..|
00000090  2f f0 a5 fd ff e5 34 b2  6d bd 1a 2d 50 a8 3a 50  |/.....4.m..-P.:P|

Isn’t any way to do the same in python, pls?

Let me Goog^W Lilo-it for you :slight_smile:
https://search.lilo.org/searchweb.php?q=python+pil+webp

That said, the binary I’ve provided can convert all your .webp images in one go.
Then you can use ROOT::TImage on the resulting files.

Hello.

My file was called 13PS1:image1:ArrayData\ 0.png
and file 13PS1:image1:ArrayData\ 0.png gives
13PS1:image1:ArrayData 0.png: PNG image data, 1226 x 1028, 16-bit grayscale, non-interlaced

Perhaps I made a mistake in the link.
I just deleted all images in google drive and uploaded only that. Now it is called test.png.

Could you please give a look again? Sorry…

https://drive.google.com/file/d/1UbFkLcEHB889in1hMd7Zg_QlQnJqTGco/view?usp=sharing
It should be completely black because it was saved in 16 bits, and originally is 12 bits.

Thanks a lot,
regards,
franciuska

yes, that file is indeed a PNG one.

as per your original issue, it seems to me you are not reading the raw uint8_t* array correctly: you bump your index z by 1 (z++).
but the pixels values are encoded on 2 bytes as its a 16bits PNG file.

so you’re only reading half a pixel’s value (and iterating over only half of the total image data).

Depending on whether TImage::GetArgbArray() returns the decoded array or the raw on-disk value, you may or may not get away with casting the returned data to a uint16_t*.
If it’s the raw on-disk value, you will have to first decode it correctly (taking care of endianness) and then cast it to a uint16_t to get the full pixels’ values.

hth,
-s

FYI, here is what I get dumping the pixels values:

$> go run ./main.go ./test.png
2018/03/05 15:22:42 decoded image from "./test.png": png
2018/03/05 15:22:42 image: (0,0)-(1226,1028)
pix(x=0000, y=0000) -> ( 89,  89,  89, 65535)
pix(x=0001, y=0000) -> (  0,   0,   0, 65535)
pix(x=0002, y=0000) -> ( 30,  30,  30, 65535)
pix(x=0003, y=0000) -> ( 65,  65,  65, 65535)
pix(x=0004, y=0000) -> ( 34,  34,  34, 65535)
pix(x=0005, y=0000) -> ( 37,  37,  37, 65535)
pix(x=0006, y=0000) -> ( 75,  75,  75, 65535)
pix(x=0007, y=0000) -> ( 32,  32,  32, 65535)
pix(x=0008, y=0000) -> (126, 126, 126, 65535)
pix(x=0009, y=0000) -> (107, 107, 107, 65535)
[...]

Hello.

Thanks a lot!
Does it mean I should change argb[index]&0xff, please? How?

Sorry and thanks,
franciuska

we should probably back up a bit: what do you want to do exactly?

I want to read the pixels content and plot it in a 2D histogram…

running the tutorial/image/image2hist.C with your test.png file as input gave me a 2D histo:

Hello.
Yes, but the scale is not the correct one.
The pixel content should go up to 4096…
Or at least at bin contents:
89, 0, 30, 65, 34, 37, 75, 32, 126, 107, 267,
132, 120, 95, 58, 129, 124, 85, 207, 239, 137, 140,
174, 181, 125, 150, 159, 152, 101, 164, 186, 189, 276,
98, 308, 279, 195, 222, 197, 229, 184, 239, 111, 184,
178, 287, 109, 206, 289, 190, 232, 204, 221, 180, 245,
214, 245, 288, 154, 186, 310, 292, 122, 260, 192, 239,
207, 280, 344, 224, 175, 255, 380, 244, 262, 276, 241,
228, 262, 251, 216, 198, 270, 309, 214, 344, 261, 194,
282, 321, 198, 303, 231, 287, 299, 281, 152, 180, 280,
330, 327, 240, 281, 250, 259, 293, 268, 328, 244, 271,
342, 362, 229, 282, 234, 273, 316, 285, 235, 192, 228,

If i delete /256 they go up to 14 only.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.