changeset 100:166a555becbf wasm

fix jpeg decoding in wasm
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 30 May 2017 22:22:04 +0200
parents efd9ef2b67f1
children af312ce4fe59
files Applications/Samples/SingleFrameApplication.h Framework/Layers/OrthancFrameLayerSource.cpp Framework/Layers/OrthancFrameLayerSource.h Framework/Toolbox/OrthancSlicesLoader.cpp
diffstat 4 files changed, 59 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/Applications/Samples/SingleFrameApplication.h	Tue May 30 21:08:31 2017 +0200
+++ b/Applications/Samples/SingleFrameApplication.h	Tue May 30 22:22:04 2017 +0200
@@ -155,9 +155,6 @@
           
           Vector x; GeometryToolbox::AssignVector(x, cos(a), sin(a), 0);
           Vector y; GeometryToolbox::AssignVector(y, -sin(a), cos(a), 0);
-          GeometryToolbox::Print(source_->GetSlice(slice_).GetGeometry().GetOrigin());
-          GeometryToolbox::Print(x);
-          GeometryToolbox::Print(y);
           SliceGeometry s(source_->GetSlice(slice_).GetGeometry().GetOrigin(), x, y);
           widget_->SetSlice(s);
 #endif
@@ -247,6 +244,7 @@
 #if 1
         std::auto_ptr<OrthancFrameLayerSource> layer
           (new OrthancFrameLayerSource(context.GetWebService()));
+        //layer->SetImageQuality(SliceImageQuality_Jpeg50);
         layer->LoadInstance(instance, frame);
         //layer->LoadSeries("6f1b492a-e181e200-44e51840-ef8db55e-af529ab6");
         layer->Register(*this);
@@ -269,6 +267,7 @@
         ct.reset(new OrthancFrameLayerSource(context.GetWebService()));
         //ct->LoadInstance("c804a1a2-142545c9-33b32fe2-3df4cec0-a2bea6d6", 0);
         //ct->LoadInstance("4bd4304f-47478948-71b24af2-51f4f1bc-275b6c1b", 0);  // BAD SLICE
+        ct->SetImageQuality(SliceImageQuality_Jpeg50);
         ct->LoadSeries("dd069910-4f090474-7d2bba07-e5c10783-f9e4fb1d");
 
         ct->Register(*this);
--- a/Framework/Layers/OrthancFrameLayerSource.cpp	Tue May 30 21:08:31 2017 +0200
+++ b/Framework/Layers/OrthancFrameLayerSource.cpp	Tue May 30 22:22:04 2017 +0200
@@ -68,7 +68,8 @@
 
 
   OrthancFrameLayerSource::OrthancFrameLayerSource(IWebService& orthanc) :
-    loader_(*this, orthanc)
+    loader_(*this, orthanc),
+    quality_(SliceImageQuality_Full)
   {
   }
 
@@ -123,8 +124,7 @@
     {
       if (loader_.LookupSlice(index, viewportSlice))
       {
-        loader_.ScheduleLoadSliceImage(index, SliceImageQuality_Full);
-        //loader_.ScheduleLoadSliceImage(index, SliceImageQuality_Jpeg50);
+        loader_.ScheduleLoadSliceImage(index, quality_);
       }
       else
       {
--- a/Framework/Layers/OrthancFrameLayerSource.h	Tue May 30 21:08:31 2017 +0200
+++ b/Framework/Layers/OrthancFrameLayerSource.h	Tue May 30 22:22:04 2017 +0200
@@ -32,7 +32,8 @@
     private OrthancSlicesLoader::ICallback
   {
   private:
-    OrthancSlicesLoader     loader_;
+    OrthancSlicesLoader  loader_;
+    SliceImageQuality    quality_;
 
     virtual void NotifyGeometryReady(const OrthancSlicesLoader& loader);
 
@@ -57,6 +58,11 @@
 
     void LoadSeries(const std::string& seriesId);
 
+    void SetImageQuality(SliceImageQuality quality)
+    {
+      quality_ = quality;
+    }
+
     virtual size_t GetSliceCount() const
     {
       return loader_.GetSliceCount();
--- a/Framework/Toolbox/OrthancSlicesLoader.cpp	Tue May 30 21:08:31 2017 +0200
+++ b/Framework/Toolbox/OrthancSlicesLoader.cpp	Tue May 30 22:22:04 2017 +0200
@@ -35,6 +35,36 @@
 
 #include <boost/lexical_cast.hpp>
 
+
+
+/**
+ * TODO This is a SLOW implementation of base64 decoding, because
+ * "Orthanc::Toolbox::DecodeBase64()" does not work properly with
+ * WASM. UNDERSTAND WHY.
+ * https://stackoverflow.com/a/34571089/881731
+ **/
+static std::string base64_decode(const std::string &in)
+{
+  std::string out;
+
+  std::vector<int> T(256,-1);
+  for (int i=0; i<64; i++) T["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[i]] = i; 
+
+  int val=0, valb=-8;
+  for (unsigned char c : in) {
+    if (T[c] == -1) break;
+    val = (val<<6) + T[c];
+    valb += 6;
+    if (valb>=0) {
+      out.push_back(char((val>>valb)&0xFF));
+      valb-=8;
+    }
+  }
+  return out;
+}
+
+
+
 namespace OrthancStone
 {
   class OrthancSlicesLoader::Operation : public Orthanc::IDynamicObject
@@ -348,9 +378,9 @@
     }
 
     NotifySliceImageSuccess(operation, image);
-  }
-    
-    
+  } 
+
+  
   void OrthancSlicesLoader::ParseSliceImageJpeg(const Operation& operation,
                                                 const void* answer,
                                                 size_t size)
@@ -394,20 +424,23 @@
       }
     }
 
-    std::string jpeg;
-    Orthanc::Toolbox::DecodeBase64(jpeg, info["PixelData"].asString());
-
     std::auto_ptr<Orthanc::ImageAccessor> reader;
 
-    try
     {
-      reader.reset(new Orthanc::JpegReader);
-      dynamic_cast<Orthanc::JpegReader&>(*reader).ReadFromMemory(jpeg);
-    }
-    catch (Orthanc::OrthancException&)
-    {
-      NotifySliceImageError(operation);
-      return;
+      std::string jpeg;
+      //Orthanc::Toolbox::DecodeBase64(jpeg, info["PixelData"].asString());
+      jpeg = base64_decode(info["PixelData"].asString());
+
+      try
+      {
+        reader.reset(new Orthanc::JpegReader);
+        dynamic_cast<Orthanc::JpegReader&>(*reader).ReadFromMemory(jpeg);
+      }
+      catch (Orthanc::OrthancException&)
+      {
+        NotifySliceImageError(operation);
+        return;
+      }
     }
 
     Orthanc::PixelFormat expectedFormat =