comparison Framework/Jpeg2000Reader.cpp @ 217:20bc074ec19a

Viewer can display DICOM pyramids whose tile sizes vary across levels
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 12 Jan 2021 14:24:18 +0100
parents 1e864138f0da
children 4eefa34657f0
comparison
equal deleted inserted replaced
216:c35a3a0627b9 217:20bc074ec19a
23 #include "Jpeg2000Reader.h" 23 #include "Jpeg2000Reader.h"
24 24
25 #include "ImageToolbox.h" 25 #include "ImageToolbox.h"
26 26
27 #include <Compatibility.h> // For std::unique_ptr 27 #include <Compatibility.h> // For std::unique_ptr
28 #include <Images/ImageProcessing.h>
28 #include <OrthancException.h> 29 #include <OrthancException.h>
29 #include <SystemToolbox.h> 30 #include <SystemToolbox.h>
30 31
31 #include <cassert> 32 #include <cassert>
32 #include <string.h> 33 #include <string.h>
38 # define OPJ_CODEC_J2K CODEC_J2K 39 # define OPJ_CODEC_J2K CODEC_J2K
39 # define OPJ_CODEC_JP2 CODEC_JP2 40 # define OPJ_CODEC_JP2 CODEC_JP2
40 typedef opj_dinfo_t opj_codec_t; 41 typedef opj_dinfo_t opj_codec_t;
41 typedef opj_cio_t opj_stream_t; 42 typedef opj_cio_t opj_stream_t;
42 #elif ORTHANC_OPENJPEG_MAJOR_VERSION == 2 43 #elif ORTHANC_OPENJPEG_MAJOR_VERSION == 2
43 #else 44 // OK, no need for compatibility macros
44 #error Unsupported version of OpenJpeg 45 #else
46 # error Unsupported version of OpenJpeg
45 #endif 47 #endif
46 48
47 49
48 namespace OrthancWSI 50 namespace OrthancWSI
49 { 51 {
293 295
294 class OpenJpegImage 296 class OpenJpegImage
295 { 297 {
296 private: 298 private:
297 opj_image_t* image_; 299 opj_image_t* image_;
298 300
301 Orthanc::ImageAccessor* ExtractChannel(unsigned int channel)
302 {
303 const unsigned int width = image_->comps[channel].w;
304 const unsigned int height = image_->comps[channel].h;
305
306 std::unique_ptr<Orthanc::ImageAccessor> target(
307 new Orthanc::Image(Orthanc::PixelFormat_Grayscale8, width, height, false));
308
309 const int32_t* q = image_->comps[channel].data;
310 assert(q != NULL);
311
312 for (unsigned int y = 0; y < height; y++)
313 {
314 uint8_t *p = reinterpret_cast<uint8_t*>(target->GetRow(y));
315
316 for (unsigned int x = 0; x < width; x++, p++, q++)
317 {
318 *p = *q;
319 }
320 }
321
322 return target.release();
323 }
324
299 void CopyChannel(Orthanc::ImageAccessor& target, 325 void CopyChannel(Orthanc::ImageAccessor& target,
300 unsigned int channel, 326 unsigned int channel,
301 unsigned int targetIncrement) 327 unsigned int targetIncrement)
302 { 328 {
303 int32_t* q = image_->comps[channel].data;
304 assert(q != NULL);
305
306 const unsigned int width = target.GetWidth(); 329 const unsigned int width = target.GetWidth();
307 const unsigned int height = target.GetHeight(); 330 const unsigned int height = target.GetHeight();
308 331
309 for (unsigned int y = 0; y < height; y++) 332 if (0 && // TODO
310 { 333 width == image_->comps[channel].w &&
311 uint8_t *p = reinterpret_cast<uint8_t*>(target.GetRow(y)) + channel; 334 height == image_->comps[channel].h)
312 335 {
313 for (unsigned int x = 0; x < width; x++, p += targetIncrement) 336 const int32_t* q = image_->comps[channel].data;
314 { 337 assert(q != NULL);
315 *p = *q; 338
316 q++; 339 for (unsigned int y = 0; y < height; y++)
317 } 340 {
318 } 341 uint8_t *p = reinterpret_cast<uint8_t*>(target.GetRow(y)) + channel;
342
343 for (unsigned int x = 0; x < width; x++, p += targetIncrement)
344 {
345 *p = *q;
346 q++;
347 }
348 }
349 }
350 else
351 {
352 // This component is subsampled
353 std::unique_ptr<Orthanc::ImageAccessor> source(ExtractChannel(channel));
354 Orthanc::Image resized(Orthanc::PixelFormat_Grayscale8, width, height, false);
355 Orthanc::ImageProcessing::Resize(resized, *source);
356
357 assert(resized.GetWidth() == target.GetWidth() &&
358 resized.GetHeight() == target.GetHeight() &&
359 resized.GetFormat() == Orthanc::PixelFormat_Grayscale8 &&
360 source->GetFormat() == Orthanc::PixelFormat_Grayscale8);
361
362 for (unsigned int y = 0; y < height; y++)
363 {
364 const uint8_t *q = reinterpret_cast<const uint8_t*>(resized.GetConstRow(y));
365 uint8_t *p = reinterpret_cast<uint8_t*>(target.GetRow(y)) + channel;
366
367 for (unsigned int x = 0; x < width; x++, p += targetIncrement)
368 {
369 *p = *q;
370 q++;
371 }
372 }
373 }
319 } 374 }
320 375
321 public: 376 public:
322 OpenJpegImage(OpenJpegDecoder& decoder, 377 OpenJpegImage(OpenJpegDecoder& decoder,
323 OpenJpegInput& input) : 378 OpenJpegInput& input) :
373 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); 428 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
374 } 429 }
375 430
376 for (unsigned int c = 0; c < static_cast<unsigned int>(image_->numcomps); c++) 431 for (unsigned int c = 0; c < static_cast<unsigned int>(image_->numcomps); c++)
377 { 432 {
378 if (image_->comps[c].dx != 1 || 433 if (image_->comps[c].x0 != 0 ||
379 image_->comps[c].dy != 1 ||
380 image_->comps[c].x0 != 0 ||
381 image_->comps[c].y0 != 0 || 434 image_->comps[c].y0 != 0 ||
382 image_->comps[c].w != image_->x1 || 435 image_->comps[c].dx * image_->comps[c].w != image_->x1 ||
383 image_->comps[c].h != image_->y1 || 436 image_->comps[c].dy * image_->comps[c].h != image_->y1 ||
384 image_->comps[c].prec != 8 || 437 image_->comps[c].prec != 8 ||
385 image_->comps[c].sgnd != 0) 438 image_->comps[c].sgnd != 0)
386 { 439 {
387 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); 440 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
388 } 441 }
427 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); 480 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
428 } 481 }
429 482
430 return image.release(); 483 return image.release();
431 } 484 }
432
433 }; 485 };
434 } 486 }
435 487
436 488
437 void Jpeg2000Reader::ReadFromMemory(const void* buffer, 489 void Jpeg2000Reader::ReadFromMemory(const void* buffer,
440 OpenJpegDecoder decoder(DetectFormatFromMemory(buffer, size)); 492 OpenJpegDecoder decoder(DetectFormatFromMemory(buffer, size));
441 OpenJpegInput input(decoder, buffer, size); 493 OpenJpegInput input(decoder, buffer, size);
442 OpenJpegImage image(decoder, input); 494 OpenJpegImage image(decoder, input);
443 495
444 image_.reset(image.ProvideImage()); 496 image_.reset(image.ProvideImage());
445 AssignReadOnly(image_->GetFormat(), 497 AssignWritable(image_->GetFormat(),
446 image_->GetWidth(), 498 image_->GetWidth(),
447 image_->GetHeight(), 499 image_->GetHeight(),
448 image_->GetPitch(), 500 image_->GetPitch(),
449 image_->GetConstBuffer()); 501 image_->GetBuffer());
450 } 502 }
451 503
452 504
453 void Jpeg2000Reader::ReadFromMemory(const std::string& buffer) 505 void Jpeg2000Reader::ReadFromMemory(const std::string& buffer)
454 { 506 {