Installation

Browser (WebGL)

Prerequisites

Project Setup

  1. Install @3cr/sdk-browser package

    npm install @3cr/sdk-browser
    
    yarn add @3cr/sdk-browser
    
  2. Register 3DICOM Core Renderer version

    WARNING

    You may soon be asked to provide an API key for your 3CR usage.

    Insert this loader script in your startup scripts on your site. This will allow you to directly interact with 3CR's instance.

    import { registerVersion } from '@3cr/sdk-browser';
    
    const VERSION_3CR: string = '1.0.0';
    
    await registerVersion(VERSION_3CR);
    
    import { registerVersion } from '@3cr/sdk-browser';
    
    const VERSION_3CR = '1.0.0';
    
    await registerVersion(VERSION_3CR);
    
  3. Create HTML Canvas

    Create a canvas element within your HTML Markup and assign it an id.

    You will have to ensure that the size (width & height) both match the inline css styling and the canvas styling

    <canvas
      id="renderer-canvas"
      width="1080"
      height="1920"
      tabindex="-1"
      style=" width: 1920px; height: 1080px; "
    >
    </canvas>
    
  4. Register response handler for 3DICOM Core Renderer Instance

    You will need to register a function that can accept the responses from the 3CR instance.

    import { registerOnPayloadHandler } from '@3cr/sdk-browser';
    import { FrontEndPayload } from '@3cr/sdk-browser/types/payload';
    
    function onPayload(json: FrontEndPayload) {
       console.log("Payload recieved from 3CR!", json)
    }
    
    await registerOnPayloadHandler(onPayload);
    
    import { registerOnPayloadHandler } from '@3cr/sdk-browser';
    
    function onPayload(json) {
       console.log("Payload recieved from 3CR!", json)
    }
    
    await registerOnPayloadHandler(onPayload);
    
  5. Attach the 3CR Instance to the HTML Canvas

    Get the HTML Element from the DOM Object and inject it into the instance.

    import { createInstance } from '@3cr/sdk-browser';
    const canvas: HTMLCanvasElement = document.querySelector('#renderer-canvas') as HTMLCanvasElement;
    
    await createInstance(canvas);
    
    import { createInstance } from '@3cr/sdk-browser';
    const canvas = document.querySelector('#renderer-canvas');
    
    await createInstance(canvas);
    
  6. Execute payload on Instance

    Get the HTML Element from the DOM Object and inject it into the instance.

    import { executePayload } from '@3cr/sdk-browser';
    import { FrontEndInterfaces, FileManagementActions } from '@3cr/sdk-browser/types/payload';
    
    await executePayload({
       Version: '1.0.0',
       Interface: FrontEndInterfaces.file_management,
       Action: FileManagementActions.fm_01,
       Message: JSON.stringify({
          Url: 'https://somethingtodownload.com/some.3vxl.compressed.encrypted',
          DecryptionKey: {
            Key: '<Encryption Key>',
            Iv: '<Encryption IV>'
          }
       }),
    });
    
    import { executePayload } from '@3cr/sdk-browser';
    
    await executePayload({
       Version: '1.0.0',
       Interface: 'file_management',
       Action: 'fm_01',
       Message: JSON.stringify({
          Url: 'https://somethingtodownload.com/some.3vxl.compressed.encrypted',
          DecryptionKey: {
            Key: '<Encryption Key>',
            Iv: '<Encryption IV>'
          }
       }),
    });
    

iOS (Swift)

Podspec Repo: @3cr/sdk-iosopen in new window

Example: @3cr/sdk-ios-exampleopen in new window

Prerequisites

  • Cocoapods
  • Swift/Objective-C iOS project

Project Setup

Note: this assumes you have Cocoapods already setup in your iOS project. If you do not, please follow this guide to get started.

Installing Cocoapodsopen in new window

Adding Cocoapods to iOS projectopen in new window

Once you have completed that and have loaded in your new Pod<> Workspace, return here!

  1. Add Pod to your dependency

    We host our releases of the 3Dicom Core Renderer on Bitbucket with use of a Podspec file and CocoaPods

    # Uncomment the next line to define a global platform for your project
    # platform :ios, '9.0'
    
    target 'Sdk3criOSExample' do
        # Add our repository as a source
        source 'https://bitbucket.org/medvr/3cr-sdk-ios.git'
        # Comment the next line if you don't want to use dynamic frameworks
        #   you will need to use dynamic frameworks for 3CR.
        use_frameworks!
    
        # Insert our pod line, be sure to check the version.
        pod 'Sdk3criOS', :git => 'https://bitbucket.org/medvr/3cr-sdk-ios.git', :tag =>'1.2.0'
    end
    
  2. Install Dependency

    Update the dependency that the pod is using

    pod install --repo-update
    
    
  3. Import package

    We need to read from the Sdk3criOS space to import our Viewer contracts.

    import Sdk3criOS
    
  4. Setup Payload Handler

    When 3CR fires an event to the front end (iOS) we need to handle it to update UI etc. In order to process these messages, we need to setup a Payload Handler callback.

    private func myCallbackFromTheViewer(_ payload: FrontEndPayload) {
        debugPrint("Test Payload:")
        debugPrint(payload)
        // ... you can add your processing here.
    }
    
    
    // Call this from anywhere in your app prior to launching the viewer
    func setupCallbackHandler() {
        ViewerSdk3CR.registerOnPayloadHandler(callback: myCallbackFromTheViewer)
    }
    
  5. Setup and Launch Viewer

    We can now launch the viewer into the app. Doing so will spawn an instance of 3CR and you can overlay buttons/UI elements to create your own views.

    // ...
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        var window = UIWindow.init(frame: UIScreen.main.bounds)
            
        ViewerSdk3CR.setup(window, launchOptions)
    
        return true
    }
    
    // Call this from anywhere in your app
    func runViewer() {
        // Note we run this async so the main thread is not blocked by 3CR loading in.
        DispatchQueue.main.async {
    
            ViewerSdk3CR.launch()
            
            // The viewer has now been loaded in, you can execute payload functions now. (see next step)
        }
    }
    
  6. Execute payload on Instance

    The viewer is now active within the instance, and we can issue commands (payloads) to control it.

    let samplePayloadMessage = "{" +
        "\"Url\":\"https://webgl-3dr.singular.health/test_scans/01440d4e-8b04-4b90-bb2c-698535ce16d6/CHEST.3vxl\"," +
        "\"DecryptionKey\":{" +
            "\"Iv\":\"XEloSh+OcO7TG77au6HjPw==\"," +
            "\"Key\":\"KUc722X1y4w42M+jCf9a3+6EGz66z7UMWK3m2aMqGxM=\"" +
        "}" +
    "}"
    
    // Call this from anywhere in your app
    // After the viewer has loaded
    func loadInSampleScan() {
    
        do {
            try ViewerSdk3CR.executePayload(payload:
                FrontEndPayload(
                    frontEndInterface: FrontEndInterfaces.fileManagement,
                    action: "fm_01",
                    message: self.samplePayloadMessage,
                    version: "1.0.0",
                    returnChannel: nil
                )
            )
        } catch {
            debugPrint(error)
        }
    }
    

Android (Java / Kotlin)

Repository: @3cr/sdk-androidopen in new window

Example: @3cr/sdk-android-exampleopen in new window

Prerequisites

  • Gradle Groovy or Kotlin DSL for Gradle
  • Android Studio

Project Setup

  1. Add Package Manager

    We host our releases of the 3Dicom Core Renderer on GitHub and use Jitpack to build the dependencies.

    // settings.gradle.kts
    
    dependencyResolutionManagement {
        repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
        repositories {
            mavenCentral()
            maven("https://jitpack.io")
        }
    }
    
    // settings.gradle
    
    dependencyResolutionManagement {
        repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
        repositories {
                mavenCentral()
                maven { url 'https://jitpack.io' }
        }
    }
    
  2. Install Dependency

    To make the Viewer visible to your Application, you will need to add the dependency to your module level gradle file. Please make sure you locate the latest version (check out the github repository)

    // build.gradle.kts
    
    dependencies {
        implementation("com.github.singularhealth:3cr-sdk-android:1.2.9")
    }
    
    
    // build.gradle
    
    dependencies {
       implementation 'com.github.singularhealth:3cr-sdk-android:1.2.9'
    }
    
    
  3. Setup 3CR Viewer Activity

    Create a new Java or Kotlin class that extends ViewerSdkActivity. This class will serve as the custom activity where you can implement your own UI and interact with the ViewerSdk. When you are ready to add your components to the FrameView, you can call addView from within your activity.

    package com.my.custom.viewer
    
    import android.app.ActivityManager
    import android.content.Context
    import android.os.Bundle
    import android.widget.Button
    import health.singular.viewer3cr.android.sdk.FrontEndInterfaces
    import health.singular.viewer3cr.android.sdk.FrontEndPayload
    import health.singular.viewer3cr.android.sdk.ViewerSdkActivity
    
    const val sampleScanPayload = "{" +
      "\"Url\":\"https://webgl-3dr.singular.health/test_scans/01440d4e-8b04-4b90-bb2c-698535ce16d6/CHEST.3vxl\"," +
      "\"DecryptionKey\":{" +
          "\"Iv\":\"XEloSh+OcO7TG77au6HjPw==\"," +
          "\"Key\":\"KUc722X1y4w42M+jCf9a3+6EGz66z7UMWK3m2aMqGxM=\"" +
      "}" +
    "}"
    
    class MyNewActivityWithThe3crViewer : ViewerSdkActivity() {
      override fun onCreate(savedInstanceState: Bundle?) {
          super.onCreate(savedInstanceState)
    
          printOpenGLVersion()
    
          val showMainButton = Button(this).apply {
              text = "LOAD SCAN"
              x = 10f
              y = 500f
    
              setOnClickListener {
                  loadSampleScan()
              }
          }
          addView(showMainButton)
      }
    
      private fun loadSampleScan() {
          // Call this function whenever you would like 3CR to perform an action
          // You will need to supply different arguments based on the documentation
          executePayload(
              FrontEndPayload(
                  FrontEndInterfaces.FILE_MANAGEMENT,
                  "fm_01",
                  sampleScanPayload,
                  "1.0.0",
              )
          )
      }
    
      // This function will be called every time 3CR emits a message to the Front End.
      // override it so you can process the results from 3CR.
      override fun onPayload(jsonPayload: FrontEndPayload?) {
          super.onPayload(jsonPayload)
    
          println(jsonPayload)
    
          // ... Do something with payload.
      }
    
      private fun printOpenGLVersion() {
          val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager;
          val configurationInfo = activityManager.deviceConfigurationInfo
          println("Device Supported OpenGL ES Version = " + configurationInfo.getGlEsVersion())
      }
    }
    
    
    
    
    package com.my.custom.viewer;
    
    import android.app.ActivityManager;
    import android.content.Context;
    import android.os.Bundle;
    import androidx.annotation.Nullable;
    import android.widget.Button;
    import health.singular.viewer3cr.android.sdk.FrontEndInterfaces;
    import health.singular.viewer3cr.android.sdk.FrontEndPayload;
    import health.singular.viewer3cr.android.sdk.ViewerSdkActivity;
    
    public class MyNewActivityWithThe3crViewer extends ViewerSdkActivity {
    
        private static final String SAMPLE_SCAN_PAYLOAD = "{" +
            "\"Url\":\"https://webgl-3dr.singular.health/test_scans/01440d4e-8b04-4b90-bb2c-698535ce16d6/CHEST.3vxl\"," +
            "\"DecryptionKey\":{" +
                "\"Iv\":\"XEloSh+OcO7TG77au6HjPw==\"," +
                "\"Key\":\"KUc722X1y4w42M+jCf9a3+6EGz66z7UMWK3m2aMqGxM=\"" +
            "}" +
        "}";
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
       
            printOpenGLVersion();
       
            Button showMainButton = new Button(this);
            showMainButton.setText("LOAD SCAN");
            showMainButton.setX(10f);
            showMainButton.setY(500f);
    
            showMainButton.setOnClickListener(view -> loadSampleScan());
    
            addView(showMainButton);
        }
    
        private void loadSampleScan() {
            executePayload(
                new FrontEndPayload(
                    FrontEndInterfaces.FILE_MANAGEMENT,
                    "fm_01",
                    SAMPLE_SCAN_PAYLOAD,
                    "1.0.0"
                )
            );
        }
    
        @Override
        public void onPayload(FrontEndPayload jsonPayload) {
            super.onPayload(jsonPayload);
       
            System.out.println(jsonPayload);
            // ... Do something with payload.
        }
    
        private void printOpenGLVersion() {
            ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
            ActivityManager.DeviceConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
            System.out.println("Device Supported OpenGL ES Version = " + configurationInfo.getGlEsVersion());
        }
    }
    
  4. Execute payload on Instance

    Inside your Activity you are able to call the executePayload function.

    // ...
    
    val someJsonStringPayload = "" // Fill this string in with a JSON representation of your payload.
    
    executePayload(
        FrontEndPayload(
            FrontEndInterfaces.FILE_MANAGEMENT,
            "fm_01",
            someJsonStringPayload,
            "1.0.0"
        )
    )
    
    // ...
    
    // ...
    
     val someJsonStringPayload = ""; // Fill this string in with a JSON representation of your payload.
     
     executePayload(
         new FrontEndPayload(
             FrontEndInterfaces.FILE_MANAGEMENT,
             "fm_01",
             someJsonStringPayload,
             "1.0.0"
         )
     );
     
     // ...
    
Last Updated:
Contributors: Elliott Cooper