Installation
Browser (WebGL)
Prerequisites
Project Setup
Install
@3cr/sdk-browser
packagenpm install @3cr/sdk-browser
yarn add @3cr/sdk-browser
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);
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>
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);
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);
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-ios
Example: @3cr/sdk-ios-example
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.
Adding Cocoapods to iOS project
Once you have completed that and have loaded in your new Pod<> Workspace, return here!
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
Install Dependency
Update the dependency that the pod is using
pod install --repo-update
Import package
We need to read from the Sdk3criOS space to import our Viewer contracts.
import Sdk3criOS
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) }
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) } }
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-android
Example: @3cr/sdk-android-example
Prerequisites
- Gradle Groovy or Kotlin DSL for Gradle
- Android Studio
Project Setup
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' } } }
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' }
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()); } }
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" ) ); // ...