Wrong file size for 4-bit RAW Grayscale file

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
Post Reply
BrianP007
Posts: 49
Joined: 2013-12-13T09:54:14-07:00
Authentication code: 6789

Wrong file size for 4-bit RAW Grayscale file

Post by BrianP007 »

When converting from JPG to TIF, Quantum Bits and XY resolution are correct:

convert bb.test.jpg -colorspace gray -resize "9x6" -depth 4 bb.test.gray.4bit.9x6.tif;

identify -quiet pic/bb.test.gray.4bit.9x6.tif
bb.test.gray.4bit.9x6.tif TIFF 9x6 9x6+0+0 4-bit Grayscale Gray 24.9KB 0.000u 0:00.009

Resolution = 9*6 = 54 pixels; 4 Quantum Bits, 1 channel grayscale. All correct
Blowing up the TIF to 5000%, the light and dark areas look right

When converting the JPG to raw, the size does not match what the XY res and QBits would produce:
Resolution = 9 wide x 6 high = 54 pixels. 1 channel, Gray, 4 bits/pixel, 54 * 4 / 8 = 27 Bytes

convert bb.test.jpg -colorspace gray -resize "9x6" -depth 4 RGB:bb.test.gray.4bit.9x6.raw;
ls -l bb.test.gray.4bit.9x6.raw
-rw-r----- 1 brianp users 84 Apr 10 15:35 bb.test.gray.4bit.9x6.raw << 84 bytes. Should be 27 bytes

Same result on windows 7
C:\bin>convert t:/pic/bb.test.jpg -colorspace gray -resize "9x6" -depth 4 RGB:bb.test.gray.4bit.9x6.raw;

C:\bin>ls -l bb.test.gray.4bit.9x6.raw
-rw-rw-rw- 1 user group 84 Apr 10 16:24 bb.test.gray.4bit.9x6.raw

How is it possible to get a 4-bit, grayscale, pure RAW image?


== VERSIONS ===================================================================
convert -version << OpenSuse 42 64-bit
Version: ImageMagick 6.9.3-7 Q16 x86_64 2016-04-08 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2016 ImageMagick Studio LLC
License: http://www.imagemagick.org/script/license.php
Features: Cipher DPC HDRI OpenMP
Delegates (built-in): bzlib fftw fontconfig freetype jng jpeg lcms lzma openexr pangocairo png tiff x xml zlib

identify -version
Version: ImageMagick 6.9.3-7 Q16 x86_64 2016-04-08 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2016 ImageMagick Studio LLC
License: http://www.imagemagick.org/script/license.php
Features: Cipher DPC HDRI OpenMP
Delegates (built-in): bzlib fftw fontconfig freetype jng jpeg lcms lzma openexr pangocairo png tiff x xml zlib

C:\bin>convert -version << windows 7 /64-bit
Version: ImageMagick 6.9.2-8 Q16 x64 2015-12-05 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2015 ImageMagick Studio LLC
License: http://www.imagemagick.org/script/license.php
Visual C++: 180040629
Features: Cipher DPC HDRI Modules OpenMP
Delegates (built-in): bzlib cairo freetype jng jp2 jpeg lcms lqr openexr pangoca
iro png ps rsvg tiff webp xml zlib
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Wrong file size for 4-bit RAW Grayscale file

Post by snibgo »

BrianP007 wrote:RGB:bb.test.gray.4bit.9x6.raw
You asked for "RGB:" format. This contains three channels: R, G and B. You could ask for "gray:" format, which will give you one channel.

9 columns at 4 bits/column would be 4.5 bytes. But IM rounds this up to 5 bytes. 6 rows at 5 bytes/row is 30 bytes total, not 27.
snibgo's IM pages: im.snibgo.com
BrianP007
Posts: 49
Joined: 2013-12-13T09:54:14-07:00
Authentication code: 6789

Re: Wrong file size for 4-bit RAW Grayscale file

Post by BrianP007 »

Snibgo,
That explains it! I have a note in ancient code that 4x6 worked and 6x9 was wrong. The 4x6 has an even number of columns.

I checked 8x12 and it works too!

In tracking this down, I noticed hat the GetPixels() returns the right number of pixels, 27, but the values are Impossibly large for 4 bit quanta:
print("Resized: X $xres, Y $yres, Depth $depth, CSpace $cspace, Mem $mem\n");
@pixels=$im->GetPixels(normalize=>'false');
printf("Pixels -> %d\n", scalar @pixels);
for($ii=0; $ii < scalar @pixels; $ii++) {
printf("P[$ii] = %.4f float = %d int, %s str, %s ref\n",
$pixels[$ii], $pixels[$ii], $pixels[$ii], ref($pixels[$ii]));
}
=->
Resized: X 9, Y 6, Depth 4, CSpace Gray, Mem 864
Pixels -> 27
P[0] = 30583.0000 float = 30583 int, 30583 str, ref << 4 bit quanta should be in [0 ..15] range
<snip>
P[6] = 34952.0000 float = 34952 int, 34952 str, ref << Print the ~same as float, int or string
...
P[12] = 30583.0000 float = 30583 int, 30583 str, ref << NOT a ref, just a scalar
P[15] = 34952.0000 float = 34952 int, 34952 str, ref << Only 3 distinct values too, 16 possible, 8 likely
P[18] = 26214.0000 float = 26214 int, 26214 str, ref
P[21] = 30583.0000 float = 30583 int, 30583 str, ref
P[24] = 26214.0000 float = 26214 int, 26214 str, ref
P[26] = 26214.0000 float = 26214 int, 26214 str, ref
Final hex length=60
Wrong HEX length=60! Xres 9 * yres 6 * qbits 4 * (1Byte/8bits) * 2 hex/byte = 54

I suspect that this is a problem with the way Perl handles INTEGERS. The size of the number in the Tens-of-Thousands indicates at least 16 bit quanta.

Is there any way to "get at" the 4 bit quanta in Perl or would the C version be more direct? There is a GetAuthenticPixels() which returns a "C Pointer". Is there a way to convert the pointed-to data to HEX (4-bit quanta) before Perl "Upgrades" it to doubles?

Thx!
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Wrong file size for 4-bit RAW Grayscale file

Post by snibgo »

You are using Q16, which means pixel values are stored in memory as integers between 0 and 2^16-1, 0 to 65535.

If you look at the hex equivalent of the decimal numbers you have posted:

34952 0x8888
30583 0x7777
26214 0x6666

Can you see a pattern? IM promotes 4-bit values to 16-bit values by replicating the 4-bit values, ie multiplying by 0x1111. If you want 4-bit values from the decimal values, divide by 0x1111.

0x1111 = 4369 decimal.

34952/4369 = 8
30583/4369 = 7
26214/4369 = 6
snibgo's IM pages: im.snibgo.com
Post Reply