DICOM File Meta Information Version padded with zeros - dicom

I've got a DICOM file that starts like this, and most of it makes sense to me based on the spec parts 5, 6 and 10, but the File Meta Information Version element (0002,0001) has me foxed.
00000000: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000010: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000020: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000030: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000040: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000050: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000060: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000070: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000080: 4449 434d 0200 0000 554c 0400 ce00 0000 DICM....UL......
00000090: 0200 0100 4f42 0000 0200 0000 0001 0200 ....OB..........
000000a0: 0200 5549 1e00 312e 322e 3834 302e 3130 ..UI..1.2.840.10
000000b0: 3030 382e 352e 312e 342e 312e 312e 3737 008.5.1.4.1.1.77
000000c0: 2e31 2e36 0200 0300 5549 3800 312e 322e .1.6....UI8.1.2.
This is the bit that I don't understand:
00000090: 0200 0100 4f42 0000 0200 0000 0001
The first four bytes are the (0002,0001) tag, and the next two are the VR 4f42 = OB. I expect 0200 for the value length (2 bytes) and 0001 for the version, but what are the two sets of 0000 in between?
I haven't found any specification of padding here, and in any case all mention of padding that I've found in the spec only extends as far as padding onto two-byte boundaries, never four or more.
And if the zeros were leading zeros in 32-bit quantities then I'd expect them to come after the 0200 and 0100, not before. And of course then the length would have to be 0400, not 0200.
The file was created by OrthancWSIDicomizer.exe, part of the Orthanc DICOM offering.
What am I missing? (Apart from the obvious: a deep understanding of DICOM!)

I haven't found any specification of padding here,
The data element is correctly encoded: in the Explicit VR Little Endian transfer syntax, there is padding depending on the data element's value representation. According to Table 7.1-1, if the VR is either of "OB", "OD", "OF", "OL", "OV", "OW", "SQ", "UC", "UR", "UT", or "UN", then the two VR bytes are followed by "Reserved (2 bytes) set to a value of 0000H", and the length of the element is defined with 4 bytes instead of just 2. In this case, these are the bytes at position 0096. The subsequent 4 bytes, at 0098, represent the length of the element: 0200 0000 (little endian for 2).
The complete data element with header is 14 bytes long: 0200 0100 4f42 0000 0200 0000 0001, (0002,0001) File Meta Information Version, OB, with the value 1.

Related

equivalent of objdump for dex files

Is there any equivalent to objdump for dex files?
I don't want to decompile them, just be able to watch their content
Just in case it helps someone in the future:
$ sudo apt install dexdump
baksmali has a dump command that generates an annotated hex dump of a dex file
baksmali dump helloworld.dex > helloworld.txt
|-----------------------------
|code_item section
|-----------------------------
|
|[0] code_item: LHelloWorld;->main([Ljava/lang/String;)V
0001c4: 0200 | registers_size = 2
0001c6: 0100 | ins_size = 1
0001c8: 0200 | outs_size = 2
0001ca: 0000 | tries_size = 0
0001cc: 0000 0000 | debug_info_off = 0x0
0001d0: 0800 0000 | insns_size = 0x8
| instructions:
0001d4: 6200 0000 | sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;
0001d8: 1a01 0000 | const-string v1, "Hello World!"
0001dc: 6e20 0100 1000 | invoke-virtual {v0, v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
0001e2: 0e00 | return-void
It is also able to list the items in some of the various constant pools
baksmali list classes helloworld.dex
LHelloWorld;
baksmali list methods helloworld.dex
LHelloWorld;->main([Ljava/lang/String;)V
Ljava/io/PrintStream;->println(Ljava/lang/String;)V
baksmali list fields helloworld.dex
Ljava/lang/System;->out:Ljava/io/PrintStream;
baksmali list strings helloworld.dex
"Hello World!"
"LHelloWorld;"
"Ljava/io/PrintStream;"
"Ljava/lang/Object;"
"Ljava/lang/String;"
"Ljava/lang/System;"
"V"
"VL"
"[Ljava/lang/String;"
"main"
"out"
"println"

Understanding IR codes for Samsung TV

Can somebody help me to understand how could I use RAW IR data in an project using ESP8266-HTTP-IR-Blaster library ?
I've created a NodeMCU board with an IR sender and receiver according to https://github.com/mdhiggins/ESP8266-HTTP-IR-Blaster
Everything is working fine as long as I'm using the captured codes for ex.:
http://NodeMCU-IP/msg?code=E0E040BF:SAMSUNG:32
This is the Code for the Power button (E0E040BF)
As I'm using it in a home automation system, it would very beneficial for me if I had a dedicated ON and OFF sequence, which I found here: http://www.remotecentral.com/cgi-bin/mboard/rc-discrete/thread.cgi?5780 , but unable to translate, modify, or send it via RAW data.
Using Node-red, tried many ways, also implemented a MQTT client to the original project, but did not accept these codes anyhow I try. Does not sends it.
Also tried as a JSON, didn't help.
[
{
"type":"raw",
"data":"[0000, 006D, 0000, 0022, 00AC, 00AC, 0015, 0040, 0015, 0040, 0015, 0040, 0015, 0015, 0015, 0015, 0015, 0015, 0015, 0015, 0015, 0015, 0015, 0040, 0015, 0040, 0015, 0040, 0015, 0015, 0015, 0015, 0015, 0015, 0015, 0015, 0015, 0015, 0015, 0015, 0015, 0015, 0015, 0015, 0015, 0040, 0015, 0040, 0015, 0015, 0015, 0015, 0015, 0040, 0015, 0040, 0015, 0040, 0015, 0040, 0015, 0015, 0015, 0015, 0015, 0040, 0015, 0040, 0015, 0015, 0015, 0689]",
"khz":38
}
]
Any idea what could I try next?
A good introduction to the 'Pronto format' that you show above is at Remote Central
For the specific example above, for a Samsung OFF code given at your remote central link, the full code is given as a sequence of 16-bit numbers represented in hexadecimal with spaces in between:
0000 006D 0000 0022 00AC 00AC 0015 0040 0015 0040 0015 0040 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0040 0015 0040 0015 0040 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0040 0015 0040 0015 0015 0015 0015 0015 0040 0015 0040 0015 0040 0015 0040 0015 0015 0015 0015 0015 0040 0015 0040 0015 0015 0015 0689
You can break that down as a preamble (broken out here for interest, but not needed if you already have a working Samsung code):
0x0000 - This is raw code format data
0x006D - Frequency 109 decimal = 38.028kHz (see above link for calculation)
0x0000 - No burst pairs in first sequence
0x0022 - 34 decimal - 34 burst pairs of signal follow
00AC 00AC - First burst of signal - on for 0xAC (172 decimal) cycles at 38kHz, off for the same amount
After that comes 32 pairs of data "burst pairs" (which is likely the only bit you need if you already have other codes for the same device)
0015 0689 - Final burst of signal - on for 0x15 (21 decimal) cycles, off for 0x689 (1673 decimal) cycles, guaranteeing 44ms without any IR before the next code can be transmitted
To interpret the data manually, copy it out (e.g. into a text editor) in groups of 8 numbers:
0015 0040 0015 0040 0015 0040 0015 0015
0015 0015 0015 0015 0015 0015 0015 0015
0015 0040 0015 0040 0015 0040 0015 0015
0015 0015 0015 0015 0015 0015 0015 0015
0015 0015 0015 0015 0015 0015 0015 0040
0015 0040 0015 0015 0015 0015 0015 0040
0015 0040 0015 0040 0015 0040 0015 0015
0015 0015 0015 0040 0015 0040 0015 0015
Then:
Ignore the columns where all the numbers are the same (even columns above, which represent the on time - 0x15 = 21 decimal cycles of IR at 38kHz )
For the remaining columns (which represent the off-time), replace the big numbers (0x40 in this case) with '1' and the small (0x15) with '0'.
For the first line
0015 0040 0015 0040 0015 0040 0015 0015
ignoring the even numbered columns leaves:
0040 0040 0040 0015
replacing those with 1's and 0's
1 1 1 0
and if you convert that into hexadecimal, it's 'E'
Next line is '0', then 'E' then '0' (already it's comforting to see it starting with the same E0E0 that starts your other Samsung code above...), and the remaining lines make it
E0E019E6
Doing the same with the ON code gives you
E0E09966
And as I've needed to solve the same problem just recently for the same codes, I can confirm that my Samsung TV responds to those codes as OFF and ON.
Not surprisingly, there are a variety of software tools to convert between formats, and a huge range of formats to describe the same signal (explained very well by xkcd). For example, irdb on GitHUB will decode the above string to "Protocol NECx2, device 7, subdevice 7, OBC 152". It's up to you to know that you have to
bit-reverse the device number '07' to get 'E0'
bit-reverse the subdevice number (also '07') to get 'E0'
convert 152 to hexadecimal and reverse the bits to get '19'
calculate the last two digits as ( 0xFF - the bit-reversed OBC ), 0xFF - 0x19 = 0xE6, giving the final 8 bits 'E6'

Incorrect wav header generated by sox

I was using sox to convert a 2 channels, 48000Hz, 24bits wav file (new.wav) to a mono wav file (post.wav).
Here are the related commands and outputs:
[Farmer#Ubuntu recording]$ soxi new.wav
Input File : 'new.wav'
Channels : 2
Sample Rate : 48000
Precision : 24-bit
Duration : 00:00:01.52 = 72901 samples ~ 113.908 CDDA sectors
File Size : 447k
Bit Rate : 2.35M
Sample Encoding: 24-bit Signed Integer PCM
[Farmer#Ubuntu recording]$ sox new.wav -c 1 post.wav
[Farmer#Ubuntu recording]$ soxi post.wav
Input File : 'post.wav'
Channels : 1
Sample Rate : 48000
Precision : 24-bit
Duration : 00:00:01.52 = 72901 samples ~ 113.908 CDDA sectors
File Size : 219k
Bit Rate : 1.15M
Sample Encoding: 24-bit Signed Integer PCM
It looks fine. But let us check the header of post.wav:
[Farmer#Ubuntu recording]$ xxd post.wav | head -10
00000000: 5249 4646 9856 0300 5741 5645 666d 7420 RIFF.V..WAVEfmt
00000010: 2800 0000 feff 0100 80bb 0000 8032 0200 (............2..
00000020: 0300 1800 1600 1800 0400 0000 0100 0000 ................
00000030: 0000 1000 8000 00aa 0038 9b71 6661 6374 .........8.qfact
00000040: 0400 0000 c51c 0100 6461 7461 4f56 0300 ........dataOV..
This is the standard wav file header structure.
The first line is no problem.
The second line "2800 0000" shows the size of sub chunk "fmt ", it should be 0x00000028 (as this is little endian) = 40 bytes. But there are 54 bytes (before sub chunk "fmt " and sub chunk "data").
The third line shows "ExtraParamSize" is 0x0018 = 22 bytes. But actually it is 36 bytes (from third line's "1600" to 5th line's "0100"). The previous 16 bytes are standard.
So what's the extra 36 bytes?
Ok,I found out the answer.
Look at the second line, we can found that audio format is "feff", actual value is 0xFFFE, so this is not a PCM standard wave format, but a extensible format.
Wav head detailed introduction can refer to this link. The article is well written and thanks to the author.
So as this is a Non-PCM format wav, "fmt " chunk space occupied 40 bytes is no problem, and followed by a "fact" chunk, and then is "data" chunk, So everything makes sense.

Questions about hexadecimal

Write a program to swap odd and even bits in an integer.
For exp, bit 0 and bit 1 are swapped, bit 2 and bit 3 are swapped.
The solution uses 0xaaaaaaaa and 0x55555555.
Can I know what does 0xaaaaaaaa and 0x55555555 means in binary number?
Each four bits constitutes a hex digit thus:
0000 0 1000 8
0001 1 1001 9
0010 2 1010 A
0011 3 1011 B
0100 4 1100 C
0101 5 1101 D
0110 6 1110 E
0111 7 1111 F
So, for example, 0x1234 would be 0001 0010 0011 01002.
For your specific examples:
0xaaaaaaaa = 1010 1010 ... 1010
0x55555555 = 0101 0101 ... 0101
The reason why a solution might use those two values is that, if you AND a value with 0xaaaaaaaa, you'll get only the odd bits (counting from the left), which you can then shift right to move them to the even bit positions.
Similarly, if you AND a value with 0x55555555, you'll get only the even bits, which you can then shift left to move them to the odd bit positions.
Then you can just OR those two values together and the bits have been swapped.
For example, let's start with the 16-bit value abcdefghijklmnop (each letter being a bit and with a zero bit being . to make it more readable):
abcdefghijklmnop abcdefghijklmnop
AND 1.1.1.1.1.1.1.1. AND .1.1.1.1.1.1.1.1
= a.c.e.g.i.k.m.o. = .b.d.f.h.j.l.n.p
>>1 = .a.c.e.g.i.k.m.o <<1 = b.d.f.h.j.l.n.p.
\___________ ___________/
\ /
.a.c.e.g.i.k.m.o
OR b.d.f.h.j.l.n.p.
= badcfehgjilknmpo
So each group of two bits has been swapped around. In C, that would be something like:
val = ((val & 0xAAAAAAAA) >> 1) | ((val & 0x55555555) << 1);
but, if this is classwork of some description, I'd suggest you work it out yourself by doing individual operations.
For an in-depth explanation of the bitwise operators that allow you to do this, see this excellent answer here.

calculating subnet mask?

how can i calculate the subnet mask having ip address 128.2.19.4 and belong to the subnet 128.2.19.0/25.please give me the detail procedure.i want to learn to calculate.
Here's the algorithm with your example:
The subnet mask is just a representation of the "/25" part of your subnet address.
In IPv4, addresses are 32 bits long, the first 25 bits of which are ones:
1111 1111 1111 1111 1111 1111 1000 0000
addresses are given in octets -- 8 bits each:
octet 1 . octet 2 . octet 3 . octet 4
0000 0000 0000 0000 0000 0000 0000 0000
1111 1111 1111 1111 1111 1111 1000 0000
So a decimal representation of each octet is:
255 . 255 . 255 . 128
That means that your subnet mask would be:
255.255.255.128
The subnet mask is a bitmask. 25 means that 25 out of 32 bits (starting from the top) is used for the network, and the rest for the hosts.
In bytes: 128.2.19.0
In binary 10000000 00000010 00010011 00000000
The bitmask: 11111111 11111111 11111111 10000000
Ergo: ------- network ------------ host
The last 7 bits are used for hosts. The bitmask as bytes is 255.255.255.128.
Here's how you can do it in C:
#include <stdio.h>
#include <arpa/inet.h>
uint32_t cidr_to_netmask(uint8_t cidr)
{
uint8_t unset_bits = 32 - cidr;
return ntohl(0xffffffff << unset_bits);
}
int main(void)
{
uint8_t cidr = 25;
uint32_t _netmask = cidr_to_netmask(cidr);
struct in_addr _netmask_addr = { _netmask };
char netmask[16];
if (inet_ntop(AF_INET, (struct in_addr *)&_netmask_addr, (char *)&netmask, sizeof(netmask)) == NULL) {
fprintf(stderr, "error.\n");
return 1;
}
printf("%d = %s\n", cidr, netmask);
return 0;
}
Output:
25 = 255.255.255.128

Resources