I am tryying to read a multi-slice (Mosaic) DICOM image from a Siemens scanner in C++, using DCMTK to read the tag and information on the nibabel pages.
As I understand, Mosaic images have a CSA header and after 8 bytes (CSA1) or 16 bytes (CSA2), contain the structure
<TAG level>
tag name [64x uchar]
vm vr dt it mm [ 5x 4 bytes]
vm: [1x int32]: number of values
vr: [4x uchar]: 'value representation' string
dt: [1x int32]: 'Syngo DT' Siemens version of vr
it: [1x int32]: number of items
mm: [1x int32]: 77 (ascii value for 'M' I guess, or 205 [+128])
<ITEM level>
a b c d [ 4x 4 bytes]
a: [1x int32]: in CSA1: size Nitem in bytes + 'it' of first tag(?!)
b: [1x int32]: in CSA2: size Nitem in bytes
c: [1x int32]: 77 or 205 again, see above
d: [1x int32]: not used by nibabel
val [Nitem bytes]: item value
padding [nextw bytes]: start of next 4-byte word
It's special. But doable. In CSA2, numbers a, b and d would be the same.
Now I've reached the tag MrPhoenixProtocol which contains a JSON structure. This is not a problem (parsers aplenty). The 5 values described above are vm=1, vr='UN', dt=0, it=6, mm=77. The value 6 for it is strange but happens in other tags as well (1 item followed by 5 empty items).
Then for the first item, a, b and d are 192 and c is 77, so all signs say the item size is 192 bytes. But this barely reaches the 1st parameter in the JSON, the field is much larger. So 192 bytes is only a small portion of the item/tag, and after that the checks show that the value 77 or 205 is not being read where it should.
before reading the tag values, the size of their data needs to be known. But in the case of this MrPhoenixProtocol tag, if it is not in those numbers (so not the value 192), can it be computed another way?
EDIT
The function csareader.py shows the MrPhoenixProtocol tag correctly. I added the line
`print('{0} values: 1:{1}, 2:{2}, 3:{3}, 4:{4}, item_len: {5}'.format(name,x0,x1,x2,x3,item_len));
just before the item is read from the buffer and opened my DICOM image. The item length is shown to be 139200 items (in the example above, a, b and d would have that value), 725 times 192 (the value that I read). Completely baffled.
If you have not found it yet, you can inspect the CSA structure of one DICOM file using:
$ gdcmdump --csa input.dcm
You should get something like this:
http://gdcm.sourceforge.net/wiki/index.php/SIEMENS_CSA_Header
The code can be inspected at:
https://github.com/malaterre/GDCM/blob/v3.0.10/Source/DataStructureAndEncodingDefinition/gdcmCSAHeader.cxx#L948
If you are only interested in the 'MrProtocol' sub-section, you can use:
$ gdcmdump --mrprotocol input.dcm
I am using libvips PHP library, I am applying some effects on my image using the library and it's work very charm, but somehow for one image it's not working properly and giving me below error
Note - I m getting this error only the image which I uploaded, in other images, it works for me
Fatal error: Uncaught Jcupitt\Vips\Exception: recomb: bands in must equal matrix width
I think the issue is with the image band the image which has 3 bands it's working but for band 1 it's giving me errors.
Here is the code which I am using for apply b & w effect on my image
$img = Vips\Image::newFromFile($inputFileName, ['access' => 'sequential']);
//Matrix for black and white image
$technicolor = Vips\Image::newFromArray([
[0.2225, 0.7169, 0.0606],
[0.2225, 0.7169, 0.0606],
[0.2227, 0.7169, 0.0606],
]);
if ($img->hasAlpha()) {
$imageWithoutAlpha = $img->extract_band(0, ['n' => $img->bands - 1]);
$alpha = $img->extract_band($img->bands - 1, ['n' => 1]);
$img = $imageWithoutAlpha->recomb($technicolor)->bandjoin($alpha);
}
$img = $img->recomb($technicolor);
$img->writeToFile($outputFileName);
Here is the image info
error-img.jpg: 2000x1334 uchar, 1 band, b-w, jpegload
width: 2000
height: 1334
bands: 1
format: uchar
coding: none
interpretation: b-w
xoffset: 0
yoffset: 0
xres: 11.811
yres: 11.811
filename: error-img.jpg
vips-loader: jpegload
jpeg-multiscan: 0
jpeg-chroma-subsample: 4:4:4
iptc-data: 12836 bytes of binary data
exif-data: 13500 bytes of binary data
resolution-unit: in
exif-ifd0-Make: Canon (Canon, ASCII, 6 components, 6 bytes)
exif-ifd0-Model: Canon EOS 7D (Canon EOS 7D, ASCII, 13 components, 13 bytes)
exif-ifd0-XResolution: 300/1 (300, Rational, 1 components, 8 bytes)
exif-ifd0-YResolution: 300/1 (300, Rational, 1 components, 8 bytes)
exif-ifd0-ResolutionUnit: 2 (Inch, Short, 1 components, 2 bytes)
exif-ifd0-Software: Adobe Photoshop Camera Raw 8.1 (Windows) (Adobe Photoshop Camera Raw 8.1 (Windows), ASCII, 41 components, 41 bytes)
exif-ifd0-DateTime: 2013:09:05 23:59:59 (2013:09:05 23:59:59, ASCII, 20 components, 20 bytes)
exif-ifd0-Artist: Nik. Gribas - gnikos#hotmail.com (Nik. Gribas - gnikos#hotmail.com, ASCII, 33 components, 33 bytes)
exif-ifd0-Copyright: Nik. Gribas (Nik. Gribas (Photographer) - [None] (Editor), ASCII, 12 components, 12 bytes)
exif-ifd1-Compression: 6 (JPEG compression, Short, 1 components, 2 bytes)
exif-ifd1-XResolution: 72/1 (72, Rational, 1 components, 8 bytes)
exif-ifd1-YResolution: 72/1 (72, Rational, 1 components, 8 bytes)
exif-ifd1-ResolutionUnit: 2 (Inch, Short, 1 components, 2 bytes)
exif-ifd2-ExposureTime: 1/5 (1/5 sec., Rational, 1 components, 8 bytes)
exif-ifd2-FNumber: 4/1 (f/4.0, Rational, 1 components, 8 bytes)
exif-ifd2-ExposureProgram: 1 (Manual, Short, 1 components, 2 bytes)
exif-ifd2-ISOSpeedRatings: 1600 (1600, Short, 1 components, 2 bytes)
exif-ifd2-ExifVersion: Exif Version 2.3 (Exif Version 2.3, Undefined, 4 components, 4 bytes)
exif-ifd2-DateTimeOriginal: 2013:08:30 23:49:47 (2013:08:30 23:49:47, ASCII, 20 components, 20 bytes)
exif-ifd2-DateTimeDigitized: 2013:08:30 23:49:47 (2013:08:30 23:49:47, ASCII, 20 components, 20 bytes)
exif-ifd2-ShutterSpeedValue: 2321928/1000000 (2.32 EV (1/4 sec.), SRational, 1 components, 8 bytes)
exif-ifd2-ApertureValue: 4/1 (4.00 EV (f/4.0), Rational, 1 components, 8 bytes)
exif-ifd2-ExposureBiasValue: 0/1 (0.00 EV, SRational, 1 components, 8 bytes)
exif-ifd2-MaxApertureValue: 3/1 (3.00 EV (f/2.8), Rational, 1 components, 8 bytes)
exif-ifd2-MeteringMode: 5 (Pattern, Short, 1 components, 2 bytes)
exif-ifd2-Flash: 16 (Flash did not fire, compulsory flash mode, Short, 1 components, 2 bytes)
exif-ifd2-FocalLength: 17/1 (17.0 mm, Rational, 1 components, 8 bytes)
exif-ifd2-SubSecTimeOriginal: 64 (64, ASCII, 3 components, 3 bytes)
exif-ifd2-SubSecTimeDigitized: 64 (64, ASCII, 3 components, 3 bytes)
exif-ifd2-FocalPlaneXResolution: 5184000/907 (5715.546, Rational, 1 components, 8 bytes)
exif-ifd2-FocalPlaneYResolution: 3456000/595 (5808.403, Rational, 1 components, 8 bytes)
exif-ifd2-FocalPlaneResolutionUnit: 2 (Inch, Short, 1 components, 2 bytes)
exif-ifd2-CustomRendered: 0 (Normal process, Short, 1 components, 2 bytes)
exif-ifd2-ExposureMode: 1 (Manual exposure, Short, 1 components, 2 bytes)
exif-ifd2-WhiteBalance: 0 (Auto white balance, Short, 1 components, 2 bytes)
exif-ifd2-SceneCaptureType: 0 (Standard, Short, 1 components, 2 bytes)
exif-ifd2-FlashPixVersion: FlashPix Version 1.0 (FlashPix Version 1.0, Undefined, 4 components, 4 bytes)
exif-ifd2-ColorSpace: 65535 (Internal error (unknown value 65535), Short, 1 components, 2 bytes)
jpeg-thumbnail-data: 12598 bytes of binary data
xmp-data: 10134 bytes of binary data
icc-profile-data: 408 bytes of binary data
The Image in which I am getting error
Your image is a one-band JPEG, so it's already black and white.
I would convert to black and white with colourspace. It will work for any image, plus it takes account of the image gamma, so it should produce a better result than a simple linear recombination. It also knows about alpha channels, and it's smart enough to pass an image that's already black and white though unchanged.
Docs are here:
https://libvips.github.io/php-vips/docs/classes/Jcupitt-Vips-ImageAutodoc.html#method_colourspace
The possible colourspaces are documented here:
https://libvips.github.io/php-vips/docs/classes/Jcupitt-Vips-Interpretation.html
So you need:
$img = Vips\Image::newFromFile($inputFileName, ['access' => 'sequential']);
$img = $img->colourspace("b-w");
$img->writeToFile($outputFileName);
The php docs are not very good, unfortunately, due to the limitations of php-doc. The python, ruby or C documentation is usually more useful, and the API is the same. Try for example:
https://libvips.github.io/pyvips/vimage.html#pyvips.Image.colourspace
I have a Python program which is accessing one of the devices on our Solar Power system. I can read the registers which are supposed to conform to the SunSpec conventions. I have been able to decode most of the values, but I'm stuck on decoding the TCP_Address and gateway which are sourced from these two registers:
TCP Address:
reg 22 value 49320 in HEX 0xc0a8
reg 23 value 64 in HEX 0x40
Gataway Address:
reg 24 value 49320 in HEX 0xc0a8
reg 25 value 1 in HEX 0x1
the documentation says that the format for these values is "uint32", which I interpret to mean unsigned 32 bit integer. The result of decoding should be something like 192.168.0.?.
Can anyone assist to understand how to convert the above to that format in Python? Thanks...RDK
I would say that
0xc0 0xa8 (0x00) 0x01
is 192.168.0.1, your gateway. Seems you've just missed to note that both registers are 16 bits so you've neglected the high byte..
Here is my solution to this problem:
def Decode_TCPIP(reg1,reg2):
# print("Reg1 = "+ reg1 + " Reg2 = " + reg2)
UpperMask = 0xff00
LowerMask = 0x00ff
First = (reg1 & UpperMask)/256
Second = (reg1 & LowerMask)
Third = (reg2 & UpperMask)/256
Forth = (reg2 & LowerMask)
return First, Second, Third, Forth
the returned values are then the four digits in the IP address....RDK
Apologies for the nubeness of the question but I've been chasing my tail for days.
I need to create a function that can verify whether the encoding of a buffer being received is actually UTF8 and then do a basic regex to exclude unwanted control chars.
I started by recursively dumping:
0x62
0xCDBC
0xE0AC89
0xF09F8489
Into a test file.
It worked fine, copied the file and text editors from windows, Linux & mac can read it (and display the correct char's)
But when I try to read it back into my test function it dies, added a
char c = fs->get();
while(fs->good())
{
int len = sizeof(c);
printf("0x%X --- %i\n",c,len);
c = fs->get();
}
Yes I know the code sucks..
but what I don't understand is why I'm getting this on the output.
Hex sizeof()
0x26 --- 1
0xFFFFFFCD --- 1
0xFFFFFFBC --- 1
0xFFFFFFE0 --- 1
0xFFFFFFAC --- 1
0xFFFFFF89 --- 1
0xFFFFFFF0 --- 1
0xFFFFFF9F --- 1
0xFFFFFF84 --- 1
0xFFFFFFB9 --- 1
The 0x62 becomes a 0x26 whilst all the other numbers are correct but padded into a 64 bit pattern...?
locale is EN_en.utf8
I'm lost, any ideas out there?
Thanks in advance
Bob.
My semestral project is due this Thursday and I have major problem with reading MP3 file (the project is about sound analysis, don't ask my what exactly is it about and why I'm doing it so late).
First, I read first 10 bytes to check for ID3 tags. If they're present, I'll just skip to the first MP3 header - or at least that's the big idea. Here is how I count ID3 tag size:
if (inbuf[0] == 'I' && inbuf[1] == 'D' && inbuf[2] == '3') //inbuf contains first 10 bytes from file
{
int size = inbuf[3] * 2097152 + inbuf[4] * 16384 + inbuf[5] * 128 + inbuf[6]; //Will change to binary shifts later
//Do something else with it - skip rest of ID3 tags etc
}
It works ok for files without ID3 tags and for some files with them, but for some other files ffmpeg (which I use for decoding) returns "no header" error, which means it didn't catch MP3 header correctly. I know that since if I remove ID3 from that .mp3 file (with Winamp for example), no errors occur. The conclusion is that size count algorithm isn't always valid.
So the question is: how do I get to know how big exactly is entire ID3 part of the .mp3 file (all possible tags, album picture and whatever)? I'm looking for it everywhere but I just keep finding this algorithm I posted above. Sometimes also something about some 10 bytes footer I need to take into account, but it seems it frequently gets more than 10 bytes for it to eventually catch proper MP3 frame.
The size of an ID3v1 Tag is always fixed 128 Bytes.
I will find the following description
If you one sum the the size of all these fields we see that 30+30+30+4+30+1 equals 125 bytes and not 128 bytes. The missing three bytes can be found at the very beginning of the tag, before the song title. These three bytes are always "TAG" and is the identification that this is indeed a ID3 tag. The easiest way to find a ID3v1/1.1 tag is to look for the word "TAG" 128 bytes from the end of a file.
Source: http://id3.org/ID3v1
There is another version, called ID3v2:
One of the design goals were that the ID3v2 should be very flexible and expandable...
Since each frame can be 16MB and the entire tag can be 256MB you'll probably never again be in the same situation as when you tried to write a useful comment in the old ID3 being limited to 30 characters.
This ID3v2 always starts at the begin of an audio file, as you can read here: http://id3.org/ID3v2Easy
ID3v2/file identifier "ID3"
ID3v2 version $03 00
ID3v2 flags %abc00000
ID3v2 size 4 * %0xxxxxxx
The ID3v2 tag size is encoded with four bytes where the most significant bit (bit 7) is set to zero in every byte, making a total of 28 bits. The zeroed bits are ignored, so a 257 bytes long tag is represented as $00 00 02 01.
bool LameDecoder::skipDataIfRequired()
{
auto data = m_file.read(3);
Q_ASSERT(data.size() == 3);
if (data.size() != 3)
return false;
if (memcmp(data.constData(), "ID3", 3))
{
m_file.seek(0);
return true;
}
// ID3v2 tag is detected; skip it
m_file.seek(3+2+1);
data = m_file.read(4);
if (data.size() != 4)
return false;
qint32 size = (data[0] << (7*3)) | (data[1] << (7*2)) |
(data[2] << 7) | data[3];
m_file.seek(3+2+1+4+size);
return true;
}