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

1124 lines
31 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 "dcmtk/oflog/loglevel.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_nDefaultWindowWidth = 0;
int g_nDefaultWindowCenter = 0;
int g_nColorType = 0;
Uint32 g_nCurrentFrame = 0;
int g_nTotalFrames = 0;
int g_nFrameTextureWidth = 0;
int g_nFrameTextureHeight = 0;
int g_nSamplesPerPixel = 0;
int g_nBitsAllocated = 0;
int g_nFrameSizeUncompressed = 0;
int g_nWindowSizeWidth = 0;
int g_nWindowSizeHeight = 0;
float g_fFrameTime = 0;
float g_fFrameDelay = 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);
g_nWindowSizeWidth = (int)g_pEventHandler->camera().windowSize().width;
g_nWindowSizeHeight = (int)g_pEventHandler->camera().windowSize().height;
float fWindowWidth = (float)g_pEventHandler->camera().windowSize().width;
float fWindowHeight = (float)g_pEventHandler->camera().windowSize().height;
float fWindowRatio = fWindowWidth / fWindowHeight;
float fFrameTextureRatio = (float)g_nFrameTextureWidth / (float)g_nFrameTextureHeight;
float fRatioX = 1.0f;
float fRatioY = 1.0f;
float fRefWidthRatio = (float)g_nFrameTextureWidth / fWindowWidth;
float fRefHeightRatio = (float)g_nFrameTextureHeight / fWindowHeight;
if(fRefWidthRatio>fRefHeightRatio)
{
fRatioX = 1.0f;
fRatioY = (fWindowWidth*((float)g_nFrameTextureHeight/(float)g_nFrameTextureWidth)) / fWindowHeight;
}
else
{
fRatioY = 1.0f;
fRatioX = (fWindowHeight*((float)g_nFrameTextureWidth/(float)g_nFrameTextureHeight)) / fWindowWidth;
}
/*
if(fRatioX>1.0f || fRatioY>1.0f)
{
float fMax = fRatioX;
if(fRatioX<fRatioY)
{
fMax = fRatioY;
}
fRatioX = fRatioX / fMax;
fRatioY = fRatioY / fMax;
}
fRatioX = 1.0f;
fRatioY = 1.0f;
*/
printf("fWindowRatio:%f, fFrameTextureRatio:%f, fRatioX:%f, fRatioY:%f, (g_nWindowWidth:%d, g_nWindowHeight:%d)\n",
fWindowRatio, fFrameTextureRatio, fRatioX, fRatioY, g_nWindowSizeWidth, g_nWindowSizeHeight);
if(g_vbo==0)
{
glGenBuffers(1, &g_vbo);
}
glBindBuffer(GL_ARRAY_BUFFER, g_vbo);
GLfloat vertices[] =
{
-1.0f*fRatioX, -1.0f*fRatioY, 0.0f, 0.0f, 1.0f,
1.0f*fRatioX, -1.0f*fRatioY, 0.0f, 1.0f, 1.0f,
-1.0f*fRatioX, 1.0f*fRatioY, 0.0f, 0.0f, 0.0f,
1.0f*fRatioX, 1.0f*fRatioY, 0.0f, 1.0f, 0.0f,
-1.0f*fRatioX, 1.0f*fRatioY, 0.0f, 0.0f, 0.0f,
1.0f*fRatioX, -1.0f*fRatioY, 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;
g_nCurrentFrame = 0;
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);
g_fFrameTime = 0;
g_fFrameDelay = 0;
// 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_nFrameTextureWidth = 0;
g_nFrameTextureHeight = 0;
g_nSamplesPerPixel = 1;
g_nBitsAllocated = 8;
Uint16 val = 0;
g_pDcmDataset->findAndGetUint16(DCM_Rows, val);
g_nFrameTextureHeight = val;
g_pDcmDataset->findAndGetUint16(DCM_Columns, val);
g_nFrameTextureWidth = val;
g_pDcmDataset->findAndGetUint16(DCM_SamplesPerPixel, val);
g_nSamplesPerPixel = val;
g_pDcmDataset->findAndGetUint16(DCM_BitsAllocated, val);
g_nBitsAllocated = val;
int nMaxValue = pow(2, g_nBitsAllocated) - 1;
int nMinValue = 0;
int nDefaultWindowWidth = nMaxValue - nMinValue;
int nDefaultWindowCenter = (nMaxValue + nMinValue)/2;
Sint32 nFrames = 0;
OFString strTmp;
OFString strFrames;
// g_pDcmDataset->findAndGetSint32(DCM_NumberOfFrames, nFrames);
g_pDcmDataset->findAndGetOFString(DCM_NumberOfFrames, strFrames);
nFrames = atoi(strFrames.c_str());
if(nFrames<=0)
{
nFrames = 1;
}
else
{
strTmp = "";
g_pDcmDataset->findAndGetOFString(DCM_FrameTime, strTmp);
printf("DCM_Frametime: %s\n", strTmp.c_str());
g_fFrameTime = atof(strTmp.c_str());
strTmp = "";
g_pDcmDataset->findAndGetOFString(DCM_FrameDelay, strTmp);
printf("DCM_FrameDelay: %s\n", strTmp.c_str());
g_fFrameDelay = atof(strTmp.c_str());
}
g_nTotalFrames = nFrames;
strTmp = "";
g_pDcmDataset->findAndGetOFString(DCM_WindowCenter, strTmp);
g_nDefaultWindowCenter = atoi(strTmp.c_str());
if(g_nDefaultWindowCenter==0)
{
g_nDefaultWindowCenter = nDefaultWindowCenter;
}
if(g_nWindowCenter<=0 && g_nDefaultWindowCenter)
{
g_nWindowCenter = g_nDefaultWindowCenter;
}
strTmp = "";
g_pDcmDataset->findAndGetOFString(DCM_WindowWidth, strTmp);
g_nDefaultWindowWidth = atoi(strTmp.c_str());
if(g_nDefaultWindowWidth==0)
{
g_nDefaultWindowWidth = nDefaultWindowWidth;
}
if(g_nWindowWidth<=0 && g_nDefaultWindowWidth>0)
{
g_nWindowWidth = g_nDefaultWindowWidth;
}
/*
Float64 fValue = 0.0f;
fValue = 0;
g_nDefaultWindowCenter = 0;
g_pDcmDataset->findAndGetFloat64(DCM_WindowCenter, fValue);
g_nDefaultWindowCenter = (int)val;
if(g_nWindowCenter<=0 && g_nDefaultWindowCenter)
{
g_nWindowCenter = g_nDefaultWindowCenter;
}
fValue = 0;
g_pDcmDataset->findAndGetFloat64(DCM_WindowWidth, fValue);
g_nDefaultWindowWidth = (int)val;
if(g_nWindowWidth<=0 && g_nDefaultWindowWidth>0)
{
g_nWindowWidth = g_nDefaultWindowWidth;
}
*/
printf("File WindowWidth: %d, WindowCenter: %d\n", g_nDefaultWindowWidth, g_nDefaultWindowCenter);
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_nFrameTextureWidth, g_nFrameTextureHeight, strFrames.c_str(), g_nTotalFrames, g_nSamplesPerPixel, g_nBitsAllocated);
if(g_nFrameTextureWidth==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);
printf("OnLoadedData: g_pixelDataElement: %x\n", 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_nFrameTextureWidth, g_nFrameTextureHeight, startFragment, g_nFrameSizeUncompressed, decompressedColorModel.c_str(), ofTest.text());
updateTextureRGB(g_nFrameTextureWidth, g_nFrameTextureHeight, 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->findAndGetUint16Array(DCM_PixelData, pImageData);
int w = g_nFrameTextureWidth;
int h = g_nFrameTextureHeight;
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
{
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_LUMINANCE_ALPHA, w, h, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, pImageData);
PrintError();
GLint nTextureID = glGetUniformLocation(g_shaderProgramGray16, "texSampler");
glActiveTexture(GL_TEXTURE0);
glUniform1i(nTextureID, 0);
}
}
void initTextureRGB()
{
const Uint8* pImageData = NULL;
g_pDcmDataset->findAndGetUint8Array(DCM_PixelData, pImageData);
int w = g_nFrameTextureWidth;
int h = g_nFrameTextureHeight;
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
GLint format = GL_RGB;
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");
glActiveTexture(GL_TEXTURE0);
glUniform1i(nTextureID, 0);
}
void redraw(EventHandler& eventHandler)
{
int nWindowSizeWidth = (int)g_pEventHandler->camera().windowSize().width;
int nWindowSizeHeight = (int)g_pEventHandler->camera().windowSize().height;
bool bSizeChange = false;
if(nWindowSizeWidth != g_nWindowSizeWidth ||
nWindowSizeHeight != g_nWindowSizeHeight)
{
bSizeChange = true;
}
if(g_bChange==true)
{
if(g_nColorType==0)
{
printf("redraw: initTextureGray16\n");
initGeometry(g_shaderProgramGray16);
glUseProgram(g_shaderProgramGray16);
initTextureGray16();
updateShader(*g_pEventHandler);
}
else if(g_nColorType==1)
{
printf("redraw: initTextureRGB\n");
initGeometry(g_shaderProgramRGB);
glUseProgram(g_shaderProgramRGB);
initTextureRGB();
updateShader(*g_pEventHandler);
}
g_bChange = false;
}
if(bSizeChange==true)
{
if(g_nColorType==0)
{
printf("redraw: SizeChange initTextureGray16\n");
initGeometry(g_shaderProgramGray16);
}
else if(g_nColorType==1)
{
printf("redraw: SizeChange initTextureRGB\n");
initGeometry(g_shaderProgramRGB);
}
g_nWindowSizeWidth = (int)g_pEventHandler->camera().windowSize().width;
g_nWindowSizeHeight = (int)g_pEventHandler->camera().windowSize().height;
}
if(g_nTotalFrames>1)
{
OFCondition ofTest;
OFString decompressedColorModel;
Uint32 nDisplayFrameIndex = g_nCurrentFrame;
ofTest = g_pixelDataElement->getUncompressedFrame(g_pDcmDataset, 1, nDisplayFrameIndex, g_pBuf, g_nFrameSizeUncompressed, decompressedColorModel);
if(g_nColorType==0)
{
updateTextureGray16(g_nFrameTextureWidth, g_nFrameTextureHeight, g_pBuf);
}
else if(g_nColorType==1)
{
//printf("updateTextureRGB: %d, %d, %d, %d, %s\nerror: %s\n", g_nFrameTextureWidth, g_nFrameTextureHeight, g_nCurrentFrame, g_nFrameSizeUncompressed, decompressedColorModel.c_str(), ofTest.text());
updateTextureRGB(g_nFrameTextureWidth, g_nFrameTextureHeight, g_pBuf);
}
if(g_nCurrentFrame>=g_nTotalFrames)
{
g_nCurrentFrame = 0;
}
}
else
{
/*
const Uint8* pImageData = NULL;
g_pDcmDataset->findAndGetUint8Array(DCM_PixelData, pImageData);
if(g_nColorType==0)
{
printf("updateTextureGray16: %d\n", g_nCurrentFrame);
updateTextureGray16(g_nFrameTextureWidth, g_nFrameTextureHeight, (void*)pImageData);
}
else if(g_nColorType==1)
{
printf("updateTextureRGB: %d, %d, %x\n", g_nFrameTextureWidth, g_nFrameTextureHeight, pImageData);
//printf("updateTextureRGB: %d, %d, %d, %d, %s\nerror: %s\n", g_nFrameTextureWidth, g_nFrameTextureHeight, g_nCurrentFrame, g_nFrameSizeUncompressed, decompressedColorModel.c_str(), ofTest.text());
updateTextureRGB(g_nFrameTextureWidth, g_nFrameTextureHeight, (void*)pImageData);
}
*/
}
if(g_nColorType==0)
{
updateWindowWidthLevelGray16(g_nPrevWindowWidth, g_nPrevWindowCenter);
}
else if(g_nColorType==1)
{
updateWindowWidthLevelRGB(g_nPrevWindowWidth, g_nPrevWindowCenter);
}
// 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 SetDisplayFrameIndex(int nIndex)
{
g_nCurrentFrame = nIndex;
if(g_nCurrentFrame>=g_nTotalFrames)
{
g_nCurrentFrame = g_nTotalFrames-1;
}
return 0;
}
EXTERN EMSCRIPTEN_KEEPALIVE int SetResizeFrame(int nWidth, int nHeight)
{
printf("SetResizeFrame: (%d, %d)\n", nWidth, nHeight);
g_pEventHandler->camera().setWindowSize(nWidth, nHeight);
return 0;
}
EXTERN EMSCRIPTEN_KEEPALIVE int GetWindowWidth()
{
return g_nWindowWidth;
}
EXTERN EMSCRIPTEN_KEEPALIVE int GetWindowCenter()
{
return g_nWindowCenter;
}
EXTERN EMSCRIPTEN_KEEPALIVE int GetTotalFrames()
{
return g_nTotalFrames;
}
EXTERN EMSCRIPTEN_KEEPALIVE float GetFrameUpdateTimeDelay()
{
return (g_fFrameDelay + g_fFrameTime);
}
EXTERN EMSCRIPTEN_KEEPALIVE bool SetCallbackUpdateDcmImageComplete(callback_UpdateDcmImage callback_)
{
printf("SetCallbackUpdateDcmImage: %x\n", callback_);
callback_UpdateDcmImageComplete = callback_;
return true;
}
int main(int argc, char** argv)
{
OFLog::configure(OFLogger::OFF_LOG_LEVEL);
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;
}