comparison OrthancServer/Internals/DicomImageDecoder.cpp @ 863:3c0d0836f704 jpeg

refactoring
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 10 Jun 2014 17:20:33 +0200
parents a546b05a43da
children 87791ebc1f50
comparison
equal deleted inserted replaced
862:5a125d587810 863:3c0d0836f704
40 (cf. function "DecodePsmctRle1()"): 40 (cf. function "DecodePsmctRle1()"):
41 41
42 Program: GDCM (Grassroots DICOM). A DICOM library 42 Program: GDCM (Grassroots DICOM). A DICOM library
43 Module: http://gdcm.sourceforge.net/Copyright.html 43 Module: http://gdcm.sourceforge.net/Copyright.html
44 44
45 Copyright (c) 2006-2011 Mathieu Malaterre 45 Copyright (c) 2006-2011 Mathieu Malaterre
46 Copyright (c) 1993-2005 CREATIS 46 Copyright (c) 1993-2005 CREATIS
47 (CREATIS = Centre de Recherche et d'Applications en Traitement de l'Image) 47 (CREATIS = Centre de Recherche et d'Applications en Traitement de l'Image)
48 All rights reserved. 48 All rights reserved.
49 49
50 Redistribution and use in source and binary forms, with or without 50 Redistribution and use in source and binary forms, with or without
51 modification, are permitted provided that the following conditions are met: 51 modification, are permitted provided that the following conditions are met:
52 52
53 * Redistributions of source code must retain the above copyright notice, 53 * Redistributions of source code must retain the above copyright notice,
54 this list of conditions and the following disclaimer. 54 this list of conditions and the following disclaimer.
55 55
56 * Redistributions in binary form must reproduce the above copyright notice, 56 * Redistributions in binary form must reproduce the above copyright notice,
57 this list of conditions and the following disclaimer in the documentation 57 this list of conditions and the following disclaimer in the documentation
58 and/or other materials provided with the distribution. 58 and/or other materials provided with the distribution.
59 59
60 * Neither name of Mathieu Malaterre, or CREATIS, nor the names of any 60 * Neither name of Mathieu Malaterre, or CREATIS, nor the names of any
61 contributors (CNRS, INSERM, UCB, Universite Lyon I), may be used to 61 contributors (CNRS, INSERM, UCB, Universite Lyon I), may be used to
62 endorse or promote products derived from this software without specific 62 endorse or promote products derived from this software without specific
63 prior written permission. 63 prior written permission.
64 64
65 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 65 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
66 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 66 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
67 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 67 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
68 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR 68 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
69 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 69 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
70 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 70 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
71 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 71 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
72 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 72 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
73 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 73 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
74 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 74 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
75 75
76 =========================================================================*/ 76 =========================================================================*/
77 77
78 78
79 79
80 #include "../../Core/OrthancException.h" 80 #include "../../Core/OrthancException.h"
81 #include "../../Core/ImageFormats/ImageProcessing.h" 81 #include "../../Core/ImageFormats/ImageProcessing.h"
424 ImageAccessor targetAccessor(target.GetAccessor()); 424 ImageAccessor targetAccessor(target.GetAccessor());
425 const DicomImageInformation& info = source.GetAccessor().GetInformation(); 425 const DicomImageInformation& info = source.GetAccessor().GetInformation();
426 426
427 bool fastVersionSuccess = false; 427 bool fastVersionSuccess = false;
428 PixelFormat sourceFormat; 428 PixelFormat sourceFormat;
429 if (info.ExtractPixelFormat(sourceFormat)) 429 if (!info.IsPlanar() &&
430 info.ExtractPixelFormat(sourceFormat))
430 { 431 {
431 try 432 try
432 { 433 {
433 ImageAccessor sourceImage; 434 ImageAccessor sourceImage;
434 sourceImage.AssignReadOnly(sourceFormat, 435 sourceImage.AssignReadOnly(sourceFormat,
458 switch (target.GetFormat()) 459 switch (target.GetFormat())
459 { 460 {
460 case PixelFormat_RGB24: 461 case PixelFormat_RGB24:
461 case PixelFormat_RGBA32: 462 case PixelFormat_RGBA32:
462 case PixelFormat_Grayscale8: 463 case PixelFormat_Grayscale8:
463 CopyPixels<uint8_t>(targetAccessor, source.GetAccessor()); 464 CopyPixels<uint8_t>(targetAccessor, source.GetAccessor());
464 break; 465 break;
465 466
466 case PixelFormat_Grayscale16: 467 case PixelFormat_Grayscale16:
467 CopyPixels<uint16_t>(targetAccessor, source.GetAccessor()); 468 CopyPixels<uint16_t>(targetAccessor, source.GetAccessor());
468 break; 469 break;
469 470
470 case PixelFormat_SignedGrayscale16: 471 case PixelFormat_SignedGrayscale16:
471 CopyPixels<int16_t>(targetAccessor, source.GetAccessor()); 472 CopyPixels<int16_t>(targetAccessor, source.GetAccessor());
472 break; 473 break;
473 474
474 default: 475 default:
475 throw OrthancException(ErrorCode_InternalError); 476 throw OrthancException(ErrorCode_InternalError);
476 } 477 }
477 } 478 }
478 } 479 }
479 480
480 481
582 583
583 return false; 584 return false;
584 } 585 }
585 586
586 587
587 bool DicomImageDecoder::Decode(ImageBuffer& target, 588 bool DicomImageDecoder::DecodeAndTruncate(ImageBuffer& target,
588 DcmDataset& dataset, 589 DcmDataset& dataset,
589 unsigned int frame, 590 unsigned int frame,
590 PixelFormat format, 591 PixelFormat format)
591 Mode mode) 592 {
592 { 593 // TODO Special case for uncompressed images
593 // TODO OPTIMIZE THIS (avoid unnecessary image copies) !!! 594
594 595 ImageBuffer source;
595 ImageBuffer tmp; 596 if (!Decode(source, dataset, frame))
596 if (!Decode(tmp, dataset, frame))
597 { 597 {
598 return false; 598 return false;
599 } 599 }
600 600
601 if (!IsUncompressedImage(dataset) && !IsJpegLossless(dataset)) 601 if (source.GetFormat() == format)
602 { 602 {
603 printf("ICI\n"); 603 // No conversion is required, return the temporary image
604 PngWriter w; 604 target.AcquireOwnership(source);
605 ImageAccessor b(tmp.GetConstAccessor()); 605 return true;
606 w.WriteToFile("toto.png", b);
607 } 606 }
608 607
609 target.SetFormat(format); 608 target.SetFormat(format);
610 target.SetWidth(tmp.GetWidth()); 609 target.SetWidth(source.GetWidth());
611 target.SetHeight(tmp.GetHeight()); 610 target.SetHeight(source.GetHeight());
612 611
613 switch (mode) 612 ImageAccessor targetAccessor(target.GetAccessor());
614 { 613 ImageAccessor sourceAccessor(source.GetAccessor());
615 case Mode_Truncate: 614 ImageProcessing::Convert(targetAccessor, sourceAccessor);
616 { 615
617 if (!IsUncompressedImage(dataset) && !IsJpegLossless(dataset)) 616 return true;
617 }
618
619
620 bool DicomImageDecoder::DecodePreview(ImageBuffer& target,
621 DcmDataset& dataset,
622 unsigned int frame)
623 {
624 // TODO Special case for uncompressed images
625
626 ImageBuffer source;
627 if (!Decode(source, dataset, frame))
628 {
629 return false;
630 }
631
632 switch (source.GetFormat())
633 {
634 case PixelFormat_RGB24:
635 {
636 // Directly return color images (RGB)
637 target.AcquireOwnership(source);
638 return true;
639 }
640
641 case PixelFormat_Grayscale8:
642 case PixelFormat_Grayscale16:
643 case PixelFormat_SignedGrayscale16:
644 {
645 // Grayscale image: Stretch its dynamics to the [0,255] range
646 target.SetFormat(PixelFormat_Grayscale8);
647 target.SetWidth(source.GetWidth());
648 target.SetHeight(source.GetHeight());
649
650 ImageAccessor targetAccessor(target.GetAccessor());
651 ImageAccessor sourceAccessor(source.GetAccessor());
652
653 int64_t a, b;
654 ImageProcessing::GetMinMaxValue(a, b, sourceAccessor);
655
656 if (a == b)
618 { 657 {
619 printf("%d => %d\n", tmp.GetFormat(), target.GetFormat()); 658 ImageProcessing::Set(targetAccessor, 0);
620 } 659 }
621 ImageAccessor a(target.GetAccessor()); 660 else
622 ImageAccessor b(tmp.GetConstAccessor()); 661 {
623 ImageProcessing::Convert(a, b); 662 ImageProcessing::ShiftScale(sourceAccessor, -a, 255.0f / static_cast<float>(b - a));
663
664 if (source.GetFormat() == PixelFormat_Grayscale8)
665 {
666 target.AcquireOwnership(source);
667 }
668 else
669 {
670 ImageProcessing::Convert(targetAccessor, sourceAccessor);
671 }
672 }
673
624 return true; 674 return true;
625 } 675 }
626 676
627 default: 677 default:
628 throw OrthancException(ErrorCode_NotImplemented); 678 throw OrthancException(ErrorCode_NotImplemented);
629 } 679 }
630 680 }
631 return false;
632 }
633
634
635
636 } 681 }