background:
As mentioned in the previous column, the local DCMTK and Cximage library responses are initiated by using CGI or fastcgi technology to forward user requests sent by the browser. The processing result is then converted to a regular image to be returned to the browser to implement the Web PACS. This blog post through the actual code test to verify the feasibility of this model, at the same time, the C language writing CGI script raised some questions.
Challenges:
Plan to take the source code of the DCMTK tool Dcm2pnm.exe. Convert DCM files to BMP files via dicomimage, then use CGI technology to return to the browser. Implementation of a simple Web PACs image transmission simulation. Detailed code such as the following,
Dcmtk-save-test.cpp: Defines the entry point of the console application. #include "dcmtk/config/osconfig.h" #include "dcmtk/dcmdata/dctk.h" #include "dcmtk/dcmdata/dcpxitem.h" #include " Dcmtk/dcmjpeg/djdecode.h "#include" dcmtk/dcmjpeg/djencode.h "#include" dcmtk/dcmjpeg/djcodece.h "#include" dcmtk/ Dcmjpeg/djrplol.h "#include" dcmtk/dcmimgle/diutils.h "#include" dcmtk/dcmimgle/dcmimage.h "void Sendimagedcmtk (char * filename) {Dcmfileformat mdcm;mdcm.loadfile (filename); E_transfersyntax Xfer = Mdcm.getdataset ()->getoriginalxfer (); unsigned long mode = Cif_maydetachpixeldata | Cif_takeoverexternaldataset;dicomimage *di = new Dicomimage (&mdcm,xfer,mode,0,0), if (di = = NULL) {print2web ("Can Not open DCM file by dicomimage! ");} printf ("content-type:image/bmp\n\n");d i->writebmp (stdout,24,0);} int main (int argc, char* argv[]) {char* filename= "C:\\TEST.DCM"; SENDIMAGEDCMTK (filename); return 0;}
Compile the CGI program that generates Dcm2bmp.exe and copy it to the site's CGI folder (my native address is c:\wamp\www\c-cgi). Start the service-side CGI program by entering Http://localhost/c-cgi/dcm2bmp.exe in the browser.
Although the program started smoothly, it did not get the result we wanted-output a strange image, such as the following: The picture on the left is the real DCM image seen in the view of PACs, and the picture on the right is the failed image I transmitted to the browser.
Verify test:
Get the wrong result, at first did not think of a very good way to eliminate the error. It was decided to first confirm the approximate scope of the problem. Since most of the books that introduce CGI technology are implemented in Perl or PHP. So the example in the book is modeled. Using Perl and PHP to achieve a normal transfer of images to the browser function, verify that the mechanism is feasible.
The following is the actual test process,
(1) Perl version number of CGI
#!c:/perl64/bin/perl.exeuse warnings;use strict;binmode stdout;print "content-type:image/bmp\n\n"; open FILE, ' < ', ' C:\test.bmp ' or die ' Can ' t open file, while (my $buf = <FILE>) { print $buf;} Close (FILE);
After testing. Able to output the correct image.
(2) PHP version number of CGI
<?Php$filename= "C:/test.bmp", $size =getimagesize ($filename), $fp =fopen ($filename, "R"), #echo $size [' MIME '];if ($size && $fp) {header ("content-type:image/bmp\n\n"); Fpassthru ($fp); exit;}? >
After testing. can also output the correct image.
Results Analysis:
Through the above two tests, it is sufficient to demonstrate that wamp+cgi/fastcgi environment is not a problem. It is therefore possible to conclude that the problem is in CGI scripts written in the C language today. Because CGI scripts are console programs on the server side. Can again command line debugging directly, but we use Dicomimage's writebmp function to output the converted BMP image to the stdout, the actual debugging will output a bunch of garbled, because the stdout default is ASCII format. So the idea of debugging CGI scripts on the command line won't work. So decided to start at the bottom, using the RawCap.exe tool. Crawl the packet between the browser and the server-side CGI program. Identify where the problem occurs by analyzing the packet expectations.
1) Rawcap+wireshark Local Grab pack + analysis
Rawcap's operation was introduced in the earlier blog post, and there is no specific introduction here. Select the [2] interface after entering RawCap.exe on the command line. That is, the local loop 127.0.0.1 the packet. You can start crawling local loop packets. The same as in front of the blog post test CGI method, respectively, the output error written in C programming CGI program and the output of PHP written in the correct CGI program, the data packets fetched are WRONGIMAGE.PCAP and Rightimage.pcap respectively. Want to end crawl can input CTRL + C.
watermark/2/text/ahr0cdovl2jsb2cuy3nkbi5uzxqvennzdxjlcwg=/font/5a6l5l2t/fontsize/400/fill/i0jbqkfcma==/ Dissolve/70/gravity/center ">
After the crawl is complete, open Wrongimage.pcap and Rightimage.pcap in Wireshark. In this case, the statistical analysis tool in Wireshark is used directly because it concerns only the packet problem of the image transmission. For details such as the following, click "Statistic" in the menu bar, select Session--conversations, open the session form:
Then click the TCP protocol. Select a session with a large amount of data. Click Follow Stream below the form. The ability to open CGI scripts to transmit images to the service side of the real data stream.
watermark/2/text/ahr0cdovl2jsb2cuy3nkbi5uzxqvennzdxjlcwg=/font/5a6l5l2t/fontsize/400/fill/i0jbqkfcma==/ Dissolve/70/gravity/center ">
At the same time, use follow stream to track the flow of data in Wrongimage.pcap and Rightimage.pcap, as follows:
From this, we can see the real image data transmission stream, control the left (right image) and right (error image), can see two data streams indicate that they are BMP files, with 0x42 4D type marker.
According to the BMP file structure, then the color table. As seen in the large red rectangle box. But careful observation can see the error in the image of the 0a 0a 0a color table entries into the 0d 0a0d 0a 0d the 0a xx. By searching for the wrong data stream, it is found that the 0a in the original data stream is replaced by 0d 0a.
It is therefore concluded that this should be the cause of the image transmission failure.
To be very good at understanding the cause of the above error. Here are some additional basics that can be found in the post-blog web site.
2) Knowledge point supplement:(1) Text files VS binary files
Known. The computer is very two and only knows 0 and 1. No matter what the content is stored in the computer in 0 and 1, so why is it differentiated between text files and binaries? That's how I understand it. Although the bottom of the computer is stored in binary format, we are able to customize different interpretation standards. the same 0 and 1 sequences. interpreted in different ways. The meaning of the expression is different . In fact, the use of different standards to interpret the same sequence of phenomena in the computer field is not common. In a 32-bit machine, the same four-byte 01 sequence. May represent an unsigned integer or a signed integer (in the C + + language) or an IP address (in socket programming). It may also indicate that the label or delimiter (the label of the object in the DICOM protocol is in the four-byte format, as 0x0002 0010 represents the Transfersyntax UID). The colorful and changeable information world originates from different interpretation standards or interpretation rules. So learn the standards and understand the actual application scenarios.
Text files and binaries can be understood as 01 sequences that apply different standard stores, and text files mean that all information is stored in ASCII format. Each byte corresponds to an ASCII character--ascii is readable by people (and of course, the text that we can recognize is also obtained through multiple transformations within the computer.) It can be simply understood that for different 01 sequences, the computer draws the corresponding graphics to the screen--the generation of the graph can be easily understood as a plurality of neighboring crystals, and the binary file refers to storing the actual 01 sequence intact, without any processing (which is a way of interpreting). So the distinction between a text file and a binary file is a declaration, a declaration that tells the 01 sequence to be interpreted. To make an inappropriate analogy, the 01 sequence is like a telegram sent by an enemy, while a "text file" and a "binary file" represent two password, the same telegram with a different password translation. The result and meaning are naturally different (of course, there is usually a failure to provide us with effective information).
(2) CRLF
In programming languages, text files and binaries represent different ways of doing things, or simply can be understood as using different functions. Through the above explanation, it can be felt that different functions within the function are according to different standards (text file standards and binary file standards) to operate the 01 sequence, such as reading, writing and so on.
--Sometimes it's not necessary to dwell on the result of a function, just remember that this is what the standard behind the function is. As for the formulation of standards is not necessary to delve into, in short, a wave of cattle-man set.
The error two bytes above--0x0d 0x0a--is a very special two bytes in the computer, they represent a carriage return (cr=carriage return) and a newline (lf=line Feed).
Different systems have different interpretations of CRNL. The first UNIX system used only a newline (that is, \ n) to represent another row of data, and the Windows system uses carriage return + newline to represent it, while the MAC system uses only a carriage return . That is \ r.
When a file is read from disk to memory (program data area or buffer), in the text and binary mode, the contents of the memory are not the same, which is the substantive difference between the two open methods.
due to the different CRLF. Under Windows, it will do a processing. When you write a file, the newline character is converted to a carriage return + newline character exists on the disk file, and it is reversed when the file on the disk is read. is to convert a sequential carriage return + newline character in a file into a newline character . therefore, when reading a disk file, the text read to the file content is very likely to be shorter than the binary file, because the text read to the carriage return and newline two characters into a character, equivalent to truncate the file. But why is it possible? Since there is a possibility that there is no attached 0x0d,0x0a in this article two bytes (0x0a is the ASCII code for CR carriage return.) 0X0D is the ASCII code of the newline character cl, there is no "truncated" operation, so the content read is the same. In detail, the file file (written in text) is best read in text mode. Binary file (written in binary mode). It is best to read in binary mode.
(3) stdin, stdout
From (2) The knowledge point can roughly infer that the Windows system is writing to the stdout BMP data stream. The 0x0a were replaced by the 0x0d 0x0a, and he felt it changed. so why would 0x0a be converted to 0x0d 0x0a when writing to the STDOUT data stream? Is there a way to not convert? here is a simple introduction to the standard input and output stream in C. We all know that stdin is bound to the keyboard by default; StdOut is bound to the display by default. In fact stdin and stdout are the same type of file* that we often use to manipulate files. It is simple to think that the program interacts with the keyboard and display information in a buffer. In particular, in the CGI architecture, stdin and STDOUT are responsible for interacting with the browser and the server.
Since stdin and stdout are no different from ordinary file*, can we limit the system to convert 0xa to 0x0d 0x0a, based on our understanding of text format and binary format? Because the display defaults to the character type output, debugging is not convenient. We use a file file* to replace the stdout, and then use different writing methods to verify the conjecture we just made.
The test input file (that is, the data we first read into memory) is a BMP image that is converted using the Dcm2pnm.exe tool. We chose the "RB" binary mode when reading the file in order to limit the conversion of Windows system to CRLF. Test code such as the following:
As you can see, the binary method is written to get the correct image. The text format is written with the error results we encountered earlier.
It is therefore possible to demonstrate that the text format is dicomimage in the process of writing data to stdout. The stdout should be written in binary mode, presumably with the correct results.
3) Try to change the C language version number of the CGI program:
Now that the root of the problem has been found. Then we will change the CGI program of C language again. The known stdout is the same as file*. Then direct use of common C language file manipulation functions. Output data to the STDOUT in binary mode. To verify our ideas.
Test code such as the following:
Dcmtk-save-test.cpp: Defines the entry point of the console application. #include "dcmtk/config/osconfig.h" #include "dcmtk/dcmdata/dctk.h" #include "dcmtk/dcmdata/dcpxitem.h" #include " Dcmtk/dcmjpeg/djdecode.h "#include" dcmtk/dcmjpeg/djencode.h "#include" dcmtk/dcmjpeg/djcodece.h "#include" dcmtk/ Dcmjpeg/djrplol.h "#include" dcmtk/dcmimgle/diutils.h "#include" dcmtk/dcmimgle/dcmimage.h "#include <stdio.h> #include <iostream> #include <iomanip> #include <bitset> #include <windows.h>using std::cout; Using std::bitset;using std::hex;void print2web (char* msg) {printf ("content-type:text/html\n\n");p rintf ("<HTML >\n ");p rintf (" After many of the above attempts. There is still a problem finding the data. As a result, the file manipulation function of the C language may have a special operation on StdOut writes, which cannot be written in binary format. The problem is still unresolved in the C language environment. Imagine a friend who knows why. Please also advise . Perhaps I will continue to analyze, I hope to find out the reasons as soon as possible.
To be Continued ...
References :
[1]http://blog.csdn.net/silyvin/article/details/7275037
[2]http://blog.csdn.net/lanbing510/article/details/8183343
[3]http://www.jb51.net/article/31458.htm
[4]http://blog.csdn.net/babygjx/article/details/5832235
Perhaps a column about the blog:
Build Wmlserver with DCMTK
Direct operation of DICOM data with Oracle
Application of the asynchronous programming pattern of C # in fo-dicom
Actual test of VMware three network connection modes
[email Protected]
Date: 2014-10-27
DICOM Medical Image processing: A preliminary talk on WEB PACs two, image transmission