SDcmWeb/webassembly/dcm_mod.cc
2025-10-12 00:17:30 +09:00

971 lines
27 KiB
C++

//
// Emscripten/SDL2/OpenGLES2 sample that demonstrates simple geometry and shaders, mouse and touch input, and window resizing
//
// Setup:
// Install emscripten: http://kripken.github.io/emscripten-site/docs/getting_started/downloads.html
//
// Build:
// emcc -std=c++11 hello_triangle.cpp events.cpp camera.cpp -s USE_SDL=2 -s FULL_ES2=1 -s WASM=0 -o hello_triangle.html
//
// Run:
// emrun hello_triangle.html
//
// Result:
// A colorful triangle. Left mouse pans, mouse wheel zooms in/out. Window is resizable.
//
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif
#include <SDL2/SDL.h>
#include <SDL2/SDL_opengles2.h>
//#include <SDL2/SDL_opengles2_gl2ext.h>
//#include <GLES3/gl3.h>
#include <dcmtk/ofstd/ofstring.h>
#include "dcmtk/config/osconfig.h"
#include "dcmtk/dcmdata/dcfilefo.h"
#include "dcmtk/dcmdata/dcdeftag.h"
#include "dcmtk/dcmdata/dcuid.h"
#include "dcmtk/dcmdata/dcmetinf.h"
#include "dcmtk/dcmdata/dcdict.h"
#include "dcmtk/dcmdata/dcdicent.h"
#include "dcmtk/dcmdata/dcxfer.h"
#include "dcmtk/dcmjpeg/djdecode.h" /* for JPEG decoders */
#include "dcmtk/dcmjpeg/djencode.h" /* for JPEG encoders */
#include "dcmtk/dcmjpls/djdecode.h" /* for JPEG-LS decoders */
#include "dcmtk/dcmjpls/djencode.h" /* for JPEG-LS encoders */
#include "dcmtk/dcmdata/dcrledrg.h" /* for RLE decoder */
#include "dcmtk/dcmdata/dcrleerg.h" /* for RLE encoder */
#include "dcmtk/dcmjpeg/dipijpeg.h" /* for dcmimage JPEG plugin */
#include "dcmtk/dcmjpeg/djrplol.h"
#include "dcmtk/dcmimage/diregist.h"
#include "dcmtk/dcmdata/dcpixseq.h"
#include "dcmtk/dcmjpeg/djcparam.h"
#include "dcmtk/dcmjpeg/djeijg8.h"
#include "dcmtk/dcmjpeg/djcodece.h"
#include "dcmtk/dcmdata/dcchrstr.h"
#include "dcmtk/ofstd/ofchrenc.h"
#include "dcmtk/dcmdata/dcvrui.h"
#include "dcmtk/dcmdata/dcvrsh.h"
#include "dcmtk/dcmdata/dcistrmb.h"
#include "events.h"
typedef void (*callback_UpdateDcmImage) ();
callback_UpdateDcmImage callback_UpdateDcmImageComplete = NULL;
DcmDataset* g_pDcmDataset = NULL;
DcmElement* g_pixelDataElement = NULL;
bool g_bChange = false;
EventHandler* g_pEventHandler = NULL;
GLuint textureObj = 0;
GLuint g_shaderProgramGray16 = 0;
GLuint g_shaderProgramRGB = 0;
// Vertex shader
GLint g_shaderPanGray16, g_shaderZoomGray16, g_shaderAspectGray16, g_shaderWindowCenterGray16, g_shaderWindowWidthGray16;
GLint g_shaderPanRGB, g_shaderZoomRGB, g_shaderAspectRGB, g_shaderWindowCenterRGB, g_shaderWindowWidthRGB;
int g_nWindowWidth = 0;
int g_nWindowCenter = 0;
int g_nPrevWindowWidth = 0;
int g_nPrevWindowCenter = 0;
int g_nColorType = 0;
Uint32 g_nCurrentFrame = 0;
int g_nTotalFrames = 0;
int g_nFrameWidth = 0;
int g_nFrameHeight = 0;
int g_nSamplesPerPixel = 0;
int g_nBitsAllocated = 0;
int g_nFrameSizeUncompressed = 0;
char* g_pBuf = NULL;
const GLchar* vertexSourceGray16 =
"uniform vec2 pan; \n"
"uniform float zoom; \n"
"uniform float aspect; \n"
"attribute vec4 position; \n"
"attribute vec2 a_texCoord; \n"
"varying vec2 texCoord; \n"
"void main() \n"
"{ \n"
" gl_Position = vec4(position.xyz, 1.0); \n"
" gl_Position.xy += pan; \n"
" gl_Position.xy *= zoom; \n"
" texCoord = a_texCoord; \n"
" gl_Position.y *= aspect; \n"
"} \n";
// Fragment/pixel shader
const GLchar* fragmentSourceGray16 =
"precision mediump float; \n"
"varying vec2 texCoord; \n"
"uniform sampler2D texSampler; \n"
"uniform float fWindowCenter; \n"
"uniform float fWindowWidth; \n"
"void main() \n"
"{ \n"
" vec4 colorOut = texture2D(texSampler, texCoord); \n"
" float fMin = fWindowCenter - fWindowWidth/2.0;\n"
" float fMax = fWindowCenter + fWindowWidth/2.0;\n"
" float fData = ( ((colorOut.a + colorOut.r*256.0)*256.0) - fMin)/(fMax-fMin); \n"
" fData = ( ((colorOut.a + colorOut.a*256.0)*256.0) - fMin)/(fMax-fMin); \n"
" fData = colorOut.r;\n"
" fData = (((colorOut.a * 256.0 + colorOut.r)*256.0) - fMin) / (fMax-fMin);"
" float fTmpData = fMin;\n"
" gl_FragColor = vec4(fData, fData, fData, 1.0); \n"
"} \n";
const GLchar* vertexSourceRGB =
"uniform vec2 panRGB; \n"
"uniform float zoomRGB; \n"
"uniform float aspectRGB; \n"
"attribute vec4 position; \n"
"attribute vec2 a_texCoord; \n"
"varying vec2 texCoord; \n"
"void main() \n"
"{ \n"
" gl_Position = vec4(position.xyz, 1.0); \n"
" gl_Position.xy += panRGB; \n"
" gl_Position.xy *= zoomRGB; \n"
" texCoord = a_texCoord; \n"
" gl_Position.y *= aspectRGB; \n"
"} \n";
// Fragment/pixel shader
const GLchar* fragmentSourceRGB =
"precision mediump float; \n"
"varying vec2 texCoord; \n"
"uniform sampler2D texSampler; \n"
"uniform float fWindowCenterRGB; \n"
"uniform float fWindowWidthRGB; \n"
"void main() \n"
"{ \n"
" vec4 colorOut = texture2D(texSampler, texCoord); \n"
" float fMin = fWindowCenterRGB - fWindowWidthRGB/2.0;\n"
" float fMax = fWindowCenterRGB + fWindowWidthRGB/2.0;\n"
" float fTestValue = (fMax - fMin);\n"
" float fR = (colorOut.r*256.0 - fMin) / (fMax-fMin);\n"
" float fG = (colorOut.g*256.0 - fMin) / (fMax-fMin);\n"
" float fB = (colorOut.b*256.0 - fMin) / (fMax-fMin);\n"
" gl_FragColor = vec4(fR, fG, fB, 1.0); \n"
//" gl_FragColor = vec4(colorOut.r/fTestValue, 1.0, 1.0, 1.0); \n"
"} \n";
void updateShader(EventHandler& eventHandler)
{
Camera& camera = eventHandler.camera();
printf("updateShader: g_nColorType=%d\n", g_nColorType);
if(g_nColorType==0)
{
glUseProgram(g_shaderProgramGray16);
glUniform2fv(g_shaderPanGray16, 1, camera.pan());
glUniform1f(g_shaderZoomGray16, camera.zoom());
glUniform1f(g_shaderAspectGray16, camera.aspect());
}
else if(g_nColorType==1)
{
glUseProgram(g_shaderProgramRGB);
glUniform2fv(g_shaderPanRGB, 1, camera.pan());
glUniform1f(g_shaderZoomRGB, camera.zoom());
glUniform1f(g_shaderAspectRGB, camera.aspect());
}
}
void onErrorData(void* arg)
{
printf("onErrorData %d\n", (int)arg);
}
void updateTextureGray16(int nWidth, int nHeight, void* pData)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, nWidth, nHeight, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, pData);
}
void updateTextureRGB(int nWidth, int nHeight, void* pData)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, nWidth, nHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, pData);
}
void updateWindowWidthLevelGray16(int nWidth, int nLevel)
{
glUniform1f(g_shaderWindowCenterGray16, (float)nLevel);
glUniform1f(g_shaderWindowWidthGray16, (float)nWidth);
}
void updateWindowWidthLevelRGB(int nWidth, int nLevel)
{
glUniform1f(g_shaderWindowCenterRGB, (float)nLevel);
glUniform1f(g_shaderWindowWidthRGB, (float)nWidth);
}
void initShaderGray16()
{
// Create and compile vertex shader
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexSourceGray16, NULL);
glCompileShader(vertexShader);
// Create and compile fragment shader
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentSourceGray16, NULL);
glCompileShader(fragmentShader);
// Link vertex and fragment shader into shader program and use it
g_shaderProgramGray16 = glCreateProgram();
glAttachShader(g_shaderProgramGray16, vertexShader);
glAttachShader(g_shaderProgramGray16, fragmentShader);
glLinkProgram(g_shaderProgramGray16);
//glUseProgram(g_shaderProgramGray16);
// Get shader variables and initialize them
g_shaderPanGray16 = glGetUniformLocation(g_shaderProgramGray16, "pan");
g_shaderZoomGray16 = glGetUniformLocation(g_shaderProgramGray16, "zoom");
g_shaderAspectGray16 = glGetUniformLocation(g_shaderProgramGray16, "aspect");
g_shaderWindowCenterGray16 = glGetUniformLocation(g_shaderProgramGray16, "fWindowCenter");
g_shaderWindowWidthGray16 = glGetUniformLocation(g_shaderProgramGray16, "fWindowWidth");
glUniform1f(g_shaderWindowCenterGray16, 128.0f);
glUniform1f(g_shaderWindowWidthGray16, 255.0f);
//printf("pan:%d, zoom:%d, aspect:%d, g_shaderWindowCenterGray16:%d, g_shaderWindowWidthGray16:%d\n", g_shaderPanGray16, g_shaderZoomGray16, g_shaderAspectGray16, g_shaderWindowCenterGray16, g_shaderWindowWidthGray16);
}
void initShaderRGB()
{
// Create and compile vertex shader
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexSourceRGB, NULL);
glCompileShader(vertexShader);
// Create and compile fragment shader
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentSourceRGB, NULL);
glCompileShader(fragmentShader);
// Link vertex and fragment shader into shader program and use it
g_shaderProgramRGB = glCreateProgram();
//printf("g_shaderProgramRGB: %d\n", g_shaderProgramRGB);
glAttachShader(g_shaderProgramRGB, vertexShader);
glAttachShader(g_shaderProgramRGB, fragmentShader);
glLinkProgram(g_shaderProgramRGB);
//glUseProgram(g_shaderProgramRGB);
// Get shader variables and initialize them
g_shaderPanRGB = glGetUniformLocation(g_shaderProgramRGB, "panRGB");
g_shaderZoomRGB = glGetUniformLocation(g_shaderProgramRGB, "zoomRGB");
g_shaderAspectRGB = glGetUniformLocation(g_shaderProgramRGB, "aspectRGB");
g_shaderWindowCenterRGB = glGetUniformLocation(g_shaderProgramRGB, "fWindowCenterRGB");
g_shaderWindowWidthRGB = glGetUniformLocation(g_shaderProgramRGB, "fWindowWidthRGB");
glUniform1f(g_shaderWindowCenterRGB, 128.0f);
glUniform1f(g_shaderWindowWidthRGB, 255.0f);
//printf("pan:%d, zoom:%d, aspect:%d, g_shaderWindowCenterRGB:%d, g_shaderWindowWidthRGB:%d\n", g_shaderPanRGB, g_shaderZoomRGB, g_shaderAspectRGB, g_shaderWindowCenterRGB, g_shaderWindowWidthRGB);
}
GLuint initShader(EventHandler& eventHandler)
{
initShaderGray16();
initShaderRGB();
updateShader(eventHandler);
g_pEventHandler = &eventHandler;
return g_shaderProgramGray16;
}
GLuint g_vbo = 0;
void initGeometry(GLuint shaderProgram)
{
// Create vertex buffer object and copy vertex data into it
//printf("g_vbo: %d\n", g_vbo);
glGenBuffers(1, &g_vbo);
glBindBuffer(GL_ARRAY_BUFFER, g_vbo);
GLfloat vertices[] =
{
-1.0f, -1.0f, 0.0f, 0.0f, 1.0f,
1.0f, -1.0f, 0.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 0.0f, 0.0f, 0.0f,
1.0f, 1.0f, 0.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 0.0f, 0.0f,
1.0f, -1.0f, 0.0f, 1.0f, 1.0f,
};
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// Specify the layout of the shader vertex data (positions only, 3 floats)
GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
glEnableVertexAttribArray(posAttrib);
// glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 0, 0);
glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (GLvoid*)0);
// glEnableVertexAttribArray(0);
GLint texAttrib = glGetAttribLocation(shaderProgram, "a_texCoord");
glEnableVertexAttribArray(texAttrib);
glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat)));
//glEnableVertexAttribArray(2);
// glBindBuffer(GL_ARRAY_BUFFER, 0);
//printf("initGeometry(%d, %d)\n", posAttrib, texAttrib);
}
void PrintError()
{
int nError = 0;
nError = glGetError();
printf("Error Code: %d\n", nError);
}
void onLoadedData(void* arg, void* buffer, int nSize)
{
//printf("onLoadedData %d, %d\n", (int)arg, nSize);
OFCondition error;
E_TransferSyntax opt_ixfer = EXS_Unknown;
E_FileReadMode opt_readMode = ERM_autoDetect;
Uint8* pData = (Uint8*)buffer;
int nFindIndex = 0;
bool bFind = false;
int i=0;
Uint8* pDataTmp = (Uint8*)buffer;
for(i=0 ; i<nSize-4 && bFind==false ; i++)
{
if(pDataTmp[i]=='D' && pDataTmp[i+1]=='I' && pDataTmp[i+2]=='C' && pDataTmp[i+3]=='M')
{
nFindIndex = i;
bFind = true;
break;
}
}
memset(pData, 0x00, nFindIndex-1);
// printf("nFindIndex = 0x%x", nFindIndex);
DcmInputBufferStream dcmBuffer;
dcmBuffer.setBuffer(pData, nSize);
dcmBuffer.setEos();
DcmInputBufferStream dcmBuffer2;
dcmBuffer2.setBuffer(pData, nSize);
dcmBuffer2.setEos();
// printf("%02x %02x %02x %02x\n", pData[0], pData[1], pData[2], pData[3]);
if(g_pDcmDataset!=NULL)
{
delete g_pDcmDataset;
}
g_pDcmDataset = new DcmDataset;
OFString strTransferSyntaxUID;
g_pDcmDataset->transferInit();
{
error = g_pDcmDataset->read(dcmBuffer2, EXS_LittleEndianExplicit);
g_pDcmDataset->findAndGetOFString(DCM_TransferSyntaxUID, strTransferSyntaxUID);
g_pDcmDataset->transferEnd();
dcmBuffer2.releaseBuffer();
delete g_pDcmDataset;
g_pDcmDataset = new DcmDataset;
}
if (strTransferSyntaxUID.size() > 0)
{
}
DcmXfer dcmXfer(strTransferSyntaxUID.c_str());
g_pDcmDataset->transferInit();
//error = g_pDcmDataset->read(dcmBuffer, EXS_JPEGProcess14SV1);
error = g_pDcmDataset->read(dcmBuffer, dcmXfer.getXfer());
if(error.bad())
{
printf("Dataset State: %u(%s)\n", g_pDcmDataset->transferState(), error.text());
}
g_pDcmDataset->transferEnd();
dcmBuffer.releaseBuffer();
g_nTotalFrames = 1;
g_nFrameWidth = 0;
g_nFrameHeight = 0;
g_nSamplesPerPixel = 1;
g_nBitsAllocated = 8;
Uint16 val = 0;
g_pDcmDataset->findAndGetUint16(DCM_Rows, val);
g_nFrameHeight = val;
g_pDcmDataset->findAndGetUint16(DCM_Columns, val);
g_nFrameWidth = val;
g_pDcmDataset->findAndGetUint16(DCM_SamplesPerPixel, val);
g_nSamplesPerPixel = val;
g_pDcmDataset->findAndGetUint16(DCM_BitsAllocated, val);
g_nBitsAllocated = val;
Sint32 nFrames = 0;
OFString strFrames;
// g_pDcmDataset->findAndGetSint32(DCM_NumberOfFrames, nFrames);
g_pDcmDataset->findAndGetOFString(DCM_NumberOfFrames, strFrames);
nFrames = atoi(strFrames.c_str());
if(nFrames<=0)
{
nFrames = 1;
}
g_nTotalFrames = nFrames;
OFString strTmp;
strTmp = "";
g_pDcmDataset->findAndGetOFString(DCM_WindowCenter, strTmp);
if(g_nWindowCenter<=0)
g_nWindowCenter = atoi(strTmp.c_str());
strTmp = "";
g_pDcmDataset->findAndGetOFString(DCM_WindowWidth, strTmp);
if(g_nWindowWidth<=0)
g_nWindowWidth = atoi(strTmp.c_str());
g_nPrevWindowCenter = g_nWindowCenter;
g_nPrevWindowWidth = g_nWindowWidth;
if(g_nSamplesPerPixel==3 && g_nBitsAllocated==8)
{
g_nColorType = 1;
}
else
{
g_nColorType = 0;
}
printf("ColorType:%d, Width:%d, Height:%d, TotalFrames:(%s)(%d) SamplesPerPixel:%d, BitsAllocated:%d\n", g_nColorType, g_nFrameWidth, g_nFrameHeight, strFrames.c_str(), g_nTotalFrames, g_nSamplesPerPixel, g_nBitsAllocated);
if(g_nFrameWidth==0)
{
DcmElement* pElement = NULL;
g_pDcmDataset->findAndGetElement(DCM_Columns, pElement);
printf("pElement: %x\n", pElement);
}
g_pixelDataElement = NULL;
g_pDcmDataset->findAndGetElement(DCM_PixelData, g_pixelDataElement);
const Uint8* pImageData = NULL;
g_pDcmDataset->findAndGetUint8Array(DCM_PixelData, pImageData);
if(pImageData!=NULL)
{
error = g_pDcmDataset->chooseRepresentation(EXS_LittleEndianExplicit, NULL);
if(error.bad())
{
printf("chooseRepresentation: %s\n", error.text());
}
else
{
g_pDcmDataset->findAndGetUint8Array(DCM_PixelData, pImageData);
}
}
else
{
printf("Find Pixel Data!!!\n");
if(g_pixelDataElement->isEmpty()==true)
{
printf("PixelData is Empty!!\n");
}
else
{
printf("ok0\n");
Uint32 nFrameSizeUncompressed = 0;
g_pixelDataElement->getUncompressedFrameSize(g_pDcmDataset, nFrameSizeUncompressed);
g_nFrameSizeUncompressed = nFrameSizeUncompressed;
printf("ok1: %d\n", g_nFrameSizeUncompressed);
if(g_pBuf!=NULL)
{
delete[] g_pBuf;
}
g_pBuf = new char[g_nFrameSizeUncompressed];
OFCondition ofTest;
OFString decompressedColorModel;
Uint32 startFragment = 0;
ofTest = g_pixelDataElement->getUncompressedFrame(g_pDcmDataset, 1, startFragment, g_pBuf, g_nFrameSizeUncompressed, decompressedColorModel);
//printf("updateTextureRGB: %d, %d, %d, %d, %s\nerror: %s\n", g_nFrameWidth, g_nFrameHeight, startFragment, g_nFrameSizeUncompressed, decompressedColorModel.c_str(), ofTest.text());
updateTextureRGB(g_nFrameWidth, g_nFrameHeight, g_pBuf);
//printf("sizeF: %d\n", sizeF);
}
}
if(callback_UpdateDcmImageComplete!=NULL)
{
printf("callback_UpdateDcmImageComplete\n");
callback_UpdateDcmImageComplete();
}
g_bChange = true;
//g_bChange = false;
//printf("load OK!\n");
}
void initTextureGray16()
{
const Uint16* pImageData = NULL;
//g_pDcmDataset->findAndGetUint8Array(DCM_PixelData, pImageData);
g_pDcmDataset->findAndGetUint16Array(DCM_PixelData, pImageData);
//printf("PixelPointer: %x\n", pImageData);
int w = g_nFrameWidth;
int h = g_nFrameHeight;
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//SDL_Surface* image = SDL_CreateRGBSurface(0, w, h, 24, 0, 0, 0, 0);
//memset(image->pixels, 0x1f, image->w * image->h * 3);
//
//Uint8* pData = new Uint8[1920*1080*4];
//memset(pData, 0xff, 1920*1080*4);
//if(image!=NULL)
{
glGenTextures(1, &textureObj);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureObj);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
PrintError();
// glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, GL_UNSIGNED_BYTE, pData);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, w, h, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, pImageData);
// glTexImage2D(GL_TEXTURE_2D, 0, GL_R16I, w, h, 0, GL_RED_INTEGER, GL_UNSIGNED_SHORT, pData16);
PrintError();
GLint nTextureID = glGetUniformLocation(g_shaderProgramGray16, "texSampler");
//printf("texSampler: %d\n", nTextureID);
glActiveTexture(GL_TEXTURE0);
glUniform1i(nTextureID, 0);
// glBindTexture(GL_TEXTURE_2D, 0);
}
// updateWindowWidthLevelGray16(g_nWindowWidth, g_nWindowCenter);
// glUniform1f(g_shaderWindowCenterGray16, (float)g_nWindowCenter);
// glUniform1f(g_shaderWindowWidthGray16, (float)g_nWindowWidth);
//printf("WindowCenter: %d, WindowWidth: %d\n", g_nWindowCenter, g_nWindowWidth);
//delete g_pDcmDataset;
//glUseProgram(g_shaderProgramGray16);
}
void initTextureRGB()
{
//printf("initTextureRGB\n");
const Uint8* pImageData = NULL;
g_pDcmDataset->findAndGetUint8Array(DCM_PixelData, pImageData);
//printf("PixelPointer: %x\n", pImageData);
int w = g_nFrameWidth;
int h = g_nFrameHeight;
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
GLint format = GL_RGB;
//printf("textureObj: %d\n", textureObj);
if(textureObj>=0)
{
glBindTexture(GL_TEXTURE_2D, 0);
glDeleteTextures(1, &textureObj);
}
glGenTextures(1, &textureObj);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureObj);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
PrintError();
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, pImageData);
PrintError();
GLint nTextureID = glGetUniformLocation(g_shaderProgramRGB, "texSampler");
//printf("texSampler: %d\n", nTextureID);
glActiveTexture(GL_TEXTURE0);
glUniform1i(nTextureID, 0);
// updateWindowWidthLevelRGB(g_nWindowWidth, g_nWindowCenter);
// glUniform1f(g_shaderWindowCenterRGB, (float)g_nWindowCenter);
// glUniform1f(g_shaderWindowWidthRGB, (float)g_nWindowWidth);
// printf("WindowCenter: %d, WindowWidth: %d\n", g_nWindowCenter, g_nWindowWidth);
/*
if(g_pDcmDataset!=NULL)
{
delete g_pDcmDataset;
g_pDcmDataset = NULL;
}
*/
}
void redraw(EventHandler& eventHandler)
{
if(g_bChange==true)
{
if(g_nColorType==0)
{
initGeometry(g_shaderProgramGray16);
glUseProgram(g_shaderProgramGray16);
initTextureGray16();
updateShader(*g_pEventHandler);
}
else if(g_nColorType==1)
{
initGeometry(g_shaderProgramRGB);
glUseProgram(g_shaderProgramRGB);
initTextureRGB();
updateShader(*g_pEventHandler);
}
g_bChange = false;
}
//printf("g_nTotalFrames: %d\n", g_nTotalFrames);
if(g_nTotalFrames>0)
{
OFCondition ofTest;
OFString decompressedColorModel;
ofTest = g_pixelDataElement->getUncompressedFrame(g_pDcmDataset, 1, g_nCurrentFrame, g_pBuf, g_nFrameSizeUncompressed, decompressedColorModel);
if(g_nColorType==0)
{
printf("updateTextureRGB: %d\n", g_nCurrentFrame);
updateTextureGray16(g_nFrameWidth, g_nFrameHeight, g_pBuf);
}
else if(g_nColorType==1)
{
//printf("updateTextureRGB: %d, %d, %d, %d, %s\nerror: %s\n", g_nFrameWidth, g_nFrameHeight, g_nCurrentFrame, g_nFrameSizeUncompressed, decompressedColorModel.c_str(), ofTest.text());
updateTextureRGB(g_nFrameWidth, g_nFrameHeight, g_pBuf);
}
if(g_nCurrentFrame>=g_nTotalFrames)
{
g_nCurrentFrame = 0;
}
}
if(g_nColorType==0)
{
updateWindowWidthLevelGray16(g_nPrevWindowWidth, g_nPrevWindowCenter);
// glUniform1f(g_shaderWindowCenterGray16, (float)g_nPrevWindowCenter);
// glUniform1f(g_shaderWindowWidthGray16, (float)g_nPrevWindowWidth);
}
else if(g_nColorType==1)
{
updateWindowWidthLevelRGB(g_nPrevWindowWidth, g_nPrevWindowCenter);
// glUniform1f(g_shaderWindowCenterRGB, (float)g_nPrevWindowCenter);
// glUniform1f(g_shaderWindowWidthRGB, (float)g_nPrevWindowWidth);
}
// Clear screen
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
//glUseProgram(g_shaderProgramGray16);
// glActiveTexture(GL_TEXTURE0);
// glBindTexture(GL_TEXTURE_2D, textureObj);
//glBindBuffer(GL_ARRAY_BUFFER, g_vbo);
// Draw the vertex buffer
glDrawArrays(GL_TRIANGLES, 0, 6);
//glDrawArrays(GL_QUADS, 0, 4);
// Swap front/back framebuffers
eventHandler.swapWindow();
//printf("redraw\n");
}
void mainLoop(void* mainLoopArg)
{
EventHandler& eventHandler = *((EventHandler*)mainLoopArg);
eventHandler.processEvents();
int nType = eventHandler.GetEventType();
if(nType==1 || nType==2)
{
float fDeltaX = eventHandler.GetDeltaX();
float fDeltaY = eventHandler.GetDeltaY();
g_nPrevWindowCenter = g_nWindowCenter+fDeltaY;
g_nPrevWindowWidth = g_nWindowWidth + fDeltaX;
//printf("DeltaX: %f, DeltaY:%f, (%d, %d)\n", fDeltaX, fDeltaY, g_nPrevWindowCenter, g_nPrevWindowWidth);
// glUniform1f(g_shaderWindowCenterGray16, (float)g_nPrevWindowCenter);
// glUniform1f(g_shaderWindowWidthGray16, (float)g_nPrevWindowWidth);
//
}
else if(nType==3 || nType==4)
{
g_nWindowCenter = g_nPrevWindowCenter;
g_nWindowWidth = g_nPrevWindowWidth;
}
// glUniform1f(g_shaderWindowCenterGray16, (float)g_nPrevWindowCenter);
// glUniform1f(g_shaderWindowWidthGray16, (float)g_nPrevWindowWidth);
// Update shader if camera changed
if (eventHandler.camera().updated())
updateShader(eventHandler);
redraw(eventHandler);
}
#ifdef __cplusplus
#define EXTERN extern "C"
#else
#define EXTERN
#endif
EXTERN EMSCRIPTEN_KEEPALIVE int UpdateDcmImage(std::string strFile)
{
printf("UpdateDcmImage: %s\n", strFile.c_str());
emscripten_async_wget_data(strFile.c_str(), (void*)135, onLoadedData, onErrorData);
return 0;
}
EXTERN EMSCRIPTEN_KEEPALIVE int SetWindowWidthLevel(int nWindowCenter, int nWindowWidth)
{
printf("New nWindowCenter:%d, nWindowWidth:%d\n", nWindowCenter, nWindowWidth);
g_nWindowCenter = nWindowCenter;
g_nWindowWidth = nWindowWidth;
g_nPrevWindowCenter = g_nWindowCenter;
g_nPrevWindowWidth = g_nWindowWidth;
return 0;
}
EXTERN EMSCRIPTEN_KEEPALIVE int GetWindowWidth()
{
return g_nWindowWidth;
}
EXTERN EMSCRIPTEN_KEEPALIVE int GetWindowCenter()
{
return g_nWindowCenter;
}
EXTERN EMSCRIPTEN_KEEPALIVE bool SetCallbackUpdateDcmImageComplete(callback_UpdateDcmImage callback_)
{
printf("SetCallbackUpdateDcmImage: %x\n", callback_);
callback_UpdateDcmImageComplete = callback_;
return true;
}
int main(int argc, char** argv)
{
EventHandler eventHandler("dcm image viewer");
// Initialize shader and geometry
GLuint shaderProgram = initShader(eventHandler);
//initTexture();
// Start the main loop
void* mainLoopArg = &eventHandler;
DJDecoderRegistration::registerCodecs();
DJLSDecoderRegistration::registerCodecs();
DcmRLEDecoderRegistration::registerCodecs();
//emscripten_async_wget_data("http://49.171.226.18:1901/3.dcm", (void*)135, onLoadedData, onErrorData);
#ifdef __EMSCRIPTEN__
int fps = 0; // Use browser's requestAnimationFrame
emscripten_set_main_loop_arg(mainLoop, mainLoopArg, fps, true);
#else
while(true)
mainLoop(mainLoopArg);
#endif
glDeleteTextures(1, &textureObj);
glBindTexture(GL_TEXTURE_2D, 0);
DJDecoderRegistration::cleanup();
DJLSDecoderRegistration::cleanup();
DcmRLEDecoderRegistration::cleanup();
if(g_pDcmDataset!=NULL)
{
delete g_pDcmDataset;
g_pDcmDataset = NULL;
}
printf("exit!!!!! c++ dcm_image_mod");
return 0;
}