Mercurial > hg > orthanc
comparison OrthancServer/FromDcmtkBridge.cpp @ 846:715ab7674993 jpeg
refactoring
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 05 Jun 2014 16:23:03 +0200 |
parents | 84513f2ee1f3 |
children | 839be3022203 |
comparison
equal
deleted
inserted
replaced
845:48016722c770 | 846:715ab7674993 |
---|---|
29 * along with this program. If not, see <http://www.gnu.org/licenses/>. | 29 * along with this program. If not, see <http://www.gnu.org/licenses/>. |
30 **/ | 30 **/ |
31 | 31 |
32 | 32 |
33 | 33 |
34 /*========================================================================= | |
35 | |
36 This file is based on portions of the following project: | |
37 | |
38 Program: GDCM (Grassroots DICOM). A DICOM library | |
39 Module: http://gdcm.sourceforge.net/Copyright.html | |
40 | |
41 Copyright (c) 2006-2011 Mathieu Malaterre | |
42 Copyright (c) 1993-2005 CREATIS | |
43 (CREATIS = Centre de Recherche et d'Applications en Traitement de l'Image) | |
44 All rights reserved. | |
45 | |
46 Redistribution and use in source and binary forms, with or without | |
47 modification, are permitted provided that the following conditions are met: | |
48 | |
49 * Redistributions of source code must retain the above copyright notice, | |
50 this list of conditions and the following disclaimer. | |
51 | |
52 * Redistributions in binary form must reproduce the above copyright notice, | |
53 this list of conditions and the following disclaimer in the documentation | |
54 and/or other materials provided with the distribution. | |
55 | |
56 * Neither name of Mathieu Malaterre, or CREATIS, nor the names of any | |
57 contributors (CNRS, INSERM, UCB, Universite Lyon I), may be used to | |
58 endorse or promote products derived from this software without specific | |
59 prior written permission. | |
60 | |
61 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' | |
62 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
63 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
64 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR | |
65 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
66 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
67 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
68 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
69 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
70 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
71 | |
72 =========================================================================*/ | |
73 | |
74 | |
75 #include "PrecompiledHeadersServer.h" | 34 #include "PrecompiledHeadersServer.h" |
76 | 35 |
77 #ifndef NOMINMAX | 36 #ifndef NOMINMAX |
78 #define NOMINMAX | 37 #define NOMINMAX |
79 #endif | 38 #endif |
80 | 39 |
40 #include "Internals/DicomImageDecoder.h" | |
41 | |
81 #include "FromDcmtkBridge.h" | 42 #include "FromDcmtkBridge.h" |
82 | |
83 #include "ToDcmtkBridge.h" | 43 #include "ToDcmtkBridge.h" |
84 #include "../Core/Toolbox.h" | 44 #include "../Core/Toolbox.h" |
85 #include "../Core/OrthancException.h" | 45 #include "../Core/OrthancException.h" |
86 #include "../Core/ImageFormats/PngWriter.h" | 46 #include "../Core/ImageFormats/PngWriter.h" |
87 #include "../Core/Uuid.h" | 47 #include "../Core/Uuid.h" |
557 w.WriteToMemory(result, accessor.GetWidth(), accessor.GetHeight(), | 517 w.WriteToMemory(result, accessor.GetWidth(), accessor.GetHeight(), |
558 accessor.GetWidth() * sizeof(T), format, &image[0]); | 518 accessor.GetWidth() * sizeof(T), format, &image[0]); |
559 } | 519 } |
560 | 520 |
561 | 521 |
562 static bool DecodePsmctRle1(std::string& output, | |
563 DcmDataset& dataset) | |
564 { | |
565 static const DicomTag tagContent(0x07a1, 0x100a); | |
566 static const DicomTag tagCompressionType(0x07a1, 0x1011); | |
567 | |
568 DcmElement* e; | |
569 char* c; | |
570 | |
571 // Check whether the DICOM instance contains an image encoded with | |
572 // the PMSCT_RLE1 scheme. | |
573 if (!dataset.findAndGetElement(ToDcmtkBridge::Convert(tagCompressionType), e).good() || | |
574 e == NULL || | |
575 !e->isaString() || | |
576 !e->getString(c).good() || | |
577 c == NULL || | |
578 strcmp("PMSCT_RLE1", c)) | |
579 { | |
580 return false; | |
581 } | |
582 | |
583 // OK, this is a custom RLE encoding from Philips. Get the pixel | |
584 // data from the appropriate private DICOM tag. | |
585 Uint8* pixData = NULL; | |
586 if (!dataset.findAndGetElement(ToDcmtkBridge::Convert(tagContent), e).good() || | |
587 e == NULL || | |
588 e->getUint8Array(pixData) != EC_Normal) | |
589 { | |
590 return false; | |
591 } | |
592 | |
593 // The "unsigned" below IS VERY IMPORTANT | |
594 const uint8_t* inbuffer = reinterpret_cast<const uint8_t*>(pixData); | |
595 const size_t length = e->getLength(); | |
596 | |
597 /** | |
598 * The code below is an adaptation of a sample code for GDCM by | |
599 * Mathieu Malaterre (under a BSD license). | |
600 * http://gdcm.sourceforge.net/html/rle2img_8cxx-example.html | |
601 **/ | |
602 | |
603 // RLE pass | |
604 std::vector<uint8_t> temp; | |
605 temp.reserve(length); | |
606 for (size_t i = 0; i < length; i++) | |
607 { | |
608 if (inbuffer[i] == 0xa5) | |
609 { | |
610 temp.push_back(inbuffer[i+2]); | |
611 for (uint8_t repeat = inbuffer[i + 1]; repeat != 0; repeat--) | |
612 { | |
613 temp.push_back(inbuffer[i+2]); | |
614 } | |
615 i += 2; | |
616 } | |
617 else | |
618 { | |
619 temp.push_back(inbuffer[i]); | |
620 } | |
621 } | |
622 | |
623 // Delta encoding pass | |
624 uint16_t delta = 0; | |
625 output.clear(); | |
626 output.reserve(temp.size()); | |
627 for (size_t i = 0; i < temp.size(); i++) | |
628 { | |
629 uint16_t value; | |
630 | |
631 if (temp[i] == 0x5a) | |
632 { | |
633 uint16_t v1 = temp[i + 1]; | |
634 uint16_t v2 = temp[i + 2]; | |
635 value = (v2 << 8) + v1; | |
636 i += 2; | |
637 } | |
638 else | |
639 { | |
640 value = delta + (int8_t) temp[i]; | |
641 } | |
642 | |
643 output.push_back(value & 0xff); | |
644 output.push_back(value >> 8); | |
645 delta = value; | |
646 } | |
647 | |
648 if (output.size() % 2) | |
649 { | |
650 output.resize(output.size() - 1); | |
651 } | |
652 | |
653 return true; | |
654 } | |
655 | 522 |
656 | 523 |
657 void FromDcmtkBridge::ExtractPngImage(std::string& result, | 524 void FromDcmtkBridge::ExtractPngImage(std::string& result, |
658 DcmDataset& dataset, | 525 DcmDataset& dataset, |
659 unsigned int frame, | 526 unsigned int frame, |
677 { | 544 { |
678 accessor.reset(new DicomIntegerPixelAccessor(m, pixData, e->getLength())); | 545 accessor.reset(new DicomIntegerPixelAccessor(m, pixData, e->getLength())); |
679 accessor->SetCurrentFrame(frame); | 546 accessor->SetCurrentFrame(frame); |
680 } | 547 } |
681 } | 548 } |
682 else if (DecodePsmctRle1(privateContent, dataset)) | 549 else if (DicomImageDecoder::DecodePsmctRle1(privateContent, dataset)) |
683 { | 550 { |
684 LOG(INFO) << "The PMSCT_RLE1 decoding has succeeded"; | 551 LOG(INFO) << "The PMSCT_RLE1 decoding has succeeded"; |
685 Uint8* pixData = NULL; | 552 Uint8* pixData = NULL; |
686 if (privateContent.size() > 0) | 553 if (privateContent.size() > 0) |
687 pixData = reinterpret_cast<Uint8*>(&privateContent[0]); | 554 pixData = reinterpret_cast<Uint8*>(&privateContent[0]); |