diff --git a/CMakeLists.txt b/CMakeLists.txt index 7898d15c..8110f8fd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -253,6 +253,20 @@ mark_as_advanced(BUILD_VIEWER) mark_as_advanced(BUILD_JAVA) mark_as_advanced(BUILD_JP3D) +option(BUILD_FLVIEWER "Build the flviewer executable (C++)" OFF) +option(BUILD_FLVIEWER_WITH_SHARED_LIBS "Build the flviewer with shared libraries" OFF) +option(BUILD_FLVIEWER_WITH_JPWL_LIB "Build the flviewer with JPWL library" OFF) +option(FLTK_SKIP_OPENGL "Build flviewer without OPENGL support" ON) +option(BUILD_WITH_GERMAN "Build flviewer with GERMAN language" OFF) +if(FLTK_SKIP_OPENGL) + SET(FLTK_GL_LIBRARY "") +endif() +mark_as_advanced(BUILD_FLVIEWER) +mark_as_advanced(BUILD_FLVIEWER_WITH_SHARED_LIBS) +mark_as_advanced(BUILD_FLVIEWER_WITH_JPWL_LIB) +mark_as_advanced(FLTK_SKIP_OPENGL) +mark_as_advanced(BUILD_WITH_GERMAN) + if(BUILD_CODEC OR BUILD_MJ2) # OFF: It will only build 3rd party libs if they are not found on the system # ON: 3rd party libs will ALWAYS be build, and used diff --git a/README.flviewer.md b/README.flviewer.md new file mode 100644 index 00000000..5c874fbb --- /dev/null +++ b/README.flviewer.md @@ -0,0 +1,90 @@ +**If you want to use 'flviewer' for LINUX, APPLE, MS-WINDOWS:** + +01. Download the FLTK library from + + http://www.fltk.org + + e.g. fltk-1.3.x-r10813.tar.bz2 + and expand it. + +02. For versions < r10813 MANUALLY uncomment in + + FL/Enumerations.H + + the line + +//#define FL_ABI_VERSION 10304 + + If you do not + +#define FL_ABI_VERSION 10304 + + the horizontal BAR is not activated. + + For versions >= r10813, you can do: + + either: configure --abi-version=10304 + or : cmake -DFL_ABI_VERSION:string="10304" + +03. MS-WINDOWS may need in-source configuration/compilation. + MS-WINDOWS out-source configuration/compilation may need + '-DOPTION_BUILD_EXAMPLES:bool=off'. + +04. Compile the FLTK library. + +05. Install the FLTK library. + +06. For FLVIEWER, CMAKE arguments for the OPENJPEG library may be: + + -DBUILD_SHARED_LIBS:bool=on + -DBUILD_FLVIEWER:bool=on + -DBUILD_FLVIEWER_WITH_SHARED_LIBS:bool=on + -DFLTK_SKIP_OPENGL:bool=on + -DBUILD_WITH_GERMAN:bool=off + +07. Compile the OPENJPEG library. + +08. Call 'bin/flviewer --version'. + +09. Call 'bin/flviewer' to test the application. + +10. Some files with a large number of SOP markers, e.g. + + 'openjpeg-data/input/conformance/p0_07.j2k' + + with 256 tiles, may need some time. On my computer about 2 minutes. + The SOP markers are therefore ON only on demand (read_jpeg2000.cxx). + +11. The FLVIEWER menu has some buttons, inputs and outputs: + + Tracks, Frames, Threads : for MJ2 + Stop, Go on, Restart, Close, <-Step, Step-> : for MJ2, JPX, JPM + Tile, Reduction and Area : for JP2/J2K, JPM, JPX + Section and Browse : for all file types + Layer and Component : for resp. files + + To use 'Section': + Push the left mouse button and draw a rectangle + Press 'Section' + To remove the rectangle, click into the main window + + In the section window use the right mouse button to select an action. + + Only one section window can be open. + + Use the right mouse button to close the section window. + + If you handle an animation of type MJ2 you must first press + the 'Stop' button to stop the movie before you can get a section. + +12. Install the OPENJPEG library together with FLVIEWER. + +13. JPM and JPX files can be found on: + + http://home.arcor.de + + or (possibly) on + + https://share.openanalytics.eu/data/public/76cb6a.php + https://share.openanalytics.eu/data/public/1e7708.php + diff --git a/src/bin/CMakeLists.txt b/src/bin/CMakeLists.txt index edf85feb..abcb3c11 100644 --- a/src/bin/CMakeLists.txt +++ b/src/bin/CMakeLists.txt @@ -16,6 +16,10 @@ endif() if(BUILD_JP3D) add_subdirectory(jp3d) endif() - +if(BUILD_VIEWER) # wx apps: -add_subdirectory(wx) + add_subdirectory(wx) +endif() +if(BUILD_FLVIEWER) + add_subdirectory(fltk) +endif() diff --git a/src/bin/fltk/CMakeLists.txt b/src/bin/fltk/CMakeLists.txt new file mode 100644 index 00000000..e7ebc852 --- /dev/null +++ b/src/bin/fltk/CMakeLists.txt @@ -0,0 +1,4 @@ +if(BUILD_FLVIEWER) + add_subdirectory(flviewer) +endif() + diff --git a/src/bin/fltk/flviewer/CMake/FindNPTH.cmake b/src/bin/fltk/flviewer/CMake/FindNPTH.cmake new file mode 100644 index 00000000..b18d5d03 --- /dev/null +++ b/src/bin/fltk/flviewer/CMake/FindNPTH.cmake @@ -0,0 +1,27 @@ +# - Find NPTH library +# +# NPTH_INCLUDE_DIR +# NPTH_LIBRARIES +# NPTH_FOUND +# +# also defined, but not for general use are +# NPTH_LIBRARY + +FIND_PATH(NPTH_INCLUDE_DIR npth.h + PATHS /usr/include /usr/local/include /opt/include /opt/local/include) + +SET(NPTH_NAMES ${NPTH_NAMES} npth libnpth libnpth_static) + +FIND_LIBRARY(NPTH_LIBRARY NAMES ${NPTH_NAMES} ) + +MARK_AS_ADVANCED(NPTH_INCLUDE_DIR NPTH_LIBRARY) + +# handle the QUIETLY and REQUIRED arguments and set NPTH_FOUND to TRUE if +# all listed variables are TRUE +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(NPTH DEFAULT_MSG NPTH_LIBRARY NPTH_INCLUDE_DIR) + +IF(NPTH_FOUND) + SET(NPTH_INCLUDE_DIRS ${NPTH_INCLUDE_DIR}) + SET(NPTH_LIBRARIES ${NPTH_LIBRARY} ) +ENDIF(NPTH_FOUND) diff --git a/src/bin/fltk/flviewer/CMake/defs.cmake b/src/bin/fltk/flviewer/CMake/defs.cmake new file mode 100644 index 00000000..e97608c4 --- /dev/null +++ b/src/bin/fltk/flviewer/CMake/defs.cmake @@ -0,0 +1,124 @@ +# +INCLUDE(${CMAKE_ROOT}/Modules/CheckFunctionExists.cmake) +CHECK_FUNCTION_EXISTS(_fseeki64 HAVE_FSEEKI64) +CHECK_FUNCTION_EXISTS(fseeko HAVE_FSEEKO) +# +INCLUDE(${CMAKE_ROOT}/Modules/CheckTypeSize.cmake) +# +CHECK_TYPE_SIZE("ptrdiff_t" PTRDIFF_HAS_SIZE) +IF(PTRDIFF_HAS_SIZE) + SET(PTRDIFF_S "#define PTRDIFF_T ptrdiff_t") + IF(UNIX) + SET(PTRDIFF_FORMAT_S "#define PTRDIFF_FORMAT \"%ld\"") + ELSE() + IF(PTRDIFF_HAS_SIZE EQUAL 8) + SET(PTRDIFF_FORMAT_S "#define PTRDIFF_FORMAT \"%I64d\"") + ELSE() + SET(PTRDIFF_FORMAT_S "#define PTRDIFF_FORMAT \"%ld\"") + ENDIF() + ENDIF() +ELSE() + SET(PTRDIFF_S "/* #undef PTRDIFF_T */") + SET(PTRDIFF_FORMAT_S "/* #undef PTRDIFF_FORMAT */") +ENDIF() +# +CHECK_TYPE_SIZE("size_t" SIZE_T_HAS_SIZE) +IF(SIZE_T_HAS_SIZE) + SET(SIZE_T_S "size_t") +ENDIF() +# +IF(UNIX) + CHECK_TYPE_SIZE("int64_t" INT64_HAS_SIZE) + IF(INT64_HAS_SIZE EQUAL 8) + SET(INT64_S "int64_t") + SET(INT64_FORMAT_S "\"%ld\"") + ENDIF() + CHECK_TYPE_SIZE("uint64_t" UINT64_HAS_SIZE) + IF(UINT64_HAS_SIZE EQUAL 8) + SET(UINT64_S "uint64_t") + SET(UINT64_FORMAT_S "\"%lu\"") + ENDIF() +ELSE() + CHECK_TYPE_SIZE("signed __int64" INT64_HAS_SIZE) + IF(INT64_HAS_SIZE EQUAL 8) + SET(INT64_S "signed __int64") + SET(INT64_FORMAT_S "\"%I64d\"") + ENDIF() + CHECK_TYPE_SIZE("unsigned __int64" UINT64_HAS_SIZE) + IF(UINT64_HAS_SIZE EQUAL 8) + SET(UINT64_S "unsigned __int64") + SET(UINT64_FORMAT_S "\"%I64u\"") + ENDIF() +ENDIF() +# +IF(INT64_HAS_SIZE LESS 8) + CHECK_TYPE_SIZE("signed long" INT64_HAS_SIZE) + IF(INT64_HAS_SIZE EQUAL 8) + SET(INT64_S "signed long") + SET(INT64_FORMAT_S "\"%ld\"") + ENDIF() +ENDIF() +# +IF(UINT64_HAS_SIZE LESS 8) + CHECK_TYPE_SIZE("unsigned long" UINT64_HAS_SIZE) + IF(UINT64_HAS_SIZE EQUAL 8) + SET(UINT64_S "unsigned long") + SET(UINT64_FORMAT_S "\"%lu\"") + ENDIF() +ENDIF() +# +IF(INT64_HAS_SIZE LESS 8) + IF(UNIX) + CHECK_TYPE_SIZE("signed long long" LONG_LONG_HAS_SIZE) + IF(LONG_LONG_HAS_SIZE EQUAL 8) + SET(INT64_S "signed long long") + SET(INT64_FORMAT_S "\"%lld\"") + SET(INT64_HAS_SIZE 8) + ENDIF() + ELSE() + CHECK_TYPE_SIZE("signed long long" LONG_LONG_HAS_SIZE) + IF(LONG_LONG_HAS_SIZE EQUAL 8) + SET(INT64_S "signed long long") + SET(INT64_FORMAT_S "\"%I64d\"") + SET(INT64_HAS_SIZE 8) + ENDIF() + ENDIF() +ENDIF() +# +IF(UINT64_HAS_SIZE LESS 8) + IF(UNIX) + CHECK_TYPE_SIZE("unsigned long long" ULONG_LONG_HAS_SIZE) + IF(ULONG_LONG_HAS_SIZE EQUAL 8) + SET(UINT64_S "unsigned long long") + SET(UINT64_FORMAT_S "\"%llu\"") + SET(UINT64_HAS_SIZE 8) + ENDIF() + ELSE() + CHECK_TYPE_SIZE("unsigned long long" ULONG_LONG_HAS_SIZE) + IF(ULONG_LONG_HAS_SIZE EQUAL 8) + SET(UINT64_S "unsigned long long") + SET(UINT64_FORMAT_S "\"%I64u\"") + SET(UINT64_HAS_SIZE 8) + ENDIF() + ENDIF() +ENDIF() +# +IF(INT64_HAS_SIZE LESS 8) + CHECK_TYPE_SIZE("signed long" INT64_HAS_SIZE) + IF(INT64_HAS_SIZE) + SET(INT64_S "signed long") + SET(INT64_FORMAT_S "\"%ld\"") + ENDIF() +ENDIF() +# +IF(UINT64_HAS_SIZE LESS 8) + CHECK_TYPE_SIZE("unsigned long" UINT64_HAS_SIZE) + IF(UINT64_HAS_SIZE) + SET(UINT64_S "unsigned long") + SET(UINT64_FORMAT_S "\"%lu\"") + ENDIF() +ENDIF() +# +#MESSAGE(STATUS "INT64_HAS_SIZE => ${INT64_HAS_SIZE}") +#MESSAGE(STATUS "UINT64_HAS_SIZE => ${UINT64_HAS_SIZE}") +# diff --git a/src/bin/fltk/flviewer/CMake/vers.cmake b/src/bin/fltk/flviewer/CMake/vers.cmake new file mode 100644 index 00000000..cde6df18 --- /dev/null +++ b/src/bin/fltk/flviewer/CMake/vers.cmake @@ -0,0 +1,3 @@ +SET(FLVIEWER_VERSION_MAJOR 0) +SET(FLVIEWER_VERSION_MINOR 2) +SET(FLVIEWER_VERSION_PATCH 4) diff --git a/src/bin/fltk/flviewer/CMakeLists.txt b/src/bin/fltk/flviewer/CMakeLists.txt new file mode 100644 index 00000000..bd1af599 --- /dev/null +++ b/src/bin/fltk/flviewer/CMakeLists.txt @@ -0,0 +1,172 @@ +# +PROJECT(flviewer) +SET(exe flviewer) +# +# +IF(CMAKE_COMPILER_IS_GNUCC) +SET(CMAKE_CXX_FLAGS "-Wall -Wunused-but-set-variable -Wunused-variable ${CMAKE_CXX_FLAGS}") +ENDIF() +# +INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/CMake/vers.cmake) + +SET(FLVIEWER_VERSION + "${FLVIEWER_VERSION_MAJOR}.${FLVIEWER_VERSION_MINOR}.${FLVIEWER_VERSION_PATCH}") +SET(FLVIEWER_PACKAGE_STRING "flviewer-${FLVIEWER_VERSION}") +# +SET(FLVIEWER_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +# +SET(CMAKE_MODULE_PATH + ${CMAKE_CURRENT_SOURCE_DIR}/CMake + ${CMAKE_MODULE_PATH} +) +#------- fltk-1.3.x +FIND_PACKAGE(FLTK REQUIRED) +FIND_PACKAGE(JPEG) +# +ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS) +#------------------------------------------------- +INCLUDE_DIRECTORIES( + ${FLTK_INCLUDE_DIR} + ${JPEG_INCLUDE_DIR} + ${PNG_INCLUDE_DIRNAME} + ${ZLIB_INCLUDE_DIRNAME} + ${LCMS_INCLUDE_DIRNAME} + ${CMAKE_CURRENT_SOURCE_DIR} + ${OPENJPEG_BINARY_DIR}/src/lib/openjp2 #opj_config.h + ${OPENJPEG_BINARY_DIR}/src/bin/common # opj_apps_config.h + ${OPENJPEG_SOURCE_DIR}/src/lib/openjp2 + ${OPENJPEG_BINARY_DIR}/src/bin/fltk/flviewer + ${CMAKE_CURRENT_BINARY_DIR} +) +if(BUILD_THIRDPARTY) + include_directories( + ${OPENJPEG_SOURCE_DIR}/thirdparty/include + ${OPENJPEG_SOURCE_DIR}/thirdparty/liblcms2/include + ${OPENJPEG_SOURCE_DIR}/thirdparty/libpng + ${OPENJPEG_SOURCE_DIR}/thirdparty/libtiff + ${OPENJPEG_BINARY_DIR}/thirdparty/libtiff + ) +endif() +# +IF(UNIX) + FIND_PACKAGE(Threads) +ELSE() + IF(WIN32) + FIND_PACKAGE(NPTH) + ENDIF() +ENDIF() +# +SET(HAVE_THREADS) +SET(HAVE_WINPORT) +INCLUDE(${CMAKE_ROOT}/Modules/CheckPrototypeDefinition.cmake) +# +IF(WIN32) + IF(NPTH_FOUND) + SET(HAVE_THREADS 1) + ELSE() + SET(HAVE_THREADS 1) + SET(HAVE_WINPORT 1) + ENDIF() +ELSE() #UNIX + IF(CMAKE_HAVE_THREADS_LIBRARY) + SET(HAVE_THREADS 1) + ENDIF() +ENDIF() +#------------------- +IF(UNIX) + FIND_PROGRAM(FLTK_CONFIG_SCRIPT fltk-config PATHS ${FLTK_BIN_DIR}) +# + IF(BUILD_FLVIEWER_WITH_SHARED_LIBS) + EXEC_PROGRAM(${FLTK_CONFIG_SCRIPT} ARGS --use-images --ldflags + OUTPUT_VARIABLE FLIBS) + SET(LIBS ${FLIBS} ${JPEG_LIBRARIES}) + ELSE() + EXEC_PROGRAM(${FLTK_CONFIG_SCRIPT} ARGS --use-images --ldstaticflags + OUTPUT_VARIABLE FLIBS) + SET(LIBS ${FLIBS} ${JPEG_LIBRARIES}) + ENDIF() +ELSE() + SET(LIBS ${FLTK_BASE_LIBRARY} ${FLTK_FORMS_LIBRARY} ${FLTK_GL_LIBRARY} ${FLTK_IMAGES_LIBRARY} ) +# IF(NOT FLTK_SKIP_OPENGL) +# SET(LIBS ${LIBS} ${FLTK_GL_LIBRARY}) +# ENDIF() + IF(BUILD_FLVIEWER_WITH_SHARED_LIBS) + SET(LIBS ${LIBS} ${JPEG_LIBRARIES}) + ELSE() +#If fltk has been compiled statically: +#please enter the full paths of zlib.lib, fltkjpeg.lib, fltkpng.lib +#SET(LIBS ${LIBS} C:/Public/Users/lib/zlib.lib C:/Public/Users/lib/fltkjpeg.lib C:/Public/Users/lib/fltkpng.lib +#SET(LIBS ${LIBS} C:/WINDOWS/system32/user/lib/zlib.lib C:/WINDOWS/system32/user/lib/fltkjpeg.lib C:/WINDOWS/system32/user/lib/fltkpng.lib ) + ENDIF() +ENDIF() +#------------------- +SET(SRCS flviewer.cxx ps_image.cxx print_gui.cxx rgb_color.cxx) +SET(SRCS ${SRCS} color.cxx read_jpeg2000.cxx read_mj2.cxx read_jpx.cxx read_jpm.cxx) +# +IF(OPJ_HAVE_LIBPNG) + SET(SRCS ${SRCS} PNG.cxx) + SET(LIBS ${LIBS} ${PNG_LIBNAME} ${Z_LIBNAME}) +ENDIF() +# +SET(SRCS ${SRCS} OPENJPEG.cxx PGX.cxx OPENMJ2.cxx JP2.cxx) +# +#IF(BUILD_JPWL AND BUILD_FLVIEWER_WITH_JPWL_LIB) +# INCLUDE_DIRECTORIES(${OPENJPEGJPWL_INCLUDE_DIR}) +# SET(LIBS ${LIBS} ${OPENJPEGJPWL_LIBRARY_NAME}) +#ELSE() + INCLUDE_DIRECTORIES(${OPENJPEG_INCLUDE_DIR}) + SET(LIBS ${LIBS} ${OPENJPEG_LIBRARY_NAME}) +#ENDIF() +# +IF(OPJ_HAVE_LIBLCMS2 OR OPJ_HAVE_LIBLCMS1) + SET(LIBS ${LIBS} ${LCMS_LIBNAME}) +ENDIF() +# +IF(BUILD_WITH_GERMAN) + SET(WITH_GERMAN 1) +ELSE() + SET(WITH_ENGLISH 1) +ENDIF() +# +INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/CMake/defs.cmake) +# +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake + ${CMAKE_CURRENT_BINARY_DIR}/config.h) +# +IF(UNIX) + IF("${FLTK_MATH_LIBRARY}" STREQUAL "FLTK_MATH_LIBRARY-NOTFOUND") + MESSAGE("FLTK_MATH_LIBRARY NOT FOUND") + ELSE() + SET(LIBS ${LIBS} ${FLTK_MATH_LIBRARY}) + ENDIF() +ENDIF() +# +IF(WIN32) + IF(BUILD_FLVIEWER_WITH_SHARED_LIBS) + ADD_DEFINITIONS(-DOPJ_EXPORTS) + ELSE() + ADD_DEFINITIONS(-DOPJ_STATIC) + ENDIF() +ENDIF() +# +ADD_EXECUTABLE(${exe} ${SRCS}) +# +TARGET_LINK_LIBRARIES(${exe} ${LIBS}) +# +IF(UNIX) + TARGET_LINK_LIBRARIES(${exe} m) +ENDIF() +# +IF(MSVC) +SET_TARGET_PROPERTIES(${exe} PROPERTIES LINK_FLAGS_RELEASE + "/NODEFAULTLIB:libcmt.lib + /NODEFAULTLIB:libcmtd.lib + /NODEFAULTLIB:msvcrtd.lib + /SUBSYSTEM:CONSOLE" ) +ENDIF() +# +INSTALL(TARGETS ${exe} + RUNTIME + DESTINATION bin +) +# diff --git a/src/bin/fltk/flviewer/JP2.cxx b/src/bin/fltk/flviewer/JP2.cxx new file mode 100644 index 00000000..c16370ce --- /dev/null +++ b/src/bin/fltk/flviewer/JP2.cxx @@ -0,0 +1,1203 @@ +#include +/* + * author(s) and license +*/ +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#include +#define strcasecmp _stricmp +#define strncasecmp _strnicmp +#define snprintf _snprintf +#define sprintf _scprintf +#define strdup _strdup +#else /* not _WIN32 */ +#define __STDC_FORMAT_MACROS +#include +#include +#endif /* _WIN32 */ + +#include + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#include "openjpeg.h" +#include "opj_apps_config.h" +#include "color.hh" + } +#else +#include "openjpeg.h" +#include "opj_apps_config.h" +#include "color.hh" +#endif /* __cplusplus */ + + +#include "flviewer.hh" +#include "viewerdefs.hh" +#include "tree.hh" +#include "JP2.hh" +#include "lang/opj_lang.h_utf8" +#include "viewerdefs.hh" + +//#define DEBUG_NUMCOMPS + +#define READ_JP2 1 +#define WRITE_JP2 0 + +static void dst_destroy(ImageInfo *dst) +{ + if(dst->free_red) free(dst->red); + if(dst->free_green) free(dst->green); + if(dst->free_blue) free(dst->blue); +// do NOT free dst->alpha +} + +static unsigned char *read_image(opj_image_t *image, ImageInfo *dst, + int *out_type, unsigned int *out_w, unsigned int *out_h) +{ + unsigned char *dst_buf, *d; + int *red, *green, *blue, *alpha; + int compw, comph, max_comp, i, has_alpha, triple; + size_t j, max; + int shiftR, shiftG, shiftB, shiftA; + int addR, addG, addB, addA; + unsigned int mask = 0xffff; + + if(image->color_space == OPJ_CLRSPC_SYCC) + { + +fprintf(stderr,"%s:%d:\n\tINTERNAL ERROR\n",__FILE__,__LINE__); + + return NULL; /* handled in COLOR_sycc_to_rgb() */ + } + has_alpha = 0; triple = 0; + max_comp = dst->numcomps; + +#ifdef DEBUG_NUMCOMPS +fprintf(stderr,"%s:%d:\n\tENTER read_image\n\tmax_comp(%d)" +" color_space(%d)\n",__FILE__,__LINE__,max_comp,dst->color_space); + +fprintf(stderr,"\tDX(%d,%d,%d) DY(%d,%d,%d) PREC(%d,%d,%d) SIGNED(%d,%d,%d)\n", +dst->dx[0],dst->dx[1],dst->dx[2], +dst->dy[0],dst->dy[1],dst->dy[2], +dst->prec[0],dst->prec[1],dst->prec[2], +dst->sgnd[0],dst->sgnd[1],dst->sgnd[2]); + +fprintf(stderr,"\tRED(%p) GREEN(%p) BLUE(%p) ALPHA(%p)\n\n",(void*)dst->red, +(void*)dst->green,(void*)dst->blue,(void*)dst->alpha); +#endif + + if(max_comp > 4) max_comp = 4; + + if(dst->color_space == OPJ_CLRSPC_GRAY + && max_comp > 2) + { + max_comp -= 2; + } + + if((max_comp <= 2) + || (max_comp > 2 && max_comp < 5 + && dst->dx[0] == dst->dx[1] + && dst->dx[1] == dst->dx[2] + && dst->dy[0] == dst->dy[1] + && dst->dy[1] == dst->dy[2] + && dst->prec[0] == dst->prec[1] + && dst->prec[1] == dst->prec[2] + )) + { + int pix, ushift, dshift, prec0, force8; + + has_alpha = (max_comp == 4 || max_comp == 2); + triple = (max_comp > 2); + + compw = image->comps[0].w; + comph = image->comps[0].h; + max = compw * comph; + shiftR = shiftG = shiftB = shiftA = 0; + green = blue = alpha = NULL; + prec0 = dst->prec[0]; + force8 = (prec0 < 8); + + if(prec0 > 16) + { + fprintf(stderr,"%s:%d:\n\tPREC(%d) not handled. Quitting.\n", + __FILE__,__LINE__,prec0); + return NULL; + } + dshift = ushift = 0; + + if(prec0 > 8) + shiftR = prec0 - 8; + + if(triple) + { + if(dst->prec[1] > 8) + shiftG = dst->prec[1] - 8; + + if(dst->prec[2] > 8) + shiftB = dst->prec[2] - 8; + } + + if(force8) + { + ushift = 8 - prec0; dshift = prec0 - ushift; + + if(prec0 == 7) mask = 0x0000007f; + else + if(prec0 == 6) mask = 0x0000003f; + else + if(prec0 == 5) mask = 0x0000001f; + else + if(prec0 == 4) mask = 0x0000000f; + else + if(prec0 == 3) mask = 0x00000007; + else + if(prec0 == 2) mask = 0x00000003; + else +/* if(prec0 == 1) */ mask = 0x00000001; + + } + addR = (dst->sgnd[0] ? 1<<(prec0 - 1) : 0); + addG = addB = addA = 0; + + if(triple) + { + addG = + (dst->sgnd[1] ? 1<<(dst->prec[1] - 1) : 0); + addB = + (dst->sgnd[2] ? 1<<(dst->prec[2] - 1) : 0); + } + + if(has_alpha) + { + i = (triple?3:1); + + alpha = dst->alpha; + + if(alpha == NULL) + has_alpha = 0; + else + { + if(dst->prec[i] > 8) + shiftA = dst->prec[i] - 8; + + addA = + (dst->sgnd[i] ? 1<<(dst->prec[i] - 1) : 0); + } + } + *out_type = (int)max_comp; + + *out_w = compw; *out_h = comph; + + d = dst_buf = (unsigned char*)malloc(max * max_comp); + + red = dst->red; + + if(triple) + { + green = dst->green; + + blue = dst->blue; + } + + for(j = 0; j < max; ++j) + { + pix = *red++ + addR; + + if(force8) + { + pix = pix&mask; + pix = (pix<>dshift); + } + else// prec >= 8 and <= 16 + { + if(shiftR) pix = ((pix>>shiftR)+((pix>>(shiftR-1))%2)); + + if(pix > 255) pix = 255; else if(pix < 0) pix = 0; + } + *d++ = (unsigned char)pix; + + if(triple) + { + pix = *green++ + addG; + if(force8) + { + pix = pix&mask; + pix = (pix<>dshift); + } + else// prec >= 8 and <= 16 + { + if(shiftG) pix = ((pix>>shiftG)+((pix>>(shiftG-1))%2)); + + if(pix > 255) pix = 255; else if(pix < 0) pix = 0; + } + *d++ = (unsigned char) pix; + + pix = *blue++ + addB; + if(force8) + { + pix = pix&mask; + pix = (pix<>dshift); + } + else// prec >= 8 and <= 16 + { + if(shiftB) pix = ((pix>>shiftB)+((pix>>(shiftB-1))%2)); + + if(pix > 255) pix = 255; else if(pix < 0) pix = 0; + } + *d++ = (unsigned char) pix; + } /* if(triple) */ + + if(has_alpha) + { + pix = *alpha++ + addA; + if(force8) + { + pix = pix&mask; + pix = (pix<>dshift); + } + else + { + if(shiftA) pix = ((pix>>shiftA)+((pix>>(shiftA-1))%2)); + + if(pix > 255) pix = 255; else if(pix < 0) pix = 0; + } + *d++ = (unsigned char) pix; + } + } //for(j = 0; j < max; ++j) + + return dst_buf; + }// if((max_comp <= 2) ... ) + + return NULL; + +}// read_image() + +static OPJ_CODEC_FORMAT ext_codec_format(const char *filename) +{ + unsigned int i; + + static const char *extension[] = + { + "j2k", "jp2", "j2c", "jpc" + }; + + static const OPJ_CODEC_FORMAT format[] = + { +/* J2K_CFMT, JP2_CFMT, J2K_CFMT, J2K_CFMT */ + OPJ_CODEC_J2K, OPJ_CODEC_JP2, OPJ_CODEC_J2K, OPJ_CODEC_J2K + }; + + const char *ext = strrchr(filename, '.'); + if(ext) + { + ext++; + if(*ext) + { + for(i = 0; i < sizeof(format)/sizeof(*format); i++) + { + if(strncasecmp(ext, extension[i], 3) == 0) + return format[i]; + } + } + } + return OPJ_CODEC_UNKNOWN; +} + +static opj_image_t *to_opj_image(const unsigned char *buf, + int width, int height, + int nr_comp, int sub_dx, int sub_dy) +{ + const unsigned char *cs; + opj_image_t *image; + int *r, *g, *b, *a; + int has_rgba, has_graya, has_rgb, comp; + unsigned int i, max; + opj_image_cmptparm_t cmptparm[4]; + + memset(&cmptparm, 0, 4 * sizeof(opj_image_cmptparm_t)); + + for(comp = 0; comp < nr_comp; ++comp) + { + cmptparm[comp].prec = 8; + cmptparm[comp].bpp = 8; + cmptparm[comp].sgnd = 0; + cmptparm[comp].dx = sub_dx; + cmptparm[comp].dy = sub_dy; + cmptparm[comp].w = width; + cmptparm[comp].h = height; + } + + { + OPJ_COLOR_SPACE csp = (nr_comp > 2?OPJ_CLRSPC_SRGB:OPJ_CLRSPC_GRAY); + + image = opj_image_create(nr_comp, &cmptparm[0], csp); + } + + if(image == NULL) + { + fl_alert("%s", GOT_NO_IMAGE_s); + + return NULL; + } + + image->x0 = 0; + image->y0 = 0; + image->x1 = (width - 1) * sub_dx + 1; + image->y1 = (height - 1) * sub_dy + 1; + + r = g = b = a = NULL; + has_rgba = has_graya = has_rgb = 0; + + if(nr_comp == 4) /* RGBA */ + { + has_rgba = 1; + r = image->comps[0].data; + g = image->comps[1].data; + b = image->comps[2].data; + a = image->comps[3].data; + } + else + if(nr_comp == 2) /* GA */ + { + has_graya = 1; + r = image->comps[0].data; + a = image->comps[1].data; + } + else + if(nr_comp == 3) /* RGB */ + { + has_rgb = 1; + r = image->comps[0].data; + g = image->comps[1].data; + b = image->comps[2].data; + } + else /* G */ + { + r = image->comps[0].data; + } + cs = buf; + max = height * width; + + for(i = 0; i < max; ++i) + { + if(has_rgba) + { +#ifdef OPJ_BIG_ENDIAN +//RGBA + *r++ = (int)*cs++; *g++ = (int)*cs++; *b++ =(int)*cs++;; + *a++ = (int)*cs++; + continue; +#else +//RGBA + *r++ = (int)*cs++; *g++ = (int)*cs++; *b++ =(int)*cs++;; + *a++ = (int)*cs++; + continue; +#endif + } + + if(has_rgb) + { +#ifdef OPJ_BIG_ENDIAN +//RGB + *r++ = (int)*cs++; *g++ = (int)*cs++; *b++ = (int)*cs++; + continue; +#else +//RGB + *r++ = (int)*cs++; *g++ = (int)*cs++; *b++ = (int)*cs++; + continue; +#endif + } + + if(has_graya) + { +#ifdef OPJ_BIG_ENDIAN +//RA + *r++ = (int)*cs++; *a++ = (int)*cs++; + continue; +#else +//RA + *r++ = (int)*cs++; *a++ = (int)*cs++; + continue; +#endif + } +/* G */ + *r++ = *cs++; + + }/* for(i = 0; i < max; ++i) */ + + return image; + +}/* to_opj_image() */ + +void JP2_save_file(Canvas *canvas, const char *write_idf) +{ + FILE *writer; + opj_cparameters_t parameters; + opj_image_t *image; + int width, height, nr_comp, sub_dx, sub_dy; + OPJ_CODEC_FORMAT codec_format; + + codec_format = ext_codec_format(write_idf); + + if(codec_format < (OPJ_CODEC_FORMAT)0) + { + fl_alert(WRONG_DST_EXT_s, write_idf); + return; + } + if((writer = fopen(write_idf, "wb")) == NULL) + { + fl_alert(DST_DID_NOT_OPEN_s, write_idf); + return; + } + opj_set_default_encoder_parameters(¶meters); + + if(parameters.cp_comment == NULL) + { + char buf[80]; + snprintf(buf, 80, "Created by OpenJPEG version %s", opj_version()); + parameters.cp_comment = strdup(buf); + } + + if (parameters.tcp_numlayers == 0) + { + parameters.tcp_rates[0] = 0; /* MOD antonin : losslessbug */ + parameters.tcp_numlayers++; + parameters.cp_disto_alloc = 1; + } + sub_dx = parameters.subsampling_dx; + sub_dy = parameters.subsampling_dy; + + width = canvas->new_iwidth; + height = canvas->new_iheight; + nr_comp = canvas->new_idepth; +/*--------------------------------------------------------*/ + image = to_opj_image((unsigned char*)canvas->cbuf, + width, height, nr_comp, sub_dx, sub_dy); +/*--------------------------------------------------------*/ + if(image == NULL) + { + fl_alert("%s", WRITE_JP2_FAILS_s); + free(parameters.cp_comment); + return; + } + { + opj_stream_t *stream; + opj_codec_t* codec; + + stream = NULL; + parameters.tcp_mct = image->numcomps == 3 ? 1 : 0; + + fclose(writer); writer = NULL; + + codec = opj_create_compress(codec_format); + + if(codec == NULL) goto fin; + + opj_setup_encoder(codec, ¶meters, image); + + stream = + opj_stream_create_default_file_stream(write_idf, WRITE_JP2); + + if(stream == NULL) goto fin; + + if( !opj_start_compress(codec,image,stream)) goto fin; + + if( !opj_encode(codec, stream)) goto fin; + + opj_end_compress(codec, stream); + +fin: + + if(stream) opj_stream_destroy(stream); + + if(codec) opj_destroy_codec(codec); + + opj_image_destroy(image); + + free(parameters.cp_comment); + } + +}//JP2_save_file() + +static unsigned char *read_image_component(opj_image_t *local_image, + int selected_component, + int *out_type, unsigned int *out_w, unsigned int *out_h) +{ + unsigned char *dst_buf, *d; + int *red; + int compw, comph, max_comp; + size_t j, max; + int shiftR, addR; + unsigned int mask = 0xffff; + int pix, ushift, dshift, prec, force8; + int is_rgb; + + prec = local_image->comps[0].prec; + + if(prec > 16) + { + fprintf(stderr,"%s:%d:\n\tread_image_component\n" + "\tPREC(%d) not handled. Quitting.\n",__FILE__,__LINE__,prec); + + return NULL; + } + max_comp = local_image->numcomps; + + if(max_comp > 4) max_comp = 4; + + if((max_comp == 1)) + { +// Nothing to do: + *out_w = local_image->comps[0].w; + *out_h = local_image->comps[0].h; + + return NULL; + } + is_rgb = + ( local_image->color_space <= OPJ_CLRSPC_SRGB + || local_image->color_space == OPJ_CLRSPC_GRAY + ); + + if(is_rgb + && (max_comp == 2 || max_comp == 4) )//GRAYA or RGBA + { + --max_comp;//1 or 3 in SRGB + } +//----------------------------- + --selected_component; +//----------------------------- +//SRGB,GRAY,SYCC,EYCC,CMYK + is_rgb = + ( local_image->color_space <= OPJ_CLRSPC_SRGB + || local_image->color_space == OPJ_CLRSPC_GRAY + || local_image->color_space == OPJ_CLRSPC_CMYK + ); + + if(is_rgb) + { + compw = local_image->comps[selected_component].w; + comph = local_image->comps[selected_component].h; + } + else +// YUV420_FORMAT + if((local_image->comps[0].dx == 1) + && (local_image->comps[1].dx == 2) + && (local_image->comps[2].dx == 2) + && (local_image->comps[0].dy == 1) + && (local_image->comps[1].dy == 2) + && (local_image->comps[2].dy == 2))// horizontal and vertical sub-sample + { + compw = local_image->comps[selected_component].w; + comph = local_image->comps[selected_component].h; + + } + else +// YUV422 + if((local_image->comps[0].dx == 1) + && (local_image->comps[1].dx == 2) + && (local_image->comps[2].dx == 2) + && (local_image->comps[0].dy == 1) + && (local_image->comps[1].dy == 1) + && (local_image->comps[2].dy == 1))// horizontal sub-sample onl + { + compw = local_image->comps[selected_component].w; + comph = local_image->comps[selected_component].h; + } + else +// YUV444 + if((local_image->comps[0].dx == 1) + && (local_image->comps[1].dx == 1) + && (local_image->comps[2].dx == 1) + && (local_image->comps[0].dy == 1) + && (local_image->comps[1].dy == 1) + && (local_image->comps[2].dy == 1))// no sub-sample + { + compw = local_image->comps[selected_component].w; + comph = local_image->comps[selected_component].h; + } + else + { + fprintf(stderr,"%s:%d:\n\tread_image_component fails.\n" + "\tImage type unknown. Quitting.\n",__FILE__,__LINE__); +// Nothing to do: + *out_w = local_image->comps[0].w; + *out_h = local_image->comps[0].h; + + return NULL; + } + *out_type = 1;//MONO + *out_w = compw; + *out_h = comph; + + max = compw * comph; + + shiftR = 0; + force8 = (prec < 8); + + dshift = ushift = 0; + + if(prec > 8) + shiftR = prec - 8; + + if(force8) + { + ushift = 8 - prec; dshift = prec - ushift; + + if(prec == 7) mask = 0x0000007f; + else + if(prec == 6) mask = 0x0000003f; + else + if(prec == 5) mask = 0x0000001f; + else + if(prec == 4) mask = 0x0000000f; + else + if(prec == 3) mask = 0x00000007; + else + if(prec == 2) mask = 0x00000003; + else +/* if(prec == 1) */ mask = 0x00000001; + } + + addR = + (local_image->comps[selected_component].sgnd ? 1<<(prec - 1) : 0); + + d = dst_buf = (unsigned char*)malloc(max); + + red = local_image->comps[selected_component].data; + + for(j = 0; j < max; ++j) + { + pix = *red++ + addR; + + if(force8) + { + pix = pix&mask; + pix = (pix<>dshift); + } + else// prec >= 8 and <= 16 + { + if(shiftR) pix = ((pix>>shiftR)+((pix>>(shiftR-1))%2)); + + if(pix > 255) pix = 255; else if(pix < 0) pix = 0; + } + *d++ = (unsigned char)pix; + + }//for(j = 0; j < max; ++j) + + return dst_buf; + +}/* read_image_component() */ + +typedef struct buffer_info +{ + unsigned char *sample_buf; + unsigned char *cur_buf; + uint64_t sample_size; + +}BufferInfo; + +static OPJ_SIZE_T read_from_buffer(void *p_buffer, OPJ_SIZE_T p_nb_bytes, + BufferInfo *bufinfo) +{ + OPJ_SIZE_T l_nb_read; + unsigned char *sample_end = + (bufinfo->sample_buf + bufinfo->sample_size); + + if((bufinfo->cur_buf + (ptrdiff_t)p_nb_bytes) < sample_end) + { + l_nb_read = p_nb_bytes; + } + else + { + l_nb_read = (OPJ_SIZE_T)(sample_end - bufinfo->cur_buf); + } + + if(l_nb_read > 0) + { + memcpy(p_buffer, bufinfo->cur_buf, l_nb_read); + bufinfo->cur_buf += l_nb_read; + } + return l_nb_read ? l_nb_read : (OPJ_SIZE_T)-1; +} + +static OPJ_SIZE_T write_from_buffer(void *p_buffer, OPJ_SIZE_T p_nb_bytes, + BufferInfo *bufinfo) +{ + memcpy(bufinfo->cur_buf,p_buffer, p_nb_bytes); + bufinfo->cur_buf += (ptrdiff_t)p_nb_bytes; + bufinfo->sample_size += p_nb_bytes; + + return p_nb_bytes; +} + +static OPJ_OFF_T skip_from_buffer(OPJ_OFF_T p_nb_bytes, + BufferInfo *bufinfo) +{ + unsigned char *sample_end = + (bufinfo->sample_buf + bufinfo->sample_size); + OPJ_OFF_T delta; + + if(sample_end > bufinfo->cur_buf) + delta = (sample_end - bufinfo->cur_buf); + else + delta = 0; + + if(p_nb_bytes <= delta) + { + bufinfo->cur_buf += p_nb_bytes; + + return p_nb_bytes; + } + bufinfo->cur_buf = sample_end; + + + return p_nb_bytes; +} + +static OPJ_BOOL seek_from_buffer(OPJ_OFF_T p_nb_bytes, + BufferInfo *bufinfo) +{ + if((uint64_t)p_nb_bytes <= bufinfo->sample_size ) + { + bufinfo->cur_buf = (bufinfo->sample_buf + (ptrdiff_t)p_nb_bytes); + + return OPJ_TRUE; + } + bufinfo->cur_buf = (bufinfo->sample_buf + (ptrdiff_t)bufinfo->sample_size); + + return OPJ_FALSE; +} + +static opj_stream_t* stream_create_buffer_stream(BufferInfo *bufinfo, + OPJ_SIZE_T p_size, OPJ_BOOL p_is_read_stream) +{ + opj_stream_t* l_stream; + + l_stream = opj_stream_create(p_size, p_is_read_stream); + + if(! l_stream) return NULL; + + opj_stream_set_user_data(l_stream, bufinfo, NULL); + + opj_stream_set_user_data_length(l_stream, + bufinfo->sample_size); + + opj_stream_set_read_function(l_stream, + (opj_stream_read_fn) read_from_buffer); + + opj_stream_set_write_function(l_stream, + (opj_stream_write_fn) write_from_buffer); + + opj_stream_set_skip_function(l_stream, + (opj_stream_skip_fn) skip_from_buffer); + + opj_stream_set_seek_function(l_stream, + (opj_stream_seek_fn) seek_from_buffer); + + return l_stream; +} + +// +// DO NOT FREE src; is freed outside in OPENMJ2.cxx +// +unsigned char *JP2_decode(const char *read_idf, unsigned char *src, + uint64_t fsize, int is_still, int decod_format, + unsigned int *out_width, unsigned int *out_height, + int *out_type, int *out_selected) +{ + opj_image_t *l_image; + opj_codec_t *l_codec; + opj_stream_t *l_stream; + unsigned char *dst_buf; + unsigned int numcomps; + int cur_tile, cur_reduction, max_tiles, max_reduction; + int selected_component, fails; + BufferInfo bufinfo; + opj_dparameters_t parameters; + OPJ_CODEC_FORMAT codec_format; + ImageInfo dst; + + *out_width = 0; *out_height = 0; *out_type = -1; + *out_selected = -1; + + memset(&bufinfo, 0, sizeof(BufferInfo)); + fails = 1; + cur_tile = -1; cur_reduction = 0; max_tiles = max_reduction = 0; + l_codec = NULL; l_stream = NULL; l_image = NULL; + memset(¶meters, 0, sizeof(opj_dparameters_t)); + + opj_set_default_decoder_parameters(¶meters); + + strcpy(parameters.infile, read_idf); + parameters.decod_format = decod_format; + + parameters.cp_layer = FLViewer_layers(); + + if(decod_format == J2K_CFMT)//0 + codec_format = OPJ_CODEC_J2K; + else + if(decod_format == JP2_CFMT)//1 + codec_format = OPJ_CODEC_JP2; + else + if(decod_format == JPT_CFMT)//2 + codec_format = OPJ_CODEC_JPT; + else + { +/* clarified in infile_format() : */ + return NULL; + } + + if(is_still == 0)//MJ2 buffer + { + bufinfo.cur_buf = bufinfo.sample_buf = src; + bufinfo.sample_size = fsize; + + l_stream = + stream_create_buffer_stream(&bufinfo, fsize, READ_JP2); + } + else //STILL image, src == NULL + { + l_stream = + opj_stream_create_default_file_stream(read_idf, READ_JP2); + } + + if(l_stream == NULL) + { + fprintf(stderr,"%s:%d:\n\tSTREAM == NULL\n",__FILE__,__LINE__); + goto fin; + } + + l_codec = opj_create_decompress(codec_format); + + if(l_codec == NULL) + { + fprintf(stderr,"%s:%d:\n\tCODEC == NULL\n",__FILE__,__LINE__); + goto fin; + } + + if(is_still == 1) + { + FLViewer_wait(); + } + + if( !opj_setup_decoder(l_codec, ¶meters)) + { + fprintf(stderr,"%s:%d:\n\topj_setup_decoder failed\n",__FILE__,__LINE__); + goto fin; + } + + FLViewer_get_tile_and_reduction(&cur_tile, &cur_reduction); + + opj_set_decoded_resolution_factor(l_codec, cur_reduction); + + if( !opj_read_header(l_stream, l_codec, &l_image)) + { + fprintf(stderr,"%s:%d:\n\topj_read_header failed\n",__FILE__,__LINE__); + goto fin; + } + + FLViewer_get_max_tiles_and_reduction(&max_tiles, &max_reduction); + + if( !FLViewer_has_tile_and_reduction() + || (max_tiles <= 0) + || (max_reduction <= 0) ) + { + opj_codestream_info_v2_t *cstr; + + cstr = opj_get_cstr_info(l_codec); + + max_tiles = cstr->tw * cstr->th; + max_reduction = cstr->m_default_tile_info.tccp_info->numresolutions; + + FLViewer_put_max_tiles_and_reduction(max_tiles, max_reduction); + } + + if(cur_tile < 0) + { + int x0, y0, x1, y1; + + x0 = y0 = x1 = y1 = 0; + + if(FLViewer_has_area_values()) + { + FLViewer_get_area_values(&x0, &y0, &x1, &y1); + } + if( !opj_set_decode_area(l_codec, l_image, x0, y0, x1, y1)) + { + fprintf(stderr,"%s:%d:\n\topj_set_decode_area failed\n",__FILE__,__LINE__); + goto fin; + } + + if( !opj_decode(l_codec, l_stream, l_image)) + { + fprintf(stderr,"%s:%d:\n\topj_decode failed\n",__FILE__,__LINE__); + goto fin; + } + } + else /* decode a tile */ + { + if( !opj_get_decoded_tile(l_codec, l_stream, l_image, cur_tile)) + { + fprintf(stderr,"%s:%d:\n\topj_get_decoded_tile %d failed.\n", + __FILE__,__LINE__, cur_tile); + goto fin; + } + } + + if( !opj_end_decompress(l_codec, l_stream)) + { + fprintf(stderr,"%s:%d:\n\topj_end_decompress failed\n",__FILE__,__LINE__); + goto fin; + } + fails = 0; + +fin: +// DO NOT FREE src; is freed outside in OPENMJ2.cxx + + if(l_stream) opj_stream_destroy(l_stream); + + if(l_codec) opj_destroy_codec(l_codec); + + if(fails) + { + if(l_image) opj_image_destroy(l_image); + + fl_alert("%s\n %s", JP2_DECODE_FAILS_s, read_idf); + + FLViewer_reset_tiles_and_reduction(); + + return NULL; + } + + numcomps = l_image->numcomps; + + if(numcomps > 4) numcomps = 4; +#ifdef DEBUG_NUMCOMPS +fprintf(stderr,"%s:%d:\n\tTRACE numcomps(%d) color_space(%d)\n", +__FILE__,__LINE__,numcomps,l_image->color_space); +#endif + + memset(&dst, 0, sizeof(ImageInfo)); + + dst.is_still = is_still; + + dst.red = l_image->comps[0].data; + dst.dx[0] = l_image->comps[0].dx; + dst.dy[0] = l_image->comps[0].dy; + dst.prec[0] = l_image->comps[0].prec; + dst.sgnd[0] = l_image->comps[0].sgnd; + + if(numcomps > 1) + { + dst.green = l_image->comps[1].data; + dst.dx[1] = l_image->comps[1].dx; + dst.dy[1] = l_image->comps[1].dy; + dst.prec[1] = l_image->comps[1].prec; + dst.sgnd[1] = l_image->comps[1].sgnd; + } + if(numcomps > 2) + { + dst.blue = l_image->comps[2].data; + dst.dx[2] = l_image->comps[2].dx; + dst.dy[2] = l_image->comps[2].dy; + dst.prec[2] = l_image->comps[2].prec; + dst.sgnd[2] = l_image->comps[2].sgnd; + } + if(numcomps > 3) + { + dst.alpha = l_image->comps[3].data; + dst.dx[3] = l_image->comps[3].dx; + dst.dy[3] = l_image->comps[3].dy; + dst.prec[3] = l_image->comps[3].prec; + dst.sgnd[3] = l_image->comps[3].sgnd; + } + if(numcomps == 2)//GA + { + dst.alpha = l_image->comps[1].data; + dst.dx[3] = l_image->comps[1].dx; + dst.dy[3] = l_image->comps[1].dy; + dst.prec[3] = l_image->comps[1].prec; + dst.sgnd[3] = l_image->comps[1].sgnd; + } + + if(l_image->color_space < OPJ_CLRSPC_SRGB + && l_image->color_space >= 0 + && numcomps == 3 + && l_image->comps[0].dx == l_image->comps[0].dy + && l_image->comps[1].dx != 1 + ) + l_image->color_space = OPJ_CLRSPC_SYCC; + else + if(numcomps <= 2) + l_image->color_space = OPJ_CLRSPC_GRAY; + + dst.color_space = l_image->color_space; + dst.numcomps = numcomps; + + selected_component = FLViewer_component(); + + *out_selected = selected_component; + + if(selected_component) + { + dst_buf = + read_image_component(l_image, selected_component, + out_type, out_width, out_height); + } + else + { + if(l_image->color_space == OPJ_CLRSPC_GRAY) + FLViewer_set_max_components(1); + else + if(l_image->color_space <= OPJ_CLRSPC_SRGB + && numcomps > 3) + FLViewer_set_max_components(3); + else + FLViewer_set_max_components(l_image->numcomps); + +#ifdef DEBUG_NUMCOMPS +fprintf(stderr,"%s:%d:\n\tTRACE numcomps(%d) color_space(%d)\n" +"\tICC buf(%p) buflen(%d)\n", +__FILE__,__LINE__,numcomps,l_image->color_space, +(void*)l_image->icc_profile_buf,l_image->icc_profile_len); +#endif + + if(l_image->color_space == OPJ_CLRSPC_SYCC) + { + COLOR_sycc_to_rgb(l_image, &dst); + } + else + if(l_image->color_space == OPJ_CLRSPC_CMYK) + { + COLOR_cmyk_to_rgb(l_image, &dst); + } + else + if(l_image->color_space == OPJ_CLRSPC_EYCC) + { + COLOR_esycc_to_rgb(l_image, &dst); + } + + if(l_image->icc_profile_buf) + { +#if defined(OPJ_HAVE_LIBLCMS1) || defined(OPJ_HAVE_LIBLCMS2) + if(l_image->icc_profile_len) + { + COLOR_apply_icc_profile(l_image, &dst); + } + else + { + COLOR_apply_conversion(l_image, &dst); + } +#endif + } + + if(l_image->color_space == OPJ_CLRSPC_SYCC) + { + l_image->color_space = OPJ_CLRSPC_UNSPECIFIED; + } + + dst_buf = + read_image(l_image, &dst, out_type, out_width, out_height); + + dst_destroy(&dst); + + }//if(selected_component) + + opj_image_destroy(l_image); + + + return dst_buf; + +}// JP2_decode() + +// +// rgb_buffer ==> image ==> file +// +void JP2_file_from_rgb(const unsigned char *buf, unsigned int width, + unsigned int height, unsigned int numcomps, const char *write_idf) +{ + FILE *writer; + opj_cparameters_t parameters; + opj_image_t *image; + int sub_dx, sub_dy; + OPJ_CODEC_FORMAT codec_format; + + codec_format = OPJ_CODEC_JP2; + + if((writer = fopen(write_idf, "wb")) == NULL) + { + fl_alert(DST_DID_NOT_OPEN_s, write_idf); + return; + } + opj_set_default_encoder_parameters(¶meters); + + if(parameters.cp_comment == NULL) + { + char buf[80]; + snprintf(buf, 80, "Created by OpenJPEG version %s", opj_version()); + parameters.cp_comment = strdup(buf); + } + + if (parameters.tcp_numlayers == 0) + { + parameters.tcp_rates[0] = 0; /* MOD antonin : losslessbug */ + parameters.tcp_numlayers++; + parameters.cp_disto_alloc = 1; + } + sub_dx = parameters.subsampling_dx; + sub_dy = parameters.subsampling_dy; + +//-------------------------------------------------------- + image = to_opj_image(buf, (int)width, (int)height, + (int)numcomps, sub_dx, sub_dy); +//-------------------------------------------------------- + if(image == NULL) + { + fl_alert("%s", WRITE_JP2_FAILS_s); + free(parameters.cp_comment); + return; + } + { + opj_stream_t *stream; + opj_codec_t* codec; + + stream = NULL; + parameters.tcp_mct = image->numcomps == 3 ? 1 : 0; + + fclose(writer); writer = NULL; + + codec = opj_create_compress(codec_format); + + if(codec == NULL) goto fin; + + opj_setup_encoder(codec, ¶meters, image); + + stream = + opj_stream_create_default_file_stream(write_idf, WRITE_JP2); + + if(stream == NULL) goto fin; + + if( !opj_start_compress(codec,image,stream)) goto fin; + + if( !opj_encode(codec, stream)) goto fin; + + opj_end_compress(codec, stream); + +fin: + + if(stream) opj_stream_destroy(stream); + + if(codec) opj_destroy_codec(codec); + + opj_image_destroy(image); + + free(parameters.cp_comment); + } + +}//JP2_file_from_rgb() diff --git a/src/bin/fltk/flviewer/JP2.hh b/src/bin/fltk/flviewer/JP2.hh new file mode 100644 index 00000000..a9d0997d --- /dev/null +++ b/src/bin/fltk/flviewer/JP2.hh @@ -0,0 +1,15 @@ +#ifndef _JP2_HH_ +#define _JP2_HH_ + +#define JP2_FILE 1 +#define MJ2_FILE 0 + +extern void JP2_save_file(Canvas *canvas, const char *write_idf); +extern unsigned char *JP2_decode(const char *read_idf, unsigned char *src, + uint64_t fsize, int is_still, int decod_format, + unsigned int *out_width, unsigned int *out_height, + int *out_type, int *out_selected); +extern void JP2_file_from_rgb(const unsigned char *buf, unsigned int width, + unsigned int height, unsigned int numcomps, const char *write_idf); + +#endif // _JP2_HH_ diff --git a/src/bin/fltk/flviewer/OPENJPEG.cxx b/src/bin/fltk/flviewer/OPENJPEG.cxx new file mode 100644 index 00000000..64253947 --- /dev/null +++ b/src/bin/fltk/flviewer/OPENJPEG.cxx @@ -0,0 +1,74 @@ +#include +/* + * author(s) and license +*/ +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#include +#else /* not _WIN32 */ +#define __STDC_FORMAT_MACROS +#include +#endif /* _WIN32 */ + +#include + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#include "openjpeg.h" +#include "color.hh" + } +#else +#include "openjpeg.h" +#include "color.hh" +#endif /* __cplusplus */ + +#include "flviewer.hh" +#include "viewerdefs.hh" +#include "tree.hh" +#include "lang/opj_lang.h_utf8" + +#include "JP2.hh" +#include "OPENJPEG.hh" + +static unsigned char *openjpeg_buf; + +static void OPENJPEG_postlude(void) +{ + if(openjpeg_buf) { free(openjpeg_buf); openjpeg_buf = NULL; } +} + +void OPENJPEG_load(Canvas *canvas, const char *read_idf, + unsigned char *src, uint64_t fsize, int decod_format) +{ + unsigned char *dst; + int selected_component = 0; + unsigned int width, height; + int type; + + dst = + JP2_decode(read_idf, src, fsize, IS_STILL, decod_format, + &width, &height, &type, &selected_component); + + FLViewer_clear_wait(); + FLViewer_url(read_idf, width, height); + + if( !dst) return; + + canvas->read_idf = read_idf; + + FLViewer_use_buffer(dst, width, height, type); + + FLViewer_tiles_activate(1); + + FLViewer_area_activate(1); + + openjpeg_buf = dst; + + canvas->cleanup = &OPENJPEG_postlude; + +}/* OPENJPEG_load() */ diff --git a/src/bin/fltk/flviewer/OPENJPEG.hh b/src/bin/fltk/flviewer/OPENJPEG.hh new file mode 100644 index 00000000..82fb02e3 --- /dev/null +++ b/src/bin/fltk/flviewer/OPENJPEG.hh @@ -0,0 +1,8 @@ +#ifndef _FLVIEWER_OPENJPEG_HH_ +#define _FLVIEWER_OPENJPEG_HH_ + +extern void OPENJPEG_load(Canvas *canvas, const char *read_idf, + unsigned char *src, uint64_t fsize, int decod_format); + + +#endif /* _FLVIEWER_OPENJPEG_HH_ */ diff --git a/src/bin/fltk/flviewer/OPENMJ2.cxx b/src/bin/fltk/flviewer/OPENMJ2.cxx new file mode 100644 index 00000000..e322986f --- /dev/null +++ b/src/bin/fltk/flviewer/OPENMJ2.cxx @@ -0,0 +1,994 @@ +#include +/* + * author(s) and license +*/ +#include +#include +#include +#include +#ifdef _WIN32 +#include +#include +#else +#define __STDC_FORMAT_MACROS +#include +#include +#endif + +#ifdef HAVE_THREADS + +#if defined(HAVE_NPTH_THREADS) && defined(_WIN32) +#include +#elif defined(HAVE_WINPORT) +#include +#include + +#define WAIT_FOR_CONDVARS 5 +#else +#include +#endif + +#include "have_threads.hh" + +#endif /* HAVE_THREADS */ + +/* #define DEBUG_NEXT_FRAME */ + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#include "openjpeg.h" /* of version 2 */ + } +#else +#include "openjpeg.h" /* of version 2 */ +#endif /* __cplusplus */ + +#include +#include + +#include "flviewer.hh" +#include "tree.hh" +#include "viewerdefs.hh" +#include "lang/mj2_lang.h_utf8" + +#include "JP2.hh" +#include "OPENMJ2.hh" + + +/* FORWARD */ +typedef struct mj2_extract_info +{ + int cur_track; + unsigned int width; + unsigned int height; + unsigned int duration; + int cur_sample; + int max_samples; + int max_tracks; + unsigned int channels; +#ifdef HAVE_FSEEKO + off_t start_offset; +#elif HAVE_FSEEKI64 + int64_t start_offset; +#else + long start_offset; +#endif + double frame_rate; + + unsigned char *sample_buf; + + int sample_nr; + + FILE *reader; + const char *read_idf; +} MJ2Extract; + +typedef struct sample_info +{ + struct sample_info *next; + + unsigned char *sample_buf; + unsigned char *rgb_buf; + unsigned int sample_size; + int sample_nr; + int inserted; + + unsigned char *cur_buf; +}SampleInfo; + + +static void next_frame(void); +static void stop_timeout(); +static void load(Canvas *canvas, const char *read_idf); + +static void free_sample_info(SampleInfo *sinfo); +static unsigned char* extract_single_frame(MJ2Extract *exinfo); +static void decode_frame(MJ2Extract *exinfo, SampleInfo *sinfo); + +static void extract_frames_close(MJ2Extract *exinfo); +static MJ2Extract *extract_frames_open(const char *read_idf); + +#ifdef HAVE_THREADS + +static void threads_prelude(MJ2Extract *exinfo); +static void threads_postlude(MJ2Extract *exinfo); + +static int threads_stopped; +static int stop_threads; +static int sample_list_busy; + +static int elems_in_list; +#ifdef _WIN32 +#define MAX_ELEMS_IN_LIST 30 +#else +#define MAX_ELEMS_IN_LIST 20 +#endif + +static SampleInfo *sample_list_head, *sample_list_tail; + +#ifdef HAVE_WINPORT +static CRITICAL_SECTION sample_list_mutex; + +static CONDITION_VARIABLE sample_list_condGET; +static CONDITION_VARIABLE sample_list_condINSERTED; +#else +static PTHREAD_cond_t sample_list_condGET; +static PTHREAD_cond_t sample_list_condINSERTED; + +static PTHREAD_mutex_t sample_list_mutex; +#endif + +static unsigned char *get_rgb_buffer(void); + +typedef struct decoder_info +{ + MJ2Extract *exinfo; + SampleInfo *sample_info; +#ifdef HAVE_WINPORT + HANDLE tid; +#else + PTHREAD_t tid; +#endif + int ID; + +}Decoder; + +static Decoder *decoder; + +#endif /* HAVE_THREADS */ + +typedef struct mj2_info +{ + MJ2Extract *exinfo; + Canvas *canvas; + double delay; + int nr_threads; + + char paused, restarted, single_step_possible; + char single_step_mode, single_step_served; + +} OPENMJ2Info; + +static OPENMJ2Info play; + +/* RGB[A] buffers: */ +static unsigned char *openmj2_buf; +static unsigned char *play_buf; +static int play_buf_nr; + +static int mj2_stopped; + +#ifdef HAVE_THREADS + +static SampleInfo *new_sample_info(void) +{ + SampleInfo *sinfo; + + sinfo = (SampleInfo*)calloc(1,sizeof(SampleInfo)); + + if(sinfo == NULL) + { + exit(1); + } + if(sample_list_head == NULL) + sample_list_head = sinfo; + else + sample_list_tail->next = sinfo; + sample_list_tail = sinfo; + + return sinfo; +} +#endif /* HAVE_THREADS */ + + +static void OPENMJ2_postlude(void) +{ + mj2_stopped = 1; + + FLViewer_movie_runs(0); + FLViewer_frames_animation(0); + + if(play.exinfo) + { + stop_timeout(); +#ifdef HAVE_WINPORT + Fl::wait(0.5); +#endif +#ifdef HAVE_THREADS + if(!threads_stopped) + { + stop_threads = 1; + threads_postlude(play.exinfo); + } +#endif + extract_frames_close(play.exinfo); + } + memset(&play, 0, sizeof(OPENMJ2Info)); + + if(openmj2_buf) + { + free(openmj2_buf); openmj2_buf = NULL; + } + else + if(play_buf) + { + free(play_buf); play_buf = NULL; + } +#ifdef HAVE_THREADS + stop_threads = 0; + play_buf_nr = 1; +#endif +} + +static void wait_cb(void *v) +{ + if(play.paused + || play.single_step_possible + ) + { + return; + } + if(play_buf == NULL) + { + fprintf(stderr,"%s:%d:### wait_cb : play_buf == NULL ###\n", + __FILE__,__LINE__); + + exit(1); + + Fl::repeat_timeout(play.delay/10., wait_cb, v); + return; + } + next_frame(); +} + +static void next_frame(void) +{ + int i; + + if(mj2_stopped) return; + +#ifdef HAVE_THREADS + if(stop_threads) return; + + if( !play.single_step_mode) + i = play_buf_nr; + else + i = play.exinfo->cur_sample-1; +#else + i = play.exinfo->cur_sample-1; +#endif + + if(i <= 0) i = 1; + + FLViewer_show_frame(i,play.exinfo->max_samples-1); + + play.single_step_served = play.single_step_mode; +/*---------------------------------------------------------------------*/ + FLViewer_use_buffer(play_buf, play.exinfo->width, play.exinfo->height, + play.exinfo->channels); +/*---------------------------------------------------------------------*/ + if(openmj2_buf) free(openmj2_buf); + + openmj2_buf = play_buf; play_buf = NULL; + +#ifdef HAVE_THREADS + if(stop_threads) return; +#endif +/* forward or backward: */ + if( !play.single_step_mode) + { + Fl::repeat_timeout(play.delay, wait_cb, play.exinfo); + } + if((i = FLViewer_frame_selected()) > 0) + { + play.exinfo->cur_sample = i; + } +#ifdef HAVE_THREADS + if(stop_threads) return; + + if( !play.single_step_mode && (play.nr_threads > 0)) + { + play_buf = get_rgb_buffer(); + assert(play_buf); + } + else + { + play_buf = extract_single_frame(play.exinfo); + assert(play_buf); + play_buf_nr = play.exinfo->sample_nr; + } +#else /* not HAVE_THREADS */ + play_buf = extract_single_frame(play.exinfo); + assert(play_buf); + play_buf_nr = play.exinfo->sample_nr; +#endif /* HAVE_THREADS */ + +}/* next_frame() */ + +static void fin_cb(void) +{ + play.canvas->cleanup = NULL; + + OPENMJ2_postlude(); + + FLViewer_movie_runs(0); + FLViewer_frames_animation(0); +} + +static void backward_cb(void) +{ + int i; + + if(mj2_stopped) return; + + if( !play.single_step_possible) return; + + play.paused = 0; + play.single_step_served = 0; + + if(play_buf) + { + free(play_buf); play_buf = NULL; + } + i = play.exinfo->cur_sample - 1; + + if(i == 0) + { + play.exinfo->cur_sample = play.exinfo->max_samples + 1; + } + play.exinfo->cur_sample -= 3; + + if((i = FLViewer_frame_selected()) > 0) + { + play.exinfo->cur_sample = i; + } + play_buf = extract_single_frame(play.exinfo); + assert(play_buf); + + play_buf_nr = play.exinfo->sample_nr; + play.single_step_mode = 1; + + next_frame(); + +}/* backward_cb() */ + +static void forward_cb(void) +{ + int i; + + if(mj2_stopped) return; + + if( !play.single_step_possible) return; + + play.paused = 0; + play.single_step_mode = 1; + play.single_step_served = 0; + + if((i = FLViewer_frame_selected()) > 0) + { + if(play_buf) { free(play_buf); play_buf = NULL; } + + play.exinfo->cur_sample = i; + + play_buf = extract_single_frame(play.exinfo); + assert(play_buf); + + play_buf_nr = play.exinfo->sample_nr; + } + else + if(!play_buf) + { + play_buf = extract_single_frame(play.exinfo); + assert(play_buf); + + play_buf_nr = play.exinfo->sample_nr; + } + next_frame(); + +}/* forward_cb() */ + +static void pause_cb(void) +{ + if(mj2_stopped) return; + + if(play.paused) return; + if(play.single_step_mode) return; + + stop_timeout(); + play.paused = 1; + + play.single_step_possible = 1; + play.single_step_served = 0; play.single_step_mode = 0; + + FLViewer_movie_runs(0); + +#ifdef HAVE_THREADS + if(play.nr_threads) + { + stop_threads = 1; + + threads_postlude(play.exinfo); + + play.nr_threads = 0; + } +#endif +}/* pause_cb() */ + +static void resume_cb(void) +{ + if(mj2_stopped) return; + + if(!play.paused + && !play.single_step_possible + ) + return; + + play.paused = 0; + play.single_step_possible = 0; + play.single_step_mode = 0; + play.single_step_served = 0; + + FLViewer_movie_runs(1); + +#ifdef HAVE_THREADS + if(threads_stopped || (play.nr_threads == 0)) + { +/*==========================================*/ + play.nr_threads = FLViewer_nr_threads(); +/*==========================================*/ + if(play.nr_threads) + { + threads_prelude(play.exinfo); + } + if( !play_buf) + { + play_buf = get_rgb_buffer(); + assert(play_buf); + } + } +#endif + + next_frame(); + +}/* resume_cb() */ + +static void restart_cb(void) +{ + Canvas *canvas; + const char *read_idf; + + canvas = play.canvas; + read_idf = play.exinfo->read_idf; + + OPENMJ2_postlude(); + + load(canvas, read_idf); + +}/* restart_cb() */ + +static void stop_timeout(void) +{ + if(!play.exinfo) return; + + if(Fl::has_timeout(wait_cb, play.exinfo)) + Fl::remove_timeout(wait_cb, play.exinfo); +} + +static void load(Canvas *canvas, const char *read_idf) +{ + MJ2Extract *exinfo; + int i; + + if((exinfo = extract_frames_open(read_idf)) == NULL) + { + fl_alert("%s\n %s", MJ2_NO_FRAMES_FROM_s, read_idf); + return; + } + + if(exinfo->max_samples == 0 || exinfo->width == 0 || exinfo->height == 0) + { + fl_alert(MJ2_SHOW_FAILS_s, read_idf, + exinfo->max_samples, exinfo->width, exinfo->height); + + OPENMJ2_postlude(); + return; + } + + mj2_stopped = 0; + + play.delay = + ((double)exinfo->duration/(double)(exinfo->max_samples-1)) * 0.001; +#ifdef _WIN32 + play.delay *= 1.10; +#endif + play.exinfo = exinfo; + + FLViewer_url(read_idf, exinfo->width, exinfo->height); + + canvas->pause = &pause_cb; + canvas->resume = &resume_cb; + canvas->restart = &restart_cb; + canvas->forward = &forward_cb; + canvas->backward = &backward_cb; + canvas->fin = &fin_cb; + canvas->cleanup = &OPENMJ2_postlude; + +#ifdef HAVE_THREADS + FLViewer_threads_activate(1); +#endif + FLViewer_mj2_animation(1); + FLViewer_set_max_mj2_tracks(Tracks[0].max_tracks); + + canvas->top_frame = exinfo->max_samples - 1; + play.canvas = canvas; + + if((i = FLViewer_frame_selected()) > 0) + { + exinfo->cur_sample = i; + } + FLViewer_movie_runs(1); + +#ifdef HAVE_THREADS +/*==========================================*/ + play.nr_threads = FLViewer_nr_threads(); +/*==========================================*/ + if(play.nr_threads) + { + play_buf_nr = 0; + + threads_prelude(exinfo); + + play_buf = get_rgb_buffer(); + assert(play_buf); + } + else + { + play_buf_nr = 0; + + play_buf = extract_single_frame(exinfo); + assert(play_buf); + } +#else /* not HAVE_THREADS */ + play_buf_nr = 0; + + play_buf = extract_single_frame(exinfo); + assert(play_buf); +#endif + + Fl::add_timeout(play.delay, wait_cb, exinfo); + +}/* load() */ + +void OPENMJ2_load(Canvas *canvas, const char *read_idf, uint64_t fsize) +{ + load(canvas, read_idf); +} + +#ifdef HAVE_THREADS + +#ifdef HAVE_WINPORT +static DWORD WINAPI decoder_thread(PVOID v) +#else +static void *decoder_thread(void *v) +#endif +{ + SampleInfo *sinfo; + + while( !stop_threads && !mj2_stopped) + { + sinfo = NULL; + +#ifdef HAVE_WINPORT + EnterCriticalSection(&sample_list_mutex); +#else + PTHREAD_mutex_lock(&sample_list_mutex); +#endif + + while( !stop_threads && !mj2_stopped + && (sample_list_busy || (elems_in_list > MAX_ELEMS_IN_LIST)) ) + { +#ifdef HAVE_WINPORT + SleepConditionVariableCS(&sample_list_condGET, &sample_list_mutex, + INFINITE); +#else + PTHREAD_cond_wait(&sample_list_condGET, &sample_list_mutex); +#endif + } + sample_list_busy = 1; + + if(!stop_threads && !mj2_stopped) + { + sinfo = new_sample_info(); + + ++elems_in_list; + } +#ifdef HAVE_WINPORT + WakeConditionVariable(&sample_list_condINSERTED); + + LeaveCriticalSection(&sample_list_mutex); +#else + PTHREAD_cond_signal(&sample_list_condINSERTED); + + PTHREAD_mutex_unlock(&sample_list_mutex); +#endif + + sample_list_busy = 0; + + if(stop_threads) break; + + decode_frame(play.exinfo, sinfo); + + }/* while( !stop_threads && !mj2_stopped) */ +#ifdef HAVE_WINPORT + return 0; +#else + return NULL; +#endif +}/* decoder_thread() */ + +static void threads_prelude(MJ2Extract *exinfo) +{ + int i; +#ifdef HAVE_WINPORT + DWORD id; +#endif + +#if defined(HAVE_NPTH_THREADS) && defined(_WIN32) + PTHREAD_init(); +#endif + +#ifdef HAVE_WINPORT + InitializeCriticalSection(&sample_list_mutex); + + InitializeConditionVariable(&sample_list_condINSERTED); + InitializeConditionVariable(&sample_list_condGET); +#else + PTHREAD_mutex_init(&sample_list_mutex, NULL); + + PTHREAD_cond_init(&sample_list_condINSERTED, NULL); + PTHREAD_cond_init(&sample_list_condGET, NULL); +#endif + + exinfo->cur_sample = play_buf_nr; + + stop_threads = 0; threads_stopped = 0; + + decoder = (Decoder*)calloc(1, sizeof(Decoder) * play.nr_threads); + + for(i = 0; i < play.nr_threads; ++i) + { + decoder[i].ID = i; + decoder[i].exinfo = exinfo; +#ifdef HAVE_WINPORT + decoder[i].tid = + CreateThread(NULL, 0, &decoder_thread, (PVOID)&decoder[i], 0, &id); +#else + PTHREAD_create(&decoder[i].tid, NULL, &decoder_thread, + (void*)&decoder[i]); +#endif + } +}/* threads_prelude() */ + +static void samples_postlude(void) +{ + SampleInfo *sinfo, *first; + + first = sample_list_head; sample_list_head = sample_list_tail = NULL; + + while((sinfo = first)) + { + first = first->next; + + free_sample_info(sinfo); + } + elems_in_list = 0; +} + +static void threads_postlude(MJ2Extract *exinfo) +{ + int i; + +#ifdef HAVE_WINPORT + WakeAllConditionVariable(&sample_list_condGET); + WakeAllConditionVariable(&sample_list_condINSERTED); + + Sleep(WAIT_FOR_CONDVARS); +#else + PTHREAD_cond_broadcast(&sample_list_condINSERTED); + PTHREAD_cond_broadcast(&sample_list_condGET); + + PTHREAD_mutex_unlock(&sample_list_mutex); +#endif + + for(i = 0; i < play.nr_threads; ++i) + { +#ifdef HAVE_WINPORT + WaitForSingleObject(decoder[i].tid, INFINITE); +#else + (void)PTHREAD_join(decoder[i].tid, NULL); +#endif + } + free(decoder); + decoder = NULL; + +#ifdef HAVE_WINPORT +#else + PTHREAD_cond_destroy(&sample_list_condINSERTED); + PTHREAD_cond_destroy(&sample_list_condGET); + + PTHREAD_mutex_destroy(&sample_list_mutex); +#endif + threads_stopped = 1; + + exinfo->cur_sample = play_buf_nr + 1; + + samples_postlude(); + +#ifdef HAVE_WINPORT + Sleep(1); +#else + usleep(10000); +#endif + + stop_threads = 0;//single_step ! + +}/* threads_postlude() */ + +static unsigned char *get_rgb_buffer(void) +{ + SampleInfo *sinfo; + unsigned char *s; + int nr; + + s = NULL; nr = 0; + +#ifdef HAVE_WINPORT + EnterCriticalSection(&sample_list_mutex); +#else + PTHREAD_mutex_lock(&sample_list_mutex); +#endif + + while( !stop_threads && !mj2_stopped + &&( !sample_list_head || !sample_list_head->rgb_buf)) + { +#ifdef HAVE_WINPORT + SleepConditionVariableCS(&sample_list_condINSERTED, &sample_list_mutex, + INFINITE); +#else + PTHREAD_cond_wait(&sample_list_condINSERTED, &sample_list_mutex); +#endif + } + sample_list_busy = 1; + + if(!stop_threads && !mj2_stopped) + { + sinfo = sample_list_head; + + if(sinfo) + { + sample_list_head = sample_list_head->next; + + if(sample_list_head == NULL) sample_list_tail = NULL; + + s = sinfo->rgb_buf; nr = sinfo->sample_nr; + + free(sinfo); --elems_in_list; + } + else + { + assert("INTERNAL ERROR" == NULL); + } + } +#ifdef HAVE_WINPORT + WakeConditionVariable(&sample_list_condGET); + + LeaveCriticalSection(&sample_list_mutex); +#else + PTHREAD_cond_signal(&sample_list_condGET); + + PTHREAD_mutex_unlock(&sample_list_mutex); +#endif + + sample_list_busy = 0; + + if(s) + { + play_buf_nr = nr; + } + + return s; +}/* get_rgb_buffer() */ + +#endif /* HAVE_THREADS */ + +void OPENMJ2_free_tracks() +{ + int t, nr; + + if(Tracks == NULL) return; + + nr = Tracks[0].nr_tracks; + + for(t = 0; t < nr; ++t) + { + if(Tracks[t].samples) + { + free(Tracks[t].samples); + } + } + free(Tracks); + Tracks = NULL; +} + +static MJ2Extract *extract_frames_open(const char *read_idf) +{ + FILE *reader; + MJ2Extract *exinfo; + track_t *track; + + if((reader = fopen(read_idf, "rb")) == NULL) + return NULL; + + exinfo = (MJ2Extract*) calloc(1, sizeof(MJ2Extract)); + + track = &Tracks[0]; + exinfo->duration = track->duration; + exinfo->width = track->width; + exinfo->height = track->height; + exinfo->max_samples = track->max_samples; + exinfo->max_tracks = track->max_tracks; + exinfo->channels = 3; + exinfo->reader = reader; + exinfo->read_idf = read_idf; + +#ifdef HAVE_FSEEKO + exinfo->start_offset = ftello(reader); +#elif HAVE_FSEEKI64 + exinfo->start_offset = _ftelli64(reader); +#else + exinfo->start_offset = ftell(reader); +#endif + return exinfo; + +}//extract_frames_open() + +static void extract_frames_close(MJ2Extract *exinfo) +{ + if(exinfo->sample_buf) free(exinfo->sample_buf); + + fclose(exinfo->reader); + + free(exinfo); +}//extract_frames_close() + +static void get_sample_buf(MJ2Extract *exinfo, SampleInfo *sinfo) +{ + sample_t *samples; + unsigned char *sample_buf; + const char *soc = "\xff\xd9"; + unsigned int size; + int i; + uint64_t pos; + + if(mj2_stopped) return; + + i = exinfo->cur_sample; + + if(i <= 0 || i == exinfo->max_samples) + { + i = 1; +#ifdef HAVE_FSEEKO + fseeko(exinfo->reader, exinfo->start_offset, SEEK_SET); +#elif HAVE_FSEEKI64 + _fseeki64(exinfo->reader, exinfo->start_offset, SEEK_SET); +#else + fseek(exinfo->reader, exinfo->start_offset, SEEK_SET); +#endif + } + exinfo->cur_sample = i + 1; + + samples = Tracks[exinfo->cur_track].samples; + + if(samples == NULL) return; + + size = samples[i].size; + + if((sample_buf = (unsigned char*)calloc(1, size+16)) == NULL) + return; + +// Skip first two markers: +// + pos = samples[i].pos + 8; + +#ifdef HAVE_FSEEKO + fseeko(exinfo->reader, pos, SEEK_SET); +#elif HAVE_FSEEKI64 + _fseeki64(exinfo->reader, pos, SEEK_SET); +#else + fseek(exinfo->reader, (long)pos, SEEK_SET); +#endif + fread(sample_buf, 1, size, exinfo->reader); + memcpy(sample_buf + size, soc, 2); + + sinfo->cur_buf = sinfo->sample_buf = sample_buf; + sinfo->sample_size = size + 2; + sinfo->sample_nr = i; + +}/* get_sample_buf() */ + +static void decode_frame(MJ2Extract *exinfo, SampleInfo *sinfo) +{ + int selected_component = 0; + unsigned int width, height; + int type; + + if(mj2_stopped) return; + + get_sample_buf(exinfo, sinfo); + + sinfo->rgb_buf = + JP2_decode(exinfo->read_idf, sinfo->sample_buf, + (uint64_t)sinfo->sample_size, IS_MOVIE, J2K_CFMT, + &width, &height, &type, &selected_component); + + (void)type; + + if(width != exinfo->width || height != exinfo->height) + { + FLViewer_url(exinfo->read_idf, width, height); + } + exinfo->width = width; exinfo->height = height; + + if(selected_component > 0) + exinfo->channels = 1; + else + exinfo->channels = 3; + + free(sinfo->sample_buf); sinfo->sample_buf = NULL; + +}/* decode_frame() */ + +static unsigned char* extract_single_frame(MJ2Extract *exinfo) +{ + SampleInfo sinfo; + + if(mj2_stopped) return NULL; + + memset(&sinfo, 0, sizeof(SampleInfo)); + + decode_frame(exinfo, &sinfo); + + if(sinfo.rgb_buf) + { + exinfo->sample_nr = sinfo.sample_nr; + } + return sinfo.rgb_buf; + +}/* extract_single_frame() */ + +static void free_sample_info(SampleInfo *sinfo) +{ + if(sinfo->sample_buf) free(sinfo->sample_buf); + if(sinfo->rgb_buf) free(sinfo->rgb_buf); + + free(sinfo); +} diff --git a/src/bin/fltk/flviewer/OPENMJ2.hh b/src/bin/fltk/flviewer/OPENMJ2.hh new file mode 100644 index 00000000..47f96dda --- /dev/null +++ b/src/bin/fltk/flviewer/OPENMJ2.hh @@ -0,0 +1,8 @@ +#ifndef _FLVIEWER_OPENMJ2_HH_ +#define _FLVIEWER_OPENMJ2_HH_ + +extern void OPENMJ2_load(Canvas *canvas, const char *read_idf, + uint64_t fsize); +extern void OPENMJ2_free_tracks(); + +#endif /* _FLVIEWER_OPENMJ2_HH_ */ diff --git a/src/bin/fltk/flviewer/PGX.cxx b/src/bin/fltk/flviewer/PGX.cxx new file mode 100644 index 00000000..0e5adec9 --- /dev/null +++ b/src/bin/fltk/flviewer/PGX.cxx @@ -0,0 +1,184 @@ +#include +/* + * author(s) and license +*/ +#include +#include +#include +#include + +#include "flviewer.hh" +#include "PGX.hh" + +#define PGX_MIN_LEN 12 + +static unsigned char *pgx_buf; + +static void PGX_postlude(void) +{ + if(pgx_buf) { free(pgx_buf); pgx_buf = NULL; } +} + +/* ML == big_endian; LM == little_endian +*/ +static unsigned short readushort(unsigned char *s, int bigendian) +{ + unsigned short c0, c1; + + c0 = *s; c1 = s[1]; + + if(bigendian) + return (unsigned short)((c0<<8) + c1); + + return (unsigned short)((c1<<8) + c0); +} + +static unsigned int readuint(unsigned char *s, int bigendian) +{ + unsigned int c0, c1, c2, c3; + + c0 = *s; c1 = s[1]; c2 = s[2]; c3 = s[3]; + + if(bigendian) + return (c0 << 24) + (c1 << 16) + (c2 << 8) + c3; + + return (c3 << 24) + (c2 << 16) + (c1 << 8) + c0; +} + +void PGX_load(Canvas *canvas, FILE *reader, const char *read_idf, + size_t fsize) +{ + unsigned char *src, *s, *dst_buf, *d; + int width, height, prec, sgnd, adjustS, adjustG ; + int i, max, bigendian; + int ushift, dshift; + char endian1, endian2; + char signbuf[80], white[80]; + + if(fsize <= PGX_MIN_LEN) + { + fprintf(stderr,"%s:%d: PGX_load\n\t%s\n\tis too short: len is %lu\n", + __FILE__,__LINE__,read_idf,(unsigned long)fsize); + FLViewer_close_reader(); + return; + } + src = (unsigned char*) calloc(1, fsize + 8); + (void)fread(src, 1, fsize, reader); + FLViewer_close_reader(); + + width = height = 0; +/*--------------------------------------*/ + i = sscanf((char*)src, "PG%[ \t]%c%c%[ \t%+-]%d%[ \t]%d%[ \t]%d", + white, &endian1, &endian2, signbuf, &prec, white, + &width, white, &height); + + if(i != 9) + { + fprintf(stderr, "%s:%d:PGX_load\n\t %s\n\tis not a valid PGX file.\n\t" + "%d elements read, 9 expected.\n",__FILE__,__LINE__,read_idf, i); + goto fails; + } + if(prec <= 0 || prec > 32) + { + fprintf(stderr, "%s:%d:PGX_load\n\tprec %d is invalid\n", + __FILE__,__LINE__,prec); + goto fails; + } + s = (unsigned char*)strchr((char*)src, '\n'); + assert(s); + ++s; + + i = 0; sgnd = 0; + + while(signbuf[i]) + { + if(signbuf[i] == '-') sgnd = 1; + i++; + } + + if(endian1 == 'M' && endian2 == 'L') + bigendian = 1; + else + if(endian1 == 'L' && endian2 == 'M') + bigendian = 0; + else + { + fprintf(stderr, "%s:%d:PGX_load\n\tneither 'ML' nor 'LM' found " + "in header.\n",__FILE__,__LINE__); + goto fails; + } + if(prec > 8) adjustG = prec - 8; else adjustG = 0; + + if(sgnd) adjustS = (1<<(prec - 1)); else adjustS = 0; + + if(prec < 8) + { + ushift = 8 - prec; dshift = prec - ushift; + } + else + { + ushift = dshift = 0; + } + max = width * height; + d = dst_buf = (unsigned char*)calloc(1, max * 3); + + for(i = 0; i < max; i++) + { + int g; + + g = 0; + + if(prec < 8) + { + g = s[0] + adjustS; ++s; + + g = (g<>dshift); + + *d++ = (unsigned char)g; *d++ = (unsigned char)g; *d++ = (unsigned char)g; + continue; + } + + if(prec == 8) + { + if(sgnd) g = (char)s[0]; else g = s[0]; ++s; + } + else + if(prec <= 16) + { + if(sgnd) + g = (short) readushort(s, bigendian); + else + g = readushort(s, bigendian); + + s += 2; + } + else + { + if(sgnd) + g = (int) readuint(s, bigendian); + else + g = readuint(s, bigendian); + + s += 4; + } + g += adjustS; + if(adjustG) + g = ((g >> adjustG)+((g >> (adjustG - 1))%2)); + if(g > 255) g = 255; else if(g < 0) g = 0; + + *d++ = (unsigned char)g; + *d++ = (unsigned char)g; + *d++ = (unsigned char)g; + }//for(i + + FLViewer_url(read_idf, width, height); + + FLViewer_use_buffer(dst_buf, width, height, 3); + + pgx_buf = dst_buf; + canvas->cleanup = &PGX_postlude; + +fails: + free(src); + +}/* PGX_load() */ diff --git a/src/bin/fltk/flviewer/PGX.hh b/src/bin/fltk/flviewer/PGX.hh new file mode 100644 index 00000000..ae3628f5 --- /dev/null +++ b/src/bin/fltk/flviewer/PGX.hh @@ -0,0 +1,7 @@ +#ifndef _FLVIEWER_PGX_HH_ +#define _FLVIEWER_PGX_HH_ + +extern void PGX_load(Canvas *canvas, FILE *reader, const char *read_idf, + size_t fsize); + +#endif /* _FLVIEWER_PGX_HH_ */ diff --git a/src/bin/fltk/flviewer/PNG.cxx b/src/bin/fltk/flviewer/PNG.cxx new file mode 100644 index 00000000..eb90eade --- /dev/null +++ b/src/bin/fltk/flviewer/PNG.cxx @@ -0,0 +1,359 @@ +#include +#include "opj_apps_config.h" + +#ifdef OPJ_HAVE_LIBPNG +/* + * author(s) and license + * +*/ + +#include +#include +#include +#include + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#include +#include + } +#else +#include +#include +#endif /* __cplusplus */ + +#include "opj_stdint.h" + +#include + +#include "flviewer.hh" +#include "PNG.hh" +#include "lang/png_lang.h_utf8" + +/* #define USE_PNG_IMAGE */ + +static unsigned char *png_buf; + +static void PNG_postlude(void) +{ + if(png_buf) { free(png_buf); png_buf = NULL; } +} + +void PNG_load(Canvas *canvas, FILE *reader, const char *read_idf, + int64_t fsize) +{ +#ifndef USE_PNG_IMAGE // uses reader + png_bytep row; + png_structp png; + png_infop info; + unsigned char *buf; + double gamma, display_exponent; + int unit, pass, nr_passes, depth; + png_uint_32 resx, resy; + png_uint_32 width, height; + unsigned int i, src_w; + int color_type, has_alpha; + int bit_depth, interlace_type,compression_type, filter_type; + +/* libpng-VERSION/example.c: + * PC : screen_gamma = 2.2; + * Mac: screen_gamma = 1.7 or 1.0; +*/ + display_exponent = 2.2; + + if((png = png_create_read_struct(PNG_LIBPNG_VER_STRING, + NULL, NULL, NULL)) == NULL) + goto fin; + if((info = png_create_info_struct(png)) == NULL) + goto fin; + + if(setjmp(png_jmpbuf(png))) + goto fin; + + FLViewer_wait(); + + png_init_io(png, reader); + png_read_info(png, info); + + png_get_IHDR(png, info, &width, &height, + &bit_depth, &color_type, &interlace_type, + &compression_type, &filter_type); + + if(color_type == PNG_COLOR_TYPE_PALETTE) + png_set_expand(png); + else + if(color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) + png_set_expand(png); + + if(png_get_valid(png, info, PNG_INFO_tRNS)) + png_set_expand(png); + + if(bit_depth == 16) + png_set_strip_16(png); + +/* GRAY => RGB; GRAY_ALPHA => RGBA +*/ + if(color_type == PNG_COLOR_TYPE_GRAY + || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + png_set_gray_to_rgb(png); + color_type = + (color_type == PNG_COLOR_TYPE_GRAY? PNG_COLOR_TYPE_RGB: + PNG_COLOR_TYPE_RGB_ALPHA); + } + + if( !png_get_gAMA(png, info, &gamma)) + gamma = 0.45455; + + png_set_gamma(png, display_exponent, gamma); + + nr_passes = png_set_interlace_handling(png); + + png_read_update_info(png, info); + + png_get_pHYs(png, info, &resx, &resy, &unit); + + color_type = png_get_color_type(png, info); + + has_alpha = (color_type == PNG_COLOR_TYPE_RGB_ALPHA); + + if(has_alpha) + depth = 4; + else + depth = 3; + + src_w = width * (3 + has_alpha); + buf = (unsigned char*)malloc(src_w * height); + + for(pass = 0; pass < nr_passes; pass++) + { + row = buf; + + for(i = 0; i < height; i++) + { +/* libpng.3: + * If you want the "sparkle" effect, just call png_read_rows() as + * normal, with the third parameter NULL. +*/ + png_read_rows(png, &row, NULL, 1); + + row += src_w; + } + } + FLViewer_url(read_idf, width, height); + + FLViewer_use_buffer(buf, width, height, depth); + + png_buf = buf; + canvas->cleanup = &PNG_postlude; + +fin: + if(png) + png_destroy_read_struct(&png, &info, NULL); + FLViewer_close_reader(); + +#else // USE_PNG_IMAGE uses read_idf + unsigned char *buf; + png_image image; + int depth = 3; + + buf = NULL; + memset(&image, 0, (sizeof image)); + image.version = PNG_IMAGE_VERSION; + + FLViewer_close_reader(); + + FLViewer_wait(); + + if(png_image_begin_read_from_file(&image, read_idf)) + { + png_bytep buffer; + + depth = PNG_IMAGE_SAMPLE_CHANNELS(image.format); + + if(depth == 3 || depth == 1) + { + image.format = PNG_FORMAT_RGB; depth = 3; + } + else + if(depth == 4 || depth == 2) + { + image.format = PNG_FORMAT_RGBA; depth = 4; + } + buffer = (png_bytep)malloc(PNG_IMAGE_SIZE(image)); + + if(buffer != NULL + && png_image_finish_read(&image, NULL/*background*/, + buffer, + 0/*row_stride*/, NULL/*colormap*/)) + { + buf = buffer; + } + else + { + if(buffer == NULL) + png_image_free(&image); + else + free(buffer); + } + } + if(buf == NULL) return; + + FLViewer_url(read_idf, image.width, image.height); + + FLViewer_use_buffer(buf, image.width, image.height, depth); + + png_buf = buf; + canvas->cleanup = &PNG_postlude; + +#endif /* USE_PNG_IMAGE */ +}/* PNG_load() */ + +static int to_png(unsigned char *buf, int width, int height, int nr_comp, + FILE *writer) +{ + png_structp png; + png_infop info; + unsigned char *s; + int color_type, step; + int y, ok; + png_color_8 sig_bit; + + ok = 0; + info = NULL; +/* Create and initialize the png_struct with the desired error handler + * functions. If you want to use the default stderr and longjump method, + * you can supply NULL for the last three parameters. We also check that + * the library version is compatible with the one used at compile time, + * in case we are using dynamically linked libraries. REQUIRED. +*/ + png = png_create_write_struct(PNG_LIBPNG_VER_STRING, + NULL, NULL, NULL); + + if(png == NULL) goto fin; + +/* Allocate/initialize the image information data. REQUIRED +*/ + info = png_create_info_struct(png); + + if(info == NULL) goto fin; + +/* Set error handling. REQUIRED if you are not supplying your own + * error handling functions in the png_create_write_struct() call. +*/ + if(setjmp(png_jmpbuf(png))) goto fin; + +/* I/O initialization functions is REQUIRED +*/ + png_init_io(png, writer); + +/* Set the image information here. Width and height are up to 2^31, + * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on + * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY, + * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB, + * or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or + * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST + * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. + * REQUIRED + * + * ERRORS: + * + * color_type == PNG_COLOR_TYPE_PALETTE && bit_depth > 8 + * color_type == PNG_COLOR_TYPE_RGB && bit_depth < 8 + * color_type == PNG_COLOR_TYPE_GRAY_ALPHA && bit_depth < 8 + * color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8 + * +*/ + png_set_compression_level(png, Z_BEST_COMPRESSION); + + if(nr_comp == 4) + { + step = 4 * width; + sig_bit.alpha = 8; + sig_bit.red = sig_bit.green = sig_bit.blue = 8; + color_type = PNG_COLOR_TYPE_RGB_ALPHA; + } + else + if(nr_comp == 3) + { + step = 3 * width; + sig_bit.alpha = 0; + sig_bit.red = sig_bit.green = sig_bit.blue = 8; + color_type = PNG_COLOR_TYPE_RGB; + } + else + if(nr_comp == 2) + { + step = 2 * width; + sig_bit.gray = 8; + sig_bit.red = sig_bit.green = sig_bit.blue = 0; + sig_bit.alpha = 8; + color_type = PNG_COLOR_TYPE_GRAY_ALPHA; + } + else /* 1 */ + { + step = width; + sig_bit.gray = 8; + sig_bit.red = sig_bit.green = sig_bit.blue = sig_bit.alpha = 0; + color_type = PNG_COLOR_TYPE_GRAY; + } + png_set_sBIT(png, info, &sig_bit); + + png_set_IHDR(png, info, width, height, 8, + color_type, + PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + png_set_gamma(png, 2.2, 1./2.2); + + if(nr_comp > 2) + { + png_set_sRGB(png, info, PNG_sRGB_INTENT_PERCEPTUAL); + } + png_write_info(png, info); + + s = buf; + + for(y = 0; y < height; ++y) + { + png_write_row(png, s); + + s += step; + } + png_write_end(png, info); + + ok = 1; + +fin: + if(png) + { + png_destroy_write_struct(&png, &info); + } + return ok; +}/* to_png() */ + +void PNG_save_file(Canvas *canvas, const char *write_idf) +{ + FILE *writer; + int width, height, nr_comp; + + width = canvas->new_iwidth; + height = canvas->new_iheight; + nr_comp = canvas->new_idepth; + + if((writer = fopen(write_idf, "wb")) == NULL) + { + fl_alert(DST_DID_NOT_OPEN_s, write_idf); + return; + } + + if(to_png((unsigned char*)canvas->cbuf, + width, height, nr_comp, writer) == 0) + { + fl_alert("%s", WRITE_PNG_FAILS_s); + } + fclose(writer); + +}/* PNG_save_file() */ + +#endif /* OPJ_HAVE_LIBPNG */ diff --git a/src/bin/fltk/flviewer/PNG.hh b/src/bin/fltk/flviewer/PNG.hh new file mode 100644 index 00000000..8d81d5f9 --- /dev/null +++ b/src/bin/fltk/flviewer/PNG.hh @@ -0,0 +1,12 @@ +#ifdef OPJ_HAVE_LIBPNG + +#ifndef _FLVIEWER_PNG_HH_ +#define _FLVIEWER_PNG_HH_ + +extern void PNG_load(Canvas *canvas, FILE *reader, const char *read_idf, + int64_t fsize); +extern void PNG_save_file(Canvas *canvas, const char *write_idf); + +#endif /* _FLVIEWER_PNG_HH_ */ + +#endif /* OPJ_HAVE_LIBPNG */ diff --git a/src/bin/fltk/flviewer/color.cxx b/src/bin/fltk/flviewer/color.cxx new file mode 100644 index 00000000..2bf8c32c --- /dev/null +++ b/src/bin/fltk/flviewer/color.cxx @@ -0,0 +1,997 @@ +#include +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +#include "openjpeg.h" +#include "opj_apps_config.h" + +#ifdef OPJ_HAVE_LIBLCMS2 +#include +#endif +#ifdef OPJ_HAVE_LIBLCMS1 +#include +#endif + +#include "viewerdefs.hh" +#include "color.hh" + +//#define DEBUG_SYCC + +/*-------------------------------------------------------- +Matrix für sYCC, Amendment 1 to IEC 61966-2-1 + +Y : 0.299 0.587 0.114 :R +Cb: -0.1687 -0.3312 0.5 :G +Cr: 0.5 -0.4187 -0.0812 :B + +Inverse: + +R: 1 -3.68213e-05 1.40199 :Y +G: 1.00003 -0.344125 -0.714128 :Cb - 2^(prec - 1) +B: 0.999823 1.77204 -8.04142e-06 :Cr - 2^(prec - 1) + +-----------------------------------------------------------*/ +static void sycc_to_rgb(int offset, int upb, int y, int cb, int cr, + int *out_r, int *out_g, int *out_b) +{ + int r, g, b; + + cb -= offset; cr -= offset; + r = y + (int)((float)1.402 * (float)cr); + if(r < 0) r = 0; else if(r > upb) r = upb; + *out_r = r; + + g = y - (int)((float)0.344 * (float)cb + (float)0.714 * (float)cr); + if(g < 0) g = 0; else if(g > upb) g = upb; + *out_g = g; + + b = y + (int)((float)1.772 * (float)cb); + if(b < 0) b = 0; else if(b > upb) b = upb; + *out_b = b; +} + +static void sycc444_to_rgb(opj_image_t *image, ImageInfo *dst) +{ + int *r, *g, *b; + const int *y, *cb, *cr; + int maxw, maxh, max, i, offset, upb; + size_t imax; + + i = image->comps[0].prec; + offset = 1<<(i - 1); upb = (1<comps[0].w; maxh = image->comps[0].h; + max = maxw * maxh; + imax = max * sizeof(int); + + y = image->comps[0].data; + cb = image->comps[1].data; + cr = image->comps[2].data; + + dst->red = r = (int*)malloc(imax); + dst->green = g = (int*)malloc(imax); + dst->blue = b = (int*)malloc(imax); + + for(i = 0; i < max; ++i) + { + sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b); + + ++y; ++cb; ++cr; ++r; ++g; ++b; + } + dst->free_red = 1; + dst->free_green = 1; + dst->free_blue = 1; + dst->numcomps = 3; + dst->color_space = OPJ_CLRSPC_SRGB; + + dst->dx[1] = dst->dx[0]; + dst->dx[2] = dst->dx[0]; + + dst->dy[1] = dst->dy[0]; + dst->dy[2] = dst->dy[0]; + + dst->prec[1] = dst->prec[0]; + dst->prec[2] = dst->prec[0]; +}// sycc444_to_rgb() + +static void sycc422_to_rgb(opj_image_t *image, ImageInfo *dst) +{ + int *r, *g, *b; + const int *y, *cb, *cr; + int maxw, maxh, max, offset, upb; + int i, j; + size_t imax; + + i = image->comps[0].prec; + offset = 1<<(i - 1); upb = (1<comps[0].w; + maxh = image->comps[0].h; + max = maxw * maxh; + imax = max *sizeof(int); + + y = image->comps[0].data; + cb = image->comps[1].data; + cr = image->comps[2].data; + + dst->red = r = (int*)malloc(imax); + dst->green = g = (int*)malloc(imax); + dst->blue = b = (int*)malloc(imax); + + for(i = 0; i < maxh; ++i) + { + for(j = 0; j < (maxw & ~1); j += 2) + { + sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b); + + ++y; ++r; ++g; ++b; + + sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b); + + ++y; ++r; ++g; ++b; ++cb; ++cr; + } + if(j < maxw) + { + sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b); + + ++y; ++r; ++g; ++b; ++cb; ++cr; + } + } + dst->free_red = 1; + dst->free_green = 1; + dst->free_blue = 1; + dst->color_space = OPJ_CLRSPC_SRGB; + dst->numcomps = 3; + + dst->dx[1] = dst->dx[0]; + dst->dx[2] = dst->dx[0]; + + dst->dy[1] = dst->dy[0]; + dst->dy[2] = dst->dy[0]; + + dst->prec[1] = dst->prec[0]; + dst->prec[2] = dst->prec[0]; + + image->color_space = OPJ_CLRSPC_SRGB; + image->comps[1].w = maxw; image->comps[1].h = maxh; + image->comps[2].w = maxw; image->comps[2].h = maxh; + image->comps[1].dx = image->comps[0].dx; + image->comps[2].dx = image->comps[0].dx; + image->comps[1].dy = image->comps[0].dy; + image->comps[2].dy = image->comps[0].dy; + +}// sycc422_to_rgb() + +static void sycc420_to_rgb(opj_image_t *image, ImageInfo *dst) +{ + int *R, *G, *B, *nr, *ng, *nb; + const int *y, *cb, *cr, *ny; + int maxw, maxh, max, offset, upb; + int i, j; + size_t imax; + + i = image->comps[0].prec; + offset = 1<<(i - 1); upb = (1<comps[0].w; maxh = image->comps[0].h; + max = maxw * maxh; + imax = sizeof(int) * max; + + y = image->comps[0].data; + cb = image->comps[1].data; + cr = image->comps[2].data; + + R = dst->red = (int*)malloc(imax); + G = dst->green = (int*)malloc(imax); + B = dst->blue = (int*)malloc(imax); +#ifdef DEBUG_SYCC +fprintf(stderr,"%s:%d:\n\tsycc420_to_rgb\n\tis_still(%d) W(%d) H(%d)\n" +"\tRED(%p) GREEN(%p) BLUE(%p)\n",__FILE__,__LINE__, +dst->is_still,maxw,maxh,(void*)dst->red,(void*)dst->green, +(void*)dst->blue); +#endif + + for(i=0; i < (maxh & ~1); i += 2) + { + ny = y + maxw; + nr = R + maxw; ng = G + maxw; nb = B + maxw; + + for(j=0; j < (maxw & ~1); j += 2) + { + sycc_to_rgb(offset, upb, *y, *cb, *cr, R, G, B); + + ++y; ++R; ++G; ++B; + + sycc_to_rgb(offset, upb, *y, *cb, *cr, R, G, B); + + ++y; ++R; ++G; ++B; + + sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb); + + ++ny; ++nr; ++ng; ++nb; + + sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb); + + ++ny; ++nr; ++ng; ++nb; ++cb; ++cr; + } + + if(j < maxw) + { + sycc_to_rgb(offset, upb, *y, *cb, *cr, R, G, B); + + ++y; ++R; ++G; ++B; + + sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb); + + ++ny; ++nr; ++ng; ++nb; ++cb; ++cr; + } + + y += maxw; R += maxw; G += maxw; B += maxw; + } + + if(i < maxh) + { + for(j = 0; j < (maxw & ~1); j += 2) + { + sycc_to_rgb(offset, upb, *y, *cb, *cr, R, G, B); + + ++y; ++R; ++G; ++B; + + sycc_to_rgb(offset, upb, *y, *cb, *cr, R, G, B); + + ++y; ++R; ++G; ++B; ++cb; ++cr; + } + if(j < maxw) + { + sycc_to_rgb(offset, upb, *y, *cb, *cr, R, G, B); + } + } + + dst->free_red = 1; + dst->free_green = 1; + dst->free_blue = 1; + dst->numcomps = 3; + dst->color_space = OPJ_CLRSPC_SRGB; + + dst->dx[1] = dst->dx[0]; + dst->dx[2] = dst->dx[0]; + + dst->dy[1] = dst->dy[0]; + dst->dy[2] = dst->dy[0]; + + dst->prec[1] = dst->prec[0]; + dst->prec[2] = dst->prec[0]; + + image->color_space = OPJ_CLRSPC_SRGB; + image->comps[1].w = maxw; image->comps[1].h = maxh; + image->comps[2].w = maxw; image->comps[2].h = maxh; + image->comps[1].dx = image->comps[0].dx; + image->comps[2].dx = image->comps[0].dx; + image->comps[1].dy = image->comps[0].dy; + image->comps[2].dy = image->comps[0].dy; + +}// sycc420_to_rgb() + +void COLOR_sycc_to_rgb(opj_image_t *image, ImageInfo *dst) +{ +#ifdef DEBUG_SYCC +fprintf(stderr,"%s:%d:COLOR_sycc_to_rgb\n", +__FILE__,__LINE__); + fprintf(stderr,"\tcomponents(%d) dx(%d,%d,%d) dy(%d,%d,%d)\n", + image->numcomps, + image->comps[0].dx,image->comps[1].dx,image->comps[2].dx, + image->comps[0].dy,image->comps[1].dy,image->comps[2].dy); +#endif + + if(image->numcomps < 3) + { + image->color_space = OPJ_CLRSPC_GRAY; + dst->color_space = OPJ_CLRSPC_GRAY; + dst->numcomps = image->numcomps; + + return; + } + + if((image->comps[0].dx == 1) + && (image->comps[1].dx == 2) + && (image->comps[2].dx == 2) + && (image->comps[0].dy == 1) + && (image->comps[1].dy == 2) + && (image->comps[2].dy == 2))// horizontal and vertical sub-sample + { + sycc420_to_rgb(image, dst); + return; + } + + if((image->comps[0].dx == 1) + && (image->comps[1].dx == 2) + && (image->comps[2].dx == 2) + && (image->comps[0].dy == 1) + && (image->comps[1].dy == 1) + && (image->comps[2].dy == 1))// horizontal sub-sample only + { + sycc422_to_rgb(image, dst); + return; + } + + if((image->comps[0].dx == 1) + && (image->comps[1].dx == 1) + && (image->comps[2].dx == 1) + && (image->comps[0].dy == 1) + && (image->comps[1].dy == 1) + && (image->comps[2].dy == 1))// no sub-sample + { + sycc444_to_rgb(image, dst); + return; + } + + if((image->comps[0].dx == 4) + && (image->comps[1].dx == 4) + && (image->comps[2].dx == 4) + && (image->comps[0].dy == 4) + && (image->comps[1].dy == 4) + && (image->comps[2].dy == 4)) + { +// OK + fprintf(stderr,"%s:%d:COLOR_sycc_to_rgb\n\tNO COVERSION\n", + __FILE__,__LINE__); + fprintf(stderr,"\tcomponents(%d) dx(%d,%d,%d) dy(%d,%d,%d)\n", + image->numcomps, + image->comps[0].dx,image->comps[1].dx,image->comps[2].dx, + image->comps[0].dy,image->comps[1].dy,image->comps[2].dy); + + return; + } + fprintf(stderr,"%s:%d:COLOR_sycc_to_rgb\n\tCAN NOT CONVERT\n", + __FILE__,__LINE__); + fprintf(stderr,"\tcomponents(%d) dx(%d,%d,%d) dy(%d,%d,%d)\n", + image->numcomps, + image->comps[0].dx,image->comps[1].dx,image->comps[2].dx, + image->comps[0].dy,image->comps[1].dy,image->comps[2].dy); + + +}// COLOR_sycc_to_rgb() + +#if defined(OPJ_HAVE_LIBLCMS2) || defined(OPJ_HAVE_LIBLCMS1) + +#ifdef OPJ_HAVE_LIBLCMS1 +// Bob Friesenhahn proposed: +// +#define cmsSigXYZData icSigXYZData +#define cmsSigLabData icSigLabData +#define cmsSigCmykData icSigCmykData +#define cmsSigYCbCrData icSigYCbCrData +#define cmsSigLuvData icSigLuvData +#define cmsSigGrayData icSigGrayData +#define cmsSigRgbData icSigRgbData +#define cmsUInt32Number DWORD +#define cmsUInt16Number WORD + +#define cmsColorSpaceSignature icColorSpaceSignature +#define cmsGetHeaderRenderingIntent cmsTakeRenderingIntent + +#endif // OPJ_HAVE_LIBLCMS1 + +//#define DEBUG_PROFILE + +void COLOR_apply_icc_profile(opj_image_t *image, ImageInfo *dst) +{ + cmsHPROFILE in_prof, out_prof; + cmsHTRANSFORM transform; + cmsColorSpaceSignature out_space; + cmsUInt32Number intent, in_type, out_type; + size_t nr_samples; + int *r, *g, *b; + unsigned int prec, i, max, max_w, max_h, dmax, has_alpha2 = 0; + OPJ_COLOR_SPACE oldspace; + +#ifdef DEBUG_PROFILE + { + FILE *writer = fopen("debug.icm","wb"); + fwrite(image->icc_profile_buf, 1, image->icc_profile_len, writer); + fclose(writer); + } +#endif + + in_prof = + cmsOpenProfileFromMem(image->icc_profile_buf, + image->icc_profile_len); + + if(in_prof == NULL) return ; + + (void)cmsGetPCS(in_prof); + out_space = cmsGetColorSpace(in_prof); + intent = cmsGetHeaderRenderingIntent(in_prof); + + max_w = image->comps[0].w; + max_h = image->comps[0].h; + prec = image->comps[0].prec; + + oldspace = image->color_space; + + if(out_space == cmsSigRgbData) // enumCS 16 + { + if( prec <= 8 ) + { + in_type = TYPE_RGB_8; + out_type = TYPE_RGB_8; + } + else + { + in_type = TYPE_RGB_16; + out_type = TYPE_RGB_16; + } + out_prof = cmsCreate_sRGBProfile(); + image->color_space = OPJ_CLRSPC_SRGB; + } + else + if(out_space == cmsSigGrayData) // enumCS 17 + { + if( prec <= 8 ) + { + in_type = TYPE_GRAY_8; + out_type = TYPE_RGB_8; + } + else //prec > 8 + { + in_type = TYPE_GRAY_16; + out_type = TYPE_RGB_16; + } + out_prof = cmsCreate_sRGBProfile(); + image->color_space = OPJ_CLRSPC_SRGB; + } + else + if(out_space == cmsSigYCbCrData) // enumCS 18 + { + fprintf(stderr,"\n%s:%d:\n\tout_space == cmsSigYCbCrData NOT HANDLED\n\n", + __FILE__,__LINE__); + cmsCloseProfile(in_prof); + return ; +#ifdef HIDDEN_CODE + + in_type = TYPE_YCbCr_16; + out_type = TYPE_RGB_16; + out_prof = cmsCreate_sRGBProfile(); + image->color_space = OPJ_CLRSPC_SRGB; + +#endif //HIDDEN_CODE + } + else + { + cmsCloseProfile(in_prof); + return ; + } + + transform = cmsCreateTransform(in_prof, in_type, + out_prof, out_type, intent, 0); + +#ifdef OPJ_HAVE_LIBLCMS2 +// Possible for: LCMS_VERSION >= 2000 : + cmsCloseProfile(in_prof); + cmsCloseProfile(out_prof); +#endif + + if(transform == NULL) + { + image->color_space = oldspace; +#ifdef OPJ_HAVE_LIBLCMS1 + cmsCloseProfile(in_prof); + cmsCloseProfile(out_prof); +#endif + return ; + } + max = max_w * max_h; + dmax = max * sizeof(int); + + if(image->numcomps > 2)// RGB, RGBA + { + if( prec <= 8 ) + { + unsigned char *inbuf, *outbuf, *in, *out; + + nr_samples = + (cmsUInt32Number)max * 3 * (cmsUInt32Number)sizeof(unsigned char); + + in = inbuf = (unsigned char*)malloc(nr_samples); + out = outbuf = (unsigned char*)malloc(nr_samples); + + r = image->comps[0].data; + g = image->comps[1].data; + b = image->comps[2].data; +// max = max_w * max_h; dmax = max * sizeof(int); + + for(i = 0; i < max; ++i) + { + *in++ = (unsigned char)*r++; + *in++ = (unsigned char)*g++; + *in++ = (unsigned char)*b++; + } + cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max); + + r = dst->red = (int*)malloc(dmax); + g = dst->green = (int*)malloc(dmax); + b = dst->blue = (int*)malloc(dmax); + + dst->free_red = 1; + dst->free_green = 1; + dst->free_blue = 1; + dst->numcomps = 3; + dst->color_space = OPJ_CLRSPC_SRGB; + + for(i = 0; i < max; ++i) + { + *r++ = (int)*out++; + *g++ = (int)*out++; + *b++ = (int)*out++; + } + free(inbuf); free(outbuf); + } + else //prec > 8 + { + unsigned short *inbuf, *outbuf, *in, *out; + + nr_samples = max * 3 * sizeof(unsigned short); + + in = inbuf = (unsigned short*)malloc(nr_samples); + out = outbuf = (unsigned short*)malloc(nr_samples); + + r = image->comps[0].data; + g = image->comps[1].data; + b = image->comps[2].data; +// max = max_w * max_h; dmax = max * sizeof(int); + + for(i = 0; i < max; ++i) + { + *in++ = (unsigned short)*r++; + *in++ = (unsigned short)*g++; + *in++ = (unsigned short)*b++; + } + cmsDoTransform(transform, inbuf, outbuf, max); + + r = dst->red = (int*)malloc(dmax); + g = dst->green = (int*)malloc(dmax); + b = dst->blue = (int*)malloc(dmax); + + dst->free_red = 1; + dst->free_green = 1; + dst->free_blue = 1; + dst->numcomps = 3; + dst->color_space = OPJ_CLRSPC_SRGB; + + for(i = 0; i < max; ++i) + { + *r++ = (int)*out++; + *g++ = (int)*out++; + *b++ = (int)*out++; + } + free(inbuf); free(outbuf); + } + } + else // image->numcomps <= 2 : GRAY -> RGB, GRAYA -> RGBA + { + has_alpha2 = (image->numcomps == 2); + + if(prec <= 8) + { + unsigned char *in, *inbuf, *out, *outbuf; + + nr_samples = max * 3 * sizeof(unsigned char); + + in = inbuf = (unsigned char*)malloc(nr_samples); + out = outbuf = (unsigned char*)malloc(nr_samples); + + r = image->comps[0].data; + + if(has_alpha2) + { + dst->alpha = image->comps[1].data; + dst->prec[3] = image->comps[1].prec; + dst->sgnd[3] = image->comps[1].sgnd; + dst->has_alpha = 1; + } +// max = max_w * max_h; dmax = max * sizeof(int); + + for(i = 0; i < max; ++i) + { + *in++ = (unsigned char)*r++; + } + cmsDoTransform(transform, inbuf, outbuf, max); + + r = dst->red = (int*)malloc(dmax); + g = dst->green = (int*)malloc(dmax); + b = dst->blue = (int*)malloc(dmax); + + dst->free_red = 1; + dst->free_green = 1; + dst->free_blue = 1; + dst->numcomps = 3 + has_alpha2; + dst->color_space = OPJ_CLRSPC_SRGB; + + for(i = 0; i < max; ++i) + { + *r++ = (int)*out++; + *g++ = (int)*out++; + *b++ = (int)*out++; + } + free(inbuf); free(outbuf); + } + else // prec > 8 + { + unsigned short *inbuf, *outbuf, *in, *out; + + nr_samples = + (cmsUInt32Number)max * 3 * (cmsUInt32Number)sizeof(unsigned short); + + in = inbuf = (unsigned short*)malloc(nr_samples); + out = outbuf = (unsigned short*)malloc(nr_samples); + + r = image->comps[0].data; + + if(has_alpha2) + { + dst->alpha = image->comps[1].data; + dst->prec[3] = image->comps[1].prec; + dst->sgnd[3] = image->comps[1].sgnd; + dst->has_alpha = 1; + } +// max = max_w * max_h; dmax = max * sizeof(int); + + for(i = 0; i < max; ++i) + { + *in++ = (unsigned short)*r++; + } + cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max); + + r = dst->red = (int*)malloc(dmax); + g = dst->green = (int*)malloc(dmax); + b = dst->blue = (int*)malloc(dmax); + + dst->free_red = 1; + dst->free_green = 1; + dst->free_blue = 1; + dst->numcomps = 3 + has_alpha2; + dst->color_space = OPJ_CLRSPC_SRGB; + + for(i = 0; i < max; ++i) + { + *r++ = (int)*out++; + *g++ = (int)*out++; + *b++ = (int)*out++; + } + free(inbuf); free(outbuf); + } //if(prec <= 8) + + dst->dx[0] = image->comps[0].dx; + dst->dy[0] = image->comps[0].dy; + dst->prec[0] = image->comps[0].prec; + dst->sgnd[0] = image->comps[0].sgnd; + + dst->dx[1] = image->comps[0].dx; + dst->dy[1] = image->comps[0].dy; + dst->prec[1] = image->comps[0].prec; + dst->sgnd[1] = image->comps[0].sgnd; + + dst->dx[2] = image->comps[0].dx; + dst->dy[2] = image->comps[0].dy; + dst->prec[2] = image->comps[0].prec; + dst->sgnd[2] = image->comps[0].sgnd; + + if(has_alpha2 == 0) + { + dst->dx[3] = image->comps[0].dx; + dst->dy[3] = image->comps[0].dy; + dst->prec[3] = image->comps[0].prec; + dst->sgnd[3] = image->comps[0].sgnd; + } + }// if(image->numcomps > 2) + + cmsDeleteTransform(transform); + +#ifdef OPJ_HAVE_LIBLCMS1 + cmsCloseProfile(in_prof); + cmsCloseProfile(out_prof); +#endif + +}// COLOR_apply_icc_profile() + +void COLOR_apply_conversion(opj_image_t *image, ImageInfo *dst) +{ + int *row; + int enumcs, numcomps; + + image->color_space = OPJ_CLRSPC_SRGB; + dst->color_space = OPJ_CLRSPC_SRGB; + + numcomps = dst->numcomps; + + if(numcomps != 3) + { + fprintf(stderr,"%s:%d:\n\tnumcomps %d not handled. Quitting.\n", + __FILE__,__LINE__,numcomps); + return; + } + + row = (int*)image->icc_profile_buf; + enumcs = row[0]; + + if(enumcs == 14)// CIELab + { + int *L, *a, *b, *red, *green, *blue; + double rl, ol, ra, oa, rb, ob, prec0, prec1, prec2; + double minL, maxL, mina, maxa, minb, maxb; + unsigned int default_type; + unsigned int i, max; + cmsHPROFILE in, out; + cmsHTRANSFORM transform; + cmsUInt16Number RGB[3]; + cmsCIELab Lab; + + in = cmsCreateLab4Profile(NULL); + out = cmsCreate_sRGBProfile(); + + transform = + cmsCreateTransform(in, TYPE_Lab_DBL, out, TYPE_RGB_16, + INTENT_PERCEPTUAL, 0); + +#ifdef OPJ_HAVE_LIBLCMS2 + cmsCloseProfile(in); + cmsCloseProfile(out); +#endif + if(transform == NULL) + { +#ifdef OPJ_HAVE_LIBLCMS1 + cmsCloseProfile(in); + cmsCloseProfile(out); +#endif + return; + } + prec0 = (double)image->comps[0].prec; + prec1 = (double)image->comps[1].prec; + prec2 = (double)image->comps[2].prec; + + default_type = row[1]; + + if(default_type == 0x44454600)// DEF : default + { + rl = 100; ra = 170; rb = 200; + ol = 0; + oa = pow(2, prec1 - 1); + ob = pow(2, prec2 - 2) + pow(2, prec2 - 3); + } + else + { + rl = row[2]; ra = row[4]; rb = row[6]; + ol = row[3]; oa = row[5]; ob = row[7]; + } + L = image->comps[0].data; + a = image->comps[1].data; + b = image->comps[2].data; + + max = image->comps[0].w * image->comps[0].h; + + red = dst->red = (int*)malloc(max * sizeof(int)); + green = dst->green = (int*)malloc(max * sizeof(int)); + blue = dst->blue = (int*)malloc(max * sizeof(int)); + + minL = -(rl * ol)/(pow(2, prec0)-1); + maxL = minL + rl; + + mina = -(ra * oa)/(pow(2, prec1)-1); + maxa = mina + ra; + + minb = -(rb * ob)/(pow(2, prec2)-1); + maxb = minb + rb; + + for(i = 0; i < max; ++i) + { + Lab.L = minL + (double)(*L) * (maxL - minL)/(pow(2, prec0)-1); ++L; + Lab.a = mina + (double)(*a) * (maxa - mina)/(pow(2, prec1)-1); ++a; + Lab.b = minb + (double)(*b) * (maxb - minb)/(pow(2, prec2)-1); ++b; + + cmsDoTransform(transform, &Lab, RGB, 1); + + *red++ = RGB[0]; + *green++ = RGB[1]; + *blue++ = RGB[2]; + } + cmsDeleteTransform(transform); +#ifdef OPJ_HAVE_LIBLCMS1 + cmsCloseProfile(in); + cmsCloseProfile(out); +#endif + + dst->free_red = 1; + dst->free_green = 1; + dst->free_blue = 1; + dst->numcomps = 3; + dst->color_space = OPJ_CLRSPC_SRGB; + dst->prec[0] = 16; + dst->prec[1] = 16; + dst->prec[2] = 16; + + dst->alpha = NULL; + dst->has_alpha = 0; + + image->color_space = OPJ_CLRSPC_SRGB; + image->comps[0].prec = 16; + image->comps[1].prec = 16; + image->comps[2].prec = 16; + + return; + } + + fprintf(stderr,"%s:%d:\n\tenumCS %d not handled. Ignoring.\n", + __FILE__,__LINE__, enumcs); + +}// COLOR_apply_conversion() + +#endif // OPJ_HAVE_LIBLCMS2 || OPJ_HAVE_LIBLCMS1 + +void COLOR_cmyk_to_rgb(opj_image_t *image, ImageInfo *dst) +{ + int *R, *G, *B; + int *sc, *sm, *sy, *sk; + float C, M, Y, K; + unsigned int w, h, max, prec, len, i; + + w = image->comps[0].w; + h = image->comps[0].h; + prec = image->comps[0].prec; + + if(prec != 8) return; + if(image->numcomps != 4) return; + + max = w * h; + len = max * sizeof(int); + + R = dst->red = (int*)malloc(len); + G = dst->green = (int*)malloc(len); + B = dst->blue = (int*)malloc(len); + + sc = image->comps[0].data; + sm = image->comps[1].data; + sy = image->comps[2].data; + sk = image->comps[3].data; + + for(i = 0; i < max; ++i) + { +// CMYK and CMY values from 0 to 1 +// + C = (float)(*sc++)/(float)255.; + M = (float)(*sm++)/(float)255; + Y = (float)(*sy++)/(float)255; + K = (float)(*sk++)/(float)255; + +// CMYK -> CMY +// + C = ( C * ( (float)1. - K ) + K ); + M = ( M * ( (float)1. - K ) + K ); + Y = ( Y * ( (float)1. - K ) + K ); + +// CMY -> RGB : RGB results from 0 to 255 +// + *R++ = (int)(unsigned char)(( (float)1. - C ) * (float)255.); + *G++ = (int)(unsigned char)(( (float)1. - M ) * (float)255.); + *B++ = (int)(unsigned char)(( (float)1. - Y ) * (float)255.); + } + + dst->free_red = 1; + dst->free_green = 1; + dst->free_blue = 1; + dst->numcomps = 3; + dst->color_space = OPJ_CLRSPC_SRGB; + + image->color_space = OPJ_CLRSPC_SRGB; + +}// COLOR_cmyk_to_rgb() + +// +// This code has been adopted from sjpx_openjpeg.c of ghostscript +// +void COLOR_esycc_to_rgb(opj_image_t *image, ImageInfo *dst) +{ + int *s0, *s1, *s2; + int *r, *g, *b; + int y, cb, cr, sign1, sign2, val; + unsigned int w, h, max, i; + int flip_value = (1 << (image->comps[0].prec-1)); + int max_value = (~(-1 << image->comps[0].prec)); + + if(dst->numcomps != 3) return; + + w = image->comps[0].w; + h = image->comps[0].h; + + s0 = image->comps[0].data; + s1 = image->comps[1].data; + s2 = image->comps[2].data; + + sign1 = image->comps[1].sgnd; + sign2 = image->comps[2].sgnd; + + max = w * h; + + r = dst->red = (int*)malloc(max * sizeof(int)); + g = dst->green = (int*)malloc(max * sizeof(int)); + b = dst->blue = (int*)malloc(max * sizeof(int)); + + for(i = 0; i < max; ++i) + { + + y = *s0++; cb = *s1++; cr = *s2++; + + if( !sign1) cb -= flip_value; + if( !sign2) cr -= flip_value; + + val = (int) + ((float)y - (float)0.0000368 * (float)cb + + (float)1.40199 * (float)cr + (float)0.5); + + if(val > max_value) val = max_value; else if(val < 0) val = 0; + *r++ = val; + + val = (int) + ((float)1.0003 * (float)y - (float)0.344125 * (float)cb + - (float)0.7141128 * (float)cr + (float)0.5); + + if(val > max_value) val = max_value; else if(val < 0) val = 0; + *g++ = val; + + val = (int) + ((float)0.999823 * (float)y + (float)1.77204 * (float)cb + - (float)0.000008 *(float)cr + (float)0.5); + + if(val > max_value) val = max_value; else if(val < 0) val = 0; + *b++ = val; + } + dst->free_red = 1; + dst->free_green = 1; + dst->free_blue = 1; + dst->numcomps = 3; + dst->color_space = OPJ_CLRSPC_SRGB; + + image->color_space = OPJ_CLRSPC_SRGB; + +}// COLOR_esycc_to_rgb() + + +#if defined(__cplusplus) || defined(c_plusplus) + } +#endif diff --git a/src/bin/fltk/flviewer/color.hh b/src/bin/fltk/flviewer/color.hh new file mode 100644 index 00000000..8ff0f13f --- /dev/null +++ b/src/bin/fltk/flviewer/color.hh @@ -0,0 +1,61 @@ +#ifndef _FLIMAGE_COLOR_HH_ +#define _FLIMAGE_COLOR_HH_ + +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +typedef struct image_info +{ + int *red; + int *green; + int *blue; + int *alpha; + unsigned int numcomps; + OPJ_COLOR_SPACE color_space; + + unsigned int dx[4], dy[4], prec[4], sgnd[4]; + + unsigned char free_red, free_green, free_blue, unused_alpha; + int has_alpha; + int is_still; + +} ImageInfo; + +#if defined(OPJ_HAVE_LIBLCMS1) || defined(OPJ_HAVE_LIBLCMS2) +extern void COLOR_apply_icc_profile(opj_image_t *image, ImageInfo *dst); +extern void COLOR_apply_conversion(opj_image_t *image, ImageInfo *dst); +#endif + +extern void COLOR_sycc_to_rgb(opj_image_t *img, ImageInfo *dst); +extern void COLOR_cmyk_to_rgb(opj_image_t *image, ImageInfo *dst); +extern void COLOR_esycc_to_rgb(opj_image_t *image, ImageInfo *dst); + +#endif /* _FLIMAGE_COLOR_HH_ */ diff --git a/src/bin/fltk/flviewer/config.h.cmake b/src/bin/fltk/flviewer/config.h.cmake new file mode 100644 index 00000000..4d8d5431 --- /dev/null +++ b/src/bin/fltk/flviewer/config.h.cmake @@ -0,0 +1,25 @@ +#ifndef _FLIMAGE_CONFIG_H_ +#define _FLIMAGE_CONFIG_H + +#define PACKAGE_VERSION "@FLVIEWER_VERSION@" +#define PACKAGE_STRING "@FLVIEWER_PACKAGE_STRING@" + +#cmakedefine WITH_ENGLISH +#cmakedefine WITH_GERMAN + +#cmakedefine HAVE_THREADS +#cmakedefine HAVE_WINPORT + +#cmakedefine HAVE_FSEEKI64 @HAVE_FSEEKI64@ +#cmakedefine HAVE_FSEEKO + +#cmakedefine _LARGEFILE_SOURCE +#cmakedefine _FILE_OFFSET_BITS @_FILE_OFFSET_BITS@ + +#if !defined(__APPLE__) +#cmakedefine OPJ_BIG_ENDIAN +#elif defined(__BIG_ENDIAN__) +#cmakedefine OPJ_BIG_ENDIAN +#endif +# +#endif /* _FLIMAGE_CONFIG_H_ */ diff --git a/src/bin/fltk/flviewer/convert.windows/CMakeLists.txt b/src/bin/fltk/flviewer/convert.windows/CMakeLists.txt new file mode 100644 index 00000000..a02b03e0 --- /dev/null +++ b/src/bin/fltk/flviewer/convert.windows/CMakeLists.txt @@ -0,0 +1,41 @@ +#flimage-VERSION +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +# +PROJECT(convert) +# +IF(COMMAND CMAKE_POLICY) + CMAKE_POLICY(SET CMP0003 NEW) +ENDIF(COMMAND CMAKE_POLICY) +# +SET(CONVERT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +# +FIND_PACKAGE(FLTK REQUIRED) +# +ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS) +# +INCLUDE_DIRECTORIES( + ${FLTK_DIR}/include + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_BINARY_DIR} +) +#------------------- +IF(UNIX) + FIND_PROGRAM(FLTK_CONFIG_SCRIPT fltk-config PATHS ${FLTK_BIN_DIR}) +# + EXEC_PROGRAM(${FLTK_CONFIG_SCRIPT} ARGS --use-images --ldflags + OUTPUT_VARIABLE LIBS) +ELSE(UNIX) + SET(LIBS ${FLTK_BASE_LIBRARY} ${FLTK_FORMS_LIBRARY} ${FLTK_GL_LIBRARY} ${FLTK_IMAGES_LIBRARY} ) +ENDIF(UNIX) + +#------------------- +SET(exe convert) +SET(SRCS convert.cxx) +ADD_EXECUTABLE(${exe} ${SRCS}) +TARGET_LINK_LIBRARIES(${exe} ${LIBS}) +# +INSTALL(TARGETS ${exe} + RUNTIME + DESTINATION ${CMAKE_CURRENT_SOURCE_DIR} +) +# diff --git a/src/bin/fltk/flviewer/convert.windows/build-convert-cmake.sh b/src/bin/fltk/flviewer/convert.windows/build-convert-cmake.sh new file mode 100644 index 00000000..736fb829 --- /dev/null +++ b/src/bin/fltk/flviewer/convert.windows/build-convert-cmake.sh @@ -0,0 +1,3 @@ +#!/bin/sh +cmake -DFLTK_INCLUDE_DIR:path="/usr/local/fltk13/" .. + diff --git a/src/bin/fltk/flviewer/convert.windows/cmake-compile-convert.bat b/src/bin/fltk/flviewer/convert.windows/cmake-compile-convert.bat new file mode 100644 index 00000000..73892322 --- /dev/null +++ b/src/bin/fltk/flviewer/convert.windows/cmake-compile-convert.bat @@ -0,0 +1 @@ +cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXE_LINKER_FLAGS:string="/machine:x64" -DCMAKE_LIBRARY_PATH:path="C:/Users/Public" -DCMAKE_INCLUDE_PATH:path="C:/Users/Public/include" .. diff --git a/src/bin/fltk/flviewer/convert.windows/convert.cxx b/src/bin/fltk/flviewer/convert.windows/convert.cxx new file mode 100644 index 00000000..201bab93 --- /dev/null +++ b/src/bin/fltk/flviewer/convert.windows/convert.cxx @@ -0,0 +1,40 @@ +#include +#include +#include +#include + +int main(int argc, char *argv[]) +{ + const char *fname; + char *write_idf; + FILE *reader, *writer; + unsigned int slen; + char s[128]; + char d[512]; + + if(argc == 1) return 1; + fname = argv[1]; + reader = fopen(fname, "r"); + if(reader == NULL) + { + printf("Can not open src file %s\n",fname); + return 1; + } + slen = strlen(fname); + write_idf = (char*)malloc(slen+8); + strcpy(write_idf, fname); strcpy(write_idf+slen,"_utf8"); + printf("RESULT in:%s\n",write_idf); + + writer = fopen(write_idf, "w"); + + while(fgets(s, 127, reader)) + { + fl_utf8froma(d,512,s,strlen(s)); + + fprintf(writer,"%s", d); + } + + fclose(reader); fclose(writer); free(write_idf); + + return 0; +} diff --git a/src/bin/fltk/flviewer/convert.windows/dialog_lang.h b/src/bin/fltk/flviewer/convert.windows/dialog_lang.h new file mode 100644 index 00000000..305bd9a8 --- /dev/null +++ b/src/bin/fltk/flviewer/convert.windows/dialog_lang.h @@ -0,0 +1,88 @@ +#ifndef _FLIMAGE_PRINT_DIALOG_LANG_H_ +#define _FLIMAGE_PRINT_DIALOG_LANG_H_ +/* static const char _s[]={""}; */ +#ifdef WITH_ENGLISH +static const char YES_s[]={"YES"}; +static const char NO_s[]={"NO"}; +static const char PRINTERPAGE_s[]={"Print Image (PostScript)"}; +static const char FILENAME_s[]={"Filename:"}; +static const char PRINT_s[]={"Print"}; +static const char PRINTCMD_s[]={"Command:"}; +static const char PRINTERNAMES_s[]={"Name:"}; +static const char PRINTER_s[]={"Printer"}; +static const char PRINTTO_s[]={"Print To"}; +static const char FILE_s[]={"File"}; +static const char CONTINUE_PRINT_s[]= + {"File already exists.\n Continue?"}; +static const char COPIES_s[]={"Copies:"}; +static const char PORTRAIT_s[]={"Portrait"}; +static const char LANDSCAPE_s[]={"Landscape"}; +static const char LOWRES_s[]={"Low resolution"}; +static const char HIRES_s[]={"High resolution"}; +static const char COLOR_s[]={"Color"}; +static const char GRAY_s[]={"Gray"}; +static const char DOCFORMAT_s[]={"Format"}; +static const char OK_s[]={"OK"}; +static const char CANCEL_s[]={"Cancel"}; + +static const char NAME_s[]={"Name:"}; +static const char TITLE_s[]={"Title:"}; +static const char IMAGE_s[]={"Image"}; +static const char CENTER_s[]={"Center"}; +static const char MARGINS_s[]={"Margins(mm)"}; +static const char LEFT_s[]={"Left:"}; +static const char RIGHT_s[]={"Right:"}; +static const char TOP_s[]={"Top:"}; +static const char BOTTOM_s[]={"Bottom:"}; +static const char LOC_s[]={"Loc:"}; +static const char NO_FILENAME_FOUND_s[]= + {"No file name found. Please enter."}; +static const char NAME_IS_DIR_s[]= + {"Name exists and is directory name. Please change."}; +#endif /* WITH_ENGLISH */ + +#ifdef WITH_GERMAN + +static const char YES_s[]={"Ja"}; +static const char NO_s[]={"Nein"}; +static const char NO_FILENAME_FOUND_s[]= + {"Kein Datei-Name gefunden. Bitte eingeben."}; +static const char NAME_IS_DIR_s[]= + {"Name ist Verzeichnis-Name. Bitte ändern."}; +static const char LOC_s[]={"Ort:"}; +static const char PRINTERPAGE_s[]={"Bild drucken (PostScript)"}; +static const char FILENAME_s[]={"Datei-Name:"}; +static const char PRINT_s[]={"Drucken"}; +static const char PRINTCMD_s[]={"Befehl:"}; +static const char PRINTERNAMES_s[]={"Name:"}; +static const char PRINTER_s[]={"Drucker"}; +static const char PRINTTO_s[]={"Ziel"}; +static const char FILE_s[]={"Datei"}; +static const char CONTINUE_PRINT_s[]= + {"Datei besteht bereits.\n Weiter?"}; +static const char COPIES_s[]={"Kopien:"}; +static const char PORTRAIT_s[]={"Vertikal-Druck"}; +static const char LANDSCAPE_s[]={"Quer-Druck"}; +static const char LOWRES_s[]={"Auflösung gering"}; +static const char HIRES_s[]={"Auflösung hoch"}; +static const char COLOR_s[]={"Farbig"}; +static const char GRAY_s[]={"Grau"}; +static const char DOCFORMAT_s[]={"Format"}; +static const char OK_s[]={"OK"}; +static const char CANCEL_s[]={"Abbruch"}; + +static const char NAME_s[]={"Name:"}; +static const char TITLE_s[]={"Titel:"}; +static const char IMAGE_s[]={"Bild"}; +static const char CENTER_s[]={"Zentrieren"}; +static const char MARGINS_s[]={"Ränder(mm)"}; +static const char LEFT_s[]={"Links:"}; +static const char RIGHT_s[]={"Rechts:"}; +static const char TOP_s[]={"Oben:"}; +static const char BOTTOM_s[]={"Unten:"}; + +#endif /* WITH_GERMAN */ + + + +#endif /* _FLIMAGE_PRINT_DIALOG_LANG_H_ */ diff --git a/src/bin/fltk/flviewer/convert.windows/mj2_lang.h b/src/bin/fltk/flviewer/convert.windows/mj2_lang.h new file mode 100644 index 00000000..5b625bf8 --- /dev/null +++ b/src/bin/fltk/flviewer/convert.windows/mj2_lang.h @@ -0,0 +1,17 @@ +#ifndef _FLIMAGE_MJ2_FILE_LANG_H_ +#define _FLIMAGE_MJ2_FILE_LANG_H_ + +//static const char _s[]={""}; +#ifdef WITH_ENGLISH +static const char MJ2_NO_FRAMES_FROM_s[]={"MJ2:Can not extract frames from"}; +static const char MJ2_SHOW_FAILS_s[]= + {"MJ2:Can not show file\n%s\n samples(%d) width(%d) height(%d)"}; +#endif + +#ifdef WITH_GERMAN +static const char MJ2_NO_FRAMES_FROM_s[]={"MJ2:kann nichts finden in"}; +static const char MJ2_SHOW_FAILS_s[]= + {"MJ2:kann Datei nicht zeigen für\n%s\n Bilder(%d) Weite(%d) Höhe(%d)"}; +#endif + +#endif /* _FLIMAGE_MJ2_FILE_LANG_H_ */ diff --git a/src/bin/fltk/flviewer/convert.windows/opj_lang.h b/src/bin/fltk/flviewer/convert.windows/opj_lang.h new file mode 100644 index 00000000..b8a11679 --- /dev/null +++ b/src/bin/fltk/flviewer/convert.windows/opj_lang.h @@ -0,0 +1,30 @@ +#ifndef _FLIMAGE_OPJ_FILE_LANG_H_ +#define _FLIMAGE_OPJ_FILE_LANG_H_ + +//static const char _s[]={""}; +#ifdef WITH_ENGLISH +static const char JPEG2000_DECODE_FAILS_s[]={"Got no JPEG2000 image for"}; +static const char DST_DID_NOT_OPEN_s[]={"Destination %s\n\tdid not open"}; +static const char WRITE_JPEG2000_FAILS_s[]={"Writing JPEG2000 file fails"}; +static const char GOT_NO_IMAGE_s[]={"opj_image_create() failed"}; +static const char WRONG_DST_EXT_s[]= + {"Destination file %s\nhas wrong extension"}; +static const char WRITE_JP2_FAILS_s[]={"Writing JP2 file fails"}; +static const char JP2_DECODE_FAILS_s[]={"Got no JP2 image for"}; + +#endif + +#ifdef WITH_GERMAN +static const char JPEG2000_DECODE_FAILS_s[]={"JPEG2000 Dekodierungsfehler für"}; +static const char DST_DID_NOT_OPEN_s[]={"Ziel-Datei %s\n\töffnet nicht"}; +static const char WRITE_JPEG2000_FAILS_s[]= + {"JPEG2000-Datei läßt sich nicht schreiben"}; +static const char GOT_NO_IMAGE_s[]={"opj_image_create() scheitert"}; +static const char WRONG_DST_EXT_s[]= + {"Ziel-Datei %s\nhat falsche Extension"}; +static const char WRITE_JP2_FAILS_s[]={"JP2-Datei läßt sich nicht schreiben"}; +static const char JP2_DECODE_FAILS_s[]={"JP2 Dekodierungsfehler für"}; + +#endif + +#endif /* _FLIMAGE_OPJ_FILE_LANG_H_ */ diff --git a/src/bin/fltk/flviewer/convert.windows/png_lang.h b/src/bin/fltk/flviewer/convert.windows/png_lang.h new file mode 100644 index 00000000..ee11f966 --- /dev/null +++ b/src/bin/fltk/flviewer/convert.windows/png_lang.h @@ -0,0 +1,15 @@ +#ifndef _FLIMAGE_PNG_LANG_H_ +#define _FLIMAGE_PNG_LANG_H_ +//static const char _s[]={""}; +#ifdef WITH_ENGLISH +static const char DST_DID_NOT_OPEN_s[]={"Destination %s\n\tdid not open"}; +static const char WRITE_PNG_FAILS_s[]={"Writing PNG file fails"}; + +#endif +#ifdef WITH_GERMAN +static const char DST_DID_NOT_OPEN_s[]={"Ziel-Datei %s\n\töffnet nicht"}; +static const char WRITE_PNG_FAILS_s[]={"PNG-Datei läßt sich nicht schreiben"}; + +#endif + +#endif /* _FLIMAGE_PNG_LANG_H_ */ diff --git a/src/bin/fltk/flviewer/convert.windows/viewer_lang.h b/src/bin/fltk/flviewer/convert.windows/viewer_lang.h new file mode 100644 index 00000000..e7289f75 --- /dev/null +++ b/src/bin/fltk/flviewer/convert.windows/viewer_lang.h @@ -0,0 +1,119 @@ +#ifndef _FLIMAGE_FILE_LANG_H_ +#define _FLIMAGE_FILE_LANG_H_ +//static const char _s[]={""}; +#ifdef WITH_ENGLISH +static const char CANNOT_USE_FILE_s[]= {"Can not use file"}; +static const char NO_DRIVER_FOUND_s[]= {"NO DRIVER FOUND"}; +static const char FILE_NOT_FOUND_s[]= {"File not found"}; +static const char CANNOT_LOAD_FILE_s[]= {"Can not load file"}; +static const char FILESIZE_TOO_LONG_s[]={"filesize too large. Ignored."}; +static const char NO_FILE_TO_PRINT_s[]={"No file to print."}; +static const char FILE_SIZE_ZERO_s[]={"File length is zero"}; +static const char USE_SYSTEM_COMMAND_TO_PRINT_s[]= + {"Please use the system command(s)\nto print the file:"}; +static const char TILE_s[]={"Tile:"}; +static const char OF_s[]={" of "}; +static const char RELOAD_s[]={"Reload"}; +static const char REDUCTION_s[]={"Reduction:"}; +static const char NO_FILE_TO_SAVE_s[]={"No file to save"}; +static const char SAVE_AS_PNG_s[]={"Save As PNG"}; +static const char ENTER_PNG_TO_SAVE_s[]= + {"Enter a name to save a PNG file:"}; +static const char FILE_EXISTS_s[]= + {"File already exists.\n Continue?"}; +static const char SAVE_AS_OPJ_s[]={"Save As JP2/J2K"}; +static const char ENTER_OPJ_TO_SAVE_s[]= + {"Enter a name to save a JP2/J2K file:"}; +static const char MISSING_PNG_EXT_s[]={"File extension not '.png'. Goon?"}; +static const char AREA_s[]={"Area:"}; +static const char FILENAME_TOO_LONG_s[]={"filename too long. Ignored."}; + +static const char EXIT_s[]={"Exit"}; +static const char STOP_s[]={"Stop"}; +static const char GOON_s[]={"Go on"}; +static const char RESTART_s[]={"Restart"}; +static const char FORWARD_s[]={"Step @>"}; +static const char BACKWARD_s[]={"@< Step"}; +static const char CLOSEFILE_s[]={"Close"}; +static const char BROWSE_s[]={"Browse"}; +static const char START_s[]={"Start:"}; +static const char ALLFRAMES_s[]={"Frames:"}; +static const char ALLTRACKS_s[]={"Tracks:"}; +static const char FILENAME_s[]={"File:"}; +static const char BLEND_s[]={"Blend"}; +static const char SHOW_s[]={"Show"}; +static const char LAYERS_s[]={"Layer:"}; +static const char WAITPLEASE_s[]={"Please, wait ..."}; +static const char SUCCESS_WITH_s[]={"Success with file:"}; +static const char FAILURE_WITH_s[]={"Failure with file:"}; +static const char POPUP_EXIT_s[]={"_Exit"}; +static const char PRINT_s[]={"Print"}; +static const char CANNOT_OPEN_s[]={"Can not open file:"}; +static const char GAMMA_s[]={"Gamma:"}; +static const char BRIGHTNESS_s[]={"Brightness:"}; +static const char CONTRAST_s[]={"Contrast:"}; +static const char CANCEL_s[]={"Cancel"}; +static const char CROP_s[]={"Section"}; +static const char LAYER_s[]={"Layer:"}; +static const char COMPONENT_s[]={"Component:"}; +#endif + +#ifdef WITH_GERMAN +static const char LAYER_s[]={"Schicht:"}; +static const char COMPONENT_s[]={"Komponente:"}; +static const char PRINT_s[]={"Drucken"}; +static const char POPUP_EXIT_s[]={"_Abbruch"}; +static const char CANNOT_OPEN_s[]={"Kann Datei nicht öffnen:"}; +static const char SUCCESS_WITH_s[]={"Erfolg mit Datei:"}; +static const char FAILURE_WITH_s[]={"Fehler mit Datei:"}; +static const char EXIT_s[]={"Abbruch"}; +static const char STOP_s[]={"Anhalten"}; +static const char GOON_s[]={"Weiter"}; +static const char RESTART_s[]={"Neustart"}; +static const char FORWARD_s[]={"Schritt @>"}; +static const char BACKWARD_s[]={"@< Schritt"}; +static const char CLOSEFILE_s[]={"Ende"}; +static const char BROWSE_s[]={"Suchen"}; +static const char START_s[]={"Start:"}; +static const char ALLFRAMES_s[]={"Rahmen:"}; +static const char ALLTRACKS_s[]={"Tracks:"}; +static const char FILENAME_s[]={"Datei:"}; +static const char BLEND_s[]={"Mischen"}; +static const char SHOW_s[]={"Zeigen"}; +static const char LAYERS_s[]={"Schicht:"}; +static const char WAITPLEASE_s[]={"Bitte warten ..."}; +static const char GAMMA_s[]={"Gamma:"}; +static const char BRIGHTNESS_s[]={"Helligkeit:"}; +static const char CONTRAST_s[]={"Kontrast:"}; +static const char CANCEL_s[]={"Abbruch"}; +static const char CROP_s[]={"Ausschnitt"}; + +static const char CANNOT_USE_FILE_s[]= {"Kann Datei nicht verwenden"}; +static const char NO_DRIVER_FOUND_s[]= {"KEIN TREIBER GEFUNDEN"}; +static const char FILE_NOT_FOUND_s[]= {"Datei nicht gefunden"}; +static const char CANNOT_LOAD_FILE_s[]= {"Kann Datei nicht laden"}; +static const char FILESIZE_TOO_LONG_s[]={"Datei ist zu groß. Ignoriert."}; +static const char NO_FILE_TO_PRINT_s[]={"Keine druckbare Datei gefunden."}; +static const char FILE_SIZE_ZERO_s[]={"Datei-Länge ist 0"}; +static const char USE_SYSTEM_COMMAND_TO_PRINT_s[]= + {"Bitte System-Befehl(e) benutzen,\num folgende Datei zu drucken:"}; +static const char TILE_s[]={"Kachel:"}; +static const char OF_s[]={" von "}; +static const char RELOAD_s[]={"Neu laden"}; +static const char REDUCTION_s[]={"Verkleinerung:"}; +static const char NO_FILE_TO_SAVE_s[]={"Keine Datei zum Sichern gefunden"}; +static const char SAVE_AS_PNG_s[]={"Sichern als PNG"}; +static const char ENTER_PNG_TO_SAVE_s[]= + {"Einen Name eingeben für eine PNG Datei:"}; +static const char FILE_EXISTS_s[]= + {"Datei besteht bereits.\n Weiter?"}; +static const char SAVE_AS_OPJ_s[]={"Sichern als JP2/J2K"}; +static const char ENTER_OPJ_TO_SAVE_s[]= + {"Einen Name eingeben für eine JP2/J2K Datei:"}; +static const char MISSING_PNG_EXT_s[]={"Datei-Endung nicht '.png'. Weiter?"}; +static const char AREA_s[]={"Fläche:"}; +static const char FILENAME_TOO_LONG_s[]={"Datei-Name zu lang. Ignoriert."}; + +#endif + +#endif /* _FLIMAGE_LANG_H_ */ diff --git a/src/bin/fltk/flviewer/convert/Makefile b/src/bin/fltk/flviewer/convert/Makefile new file mode 100644 index 00000000..2e3977b2 --- /dev/null +++ b/src/bin/fltk/flviewer/convert/Makefile @@ -0,0 +1,10 @@ +LIBS=`fltk-config --ldflags` +INC=`fltk-config --cflags` +CC=g++ + +Convert: + rm -f convert + $(CC) -Wall $(INC) convert.c -o convert $(LIBS) + +clean: + rm -f convert diff --git a/src/bin/fltk/flviewer/convert/convert.c b/src/bin/fltk/flviewer/convert/convert.c new file mode 100644 index 00000000..201bab93 --- /dev/null +++ b/src/bin/fltk/flviewer/convert/convert.c @@ -0,0 +1,40 @@ +#include +#include +#include +#include + +int main(int argc, char *argv[]) +{ + const char *fname; + char *write_idf; + FILE *reader, *writer; + unsigned int slen; + char s[128]; + char d[512]; + + if(argc == 1) return 1; + fname = argv[1]; + reader = fopen(fname, "r"); + if(reader == NULL) + { + printf("Can not open src file %s\n",fname); + return 1; + } + slen = strlen(fname); + write_idf = (char*)malloc(slen+8); + strcpy(write_idf, fname); strcpy(write_idf+slen,"_utf8"); + printf("RESULT in:%s\n",write_idf); + + writer = fopen(write_idf, "w"); + + while(fgets(s, 127, reader)) + { + fl_utf8froma(d,512,s,strlen(s)); + + fprintf(writer,"%s", d); + } + + fclose(reader); fclose(writer); free(write_idf); + + return 0; +} diff --git a/src/bin/fltk/flviewer/convert/dialog_lang.h b/src/bin/fltk/flviewer/convert/dialog_lang.h new file mode 100644 index 00000000..305bd9a8 --- /dev/null +++ b/src/bin/fltk/flviewer/convert/dialog_lang.h @@ -0,0 +1,88 @@ +#ifndef _FLIMAGE_PRINT_DIALOG_LANG_H_ +#define _FLIMAGE_PRINT_DIALOG_LANG_H_ +/* static const char _s[]={""}; */ +#ifdef WITH_ENGLISH +static const char YES_s[]={"YES"}; +static const char NO_s[]={"NO"}; +static const char PRINTERPAGE_s[]={"Print Image (PostScript)"}; +static const char FILENAME_s[]={"Filename:"}; +static const char PRINT_s[]={"Print"}; +static const char PRINTCMD_s[]={"Command:"}; +static const char PRINTERNAMES_s[]={"Name:"}; +static const char PRINTER_s[]={"Printer"}; +static const char PRINTTO_s[]={"Print To"}; +static const char FILE_s[]={"File"}; +static const char CONTINUE_PRINT_s[]= + {"File already exists.\n Continue?"}; +static const char COPIES_s[]={"Copies:"}; +static const char PORTRAIT_s[]={"Portrait"}; +static const char LANDSCAPE_s[]={"Landscape"}; +static const char LOWRES_s[]={"Low resolution"}; +static const char HIRES_s[]={"High resolution"}; +static const char COLOR_s[]={"Color"}; +static const char GRAY_s[]={"Gray"}; +static const char DOCFORMAT_s[]={"Format"}; +static const char OK_s[]={"OK"}; +static const char CANCEL_s[]={"Cancel"}; + +static const char NAME_s[]={"Name:"}; +static const char TITLE_s[]={"Title:"}; +static const char IMAGE_s[]={"Image"}; +static const char CENTER_s[]={"Center"}; +static const char MARGINS_s[]={"Margins(mm)"}; +static const char LEFT_s[]={"Left:"}; +static const char RIGHT_s[]={"Right:"}; +static const char TOP_s[]={"Top:"}; +static const char BOTTOM_s[]={"Bottom:"}; +static const char LOC_s[]={"Loc:"}; +static const char NO_FILENAME_FOUND_s[]= + {"No file name found. Please enter."}; +static const char NAME_IS_DIR_s[]= + {"Name exists and is directory name. Please change."}; +#endif /* WITH_ENGLISH */ + +#ifdef WITH_GERMAN + +static const char YES_s[]={"Ja"}; +static const char NO_s[]={"Nein"}; +static const char NO_FILENAME_FOUND_s[]= + {"Kein Datei-Name gefunden. Bitte eingeben."}; +static const char NAME_IS_DIR_s[]= + {"Name ist Verzeichnis-Name. Bitte ändern."}; +static const char LOC_s[]={"Ort:"}; +static const char PRINTERPAGE_s[]={"Bild drucken (PostScript)"}; +static const char FILENAME_s[]={"Datei-Name:"}; +static const char PRINT_s[]={"Drucken"}; +static const char PRINTCMD_s[]={"Befehl:"}; +static const char PRINTERNAMES_s[]={"Name:"}; +static const char PRINTER_s[]={"Drucker"}; +static const char PRINTTO_s[]={"Ziel"}; +static const char FILE_s[]={"Datei"}; +static const char CONTINUE_PRINT_s[]= + {"Datei besteht bereits.\n Weiter?"}; +static const char COPIES_s[]={"Kopien:"}; +static const char PORTRAIT_s[]={"Vertikal-Druck"}; +static const char LANDSCAPE_s[]={"Quer-Druck"}; +static const char LOWRES_s[]={"Auflösung gering"}; +static const char HIRES_s[]={"Auflösung hoch"}; +static const char COLOR_s[]={"Farbig"}; +static const char GRAY_s[]={"Grau"}; +static const char DOCFORMAT_s[]={"Format"}; +static const char OK_s[]={"OK"}; +static const char CANCEL_s[]={"Abbruch"}; + +static const char NAME_s[]={"Name:"}; +static const char TITLE_s[]={"Titel:"}; +static const char IMAGE_s[]={"Bild"}; +static const char CENTER_s[]={"Zentrieren"}; +static const char MARGINS_s[]={"Ränder(mm)"}; +static const char LEFT_s[]={"Links:"}; +static const char RIGHT_s[]={"Rechts:"}; +static const char TOP_s[]={"Oben:"}; +static const char BOTTOM_s[]={"Unten:"}; + +#endif /* WITH_GERMAN */ + + + +#endif /* _FLIMAGE_PRINT_DIALOG_LANG_H_ */ diff --git a/src/bin/fltk/flviewer/convert/mj2_lang.h b/src/bin/fltk/flviewer/convert/mj2_lang.h new file mode 100644 index 00000000..5b625bf8 --- /dev/null +++ b/src/bin/fltk/flviewer/convert/mj2_lang.h @@ -0,0 +1,17 @@ +#ifndef _FLIMAGE_MJ2_FILE_LANG_H_ +#define _FLIMAGE_MJ2_FILE_LANG_H_ + +//static const char _s[]={""}; +#ifdef WITH_ENGLISH +static const char MJ2_NO_FRAMES_FROM_s[]={"MJ2:Can not extract frames from"}; +static const char MJ2_SHOW_FAILS_s[]= + {"MJ2:Can not show file\n%s\n samples(%d) width(%d) height(%d)"}; +#endif + +#ifdef WITH_GERMAN +static const char MJ2_NO_FRAMES_FROM_s[]={"MJ2:kann nichts finden in"}; +static const char MJ2_SHOW_FAILS_s[]= + {"MJ2:kann Datei nicht zeigen für\n%s\n Bilder(%d) Weite(%d) Höhe(%d)"}; +#endif + +#endif /* _FLIMAGE_MJ2_FILE_LANG_H_ */ diff --git a/src/bin/fltk/flviewer/convert/opj_lang.h b/src/bin/fltk/flviewer/convert/opj_lang.h new file mode 100644 index 00000000..b8a11679 --- /dev/null +++ b/src/bin/fltk/flviewer/convert/opj_lang.h @@ -0,0 +1,30 @@ +#ifndef _FLIMAGE_OPJ_FILE_LANG_H_ +#define _FLIMAGE_OPJ_FILE_LANG_H_ + +//static const char _s[]={""}; +#ifdef WITH_ENGLISH +static const char JPEG2000_DECODE_FAILS_s[]={"Got no JPEG2000 image for"}; +static const char DST_DID_NOT_OPEN_s[]={"Destination %s\n\tdid not open"}; +static const char WRITE_JPEG2000_FAILS_s[]={"Writing JPEG2000 file fails"}; +static const char GOT_NO_IMAGE_s[]={"opj_image_create() failed"}; +static const char WRONG_DST_EXT_s[]= + {"Destination file %s\nhas wrong extension"}; +static const char WRITE_JP2_FAILS_s[]={"Writing JP2 file fails"}; +static const char JP2_DECODE_FAILS_s[]={"Got no JP2 image for"}; + +#endif + +#ifdef WITH_GERMAN +static const char JPEG2000_DECODE_FAILS_s[]={"JPEG2000 Dekodierungsfehler für"}; +static const char DST_DID_NOT_OPEN_s[]={"Ziel-Datei %s\n\töffnet nicht"}; +static const char WRITE_JPEG2000_FAILS_s[]= + {"JPEG2000-Datei läßt sich nicht schreiben"}; +static const char GOT_NO_IMAGE_s[]={"opj_image_create() scheitert"}; +static const char WRONG_DST_EXT_s[]= + {"Ziel-Datei %s\nhat falsche Extension"}; +static const char WRITE_JP2_FAILS_s[]={"JP2-Datei läßt sich nicht schreiben"}; +static const char JP2_DECODE_FAILS_s[]={"JP2 Dekodierungsfehler für"}; + +#endif + +#endif /* _FLIMAGE_OPJ_FILE_LANG_H_ */ diff --git a/src/bin/fltk/flviewer/convert/png_lang.h b/src/bin/fltk/flviewer/convert/png_lang.h new file mode 100644 index 00000000..ee11f966 --- /dev/null +++ b/src/bin/fltk/flviewer/convert/png_lang.h @@ -0,0 +1,15 @@ +#ifndef _FLIMAGE_PNG_LANG_H_ +#define _FLIMAGE_PNG_LANG_H_ +//static const char _s[]={""}; +#ifdef WITH_ENGLISH +static const char DST_DID_NOT_OPEN_s[]={"Destination %s\n\tdid not open"}; +static const char WRITE_PNG_FAILS_s[]={"Writing PNG file fails"}; + +#endif +#ifdef WITH_GERMAN +static const char DST_DID_NOT_OPEN_s[]={"Ziel-Datei %s\n\töffnet nicht"}; +static const char WRITE_PNG_FAILS_s[]={"PNG-Datei läßt sich nicht schreiben"}; + +#endif + +#endif /* _FLIMAGE_PNG_LANG_H_ */ diff --git a/src/bin/fltk/flviewer/convert/viewer_lang.h b/src/bin/fltk/flviewer/convert/viewer_lang.h new file mode 100644 index 00000000..e7289f75 --- /dev/null +++ b/src/bin/fltk/flviewer/convert/viewer_lang.h @@ -0,0 +1,119 @@ +#ifndef _FLIMAGE_FILE_LANG_H_ +#define _FLIMAGE_FILE_LANG_H_ +//static const char _s[]={""}; +#ifdef WITH_ENGLISH +static const char CANNOT_USE_FILE_s[]= {"Can not use file"}; +static const char NO_DRIVER_FOUND_s[]= {"NO DRIVER FOUND"}; +static const char FILE_NOT_FOUND_s[]= {"File not found"}; +static const char CANNOT_LOAD_FILE_s[]= {"Can not load file"}; +static const char FILESIZE_TOO_LONG_s[]={"filesize too large. Ignored."}; +static const char NO_FILE_TO_PRINT_s[]={"No file to print."}; +static const char FILE_SIZE_ZERO_s[]={"File length is zero"}; +static const char USE_SYSTEM_COMMAND_TO_PRINT_s[]= + {"Please use the system command(s)\nto print the file:"}; +static const char TILE_s[]={"Tile:"}; +static const char OF_s[]={" of "}; +static const char RELOAD_s[]={"Reload"}; +static const char REDUCTION_s[]={"Reduction:"}; +static const char NO_FILE_TO_SAVE_s[]={"No file to save"}; +static const char SAVE_AS_PNG_s[]={"Save As PNG"}; +static const char ENTER_PNG_TO_SAVE_s[]= + {"Enter a name to save a PNG file:"}; +static const char FILE_EXISTS_s[]= + {"File already exists.\n Continue?"}; +static const char SAVE_AS_OPJ_s[]={"Save As JP2/J2K"}; +static const char ENTER_OPJ_TO_SAVE_s[]= + {"Enter a name to save a JP2/J2K file:"}; +static const char MISSING_PNG_EXT_s[]={"File extension not '.png'. Goon?"}; +static const char AREA_s[]={"Area:"}; +static const char FILENAME_TOO_LONG_s[]={"filename too long. Ignored."}; + +static const char EXIT_s[]={"Exit"}; +static const char STOP_s[]={"Stop"}; +static const char GOON_s[]={"Go on"}; +static const char RESTART_s[]={"Restart"}; +static const char FORWARD_s[]={"Step @>"}; +static const char BACKWARD_s[]={"@< Step"}; +static const char CLOSEFILE_s[]={"Close"}; +static const char BROWSE_s[]={"Browse"}; +static const char START_s[]={"Start:"}; +static const char ALLFRAMES_s[]={"Frames:"}; +static const char ALLTRACKS_s[]={"Tracks:"}; +static const char FILENAME_s[]={"File:"}; +static const char BLEND_s[]={"Blend"}; +static const char SHOW_s[]={"Show"}; +static const char LAYERS_s[]={"Layer:"}; +static const char WAITPLEASE_s[]={"Please, wait ..."}; +static const char SUCCESS_WITH_s[]={"Success with file:"}; +static const char FAILURE_WITH_s[]={"Failure with file:"}; +static const char POPUP_EXIT_s[]={"_Exit"}; +static const char PRINT_s[]={"Print"}; +static const char CANNOT_OPEN_s[]={"Can not open file:"}; +static const char GAMMA_s[]={"Gamma:"}; +static const char BRIGHTNESS_s[]={"Brightness:"}; +static const char CONTRAST_s[]={"Contrast:"}; +static const char CANCEL_s[]={"Cancel"}; +static const char CROP_s[]={"Section"}; +static const char LAYER_s[]={"Layer:"}; +static const char COMPONENT_s[]={"Component:"}; +#endif + +#ifdef WITH_GERMAN +static const char LAYER_s[]={"Schicht:"}; +static const char COMPONENT_s[]={"Komponente:"}; +static const char PRINT_s[]={"Drucken"}; +static const char POPUP_EXIT_s[]={"_Abbruch"}; +static const char CANNOT_OPEN_s[]={"Kann Datei nicht öffnen:"}; +static const char SUCCESS_WITH_s[]={"Erfolg mit Datei:"}; +static const char FAILURE_WITH_s[]={"Fehler mit Datei:"}; +static const char EXIT_s[]={"Abbruch"}; +static const char STOP_s[]={"Anhalten"}; +static const char GOON_s[]={"Weiter"}; +static const char RESTART_s[]={"Neustart"}; +static const char FORWARD_s[]={"Schritt @>"}; +static const char BACKWARD_s[]={"@< Schritt"}; +static const char CLOSEFILE_s[]={"Ende"}; +static const char BROWSE_s[]={"Suchen"}; +static const char START_s[]={"Start:"}; +static const char ALLFRAMES_s[]={"Rahmen:"}; +static const char ALLTRACKS_s[]={"Tracks:"}; +static const char FILENAME_s[]={"Datei:"}; +static const char BLEND_s[]={"Mischen"}; +static const char SHOW_s[]={"Zeigen"}; +static const char LAYERS_s[]={"Schicht:"}; +static const char WAITPLEASE_s[]={"Bitte warten ..."}; +static const char GAMMA_s[]={"Gamma:"}; +static const char BRIGHTNESS_s[]={"Helligkeit:"}; +static const char CONTRAST_s[]={"Kontrast:"}; +static const char CANCEL_s[]={"Abbruch"}; +static const char CROP_s[]={"Ausschnitt"}; + +static const char CANNOT_USE_FILE_s[]= {"Kann Datei nicht verwenden"}; +static const char NO_DRIVER_FOUND_s[]= {"KEIN TREIBER GEFUNDEN"}; +static const char FILE_NOT_FOUND_s[]= {"Datei nicht gefunden"}; +static const char CANNOT_LOAD_FILE_s[]= {"Kann Datei nicht laden"}; +static const char FILESIZE_TOO_LONG_s[]={"Datei ist zu groß. Ignoriert."}; +static const char NO_FILE_TO_PRINT_s[]={"Keine druckbare Datei gefunden."}; +static const char FILE_SIZE_ZERO_s[]={"Datei-Länge ist 0"}; +static const char USE_SYSTEM_COMMAND_TO_PRINT_s[]= + {"Bitte System-Befehl(e) benutzen,\num folgende Datei zu drucken:"}; +static const char TILE_s[]={"Kachel:"}; +static const char OF_s[]={" von "}; +static const char RELOAD_s[]={"Neu laden"}; +static const char REDUCTION_s[]={"Verkleinerung:"}; +static const char NO_FILE_TO_SAVE_s[]={"Keine Datei zum Sichern gefunden"}; +static const char SAVE_AS_PNG_s[]={"Sichern als PNG"}; +static const char ENTER_PNG_TO_SAVE_s[]= + {"Einen Name eingeben für eine PNG Datei:"}; +static const char FILE_EXISTS_s[]= + {"Datei besteht bereits.\n Weiter?"}; +static const char SAVE_AS_OPJ_s[]={"Sichern als JP2/J2K"}; +static const char ENTER_OPJ_TO_SAVE_s[]= + {"Einen Name eingeben für eine JP2/J2K Datei:"}; +static const char MISSING_PNG_EXT_s[]={"Datei-Endung nicht '.png'. Weiter?"}; +static const char AREA_s[]={"Fläche:"}; +static const char FILENAME_TOO_LONG_s[]={"Datei-Name zu lang. Ignoriert."}; + +#endif + +#endif /* _FLIMAGE_LANG_H_ */ diff --git a/src/bin/fltk/flviewer/flviewer-mj2-fehler.txt b/src/bin/fltk/flviewer/flviewer-mj2-fehler.txt new file mode 100644 index 00000000..ab2557f4 --- /dev/null +++ b/src/bin/fltk/flviewer/flviewer-mj2-fehler.txt @@ -0,0 +1,32 @@ + +flviewer /home/IMG/MJ2/hall-420-1056x576-yuv-r00.mj2 + + +*** glibc detected *** /graphics/FLVIEWER/TRUNK-2.0/v0.1.6/openjpeg-2.x-trunk-r2871-1-flviewer-0.1.6/BUILD/bin/flviewer: double free or corruption (fasttop): 0x00007fffec17f680 *** +^C +Program received signal SIGINT, Interrupt. +0x00007ffff63a2a94 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0 +(gdb) bt +#0 0x00007ffff63a2a94 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0 +#1 0x000000000041c782 in get_rgb_buffer() () +#2 0x000000000041dc44 in OPENMJ2_load(canvas*, char const*, unsigned long) () +#3 0x000000000040a3d8 in chooser_cb(char const*) () +#4 0x00007ffff72bb5ba in Fl_Widget::do_callback(Fl_Widget*, void*) () + from /usr/local/fltk13/lib/libfltk.so.1.3 +#5 0x00007ffff72982d3 in Fl_Input_::handletext(int, int, int, int, int) () + from /usr/local/fltk13/lib/libfltk.so.1.3 +#6 0x00007ffff727b5ca in Fl::focus(Fl_Widget*) () from /usr/local/fltk13/lib/libfltk.so.1.3 +#7 0x00007ffff72bb442 in Fl_Widget::take_focus() () from /usr/local/fltk13/lib/libfltk.so.1.3 +#8 0x00007ffff728bbb7 in Fl_Group::navigation(int) () from /usr/local/fltk13/lib/libfltk.so.1.3 +#9 0x00007ffff728c0e9 in Fl_Group::handle(int) () from /usr/local/fltk13/lib/libfltk.so.1.3 +#10 0x00007ffff727af1d in send(int, Fl_Widget*, Fl_Window*) () + from /usr/local/fltk13/lib/libfltk.so.1.3 +#11 0x00007ffff727c676 in Fl::handle_(int, Fl_Window*) () from /usr/local/fltk13/lib/libfltk.so.1.3 +#12 0x00007ffff727c59e in Fl::handle_(int, Fl_Window*) () from /usr/local/fltk13/lib/libfltk.so.1.3 +#13 0x00007ffff72c1d58 in fl_handle(_XEvent const&) () from /usr/local/fltk13/lib/libfltk.so.1.3 +#14 0x00007ffff72c1de5 in do_queued_events() () from /usr/local/fltk13/lib/libfltk.so.1.3 +#15 0x00007ffff72c1f9a in fl_wait(double) () from /usr/local/fltk13/lib/libfltk.so.1.3 +#16 0x00007ffff727c16d in Fl::wait(double) () from /usr/local/fltk13/lib/libfltk.so.1.3 +#17 0x00007ffff727c193 in Fl::run() () from /usr/local/fltk13/lib/libfltk.so.1.3 +#18 0x0000000000408039 in main () + diff --git a/src/bin/fltk/flviewer/flviewer.cxx b/src/bin/fltk/flviewer/flviewer.cxx new file mode 100644 index 00000000..40c004b9 --- /dev/null +++ b/src/bin/fltk/flviewer/flviewer.cxx @@ -0,0 +1,2569 @@ +#include +#include "opj_apps_config.h" +/* + * author(s) and license +*/ +//------------ see in main() ------------ +#define HAVE_OPTION_FNFC_USES_GTK +//--------------------------------------- + +#include +#include +#include + +#ifdef _WIN32 +#include +#include +#include +//FIXME remove #define snprintf sprintf_s +#else /* not _WIN32 */ +#include +#include +#define __STDC_FORMAT_MACROS +#include +#endif /* _WIN32 */ + +#include +#include +#include + + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + + +#include +#include +#include + +#include +#include + +#include "opj_stdint.h" + +#include "flviewer.hh" +#include "tree.hh" +#include "viewerdefs.hh" +#include "lang/viewer_lang.h_utf8" +#include "rgb_color.hh" + +#include "print_gui.hh" +#include "ps_image.hh" + +#ifdef OPJ_HAVE_LIBPNG +#include "PNG.hh" +#endif + +#include "OPENJPEG.hh" +#ifdef WANT_PGX +#include "PGX.hh" +#endif +#include "OPENMJ2.hh" +#include "JP2.hh" + +#ifndef OPJ_PATH_LEN +#define OPJ_PATH_LEN 4096 +#endif + +//#define RESET_REDUCTION + +#define USE_CUSTOM_ICONS +#define MAX_SPINVALUE 6. + +#define DEFAULT_BACKGROUND FL_LIGHT1 +#define DEFAULT_CANVAS_BACKGROUND FL_DARK2 + +static const char *IMG_PATTERN = +#ifdef WANT_PGX + "*.{png,j2k,j2c,jp2,jpg2,jpc,jpx,jpf,jpm,mj2,mjp2,pgx}"; +#else + "*.{png,j2k,j2c,jp2,jpg2,jpc,jpx,jpf,jpm,mj2,mjp2}"; +#endif + +static Canvas *canvas; +static short movie_runs; + +static char url_buf[512]; + +#define MAX_COLORBUF 31 +static char bgcolor_buf[MAX_COLORBUF + 1]; +static char vbuf[48]; + +//------------------- FORWARD --------------------- +static void print_cb(Fl_Widget *wid, void *v); +static void save_as_opj_cb(Fl_Widget *wid, void *v); + +#ifdef OPJ_HAVE_LIBPNG +static void save_as_png_cb(Fl_Widget *wid, void *v); +#endif + +static Fl_Double_Window *crop_win; +static Fl_Box *crop_box; +static Fl_RGB_Image *crop_img; + +static int crop_win_done; +static int crop_lhs_top_x, crop_lhs_top_y; +static int crop_width, crop_height; + +static int start_overlay; + +static void exit_cb(Fl_Widget *wid, void *v); +static void pause_cb(Fl_Widget *wid, void *v); +static void resume_cb(Fl_Widget *wid, void *v); + +static void restart_cb(Fl_Widget *wid, void *v); +static void forward_cb(Fl_Widget *wid, void *v); +static void backward_cb(Fl_Widget *wid, void *v); + +static void fin_cb(Fl_Widget *wid, void *v); +static void browse_cb(Fl_Widget *wid, void *v); + +static void goto_frame_cb(Fl_Widget *wid, void *v); +static void goto_track_cb(Fl_Widget *w, void *v); + +static void chooser_cb(const char *cs); + +#ifdef HAVE_THREADS +static int nr_threads; +#endif + +char *root_dir; + +static char *read_idf; +static FILE *reader; +static Fl_Spinner *threads_spinner; + +static int win_w, win_h; +static Fl_Group *tiles_group; + +static Fl_Button *pause_but, *resume_but, *restart_but, *backward_but, + *forward_but, *fin_but; + +static Fl_Output *url_out; +static Fl_Input *goto_frame_in, *goto_track_in; +static Fl_Output *all_frames_out, *all_tracks_out; + +static Fl_Group *tracks_group, *frames_group; + +static Fl_Input *layer_in, *component_in; +static Fl_Output *layer_out, *component_out; +static int mj2_max_tracks, max_components, max_layers; +static int cur_component, cur_layers; + +static Fl_Scroll *scroll; + +static Fl_Input *area_in, *tile_in; + +static Fl_Group *reduct_group; +static Fl_Input *reduct_in; +static Fl_Output *tiles_out; + +static Fl_Output *reduct_out; +static Fl_Button * reload_jp2; + +static int max_tiles, max_reduction, cur_tile, cur_reduction; +static int user_changed_tile, user_changed_reduct; +static int reloaded; + +static int cmd_line_reduction; + +static int area_x0, area_y0, area_x1, area_y1; +static int user_changed_area; + +static char *jp2_file; +static char *mj2_file; + +static double fscale = 1.0; + +#ifdef USE_CUSTOM_ICONS + +static const char *L_open_xpm[] = +{ + "11 11 2 1", + ". c None", + "@ c #000000", + "...@.......", + "...@@......", + "...@@@.....", + "...@@@@....", + "...@@@@@...", + "...@@@@@@..", + "...@@@@@...", + "...@@@@....", + "...@@@.....", + "...@@......", + "...@......." +}; +static Fl_Pixmap L_openpixmap(L_open_xpm); + +static const char *L_close_xpm[] = +{ + "11 11 2 1", + ". c None", + "@ c #000000", + "...........", + "...........", + "...........", + "...........", + "...........", + "@@@@@@@@@@@", + ".@@@@@@@@@.", + "..@@@@@@@..", + "...@@@@@...", + "....@@@....", + ".....@....." +}; +static Fl_Pixmap L_closepixmap(L_close_xpm); + +#endif //USE_CUSTOM_ICONS + +//----------------- end FORWARD ------------------- +UserTree *tree = NULL; + +int UserTree::handle(int event) +{ +#ifdef DEBUG_TREE +fprintf(stderr,"%s:%d:\n\tUserTree(%d,%d,%d,%d) event(%d,%d) ex(%d) ey(%d)\n", +__FILE__,__LINE__,x(),y(),x()+w(),y()+h(), +Fl::event_x(),Fl::event_y(), Fl::event_x()-x(),Fl::event_y()-y() ); +#endif + if(!Fl::event_inside(x(), y(), w(), h() ) ) + { +#ifdef DEBUG_TREE +fprintf(stderr,"%s:%d:\n\tNOT INSIDE TREE\n",__FILE__,__LINE__); +#endif + return 0; + } + if(event == FL_LEAVE) return 1; + + return Fl_Tree::handle(event); +} + +class ImageBox : public Fl_Box +{ + +public: + int start_x, start_y; + int lhs_top_x, lhs_top_y, rhs_top_x, rhs_top_y; + int lhs_bot_x, lhs_bot_y, rhs_bot_x, rhs_bot_y; + int lhs_x, top_y; + + ImageBox(int xx, int yy, int ww, int hh) + : Fl_Box(xx, yy, ww, hh, NULL) + { + lhs_x = xx; top_y = yy; + + lhs_top_x = lhs_top_y = 0; + rhs_top_x = rhs_top_y = 0; + lhs_bot_x = lhs_bot_y = 0; + rhs_bot_x = rhs_bot_y = 0; + } ; + virtual int handle(int event); +}; + +static ImageBox *scroll_box; + +class Overlay : public Fl_Overlay_Window +{ + +public: + Overlay(int xx, int yy, int ww, int hh) + : Fl_Overlay_Window(xx, yy, ww, hh) {}; + + void draw_overlay(); +}; + +static Overlay *main_win; + +void Overlay::draw_overlay() +{ + if(movie_runs || !canvas->cbuf) return; + + if(start_overlay) + { + crop_width = crop_height = 0; + start_overlay = 0; + } + fl_color(FL_YELLOW); + fl_rect(scroll_box->x() + crop_lhs_top_x, + scroll_box->y() + crop_lhs_top_y, + crop_width, crop_height); +} + +int ImageBox::handle(int event) +{ + int ex, ey; +#ifdef DEBUG_IMAGEBOX +fprintf(stderr,"%s:%d:\n\tImageBox(%d,%d,%d,%d) event(%d,%d) ex(%d) ey(%d)\n", +__FILE__,__LINE__,x(),y(),x()+w(),y()+h(), +Fl::event_x(),Fl::event_y(), Fl::event_x()-x(),Fl::event_y()-y() ); +#endif + + if(!Fl::event_inside(x(), y(), w(), h() ) ) + { +#ifdef DEBUG_IMAGEBOX +fprintf(stderr,"%s:%d:\n\tNOT INSIDE IMAGEBOX\n",__FILE__,__LINE__); +#endif + return 0; + } + + if(event == FL_LEAVE) return 1; + + if(movie_runs || !canvas->cbuf) return 1; + + ex = Fl::event_x() - x(); ey = Fl::event_y() - y(); + + switch(event) + { + case FL_PUSH: + lhs_top_x = lhs_top_y = rhs_top_x = rhs_top_y = 0; + lhs_bot_x = lhs_bot_y = rhs_bot_x = rhs_bot_y = 0; + start_x = ex; start_y = ey; + + start_overlay = 1; + main_win->redraw_overlay(); + return 1; + + case FL_DRAG: + if(ex > start_x) //rhs + { + if(ey < start_y) //up + { + lhs_top_x = start_x; lhs_top_y = ey; + rhs_top_x = ex; rhs_top_y = ey; + lhs_bot_x = start_x; lhs_bot_y = start_y; + lhs_bot_x = ex; rhs_bot_y = start_y; + } + else + if(ey > start_y) //down + { + lhs_top_x = start_x; lhs_top_y = start_y; + rhs_top_x = ex; rhs_top_y = start_y; + lhs_bot_x = start_x; lhs_bot_y = ey; + rhs_bot_x = ex; rhs_bot_y = ey; + } + } + else + if(ex < start_x) //lhs + { + if(ey < start_y) //up + { + lhs_top_x = ex; lhs_top_y = ey; + rhs_top_x = start_x; rhs_top_y = ey; + lhs_bot_x = ex; lhs_bot_y = start_y; + rhs_bot_x = start_x; rhs_bot_y = start_y; + } + else + if(ey > start_y) //down + { + lhs_top_x = ex; lhs_top_y = start_y; + rhs_top_x = start_x; rhs_top_y = start_y; + lhs_bot_x = ex; lhs_bot_y = ey; + rhs_bot_x = start_x; rhs_bot_y = ey; + } + } + crop_lhs_top_x = lhs_top_x; + crop_lhs_top_y = lhs_top_y; + crop_width = rhs_top_x - lhs_top_x; + crop_height = rhs_bot_y - rhs_top_y; + + main_win->redraw_overlay(); + + return 1; + + case FL_RELEASE: + return 1; + } + return Fl_Box::handle(event); +} + +static void crop_cancel_cb(Fl_Widget *wid, void *v) +{ + crop_win_done = 1; + crop_win->hide(); +} + +static void crop_print_cb(Fl_Widget *wid, void *v) +{ + const void *cbuf; + int iw, ih, ic; + + cbuf = canvas->cbuf; + + iw = canvas->new_iwidth; + ih = canvas->new_iheight; + ic = canvas->new_idepth; + + canvas->cbuf = crop_img->data()[0]; + canvas->new_iwidth = crop_img->w(); + canvas->new_iheight = crop_img->h(); + canvas->new_idepth = crop_img->d(); + + print_cb(wid, v); + + canvas->cbuf = cbuf; + canvas->new_iwidth = iw; + canvas->new_iheight = ih; + canvas->new_idepth = ic; +} + +#ifdef OPJ_HAVE_LIBPNG +static void crop_save_as_png_cb(Fl_Widget *wid, void *v) +{ + const void *cbuf; + int iw, ih, ic; + + cbuf = canvas->cbuf; + + iw = canvas->new_iwidth; + ih = canvas->new_iheight; + ic = canvas->new_idepth; + + canvas->cbuf = crop_img->data()[0]; + canvas->new_iwidth = crop_img->w(); + canvas->new_iheight = crop_img->h(); + canvas->new_idepth = crop_img->d(); + + save_as_png_cb(wid, v); + + canvas->cbuf = cbuf; + canvas->new_iwidth = iw; + canvas->new_iheight = ih; + canvas->new_idepth = ic; +} +#endif + +static void crop_save_as_opj_cb(Fl_Widget *wid, void *v) +{ + const void *cbuf; + int iw, ih, ic; + + cbuf = canvas->cbuf; + + iw = canvas->new_iwidth; + ih = canvas->new_iheight; + ic = canvas->new_idepth; + + canvas->cbuf = crop_img->data()[0]; + canvas->new_iwidth = crop_img->w(); + canvas->new_iheight = crop_img->h(); + canvas->new_idepth = crop_img->d(); + + save_as_opj_cb(wid, v); + + canvas->cbuf = cbuf; + canvas->new_iwidth = iw; + canvas->new_iheight = ih; + canvas->new_idepth = ic; +} + +Fl_Menu_Item crop_popup_items[] = +{ + {EXIT_s, 0, &crop_cancel_cb, NULL, FL_MENU_DIVIDER, 0, 4, 15, FL_YELLOW}, + {PRINT_s, 0, &crop_print_cb, NULL, FL_MENU_DIVIDER, 0, 4, 15, 0}, +#ifdef OPJ_HAVE_LIBPNG + {SAVE_AS_PNG_s, 0, &crop_save_as_png_cb, NULL, FL_MENU_DIVIDER, 0, 4, 15, 0}, +#endif + {SAVE_AS_OPJ_s, 0, &crop_save_as_opj_cb, NULL, FL_MENU_DIVIDER, 0, 4, 15, 0}, + {NULL, 0, NULL, NULL, 0, 0, 0, 0, 0} +}; + +static void crop_popup_create(int x, int y, int ww, int hh) +{ + Fl_Menu_Button *popup; + + popup = new Fl_Menu_Button(x, y, ww, hh); + popup->type(Fl_Menu_Button::POPUP3); + popup->menu(crop_popup_items); +} + +static void crop_window_cb(Fl_Widget *wid, void *v) +{ + unsigned char *dst, *d; + const unsigned char *s; + int ww, hh, idepth, i, iwidth, s_step, d_step; + + if(canvas->cbuf == NULL) return; + + if(crop_width == 0 && crop_height == 0) return; +//One crop window only: + if(crop_win != NULL) return; + + idepth = canvas->new_idepth; + dst = (unsigned char*)malloc(crop_width * crop_height * idepth); + + if(dst == NULL) return; + + hh = crop_height + 10; ww = crop_width + 10; + + crop_win = new Fl_Double_Window(220, 220, ww, hh); + crop_win->box(FL_FLAT_BOX); + crop_win->color(main_win->color()); + crop_win->begin(); + + crop_box = new Fl_Box(5, 5, crop_width, crop_height); + crop_box->box(FL_FLAT_BOX); + crop_box->color(scroll_box->color()); + crop_box->align(FL_ALIGN_INSIDE|FL_ALIGN_CENTER); + +// crop_win->resizable(crop_box); + + crop_popup_create(0, 0, ww, hh); + crop_win_done = 0; + crop_win->end(); + crop_win->show(); + + iwidth = canvas->new_iwidth; + + s = (const unsigned char*)canvas->cbuf + + (iwidth * crop_lhs_top_y + crop_lhs_top_x) * idepth; + + s_step = iwidth * idepth; + d_step = crop_width * idepth; + d = dst; + + for(i = 0; i < crop_height; ++i) + { + memcpy(d, s, d_step); + d += d_step; + s += s_step; + } + crop_img = new + Fl_RGB_Image(dst, crop_width, crop_height, idepth); + + crop_box->image(crop_img); + crop_box->redraw(); + + while(crop_win_done == 0) + Fl::wait(); + + crop_win_done = 0; + delete crop_img; + crop_img = NULL; + + delete crop_win; + crop_win = NULL; +} + +#ifdef _WIN32 +CRITICAL_SECTION CriticalSection; + +#else /* not _WIN32 */ + +static int semid; +static struct sembuf sema; + +static union semun +{ + int val; + struct semid_ds *buf; + unsigned short int *array; + struct seminfo *__buf; +} su; +#endif /* _WIN32 */ + +#ifdef _WIN32 + +#define IDLE_SPIN 0x00000400 + +#else /* not _WIN32 */ + +static void critical(int id, int op) +{ + sema.sem_op = op; sema.sem_flg = SEM_UNDO; + if(semop(id, &sema, 1) == -1) + fprintf(stderr,"%s:%d:semop %d failed\n",__FILE__,__LINE__,op); +} + +#define ENTER_CRITICAL(i) critical(i, -1) +#define LEAVE_CRITICAL(i) critical(i, 1) + +#endif /* _WIN32 */ + +void FLViewer_clear_tree() +{ + if(tree) tree->clear(); +} + +void FLViewer_header_deactivate() +{ + tile_in->value(""); + tiles_out->value(""); + tiles_group->deactivate(); + + reduct_in->value(""); + reduct_out->value(""); + reduct_group->deactivate(); + + reload_jp2->deactivate(); + area_in->deactivate(); + + FLViewer_area_activate(0); + FLViewer_layer_component_activate(0); + + pause_but->deactivate(); + resume_but->deactivate(); + restart_but->deactivate(); + fin_but->deactivate(); + + forward_but->deactivate(); + backward_but->deactivate(); + + goto_frame_in->value(""); + all_frames_out->value(""); + frames_group->deactivate(); + + goto_track_in->value(""); + all_tracks_out->value(""); + tracks_group->deactivate(); + +}//FLViewer_header_activate() + +#ifdef HAVE_THREADS +void FLViewer_threads_activate(int v) +{ + if(v) + threads_spinner->activate(); + else + threads_spinner->deactivate(); +} +#endif + +void FLViewer_movie_runs(int v) +{ + movie_runs = v; +} + +void FLViewer_close_reader(void) +{ + if(reader) + { + fclose(reader); reader = NULL; + } +} + +static void spinner_cb(Fl_Widget *wid, void *v) +{ + if( !wid->contains(Fl::belowmouse())) return; + +#ifdef HAVE_THREADS + { + Fl_Spinner *spin = (Fl_Spinner*)wid; + + if(spin->value() < 0. || spin->value() > MAX_SPINVALUE) + spin->value(0); + + nr_threads = (int)spin->value(); + } +#endif +} + +int FLViewer_nr_threads(void) +{ +#ifdef HAVE_THREADS + threads_spinner->value(nr_threads); + return nr_threads; +#else + threads_spinner->value(0); + return 0; +#endif +} + +static void zoomin_cb(Fl_Widget *w, void *v) +{ + if(movie_runs) return; + + fscale += 0.05; + chooser_cb(read_idf); +} + +static void zoomin_50_cb(Fl_Widget *w, void *v) +{ + if(movie_runs) return; + + fscale += 0.5; + chooser_cb(read_idf); +} + +static void zoomin_25_cb(Fl_Widget *w, void *v) +{ + if(movie_runs) return; + + fscale += 0.25; + chooser_cb(read_idf); +} + +static void zoomout_cb(Fl_Widget *w, void *v) +{ + if(movie_runs) return; + + if(fscale < 0.06) return; + + fscale -= 0.05; + chooser_cb(read_idf); +} + +static void zoomout_50_cb(Fl_Widget *w, void *v) +{ + if(movie_runs) return; + + if(fscale < 0.6) return; + + fscale -= 0.5; + chooser_cb(read_idf); +} + +static void zoomout_25_cb(Fl_Widget *w, void *v) +{ + if(movie_runs) return; + + if(fscale < 0.3) return; + + fscale -= 0.25; + chooser_cb(read_idf); +} + +static void reset_zoom_cb(Fl_Widget *w, void *v) +{ + if(movie_runs) return; + + fscale = 1.0; + chooser_cb(read_idf); +} + +static void tile_in_cb(Fl_Widget *w, void *v) +{ + const char *cs; + int i; + + if( !w->contains(Fl::belowmouse())) return; + + cs = ((Fl_Input*)w)->value(); + + if(cs == NULL || *cs == 0) + i = -1; + else + i = atoi(cs); + + if(i >= max_tiles) i = max_tiles - 1; + + cur_tile = i; + + user_changed_tile = user_changed_reduct = 1; + user_changed_area = 0; + + chooser_cb(read_idf); + + if(i < 0) + tile_in->value(""); + else + { + snprintf(vbuf, sizeof(vbuf)-1, "%d", i); + tile_in->value(vbuf); + } + tile_in->redraw(); +} + +static void area_in_cb(Fl_Widget *w, void *v) +{ + const char *cs; + + if( !w->contains(Fl::belowmouse())) return; + + cs = ((Fl_Input*)w)->value(); + + if(cs == NULL || *cs == 0) + { + area_in->value("x0,y0,x1,y1"); + area_in->redraw(); + return; + } + area_x0 = area_y0 = area_x1 = area_y1 = 0; + + if(sscanf(cs, "%d,%d,%d,%d", &area_x0,&area_y0,&area_x1,&area_y1) != 4) + { + fprintf(stderr,"AREA(%s) unusable\n",cs); + return; + } + if(area_x0 < 0 || area_x1 < 0 || area_y0 < 0 || area_y1 < 0) return; + if(area_x1 <= area_x0 || area_y1 <= area_y0) return; + + user_changed_area = 1; + user_changed_tile = user_changed_reduct = 0; + + tile_in->value(""); + tile_in->redraw(); + cur_tile = -1; + + chooser_cb(read_idf); + + snprintf(vbuf, sizeof(vbuf)-1, "%d,%d,%d,%d", area_x0, area_y0, + area_x1, area_y1); + area_in->value(vbuf); + area_in->redraw(); +} + +static void reduct_in_cb(Fl_Widget *w, void *v) +{ + const char *cs; + int i; + + if( !w->contains(Fl::belowmouse())) return; + + cs = ((Fl_Input*)w)->value(); + + if(cs == NULL || *cs == 0) + i = 0; + else + i = atoi(cs); + + if(i < 0) return; + + if(max_reduction > 0 && i >= max_reduction) return; + + cur_reduction = i; + + user_changed_tile = user_changed_reduct = 1; + + chooser_cb(read_idf); + + snprintf(vbuf, sizeof(vbuf)-1, "%d", i); + reduct_in->value(vbuf); + reduct_in->redraw(); +} + +static void test_new_jp2_file() +{ + int new_jp2_file; + + if(reloaded) + { + reloaded = 0; + + fscale = 1.0; + user_changed_area = 0; + + area_x0 = area_x1 = area_y0 = area_y1 = 0; + area_in->value("x0,y0,x1,y1"); + area_in->redraw(); + + max_tiles = max_reduction = 0; + + tile_in->value(""); + tile_in->redraw(); + reduct_in->value("0"); + reduct_in->redraw(); + + user_changed_tile = 0; user_changed_reduct = 0; + + max_tiles = max_reduction = -1; + + cur_tile = -1; cur_reduction = 0; + + cur_layers = max_layers = 0; + cur_component = max_components = 0; + component_in->value(""); + component_out->value(""); + + if(JPEG2000_build_tree(read_idf) == 0) + { + fprintf(stderr,"%s:%d:\n\t=== NO TREE BUILT ===\n",__FILE__,__LINE__); + } + + return; + } + + if(jp2_file) + { + if(strcmp(jp2_file, read_idf))/* New file */ + { + new_jp2_file = 1; + } + else + { + new_jp2_file = 0; + } + } + else + { + new_jp2_file = 1; + } + + if(new_jp2_file) + { + if(jp2_file) free(jp2_file); + + jp2_file = strdup(read_idf); + + + fscale = 1.0; + user_changed_area = 0; + area_x0 = area_y0 = area_x1 = area_y1 = 0; + area_in->value("x0,y0,x1,y1"); + area_in->redraw(); + + tile_in->value(""); + tile_in->redraw(); + cur_tile = -1; + +/* To get the new values: +*/ + max_tiles = max_reduction = 0; + user_changed_tile = 0; +#ifdef RESET_REDUCTION + cur_reduction = 0; + reduct_in->value(""); + reduct_out->value(""); + user_changed_reduct = 0; +#endif + + layer_in->value(""); + layer_out->value(""); + cur_layers = max_layers = 0; + + component_in->value(""); + component_out->value(""); + cur_component = max_components = 0; + +#ifdef HAVE_THREADS + nr_threads = 0; + threads_spinner->value(0); + threads_spinner->deactivate(); +#endif + + if(JPEG2000_build_tree(read_idf) == 0) + { + fprintf(stderr,"%s:%d:\n\t=== NO TREE BUILT ===\n",__FILE__,__LINE__); + } + } +}//test_new_jp2_file() + +static void test_new_mj2_file() +{ + int new_file; + +//FLViewer_movie_runs(1); + + if(mj2_file) + { + if(strcmp(mj2_file, read_idf)) + { + free(mj2_file); + new_file = 1; + } + else + { + new_file = 0; + } + } + else + { + new_file = 1; + } + + if(new_file) + { + mj2_file = strdup(read_idf); + + layer_in->value(""); + layer_in->deactivate(); + + layer_out->value(""); + layer_out->deactivate(); + + component_in->activate(); + component_out->activate(); + + OPENMJ2_free_tracks(); + + if(JPEG2000_build_tree(read_idf) == 0) + { + fprintf(stderr,"%s:%d:\n\t=== NO TREE BUILT ===\n",__FILE__,__LINE__); + } + } +}//test_new_mj2_file() + +static void reload_jp2_cb(Fl_Widget *w, void *v) +{ + tile_in->value(""); + tile_in->redraw(); + cur_tile = -1; + + cur_reduction = 0; + + user_changed_tile = user_changed_reduct = 0; + + reloaded = 1; + + chooser_cb(read_idf); + + reduct_in->value("0"); + reduct_in->redraw(); +} + +void FLViewer_get_max_tiles_and_reduction(int *out_mx_tiles, int *out_mx_reduct) +{ + *out_mx_tiles = max_tiles; *out_mx_reduct = max_reduction; +} + +void FLViewer_set_max_reduction(int mx_reduct) +{ + max_reduction = mx_reduct; +} + +void FLViewer_set_max_tiles(int mx_tiles) +{ + max_tiles = mx_tiles; +} + +void FLViewer_put_max_tiles_and_reduction(int mx_tiles, int mx_reduct) +{ + tiles_out->value(""); + tiles_out->redraw(); + + reduct_out->value(""); + reduct_out->redraw(); + + max_tiles = mx_tiles; + max_reduction = mx_reduct; + user_changed_tile = 1; user_changed_reduct = 1; + + snprintf(vbuf, sizeof(vbuf)-1, "%d", cur_reduction); + reduct_in->value(vbuf); + reduct_in->redraw(); +} + +void FLViewer_reset_tiles_and_reduction() +{ + tiles_out->value(""); + tiles_out->redraw(); + + reduct_out->value(""); + reduct_out->redraw(); + + user_changed_tile = user_changed_reduct = 0; + cur_tile = -1; cur_reduction = 0; + max_tiles = -1; + max_reduction = -1; + + snprintf(vbuf, sizeof(vbuf)-1, "%d", cur_reduction); + reduct_in->value(vbuf); + reduct_in->redraw(); +} + +static void tiles_write_out(void) +{ + if(user_changed_tile && user_changed_reduct) + { + if(max_tiles > 0) + { + snprintf(vbuf, sizeof(vbuf)-1, "%d", max_tiles - 1); + tiles_out->value(vbuf); + tiles_out->redraw(); + } + + if(cur_reduction > -1) + { + snprintf(vbuf, sizeof(vbuf)-1, "%d", cur_reduction); + reduct_in->value(vbuf); + reduct_in->redraw(); + } + if(max_reduction > 0) + { + snprintf(vbuf, sizeof(vbuf)-1, "%d", max_reduction - 1); + reduct_out->value(vbuf); + reduct_out->redraw(); + } + } +} + +int FLViewer_has_tile_and_reduction(void) +{ + return (user_changed_tile && user_changed_reduct); +} + +void FLViewer_get_tile_and_reduction(int *out_tile, int *out_reduct) +{ + *out_tile = cur_tile; *out_reduct = cur_reduction; +} + +int FLViewer_has_area_values(void) +{ + return user_changed_area; +} + +void FLViewer_get_area_values(int *out_x0, int *out_y0, + int *out_x1, int *out_y1) +{ + *out_x0 = area_x0; *out_y0 = area_y0; + *out_x1 = area_x1; *out_y1 = area_y1; +} + +void FLViewer_set_max_mj2_tracks(unsigned int n) +{ + int s; + + if((s = canvas->selected_track) < 1) + s = 1; + + mj2_max_tracks = (int)n-1; + snprintf(vbuf, sizeof(vbuf)-1, "%d/%d", s, mj2_max_tracks); + all_tracks_out->value(vbuf); +} + +void FLViewer_set_max_components(unsigned int n) +{ + max_components = (int)n; + snprintf(vbuf, sizeof(vbuf)-1, "%d", n); + component_out->value(vbuf); +} + +void FLViewer_set_max_layers(unsigned int n) +{ + max_layers = (int)n; + snprintf(vbuf,sizeof(vbuf)-1, "%d", max_layers); + layer_out->value(vbuf); + layer_in->value("0"); +} + +int FLViewer_layers() +{ + return cur_layers; +} + +int FLViewer_component() +{ + return cur_component; +} + +void FLViewer_layer_component_activate(int v) +{ + if(v) + { + component_in->activate(); + component_out->activate(); + + snprintf(vbuf, sizeof(vbuf)-1,"%d", cur_component); + component_in->value(vbuf); + + snprintf(vbuf,sizeof(vbuf)-1,"%d", max_components); + component_out->value(vbuf); + + layer_in->activate(); + layer_out->activate(); + + snprintf(vbuf, sizeof(vbuf)-1, "%d", cur_layers); + layer_in->value(vbuf); + + snprintf(vbuf, sizeof(vbuf)-1, "%d", max_layers); + layer_out->value(vbuf); + } + else + { + layer_in->value(""); + layer_out->value(""); + layer_in->deactivate(); + layer_out->deactivate(); + } +} + +static void layer_in_cb(Fl_Widget *wid, void *v) +{ + int i; + + if(max_layers == 0) + { + layer_in->value(""); + return; + } + i = atoi(layer_in->value()); + + if(i < 0 || i > max_layers) + { + snprintf(vbuf, sizeof(vbuf)-1, "%d", cur_layers); + layer_in->value(vbuf); + + return; + } + cur_layers = i; + + chooser_cb(read_idf); +} + +static void component_in_cb(Fl_Widget *wid, void *v) +{ + int i; + + if(max_components == 0) + { + component_in->value(""); + return; + } + i = atoi(component_in->value()); + + if(i < 0 || i > max_components) + { + snprintf(vbuf, sizeof(vbuf)-1, "%d", cur_component); + component_in->value(vbuf); + + return; + } + cur_component = i; + + chooser_cb(read_idf); +} + +class Header : public Fl_Group +{ + +public: + Header(int x, int y, int w, int h, const char *l); + virtual int handle(int event); +}; + +static Header *header; + +Header::Header(int X, int Y, int W, int H, const char *l) + : Fl_Group(X, Y, W, H, l) +{ + int xx, yy, ww, bx, bw, gw, gh; + begin(); + + xx = X; yy = Y; + { + int ux = xx + BUTTON_W + 10; + url_out = + new Fl_Output(ux, yy, xx + W - ux, BUTTON_H, FILENAME_s); + url_out->textsize(LABEL_SIZE); + url_out->labelsize(LABEL_SIZE); + url_out->clear_visible_focus(); + } + xx = X; yy += BUTTON_H + 3; + gw = 70 + FRAMES_W + 60 + FRAMES_W/2 + 4; gh = BUTTON_H + 4; + + frames_group = new Fl_Group(xx, yy, gw, gh); + frames_group->box(FL_EMBOSSED_BOX); + frames_group->begin(); + + xx += 70; yy += 2; + all_frames_out = + new Fl_Output(xx, yy, FRAMES_W, BUTTON_H, ALLFRAMES_s); + all_frames_out->labelsize(LABEL_SIZE); + all_frames_out->textsize(LABEL_SIZE); + all_frames_out->clear_visible_focus(); + + xx += FRAMES_W + 60; + goto_frame_in = + new Fl_Input(xx, yy, FRAMES_W/2, BUTTON_H, START_s); + goto_frame_in->callback(goto_frame_cb); + goto_frame_in->when(FL_WHEN_ENTER_KEY_ALWAYS); + goto_frame_in->labelsize(LABEL_SIZE); + goto_frame_in->textsize(LABEL_SIZE); + + frames_group->end(); + + xx = frames_group->x() + frames_group->w() + 5; + yy = frames_group->y(); + ww = TRACKS_W/2; + gw = 70 + ww + 60 + ww + 4; gh = BUTTON_H + 4; + + tracks_group = new Fl_Group(xx, yy, gw, gh); + tracks_group->box(FL_EMBOSSED_BOX); + tracks_group->begin(); + + xx += 70; yy += 2; + all_tracks_out = + new Fl_Output(xx, yy, ww, BUTTON_H, ALLTRACKS_s); + all_tracks_out->labelsize(LABEL_SIZE); + all_tracks_out->textsize(LABEL_SIZE); + all_tracks_out->clear_visible_focus(); + + xx += ww + 60; + goto_track_in = + new Fl_Input(xx, yy, ww, BUTTON_H, START_s); + goto_track_in->callback(goto_track_cb); + goto_track_in->when(FL_WHEN_ENTER_KEY_ALWAYS); + goto_track_in->labelsize(LABEL_SIZE); + goto_track_in->textsize(LABEL_SIZE); + + tracks_group->end(); + + xx = tracks_group->x() + tracks_group->w() + 10; + yy = tracks_group->y() + 2; + + { + Fl_Group *g = new Fl_Group(xx, yy, 115, BUTTON_H); + g->box(FL_FLAT_BOX); + g->color(DEFAULT_BACKGROUND+1); + g->begin(); + + xx += 70; + threads_spinner = new Fl_Spinner(xx, yy, 40, BUTTON_H, "Threads:"); + threads_spinner->labelsize(LABEL_SIZE); + threads_spinner->minimum(0); + threads_spinner->maximum(6); + threads_spinner->step(1); + threads_spinner->value(0); + threads_spinner->callback(spinner_cb); + threads_spinner->deactivate(); + + g->end(); + xx = g->x() + g->w(); + } + xx += 10; + reload_jp2 = new Fl_Button(xx, yy, BUTTON_W + 15, BUTTON_H, RELOAD_s); + reload_jp2->callback(reload_jp2_cb); + reload_jp2->labelsize(LABEL_SIZE); + reload_jp2->deactivate(); + + xx = X; yy = reload_jp2->y() + reload_jp2->h() + 5; + ww = 70 + 40 + 40 + 40; + + tiles_group = new Fl_Group(xx, yy, ww, BUTTON_H); + tiles_group->begin(); + + xx += 70; + tile_in = + new Fl_Input(xx, yy, 40, BUTTON_H, TILE_s); + tile_in->callback(tile_in_cb); + tile_in->when(FL_WHEN_RELEASE_ALWAYS); + tile_in->labelsize(LABEL_SIZE); + tile_in->textsize(LABEL_SIZE); + tile_in->value(""); + tile_in->redraw(); + + xx += 40 + 40; + tiles_out = + new Fl_Output(xx, yy, 40, BUTTON_H, OF_s); + tiles_out->labelsize(LABEL_SIZE); + tiles_out->textsize(LABEL_SIZE); + tiles_out->clear_visible_focus(); + tiles_out->value(""); + tiles_out->redraw(); + + tiles_group->end(); + tiles_group->deactivate(); + + xx = tiles_group->x() + tiles_group->w() + 5; + yy = tiles_group->y(); + ww = 115 + 30 + 40 + 30; + + reduct_group = new Fl_Group(xx, yy, ww, BUTTON_H); + reduct_group->begin(); + + xx += 115; + reduct_in = + new Fl_Input(xx, yy, 30, BUTTON_H, REDUCTION_s); + reduct_in->callback(reduct_in_cb); + reduct_in->when(FL_WHEN_RELEASE_ALWAYS); + reduct_in->labelsize(LABEL_SIZE); + reduct_in->textsize(LABEL_SIZE); + reduct_in->value(" "); + reduct_in->redraw(); + + xx += 30 + 40; + reduct_out = + new Fl_Output(xx, yy, 30, BUTTON_H, OF_s); + reduct_out->labelsize(LABEL_SIZE); + reduct_out->textsize(LABEL_SIZE); + reduct_out->clear_visible_focus(); + reduct_out->value(" "); + reduct_out->redraw(); + + reduct_group->end(); + reduct_group->deactivate(); + + xx = reduct_group->x() + reduct_group->w() + 10; + ww = 70 + 97; + + xx += 75; + area_in = + new Fl_Input(xx, yy, 218, BUTTON_H, AREA_s); + area_in->callback(area_in_cb); + area_in->labelsize(LABEL_SIZE); + area_in->textsize(LABEL_SIZE); + area_in->value("x0,y0,x1,y1"); + area_in->when(FL_WHEN_RELEASE_ALWAYS); + area_in->deactivate(); + + user_changed_tile = user_changed_reduct = 0; + max_tiles = 0; cur_tile = -1; + max_reduction = 0; cur_reduction = 0; + + yy = tiles_group->y() + tiles_group->h() + 5; + xx = X; + + bx = xx; + + pause_but = new Fl_Button(bx,yy,BUTTON_W,BUTTON_H,STOP_s); + pause_but->callback(pause_cb); + pause_but->labelsize(LABEL_SIZE); + bx += BUTTON_W; + + resume_but = new Fl_Button(bx,yy,BUTTON_W,BUTTON_H,GOON_s); + resume_but->callback(resume_cb); + resume_but->labelsize(LABEL_SIZE); + bx += BUTTON_W; + + restart_but = new Fl_Button(bx,yy,BUTTON_W,BUTTON_H,RESTART_s); + restart_but->callback(restart_cb); + restart_but->labelsize(LABEL_SIZE); + bx += BUTTON_W; + + fin_but = new Fl_Button(bx,yy,BUTTON_W,BUTTON_H,CLOSEFILE_s); + fin_but->callback(fin_cb); + fin_but->labelsize(LABEL_SIZE); + bx += BUTTON_W; + + xx = fin_but->x() + fin_but->w() + 5; + yy = fin_but->y(); + + bx = xx; + + backward_but = new Fl_Button(bx,yy,BUTTON_W,BUTTON_H,BACKWARD_s); + backward_but->callback(backward_cb); + backward_but->labelsize(LABEL_SIZE); + bx += BUTTON_W; + + forward_but = new Fl_Button(bx,yy,BUTTON_W,BUTTON_H,FORWARD_s); + forward_but->callback(forward_cb); + forward_but->labelsize(LABEL_SIZE); + bx += BUTTON_W; + + xx = forward_but->x() + forward_but->w() + 10; + yy = forward_but->y(); + bw = BUTTON_W + 3; + { + Fl_Button *b = new Fl_Button(xx, yy, bw, BUTTON_H, CROP_s); + b->callback(crop_window_cb); + b->labelsize(LABEL_SIZE); + } + xx += bw + 5; + { + Fl_Button *b = new Fl_Button(xx,yy,BUTTON_W,BUTTON_H,BROWSE_s); + b->callback(browse_cb); + yy = b->y() + b->h() + 5; + } + xx = X + 70; + layer_in = new Fl_Input(xx, yy, 30, BUTTON_H, LAYER_s); + layer_in->callback(layer_in_cb); + layer_in->deactivate(); + + xx += layer_in->w() + 10 + 30; + layer_out = new Fl_Output(xx, yy, 30, BUTTON_H, OF_s); + layer_out->deactivate(); + + xx += layer_out->w() + 10 + 100; + component_in = new Fl_Input(xx, yy, 30, BUTTON_H, COMPONENT_s); + component_in->callback(component_in_cb); + component_in->deactivate(); + + xx += component_in->w() + 10 + 30; + component_out = new Fl_Output(xx, yy, 30, BUTTON_H, OF_s); + component_out->deactivate(); + + + FLViewer_frames_animation(0); + + end(); +}/* Header::Header() */ + +int Header::handle(int event) +{ + if(!Fl::event_inside(x(), y(), w(), h() ) ) return 0; + + if(event == FL_LEAVE) return 1; + + return Fl_Group::handle(event); +} + +static unsigned char *print_buffer(size_t len) +{ + unsigned char *buf; + + if((buf = (unsigned char*)malloc(len))) + memcpy(buf, canvas->cbuf, len); + + return buf; +} + +static void print_cb(Fl_Widget *wid, void *v) +{ + const char *cs; + FILE *writer; + int ok, iw, ih, ic; + PSInfo ps; + PrintInfo print; + + if(movie_runs || !canvas->cbuf) + { + fl_alert("%s", NO_FILE_TO_PRINT_s); + return; + } + memset(&ps, 0, sizeof(PSInfo)); + memset(&print, 0, sizeof(PrintInfo)); +/*----------------------------*/ + Print_gui_create(&print); +/*----------------------------*/ + if( !print.ok) return; + + writer = fopen(print.fname_s, "wb"); + + if(writer == NULL) + { + cs = CANNOT_OPEN_s; + } + else + { + cs = SUCCESS_WITH_s; + ps.writer = writer; + + iw = canvas->new_iwidth; + ih = canvas->new_iheight; + ic = canvas->new_idepth; + + ps.src_buf = print_buffer(iw*ih*ic); + + if(ps.src_buf == NULL) + { + fclose(writer); ps.writer = NULL; + return; + } + ps.bg_red = 255; ps.bg_green = 255; ps.bg_blue = 255; + + ps.title_s = print.title_s; + ps.media_s = print.media_s; + ps.center = print.center; + ps.landscape = print.want_landscape; + ps.portrait = print.want_portrait; +/* want_color, want_gray */ + ps.fmedia_w = (int)(print.fpaper_w * 72./25.4); + ps.fmedia_h = (int)(print.fpaper_h * 72./25.4); + + ps.image_w = iw; ps.image_h = ih; + ps.image_channels = ic; + ps.fmargin_lhs = (int)(print.fmargin_lhs * 72./25.4); + ps.fmargin_top = (int)(print.fmargin_top * 72./25.4); + ps.fmargin_rhs = (int)(print.fmargin_rhs * 72./25.4); + ps.fmargin_bot = (int)(print.fmargin_bot * 72./25.4); +/*===============================*/ + ok = PS_image_draw(&ps); +/*===============================*/ + fclose(writer); + free(ps.src_buf); + + if( !ok) + cs = FAILURE_WITH_s; + else + if(print.command_s) + { +#ifdef _WIN32 + fl_message("%s\n%s",USE_SYSTEM_COMMAND_TO_PRINT_s, print.fname_s); +#else + char *cmd; + size_t len; + int ret; + + len = strlen(print.command_s) + strlen(print.printer_s) + + strlen(print.fname_s) + 32; + cmd = (char*)malloc(len); +/*----- +'man system': + + Do not use system() from a program with set-user-ID or set-group-ID + privileges, because strange values for some environment variables might + be used to subvert system integrity. Use the exec(3) family of func- + tions instead, but not execlp(3) or execvp(3) +------*/ + while(print.nr_copies) + { + snprintf(cmd, len, "%s%s %s", print.command_s, print.printer_s, + print.fname_s); + ret = system(cmd); + + if(WIFSIGNALED(ret) + && (WTERMSIG(ret) == SIGINT || WTERMSIG(ret) == SIGQUIT)) + break; + + --print.nr_copies; + } + free(cmd); +#endif /* _WIN32 */ + } + } + fl_message("%s\n%s", cs, print.fname_s); + + if(print.remove_fname) + remove(print.fname_s); + + free(print.fname_s); + free(print.printer_s); + free(print.command_s); + free(print.format_s); + free(print.title_s); + free(print.media_s); + +}/* print_cb() */ + +#ifdef OPJ_HAVE_LIBPNG + +static void save_as_png_cb(Fl_Widget *w, void *v) +{ + const char *cs, *period; + char *write_idf; + int ok; + struct stat sb; + + if(movie_runs || !canvas->cbuf) + { + fl_alert("%s", NO_FILE_TO_SAVE_s); + return; + } + cs = fl_input(ENTER_PNG_TO_SAVE_s, "name.png"); + + if(cs == NULL || *cs == 0) return; + + if(stat(cs, &sb) == 0) + { + if(fl_choice(FILE_EXISTS_s, "NO", "YES", NULL) == 0) return; + } + ok = + ( ((period = strrchr(cs, '.')) != NULL) + && (strncasecmp(period, ".png", 4) == 0)); + + if(!ok) + { + if(fl_choice(MISSING_PNG_EXT_s, "NO", "YES", NULL) == 0) + return; + } + write_idf = strdup(cs); + + PNG_save_file(canvas, write_idf); + + free(write_idf); +} +#endif // OPJ_HAVE_LIBPNG + +static void save_as_opj_cb(Fl_Widget *w, void *v) +{ + const char *cs; + char *write_idf; + struct stat sb; + + if(movie_runs || !canvas->cbuf) + { + fl_alert("%s", NO_FILE_TO_SAVE_s); + return; + } + cs = fl_input(ENTER_OPJ_TO_SAVE_s, "name.[jp2|j2k|jpc|j2c]"); + + if(cs == NULL || *cs == 0) return; + + if(stat(cs, &sb) == 0) + { + if(fl_choice(FILE_EXISTS_s, "NO", "YES", NULL) == 0) return; + } + write_idf = strdup(cs); + + JP2_save_file(canvas, write_idf); + + free(write_idf); +} + +/* +{"IDF",shortcut,CB,user_data,FLAGS,labeltype,LABELFONT,LABELSIZE,labelcolor} +*/ +Fl_Menu_Item popup_items[] = +{ + {EXIT_s, 0, &exit_cb, NULL, FL_MENU_DIVIDER, 0, 4, 15, FL_YELLOW}, + {PRINT_s, 0, &print_cb, NULL, FL_MENU_DIVIDER, 0, 4, 15, 0}, + {" -5%", 0, &zoomout_cb, NULL, FL_NORMAL_LABEL, 0, 4, 15, 0}, + {" -25%", 0, &zoomout_25_cb, NULL, FL_NORMAL_LABEL, 0, 4, 15, 0}, + {" -50%", 0, &zoomout_50_cb, NULL, FL_MENU_DIVIDER, 0, 4, 15, 0}, + {" +5%", 0, &zoomin_cb, NULL, FL_NORMAL_LABEL, 0, 4, 15, 0}, + {" +25%", 0, &zoomin_25_cb, NULL, FL_NORMAL_LABEL, 0, 4, 15, 0}, + {" +50%", 0, &zoomin_50_cb, NULL, FL_MENU_DIVIDER, 0, 4, 15, 0}, + {" 100%", 0, &reset_zoom_cb, NULL, FL_MENU_DIVIDER, 0, 4, 15, 0}, +#ifdef OPJ_HAVE_LIBPNG + {SAVE_AS_PNG_s, 0, &save_as_png_cb, NULL, FL_MENU_DIVIDER, 0, 4, 15, 0}, +#endif + {SAVE_AS_OPJ_s, 0, &save_as_opj_cb, NULL, FL_MENU_DIVIDER, 0, 4, 15, 0}, + {NULL, 0, NULL, NULL, 0, 0, 0, 0, 0} +}; + +static void popup_create(int x, int y) +{ + Fl_Menu_Button *popup; + + popup = new Fl_Menu_Button(x, y, MAX_SCROLLER_W, MAX_SCROLLER_H); + popup->type(Fl_Menu_Button::POPUP3); + popup->menu(popup_items); +} + +static void show_image(Fl_Image* img) +{ + int scroll_h, scroll_w, iw, ih, win_w, win_h; + int has_hbar, has_vbar, bar_size; + unsigned char type; + + if((bar_size = scroll->scrollbar_size()) == 0) bar_size = BAR_SIZE; + +#ifdef _WIN32 + EnterCriticalSection(&CriticalSection); +#else + ENTER_CRITICAL(semid); +#endif + + has_hbar = has_vbar = 0; + iw = img->w(); ih = img->h(); +/* movie without scrollbars, the whole image is visible: +*/ + if( !movie_runs) + { + if(iw > MAX_SCROLLER_W) + { + has_hbar = bar_size; + + if(ih + bar_size > MAX_SCROLLER_H) + has_vbar = bar_size; + } + else + if(ih > MAX_SCROLLER_H) + { + has_vbar = bar_size; + + if(iw + bar_size > MAX_SCROLLER_W) + has_hbar = bar_size; + } + } + + if(has_vbar) + scroll_h = MAX_SCROLLER_H; + else + scroll_h = ih + has_hbar; + + if(has_hbar) + scroll_w = MAX_SCROLLER_W; + else + scroll_w = iw + has_vbar; + + win_h = HEADER_H + scroll_h + BORDER_SIZE; + win_w = SCROLLER_X + scroll_w + BORDER_SIZE; + + if(win_w < WINDOW_MIN_W) win_w = WINDOW_MIN_W; + if(win_h < WINDOW_MIN_H) win_h = WINDOW_MIN_H; + + main_win->size(win_w, win_h); + scroll->size(scroll_w, scroll_h); + scroll_box->size(iw, ih); + scroll_box->image(img); + + type = 0; + if(has_hbar) type |= Fl_Scroll::HORIZONTAL; + if(has_vbar) type |= Fl_Scroll::VERTICAL; + + scroll->type(type); + scroll->scroll_to(0,0); + + main_win->redraw(); + +#ifdef _WIN32 + LeaveCriticalSection(&CriticalSection); +#else + LEAVE_CRITICAL(semid); +#endif + +}/* show_image() */ + +void FLViewer_use_buffer(const void *b, unsigned int w, unsigned int h, + int depth) +{ + Fl_RGB_Image *rgb, *new_rgb; + + rgb = canvas->new_rgb; + + scroll_box->image(NULL); + canvas->new_rgb = NULL; + + new_rgb = new Fl_RGB_Image((unsigned char*)b, (int)w, (int)h, depth); + + if(new_rgb) + { + if(fscale != 1.0) + { + Fl_Image *temp; + double fw, fh; + + fw = (double)new_rgb->w() * fscale; + fh = (double)new_rgb->h() * fscale; + + temp = new_rgb->copy((int)fw, (int)fh); + + delete new_rgb; + new_rgb = (Fl_RGB_Image*)temp; + } + canvas->new_idepth = new_rgb->d(); + canvas->new_iwidth = new_rgb->w(); + canvas->new_iheight = new_rgb->h(); + + canvas->cbuf = new_rgb->data()[0]; + + show_image((Fl_Image*)new_rgb); + } + if(rgb) delete rgb; + + canvas->new_rgb = new_rgb; + +}/* FLViewer_use_buffer() */ + +void FLViewer_area_activate(int v) +{ + if(v) + { + area_in->activate(); + } + else + { + area_in->deactivate(); + } +} + +void FLViewer_tiles_activate(int v) +{ + if(v) + { + tiles_group->activate(); + reduct_group->activate(); + reload_jp2->activate(); + + tiles_write_out(); + } + else + { + tiles_out->value(""); + tiles_out->redraw(); + tiles_group->deactivate(); + + cur_reduction = 0; max_reduction = 0; + reduct_in->value(""); + reduct_out->value(""); + reduct_group->deactivate(); + + reload_jp2->deactivate(); + } +} + +void FLViewer_frames_animation(int v) +{ + FLViewer_animation(v); + + goto_frame_in->value(""); + goto_frame_in->redraw(); + all_frames_out->value(""); + all_frames_out->redraw(); + + goto_track_in->value(""); + goto_track_in->redraw(); + all_tracks_out->value(""); + all_tracks_out->redraw(); + + if(v) + { + frames_group->activate(); + tracks_group->activate(); + } + else + { + frames_group->deactivate(); + tracks_group->deactivate(); + + tiles_out->value(""); + tile_in->value(""); + tiles_group->deactivate(); + + cur_reduction = 0; max_reduction = 0; + reduct_in->value(""); + reduct_out->value(""); + reduct_group->deactivate(); + } + if(canvas) + { + canvas->selected_frame = -1; + canvas->top_frame = -1; + + canvas->selected_track = -1; + canvas->top_track = -1; + } +} + +void FLViewer_animation(int v) +{ + if(v) + { + pause_but->activate(); + resume_but->activate(); + restart_but->activate(); + fin_but->activate(); + + backward_but->activate(); + forward_but->activate(); + } + else + { + pause_but->deactivate(); + resume_but->deactivate(); + restart_but->deactivate(); + fin_but->deactivate(); + + backward_but->deactivate(); + forward_but->deactivate(); + } +} + +void FLViewer_mj2_animation(int v) +{ + FLViewer_frames_animation(v); +} + +void FLViewer_show_frame(int n, int m) +{ + char all_buf[32]; + + snprintf(all_buf, sizeof(all_buf)-1, "%d/%d", n, m); + all_frames_out->value(all_buf); +} + +void FLViewer_show_track(int n, int m) +{ + char all_buf[32]; + int s; + + if((s = canvas->selected_track) < 1) + s = 1; + + snprintf(all_buf,sizeof(all_buf)-1,"%d/%d", s, m); + all_tracks_out->value(all_buf); +} + +void FLViewer_clear_wait(void) +{ + url_out->value(""); url_out->redraw(); +} + +void FLViewer_wait(void) +{ + url_out->value(WAITPLEASE_s); +} + +void FLViewer_url(const char *fname, int w, int h) +{ + const char *cs = NULL; +#ifdef _WIN32 + cs = strrchr(fname, '\\'); +#else + cs = strrchr(fname, '/'); +#endif + if(cs) ++cs; else cs = fname; + + snprintf(url_buf, 511, "%s (%d x %d)",cs,w,h); + url_out->value(url_buf); +} + +static void load_image(FILE *fp, const char *fname, uint64_t fsize) +{ + unsigned char magic_buf[32]; + + memset(magic_buf, 0, 32); + (void)fread(magic_buf, 1, 32, fp); + rewind(fp); + + FLViewer_header_deactivate(); + +#ifdef OPJ_HAVE_LIBPNG + if(memcmp(magic_buf, PNG_MAGIC, 8) == 0) + { + if(tree) tree->clear(); + + component_in->value(""); + component_in->deactivate(); + component_out->value(""); + component_out->deactivate(); + + PNG_load(canvas, fp, fname, fsize); + + return; + } +#endif + + if(memcmp(magic_buf, JP2_RFC3745_MAGIC, 12) == 0 + && memcmp(magic_buf+20, "\x6d\x6a\x70\x32", 4) == 0) + { + FLViewer_close_reader(); + + if(strlen(read_idf) > OPJ_PATH_LEN - 2) + { + fl_alert("%s:\n%s", read_idf, FILENAME_TOO_LONG_s); + return; + } + FLViewer_reset_tiles_and_reduction(); + + test_new_mj2_file(); + + OPENMJ2_load(canvas, fname, fsize); + + return; + } + + if(memcmp(magic_buf, JP2_RFC3745_MAGIC, 12) == 0 + || memcmp(magic_buf, JP2_MAGIC, 4) == 0 + || memcmp(magic_buf, J2K_CODESTREAM_MAGIC, 4) == 0 + ) + { + unsigned char *src; + FTYPInfo ftyp; + int ret; + + if(strlen(read_idf) > OPJ_PATH_LEN - 2) + { + fl_alert("%s:\n%s", read_idf, FILENAME_TOO_LONG_s); + FLViewer_close_reader(); + return; + } + + if((src = (unsigned char*)malloc(fsize)) == NULL) + { + FLViewer_close_reader(); + return; + } + (void)fread(src, 1, fsize, fp); + FLViewer_close_reader(); + + ret = JPEG2000_test_ftyp(fname, src, fsize, &ftyp); + + free(src); src = NULL; + + if(ret == 0) + { + if(ftyp.is_j2k == 0) + { + fprintf(stderr,"%s:%d:\n\tload_image(%s) FAILED\n", + __FILE__,__LINE__,fname); + return; + } + } + + FLViewer_layer_component_activate(1); + + test_new_jp2_file(); + + if(cmd_line_reduction > 0) + { + user_changed_tile = 1; user_changed_reduct = 1; + cur_reduction = cmd_line_reduction; + + FLViewer_tiles_activate(1); + + cmd_line_reduction = 0; + } + + OPENJPEG_load(canvas, fname, src, fsize, ftyp.decod_format); + + return; + } +#ifdef WANT_PGX + if(memcmp(buf, "PG", 2) == 0) + { + if(tree) tree->clear(); + + PGX_load(canvas, fp, fname, fsize); + + return; + } +#endif //WANT_PGX + + fl_alert("%s\n%s\n %s", CANNOT_USE_FILE_s, fname, + NO_DRIVER_FOUND_s); +} /* load_image() */ + +static void chooser_cb(const char *cs) +{ + struct stat sb; + + if(cs == NULL || *cs == 0) return; + + if(stat(cs, &sb) < 0) + { + fl_alert("%s\n%s", FILE_NOT_FOUND_s, cs); + return; + } + if((sb.st_mode & S_IFMT) == S_IFDIR) return; + + { + char dbuf[4096]; + +#ifdef _WIN32 + strncpy(dbuf, cs, 4095); // WIN32 without soft link +#else + ssize_t n; + unsigned int reg; + char sbuf[4096]; + + strncpy(sbuf, cs, 4095); *dbuf = 0; + + if(lstat(sbuf, &sb) == 0) + { + reg = ((S_IFREG & sb.st_mode) == (S_IFMT & sb.st_mode)); + + if( !reg && (n = readlink(sbuf, dbuf, 4095)) > 0) + dbuf[n] = 0; + else + strncpy(dbuf, cs, 4095); + } +#endif + + if(stat(dbuf, &sb) < 0) + { + fl_alert("%s\n%s", FILE_NOT_FOUND_s, dbuf); + return; + } + + if(sb.st_size == 0) + { + fl_alert("%s\n%s", FILE_SIZE_ZERO_s, dbuf); + return; + } + + if(sb.st_size > FILESIZE_LIMIT) + { + fl_alert("%s\n%s\n", dbuf, FILESIZE_TOO_LONG_s); + return; + } + + start_overlay = 1; + main_win->redraw_overlay(); + + if(canvas->cleanup) + { + canvas->cleanup(); + canvas->cleanup = NULL; + } + FLViewer_close_reader(); + + if(read_idf) + { + free(read_idf); read_idf = NULL; + } +/*-------------------------------*/ + reader = fopen(dbuf, "rb"); + + if(reader == NULL) + { + perror(dbuf); + fl_alert("%s\n%s", FILE_NOT_FOUND_s, dbuf); + + return; + } + read_idf = strdup(dbuf); + movie_runs = 0; + + load_image(reader, read_idf, (uint64_t)sb.st_size); + } +}/* chooser_cb() */ + +static void goto_frame_cb(Fl_Widget *w, void *v) +{ + const char *cs; + int i; + + if( !w->contains(Fl::belowmouse())) return; + + cs = ((Fl_Input*)w)->value(); + + if(cs && *cs) + { + i = atoi(cs); + + if(i < 1) return; + if(i > canvas->top_frame) i = canvas->top_frame; + + canvas->selected_frame = i; + } +} + +static void goto_track_cb(Fl_Widget *w, void *v) +{ + const char *cs; + int i; + + if( !w->contains(Fl::belowmouse())) return; + + cs = ((Fl_Input*)w)->value(); + + if(cs && *cs) + { + i = atoi(cs); + + if(i < 1) { goto_track_in->value(""); return; } + + if(i > canvas->top_track) + { + if(canvas->top_track < 1) + canvas->top_track = 1; + + i = canvas->top_track; + + snprintf(vbuf, sizeof(vbuf)-1, "%d", i); + goto_track_in->value(vbuf); + goto_track_in->redraw(); + } + canvas->selected_track = i; + } +} + +int FLViewer_frame_selected(void) +{ + int n; + + if((n = canvas->selected_frame) >= 1) + { + canvas->selected_frame = -1; + return n; + } + return -1; +} + +// see Fl::option(Fl::OPTION_FNFC_USES_GTK, false) in main() +// +static void browse_cb(Fl_Widget *wid, void *v) +{ + Fl_Native_File_Chooser native; + + native.title("Select Image File"); + native.type(Fl_Native_File_Chooser::BROWSE_FILE); + native.filter(IMG_PATTERN); + native.preset_file(read_idf); + +#ifdef _WIN32 + if(canvas->cleanup) + { + canvas->cleanup(); + canvas->cleanup = NULL; + } +#endif //_WIN32 + + switch(native.show()) + { + case -1: + fprintf(stderr, "FILE_CHOOSER_ERROR: %s\n", native.errmsg()); + break; + + case 1: /* Cancel */ + break; + + default: + if(native.filename()) + chooser_cb(native.filename()); + break; + } +} + +static void pause_cb(Fl_Widget *wid, void *v) +{ + if(canvas->pause) canvas->pause(); +} + +static void resume_cb(Fl_Widget *wid, void *v) +{ + if(canvas->resume) canvas->resume(); +} + +static void restart_cb(Fl_Widget *wid, void *v) +{ + if(canvas->restart) canvas->restart(); +} + +static void backward_cb(Fl_Widget *wid, void *v) +{ + if(canvas->backward) canvas->backward(); +} + +static void forward_cb(Fl_Widget *wid, void *v) +{ + if(canvas->forward) canvas->forward(); +} + +static void fin_cb(Fl_Widget *wid, void *v) +{ + if(canvas->fin) canvas->fin(); +} + +static void exit_cb(Fl_Widget *wid, void *v) +{ + if(canvas->cleanup) + { + canvas->cleanup(); + } + +#ifdef _WIN32 + DeleteCriticalSection(&CriticalSection); +#else /* not _WIN32 */ + if(semctl(semid, 0, IPC_RMID, 0) == -1) + fprintf(stderr,"%s:%d: semctl IPC_RMID failed\n",__FILE__,__LINE__); +#endif /* _WIN32 */ + + if(read_idf != NULL) free(read_idf); + if(jp2_file != NULL) free(jp2_file); + if(mj2_file != NULL) free(mj2_file); + if(reader != NULL) fclose(reader); + + free(root_dir); + delete main_win; + + exit(0); +} + +static void usage(void) +{ + const char *bar= +"\n------------------------------------------------------------------\n"; + + fputs(bar, stderr); + + fprintf(stderr,"%s\n" + "USAGE: flviewer [--bg BACKGROUND_COLOR] [--r INT] [FILE]\n", + PACKAGE_STRING); + + fputs("\twith BACKGROUND_COLOR = " + "(\"TEXT\" | \"#RGB\" | \"rgb:R/G/B\" )\n" + "\t e.g. (--bg \"red\" | --bg \"#ff0000\" " + "| --bg \"rgb:ff/00/00\" )", stderr); + fputs("\n\t--r INT means the reduction on start, e.g. --r 2\n", stderr); + fputs(bar, stderr); +} + +static void shrink_name(char *buf) +{ + char *s, *d; + int ch; + + s = d = buf; + while((ch = *s++)) + { + if(isspace(ch)) continue; + *d++ = (char)tolower(ch); + } + *d = 0; +} + +int main(int argc, char *argv[]) +{ + const char *fname, *s; + int i, x, y, found_bgcolor, reduct; + unsigned char rc, gc, bc; + + cmd_line_reduction = reduct = 0; +#ifdef _WIN32 + if(!InitializeCriticalSectionAndSpinCount(&CriticalSection, + IDLE_SPIN) ) + { + fprintf(stderr,"%s:%d: InitializeCriticalSectionAndSpinCount failed\n", + __FILE__,__LINE__); + + return 1; + } +#else /* not _WIN32 */ + semid = semget(getpid(), 1, S_IRWXU|S_IRWXG|S_IRWXO|IPC_CREAT|IPC_EXCL); + + if(semid == -1) + { + fprintf(stderr,"%s:%d:semget failed\n",__FILE__,__LINE__); + perror(NULL); + return 1; + } +/* triggers BUG in PowerPC: if(semctl(semid, 0, SETVAL, 1) == -1) */ + su.val = 1; + + if(semctl(semid, 0, SETVAL, su) == -1) + { + fprintf(stderr,"%s:%d:semctl SETVAL failed\n",__FILE__,__LINE__); + perror(NULL); + return 1; + } +#endif /* _WIN32 */ + + Fl::visual(FL_RGB); + fl_register_images(); + +#ifndef _WIN32 +#ifdef HAVE_OPTION_FNFC_USES_GTK + Fl::option(Fl::OPTION_FNFC_USES_GTK, false); +#endif +#endif + + fname = NULL; found_bgcolor = 0; + + for(i = 1; i < argc; ++i) + { + s = argv[i]; + + if(strcmp(s, "--help") == 0 + || strcmp(s, "-help") == 0 + || *s == '?' + || strcmp(s, "--version") == 0 + || strcmp(s, "-V") == 0 + ) + { + usage(); + return 0; + } + if(strcasecmp(s, "--bg") == 0) + { + ++i; + s = argv[i]; + + if(*s == '#' || strncasecmp(s, "rgb:", 4) == 0 || isalpha(*s)) + { + strncpy(bgcolor_buf, s, MAX_COLORBUF); + bgcolor_buf[MAX_COLORBUF] = 0; + found_bgcolor = 1; + + if(*s != '#') + shrink_name(bgcolor_buf); + continue; + } + continue; + } + if(strcasecmp(s, "--r") == 0) + { + ++i; + s = argv[i]; + reduct = atoi(s); + continue; + } + if(*s != '-') + { + fname = s; continue; + } + }/* for() */ +#ifdef _WIN32 + if((root_dir = getenv("UserProfile"))) + root_dir = strdup(root_dir); + else + root_dir = strdup("C:\\Windows\\Temp"); +#else + root_dir = strdup(getenv("HOME")); +#endif + start_overlay = 1; + + win_w = WINDOW_MIN_W; win_h = WINDOW_MIN_H; + + main_win = new Overlay(WIN_X, WIN_Y, win_w, win_h); + main_win->color(DEFAULT_BACKGROUND); + main_win->begin(); + + x = BORDER_SIZE; y = BORDER_SIZE; + + header = new Header(x, y, HEADER_W, HEADER_H - BORDER_SIZE, NULL); + header->resizable(NULL); + + tree = new UserTree(TREE_X, TREE_Y, TREE_W, TREE_H); + tree->begin(); + + tree->box(FL_DOWN_BOX); + tree->color((Fl_Color)55); + tree->selection_color((Fl_Color)55); + tree->labeltype(FL_NORMAL_LABEL); + tree->labelfont(0); + tree->labelsize(12); + tree->item_labelsize(12); + tree->labelcolor(FL_FOREGROUND_COLOR); + tree->align(Fl_Align(FL_ALIGN_TOP)); + tree->when(FL_WHEN_RELEASE); +#ifdef USE_CUSTOM_ICONS + tree->openicon(&L_openpixmap); + tree->closeicon(&L_closepixmap); +#endif + tree->connectorstyle(FL_TREE_CONNECTOR_SOLID); + tree->marginleft(0); + tree->connectorwidth(7); + +#if FLTK_ABI_VERSION >= 10304 + tree->item_reselect_mode(FL_TREE_SELECTABLE_ALWAYS); +#endif + + tree->root_label(" "); + tree->end(); + + canvas = (Canvas*)calloc(1, sizeof(Canvas)); + + if(found_bgcolor) + { + if( !rgb_color_values(bgcolor_buf, rc, gc, bc)) + fl_parse_color(bgcolor_buf, rc, gc, bc); + } + else + Fl::get_color(DEFAULT_CANVAS_BACKGROUND, rc, gc, bc); + + canvas->bg_red = rc; canvas->bg_green = gc; + canvas->bg_blue = bc; + + scroll = new + Fl_Scroll(SCROLLER_X, SCROLLER_Y, MIN_SCROLLER_W,MIN_SCROLLER_H); + scroll->box(FL_FLAT_BOX); + scroll->begin(); + + scroll_box = new + ImageBox(SCROLLER_X, SCROLLER_Y, MIN_SCROLLER_W,MIN_SCROLLER_H); + scroll_box->box(FL_FLAT_BOX); + scroll_box->align(FL_ALIGN_INSIDE|FL_ALIGN_CENTER); + scroll_box->color(fl_rgb_color(rc, gc, bc)); + + scroll->end(); + scroll->resizable(scroll_box); + scroll->type(0); + + popup_create(SCROLLER_X, SCROLLER_Y); + + main_win->end(); +/*--------- + main_win->size_range(main_win->w(), main_win->h(), + 0, 0, 0, 0); +-----------*/ + main_win->show(); + + if(fname) + { + if(reduct > 0) + { + cmd_line_reduction = reduct; + + user_changed_tile = 1; user_changed_reduct = 1; + cur_reduction = reduct; + + FLViewer_tiles_activate(1); + + } + chooser_cb(fname); + } + return Fl::run(); +}//main() diff --git a/src/bin/fltk/flviewer/flviewer.hh b/src/bin/fltk/flviewer/flviewer.hh new file mode 100644 index 00000000..d0a757fe --- /dev/null +++ b/src/bin/fltk/flviewer/flviewer.hh @@ -0,0 +1,97 @@ +#ifndef _FLVIEWER_HH_ +#define _FLVIEWER_HH_ + +#include +#include +#include + +/* off_t st_size; */ +#define FILESIZE_LIMIT (LONG_MAX - 100) + +#define IS_MOVIE 0 +#define IS_STILL 1 + +#define FULLY_OPAQUE 255 +#define FULLY_TRANSPARENT 0 + +#ifdef _WIN32 +#define strcasecmp _stricmp +#define strncasecmp _strnicmp +#define snprintf _snprintf +#define sprintf _scprintf +#define strdup _strdup +#define popen _popen +#define pclose _pclose +#endif /* _WIN32 */ + +typedef struct canvas +{ + Fl_RGB_Image *new_rgb; + const char *read_idf; + const void *cbuf; + int new_iwidth, new_iheight, new_idepth; + int selected_frame, top_frame; + int selected_track, top_track; + unsigned char bg_red, bg_green, bg_blue; + + void (*pause)(void); + void (*resume)(void); + void (*restart)(void); + void (*forward)(void); + void (*backward)(void); + void (*fin)(void); + void (*cleanup)(void); + void (*current)(void); + +} Canvas; + +extern char *root_dir; + +/* PROTOTYPES */ + +extern void FLViewer_url(const char *fname, int w, int h); +extern void FLViewer_animation(int v); +extern void FLViewer_frames_animation(int v); + +extern void FLViewer_show_frame(int n, int m); +extern int FLViewer_frame_selected(void); +extern void FLViewer_wait(void); + +extern void FLViewer_clear_wait(void); +extern void FLViewer_use_buffer(const void *b, unsigned int w, unsigned int h, + int depth); + +extern void FLViewer_movie_runs(int v); +extern void FLViewer_close_reader(void); + +extern void FLViewer_mj2_animation(int v); + +extern int FLViewer_has_tile_and_reduction(void); +extern void FLViewer_put_max_tiles_and_reduction(int mx_tiles, int mx_reduct); +extern void FLViewer_get_max_tiles_and_reduction(int *out_mx_tiles, + int *out_mx_reduct); + +extern void FLViewer_get_tile_and_reduction(int *out_tile, int *out_reduct); +extern void FLViewer_tiles_activate(int v); + +extern void FLViewer_area_activate(int v); +extern int FLViewer_has_area_values(); +extern void FLViewer_get_area_values(int *out_x0, int *out_y0, + int *out_x1, int *out_y1); + +extern void FLViewer_reset_tiles_and_reduction(); +extern void FLViewer_set_max_reduction(int mx_reduct); +extern void FLViewer_set_max_tiles(int mx_tiles); + +extern int FLViewer_nr_threads(void); +extern void FLViewer_canvas_top_frame(int v); + +extern void FLViewer_threads_activate(int v); +extern void FLViewer_header_deactivate(); + +extern void FLViewer_layer_component_activate(int v); + +extern void FLViewer_clear_tree(); +extern void FLViewer_show_track(int n, int m); + +#endif /* _FLVIEWER_HH_ */ diff --git a/src/bin/fltk/flviewer/have_threads.hh b/src/bin/fltk/flviewer/have_threads.hh new file mode 100644 index 00000000..aa53cc63 --- /dev/null +++ b/src/bin/fltk/flviewer/have_threads.hh @@ -0,0 +1,67 @@ +#ifndef _HAVE_THREADS_HH_ +#define _HAVE_THREADS_HH_ + +#if defined(HAVE_NPTH_THREADS) && defined(_WIN32) + +#define PTHREAD_mutex_lock npth_mutex_lock +#define PTHREAD_mutex_unlock npth_mutex_unlock +#define PTHREAD_mutex_init npth_mutex_init +#define PTHREAD_mutex_destroy npth_mutex_destroy + +#define PTHREAD_cond_wait npth_cond_wait +#define PTHREAD_cond_signal npth_cond_signal +#define PTHREAD_cond_init npth_cond_init +#define PTHREAD_cond_broadcast npth_cond_broadcast +#define PTHREAD_cond_destroy npth_cond_destroy + +#define PTHREAD_create npth_create +#define PTHREAD_join npth_join + +#define PTHREAD_cond_t npth_cond_t +#define PTHREAD_mutex_t npth_mutex_t +#define PTHREAD_t npth_t + +#define PTHREAD_init npth_init + +#elif defined(_WIN32) + +#define PTHREAD_mutex_lock pthread_mutex_lock +#define PTHREAD_mutex_unlock pthread_mutex_unlock +#define PTHREAD_mutex_init pthread_mutex_init +#define PTHREAD_mutex_destroy pthread_mutex_destroy + +#define PTHREAD_cond_wait pthread_cond_wait +#define PTHREAD_cond_signal pthread_cond_signal +#define PTHREAD_cond_init pthread_cond_init +#define PTHREAD_cond_broadcast pthread_cond_broadcast +#define PTHREAD_cond_destroy pthread_cond_destroy + +#define PTHREAD_create pthread_create +#define PTHREAD_join pthread_join + +#define PTHREAD_cond_t pthread_cond_t +#define PTHREAD_mutex_t pthread_mutex_t +#define PTHREAD_t pthread_t + +#else /* not _WIN32 */ + +#define PTHREAD_mutex_lock pthread_mutex_lock +#define PTHREAD_mutex_unlock pthread_mutex_unlock +#define PTHREAD_mutex_init pthread_mutex_init +#define PTHREAD_mutex_destroy pthread_mutex_destroy + +#define PTHREAD_cond_wait pthread_cond_wait +#define PTHREAD_cond_signal pthread_cond_signal +#define PTHREAD_cond_init pthread_cond_init +#define PTHREAD_cond_broadcast pthread_cond_broadcast +#define PTHREAD_cond_destroy pthread_cond_destroy + +#define PTHREAD_create pthread_create +#define PTHREAD_join pthread_join + +#define PTHREAD_cond_t pthread_cond_t +#define PTHREAD_mutex_t pthread_mutex_t +#define PTHREAD_t pthread_t + +#endif +#endif /* _HAVE_THREADS_HH_ */ diff --git a/src/bin/fltk/flviewer/lang/dialog_lang.h_utf8 b/src/bin/fltk/flviewer/lang/dialog_lang.h_utf8 new file mode 100644 index 00000000..9f321e97 --- /dev/null +++ b/src/bin/fltk/flviewer/lang/dialog_lang.h_utf8 @@ -0,0 +1,88 @@ +#ifndef _FLIMAGE_PRINT_DIALOG_LANG_H_ +#define _FLIMAGE_PRINT_DIALOG_LANG_H_ +/* static const char _s[]={""}; */ +#ifdef WITH_ENGLISH +static const char YES_s[]={"YES"}; +static const char NO_s[]={"NO"}; +static const char PRINTERPAGE_s[]={"Print Image (PostScript)"}; +static const char FILENAME_s[]={"Filename:"}; +static const char PRINT_s[]={"Print"}; +static const char PRINTCMD_s[]={"Command:"}; +static const char PRINTERNAMES_s[]={"Name:"}; +static const char PRINTER_s[]={"Printer"}; +static const char PRINTTO_s[]={"Print To"}; +static const char FILE_s[]={"File"}; +static const char CONTINUE_PRINT_s[]= + {"File already exists.\n Continue?"}; +static const char COPIES_s[]={"Copies:"}; +static const char PORTRAIT_s[]={"Portrait"}; +static const char LANDSCAPE_s[]={"Landscape"}; +static const char LOWRES_s[]={"Low resolution"}; +static const char HIRES_s[]={"High resolution"}; +static const char COLOR_s[]={"Color"}; +static const char GRAY_s[]={"Gray"}; +static const char DOCFORMAT_s[]={"Format"}; +static const char OK_s[]={"OK"}; +static const char CANCEL_s[]={"Cancel"}; + +static const char NAME_s[]={"Name:"}; +static const char TITLE_s[]={"Title:"}; +static const char IMAGE_s[]={"Image"}; +static const char CENTER_s[]={"Center"}; +static const char MARGINS_s[]={"Margins(mm)"}; +static const char LEFT_s[]={"Left:"}; +static const char RIGHT_s[]={"Right:"}; +static const char TOP_s[]={"Top:"}; +static const char BOTTOM_s[]={"Bottom:"}; +static const char LOC_s[]={"Loc:"}; +static const char NO_FILENAME_FOUND_s[]= + {"No file name found. Please enter."}; +static const char NAME_IS_DIR_s[]= + {"Name exists and is directory name. Please change."}; +#endif /* WITH_ENGLISH */ + +#ifdef WITH_GERMAN + +static const char YES_s[]={"Ja"}; +static const char NO_s[]={"Nein"}; +static const char NO_FILENAME_FOUND_s[]= + {"Kein Datei-Name gefunden. Bitte eingeben."}; +static const char NAME_IS_DIR_s[]= + {"Name ist Verzeichnis-Name. Bitte ändern."}; +static const char LOC_s[]={"Ort:"}; +static const char PRINTERPAGE_s[]={"Bild drucken (PostScript)"}; +static const char FILENAME_s[]={"Datei-Name:"}; +static const char PRINT_s[]={"Drucken"}; +static const char PRINTCMD_s[]={"Befehl:"}; +static const char PRINTERNAMES_s[]={"Name:"}; +static const char PRINTER_s[]={"Drucker"}; +static const char PRINTTO_s[]={"Ziel"}; +static const char FILE_s[]={"Datei"}; +static const char CONTINUE_PRINT_s[]= + {"Datei besteht bereits.\n Weiter?"}; +static const char COPIES_s[]={"Kopien:"}; +static const char PORTRAIT_s[]={"Vertikal-Druck"}; +static const char LANDSCAPE_s[]={"Quer-Druck"}; +static const char LOWRES_s[]={"Auflösung gering"}; +static const char HIRES_s[]={"Auflösung hoch"}; +static const char COLOR_s[]={"Farbig"}; +static const char GRAY_s[]={"Grau"}; +static const char DOCFORMAT_s[]={"Format"}; +static const char OK_s[]={"OK"}; +static const char CANCEL_s[]={"Abbruch"}; + +static const char NAME_s[]={"Name:"}; +static const char TITLE_s[]={"Titel:"}; +static const char IMAGE_s[]={"Bild"}; +static const char CENTER_s[]={"Zentrieren"}; +static const char MARGINS_s[]={"Ränder(mm)"}; +static const char LEFT_s[]={"Links:"}; +static const char RIGHT_s[]={"Rechts:"}; +static const char TOP_s[]={"Oben:"}; +static const char BOTTOM_s[]={"Unten:"}; + +#endif /* WITH_GERMAN */ + + + +#endif /* _FLIMAGE_PRINT_DIALOG_LANG_H_ */ diff --git a/src/bin/fltk/flviewer/lang/mj2_lang.h_utf8 b/src/bin/fltk/flviewer/lang/mj2_lang.h_utf8 new file mode 100644 index 00000000..4437c502 --- /dev/null +++ b/src/bin/fltk/flviewer/lang/mj2_lang.h_utf8 @@ -0,0 +1,17 @@ +#ifndef _FLIMAGE_MJ2_FILE_LANG_H_ +#define _FLIMAGE_MJ2_FILE_LANG_H_ + +//static const char _s[]={""}; +#ifdef WITH_ENGLISH +static const char MJ2_NO_FRAMES_FROM_s[]={"MJ2:Can not extract frames from"}; +static const char MJ2_SHOW_FAILS_s[]= + {"MJ2:Can not show file\n%s\n samples(%d) width(%d) height(%d)"}; +#endif + +#ifdef WITH_GERMAN +static const char MJ2_NO_FRAMES_FROM_s[]={"MJ2:kann nichts finden in"}; +static const char MJ2_SHOW_FAILS_s[]= + {"MJ2:kann Datei nicht zeigen für\n%s\n Bilder(%d) Weite(%d) Höhe(%d)"}; +#endif + +#endif /* _FLIMAGE_MJ2_FILE_LANG_H_ */ diff --git a/src/bin/fltk/flviewer/lang/opj_lang.h_utf8 b/src/bin/fltk/flviewer/lang/opj_lang.h_utf8 new file mode 100644 index 00000000..39ffecb2 --- /dev/null +++ b/src/bin/fltk/flviewer/lang/opj_lang.h_utf8 @@ -0,0 +1,30 @@ +#ifndef _FLIMAGE_OPJ_FILE_LANG_H_ +#define _FLIMAGE_OPJ_FILE_LANG_H_ + +//static const char _s[]={""}; +#ifdef WITH_ENGLISH +static const char JPEG2000_DECODE_FAILS_s[]={"Got no JPEG2000 image for"}; +static const char DST_DID_NOT_OPEN_s[]={"Destination %s\n\tdid not open"}; +static const char WRITE_JPEG2000_FAILS_s[]={"Writing JPEG2000 file fails"}; +static const char GOT_NO_IMAGE_s[]={"opj_image_create() failed"}; +static const char WRONG_DST_EXT_s[]= + {"Destination file %s\nhas wrong extension"}; +static const char WRITE_JP2_FAILS_s[]={"Writing JP2 file fails"}; +static const char JP2_DECODE_FAILS_s[]={"Got no JP2 image for"}; + +#endif + +#ifdef WITH_GERMAN +static const char JPEG2000_DECODE_FAILS_s[]={"JPEG2000 Dekodierungsfehler für"}; +static const char DST_DID_NOT_OPEN_s[]={"Ziel-Datei %s\n\töffnet nicht"}; +static const char WRITE_JPEG2000_FAILS_s[]= + {"JPEG2000-Datei läßt sich nicht schreiben"}; +static const char GOT_NO_IMAGE_s[]={"opj_image_create() scheitert"}; +static const char WRONG_DST_EXT_s[]= + {"Ziel-Datei %s\nhat falsche Extension"}; +static const char WRITE_JP2_FAILS_s[]={"JP2-Datei läßt sich nicht schreiben"}; +static const char JP2_DECODE_FAILS_s[]={"JP2 Dekodierungsfehler für"}; + +#endif + +#endif /* _FLIMAGE_OPJ_FILE_LANG_H_ */ diff --git a/src/bin/fltk/flviewer/lang/png_lang.h_utf8 b/src/bin/fltk/flviewer/lang/png_lang.h_utf8 new file mode 100644 index 00000000..679b494b --- /dev/null +++ b/src/bin/fltk/flviewer/lang/png_lang.h_utf8 @@ -0,0 +1,15 @@ +#ifndef _FLIMAGE_PNG_LANG_H_ +#define _FLIMAGE_PNG_LANG_H_ +//static const char _s[]={""}; +#ifdef WITH_ENGLISH +static const char DST_DID_NOT_OPEN_s[]={"Destination %s\n\tdid not open"}; +static const char WRITE_PNG_FAILS_s[]={"Writing PNG file fails"}; + +#endif +#ifdef WITH_GERMAN +static const char DST_DID_NOT_OPEN_s[]={"Ziel-Datei %s\n\töffnet nicht"}; +static const char WRITE_PNG_FAILS_s[]={"PNG-Datei läßt sich nicht schreiben"}; + +#endif + +#endif /* _FLIMAGE_PNG_LANG_H_ */ diff --git a/src/bin/fltk/flviewer/lang/viewer_lang.h_utf8 b/src/bin/fltk/flviewer/lang/viewer_lang.h_utf8 new file mode 100644 index 00000000..40fa0b1a --- /dev/null +++ b/src/bin/fltk/flviewer/lang/viewer_lang.h_utf8 @@ -0,0 +1,119 @@ +#ifndef _FLIMAGE_FILE_LANG_H_ +#define _FLIMAGE_FILE_LANG_H_ +//static const char _s[]={""}; +#ifdef WITH_ENGLISH +static const char CANNOT_USE_FILE_s[]= {"Can not use file"}; +static const char NO_DRIVER_FOUND_s[]= {"NO DRIVER FOUND"}; +static const char FILE_NOT_FOUND_s[]= {"File not found"}; +static const char CANNOT_LOAD_FILE_s[]= {"Can not load file"}; +static const char FILESIZE_TOO_LONG_s[]={"filesize too large. Ignored."}; +static const char NO_FILE_TO_PRINT_s[]={"No file to print."}; +static const char FILE_SIZE_ZERO_s[]={"File length is zero"}; +static const char USE_SYSTEM_COMMAND_TO_PRINT_s[]= + {"Please use the system command(s)\nto print the file:"}; +static const char TILE_s[]={"Tile:"}; +static const char OF_s[]={" of "}; +static const char RELOAD_s[]={"Reload"}; +static const char REDUCTION_s[]={"Reduction:"}; +static const char NO_FILE_TO_SAVE_s[]={"No file to save"}; +static const char SAVE_AS_PNG_s[]={"Save As PNG"}; +static const char ENTER_PNG_TO_SAVE_s[]= + {"Enter a name to save a PNG file:"}; +static const char FILE_EXISTS_s[]= + {"File already exists.\n Continue?"}; +static const char SAVE_AS_OPJ_s[]={"Save As JP2/J2K"}; +static const char ENTER_OPJ_TO_SAVE_s[]= + {"Enter a name to save a JP2/J2K file:"}; +static const char MISSING_PNG_EXT_s[]={"File extension not '.png'. Goon?"}; +static const char AREA_s[]={"Area:"}; +static const char FILENAME_TOO_LONG_s[]={"filename too long. Ignored."}; + +static const char EXIT_s[]={"Exit"}; +static const char STOP_s[]={"Stop"}; +static const char GOON_s[]={"Go on"}; +static const char RESTART_s[]={"Restart"}; +static const char FORWARD_s[]={"Step @>"}; +static const char BACKWARD_s[]={"@< Step"}; +static const char CLOSEFILE_s[]={"Close"}; +static const char BROWSE_s[]={"Browse"}; +static const char START_s[]={"Start:"}; +static const char ALLFRAMES_s[]={"Frames:"}; +static const char ALLTRACKS_s[]={"Tracks:"}; +static const char FILENAME_s[]={"File:"}; +static const char BLEND_s[]={"Blend"}; +static const char SHOW_s[]={"Show"}; +static const char LAYERS_s[]={"Layer:"}; +static const char WAITPLEASE_s[]={"Please, wait ..."}; +static const char SUCCESS_WITH_s[]={"Success with file:"}; +static const char FAILURE_WITH_s[]={"Failure with file:"}; +static const char POPUP_EXIT_s[]={"_Exit"}; +static const char PRINT_s[]={"Print"}; +static const char CANNOT_OPEN_s[]={"Can not open file:"}; +static const char GAMMA_s[]={"Gamma:"}; +static const char BRIGHTNESS_s[]={"Brightness:"}; +static const char CONTRAST_s[]={"Contrast:"}; +static const char CANCEL_s[]={"Cancel"}; +static const char CROP_s[]={"Section"}; +static const char LAYER_s[]={"Layer:"}; +static const char COMPONENT_s[]={"Component:"}; +#endif + +#ifdef WITH_GERMAN +static const char LAYER_s[]={"Schicht:"}; +static const char COMPONENT_s[]={"Komponente:"}; +static const char PRINT_s[]={"Drucken"}; +static const char POPUP_EXIT_s[]={"_Abbruch"}; +static const char CANNOT_OPEN_s[]={"Kann Datei nicht öffnen:"}; +static const char SUCCESS_WITH_s[]={"Erfolg mit Datei:"}; +static const char FAILURE_WITH_s[]={"Fehler mit Datei:"}; +static const char EXIT_s[]={"Abbruch"}; +static const char STOP_s[]={"Anhalten"}; +static const char GOON_s[]={"Weiter"}; +static const char RESTART_s[]={"Neustart"}; +static const char FORWARD_s[]={"Schritt @>"}; +static const char BACKWARD_s[]={"@< Schritt"}; +static const char CLOSEFILE_s[]={"Ende"}; +static const char BROWSE_s[]={"Suchen"}; +static const char START_s[]={"Start:"}; +static const char ALLFRAMES_s[]={"Rahmen:"}; +static const char ALLTRACKS_s[]={"Tracks:"}; +static const char FILENAME_s[]={"Datei:"}; +static const char BLEND_s[]={"Mischen"}; +static const char SHOW_s[]={"Zeigen"}; +static const char LAYERS_s[]={"Schicht:"}; +static const char WAITPLEASE_s[]={"Bitte warten ..."}; +static const char GAMMA_s[]={"Gamma:"}; +static const char BRIGHTNESS_s[]={"Helligkeit:"}; +static const char CONTRAST_s[]={"Kontrast:"}; +static const char CANCEL_s[]={"Abbruch"}; +static const char CROP_s[]={"Ausschnitt"}; + +static const char CANNOT_USE_FILE_s[]= {"Kann Datei nicht verwenden"}; +static const char NO_DRIVER_FOUND_s[]= {"KEIN TREIBER GEFUNDEN"}; +static const char FILE_NOT_FOUND_s[]= {"Datei nicht gefunden"}; +static const char CANNOT_LOAD_FILE_s[]= {"Kann Datei nicht laden"}; +static const char FILESIZE_TOO_LONG_s[]={"Datei ist zu groß. Ignoriert."}; +static const char NO_FILE_TO_PRINT_s[]={"Keine druckbare Datei gefunden."}; +static const char FILE_SIZE_ZERO_s[]={"Datei-Länge ist 0"}; +static const char USE_SYSTEM_COMMAND_TO_PRINT_s[]= + {"Bitte System-Befehl(e) benutzen,\num folgende Datei zu drucken:"}; +static const char TILE_s[]={"Kachel:"}; +static const char OF_s[]={" von "}; +static const char RELOAD_s[]={"Neu laden"}; +static const char REDUCTION_s[]={"Verkleinerung:"}; +static const char NO_FILE_TO_SAVE_s[]={"Keine Datei zum Sichern gefunden"}; +static const char SAVE_AS_PNG_s[]={"Sichern als PNG"}; +static const char ENTER_PNG_TO_SAVE_s[]= + {"Einen Name eingeben für eine PNG Datei:"}; +static const char FILE_EXISTS_s[]= + {"Datei besteht bereits.\n Weiter?"}; +static const char SAVE_AS_OPJ_s[]={"Sichern als JP2/J2K"}; +static const char ENTER_OPJ_TO_SAVE_s[]= + {"Einen Name eingeben für eine JP2/J2K Datei:"}; +static const char MISSING_PNG_EXT_s[]={"Datei-Endung nicht '.png'. Weiter?"}; +static const char AREA_s[]={"Fläche:"}; +static const char FILENAME_TOO_LONG_s[]={"Datei-Name zu lang. Ignoriert."}; + +#endif + +#endif /* _FLIMAGE_LANG_H_ */ diff --git a/src/bin/fltk/flviewer/paper_sizes.hh b/src/bin/fltk/flviewer/paper_sizes.hh new file mode 100644 index 00000000..b9b9c844 --- /dev/null +++ b/src/bin/fltk/flviewer/paper_sizes.hh @@ -0,0 +1,89 @@ +#ifndef _FLVIEWER_PAPER_SIZES_HH_ +#define _FLVIEWER_PAPER_SIZES_HH_ + +#define PSIZE_POS 1 + +static struct papersize +{ + const char *name; + double paper_w, paper_h; /* in mm */ + const char *media_s; +} paper_sizes[] = { +{"A3", 297, 420, "A3"}, +{"A4", 210, 297, "A4"}, +{"A5", 148, 210, "A5"}, +{"A6", 105, 148, "BBox"}, +{"9x13 cm", 88.9, 127, "BBox"}, /* 3.5x5 inch */ +{"10x15 cm", 101.6, 152.4, "BBox"}, /* 4x6 inch */ +{"PHOTO4.5x6", 114.3, 152.4, "BBox"}, /* digital cameras */ +{"13x18 cm", 127, 177.8, "BBox"}, /* 5x7 inches */ +{"20x25 cm", 203.2, 254, "BBox"}, /* 8x10 inches */ +{"LETTER", 215.9, 297.4, "letter"}, /* 8.5x11 inches */ +{"LEDGER", 279.4, 431.8, "ledger"}, /* 11x17 inches */ +{"LEGAL", 215.9, 355.6, "legal"}, /* 8.5x14 inches */ +/*-- +{""}, +{""}, +{""}, +--*/ +{NULL, 0, 0, NULL} +}; + +#ifdef INFO_ONLY +/*---------------------- +DOTS MM +media_w = paper_w * (72./25.4); +media_h = paper_h * (72./25.4); + +ISO 216 sizes +(mm × mm) A Series +A0 841 × 1189 +A1 594 × 841 +A2 420 × 594 +A3 297 × 420 +A4 210 × 297 +A5 148 × 210 +A6 105 × 148 +A7 74 × 105 +A8 52 × 74 +A9 37 × 52 +A10 26 × 37 + +ISO 216 sizes +(mm × mm) B Series +B0 1000 × 1414 +B1 707 × 1000 +B2 500 × 707 +B3 353 × 500 +B4 250 × 353 +B5 176 × 250 +B6 125 × 176 +B7 88 × 125 +B8 62 × 88 +B9 44 × 62 +B10 31 × 44 + + +269 sizes +(mm × mm) C Series +C0 917 × 1297 +C1 648 × 917 +C2 458 × 648 +C3 324 × 458 +C4 229 × 324 +C5 162 × 229 +C6 114 × 162 +C7/6 81 × 162 +C7 81 × 114 +C8 57 × 81 +C9 40 × 57 +C10 28 × 40 +DLE 110 × 220 + + + +----------------------*/ +#endif /* INFO_ONLY */ + + +#endif /* _FLVIEWER_PAPER_SIZES_HH_ */ diff --git a/src/bin/fltk/flviewer/print_gui.cxx b/src/bin/fltk/flviewer/print_gui.cxx new file mode 100644 index 00000000..b08dc06c --- /dev/null +++ b/src/bin/fltk/flviewer/print_gui.cxx @@ -0,0 +1,684 @@ +#include +/* + * author(s) and license +*/ +/* + * TODO: background_color other than FL_WHITE for transparent pixels + * TODO: minimal margin: 6.35 mm (18 dots); 6.703 mm (19 dots) +*/ +#ifdef _WIN32 +#include + +#define popen _popen +#define pclose _pclose +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "lang/dialog_lang.h_utf8" +#include "print_gui.hh" +#include "paper_sizes.hh" + +extern char *root_dir; +/* configurable option ? */ +#define SHOW_PRINTER_LOC + +#define LOCAL_PRINTER + +#ifdef LOCAL_PRINTER +#define LOCAL_CMD "pdq -P" +#define LOCAL_NAME "postscript" +#define LOCAL_LOC "Kyocera FS-920" +#endif + +#define PNAME_POS 0 +#define PRINT_CMD "lpr -P" + +#define WIN_W 640 +#define WIN_H 380 +#define TAB_W (WIN_W - 10) +#define GROUP_W TAB_W +#define GROUP_H (WIN_H - 60) +#define BOX_W (GROUP_W - 10) + + +/* lpadmin -L "location" */ + +typedef struct printer_info +{ + char *cmd; + char *name; + char *loc; +}PrinterInfo; + +static PrinterInfo *printer_info; + +static void fill_paper_size(PrintInfo *print) +{ + Fl_Choice *c = print->paper_size; + int i; + + i = 0; + while(paper_sizes[i].name) + { + c->add(paper_sizes[i].name); + ++i; + } + c->value(PSIZE_POS); + print->paper_size_pos = PSIZE_POS; +} + +static void paper_size_cb(Fl_Widget *wid, void *v) +{ + PrintInfo *print = (PrintInfo*)v; + print->paper_size_pos = print->paper_size->value(); +} + +static PrinterInfo *append(PrinterInfo *tab, const char *n) +{ + const char *o; + int i = 0; + + if(tab) + { + while((o = tab[i].name)) + { + if(strcmp(o, n) == 0) return tab; + ++i; + } + } + tab = (PrinterInfo*)realloc(tab, (i+2)*sizeof(PrinterInfo)); + + tab[i].cmd = strdup(PRINT_CMD); + tab[i].name = strdup(n); + + tab[i].loc = strdup(n); + + tab[i+1].name = NULL; tab[i+1].loc = NULL; tab[i+1].cmd = NULL; + return tab; +} +#ifndef _WIN32 +/* + +lpstat -p + +printer FS_920 is idle. enabled since ... +printer HP_Desk is idle. enabled since ... +*/ +static void add_lpr_printer_names(void) +{ + FILE *p; + char buf[1024]; + + if((p = popen("lpstat -p 2> /dev/null", "r")) == NULL) + { + fputs("\n Can not print\n", stderr); + return; + } + while(fgets(buf, sizeof(buf), p) != NULL) + { + char *start, *end; + + start = buf; + if(strncmp(start, "printer ", 8) != 0) continue; + start += 8; + if(strstr(start, "enabled") == NULL) continue; + end = start; + while(*end && !isspace(*end)) ++end; + *end = 0; + printer_info = append(printer_info, start); + } + pclose(p); +} +#endif /* _WIN32 */ + +static void free_printer_info() +{ + int i = 0; + + while(printer_info[i].name) + { + free(printer_info[i].cmd); + free(printer_info[i].name); + + free(printer_info[i].loc); + + ++i; + } + free(printer_info); + +} + +static void fill_printer_names(PrintInfo *print) +{ + Fl_Choice *c = print->printer_name; + int i = 0; + +#ifdef LOCAL_PRINTER + printer_info = (PrinterInfo*)calloc(2, sizeof(PrinterInfo)); + + + printer_info[0].cmd = strdup(LOCAL_CMD); + printer_info[0].name = strdup(LOCAL_NAME); + printer_info[0].loc = strdup(LOCAL_LOC); +#endif + +#ifndef _WIN32 + add_lpr_printer_names(); +#endif /* _WIN32 */ + + while(printer_info[i].name) + { + c->add(printer_info[i].name); + ++i; + } + c->value(PNAME_POS); + print->printer_pos = PNAME_POS; +} + +static void printer_name_cb(Fl_Widget *w, void *v) +{ + PrintInfo *print = (PrintInfo*)v; + print->printer_pos = print->printer_name->value(); + +#ifdef SHOW_PRINTER_LOC + print->loc->value(printer_info[print->printer_pos].loc); +#endif +} + +static void to_printer_cb(Fl_Widget *wid, void *data) +{ + Fl_Radio_Button *b = (Fl_Radio_Button*)wid; + PrintInfo *print = (PrintInfo*)data; + + if(!b->value()) + { + print->printer_group->deactivate(); + print->file_group->activate(); + print->fname->value("image.ps"); + } + else + { + print->printer_group->activate(); + print->fname->value(""); + print->file_group->deactivate(); + } +} + +static void to_file_cb(Fl_Widget *wid, void *data) +{ + Fl_Radio_Button *b = (Fl_Radio_Button*)wid; + PrintInfo *print = (PrintInfo*)data; + + if(!b->value()) + { + print->fname->value(""); + print->file_group->deactivate(); + print->printer_group->activate(); + } + else + { + print->fname->value("image.ps"); + print->file_group->activate(); + print->printer_group->deactivate(); + } + +} + +static void portrait_cb(Fl_Widget *w, void *data) +{ + PrintInfo *info = (PrintInfo*)data; + info->paper_layout[0] = 'P'; +} + +static void landscape_cb(Fl_Widget *w, void *data) +{ + PrintInfo *info = (PrintInfo*)data; + info->paper_layout[0] = 'L'; +} + +static void lowres_cb(Fl_Widget *w, void *data) +{ + PrintInfo *info = (PrintInfo*)data; + info->resolution = 300; +} + +static void hires_cb(Fl_Widget *w, void *data) +{ + PrintInfo *info = (PrintInfo*)data; + info->resolution = 600; +} + +static void color_cb(Fl_Widget *w, void *data) +{ + PrintInfo *info = (PrintInfo*)data; + info->pcolor[0] = 'C'; +} + +static void gray_cb(Fl_Widget *w, void *data) +{ + PrintInfo *info = (PrintInfo*)data; + info->pcolor[0] = 'G'; +} + +static void ok_cb(Fl_Widget *w, void *data) +{ + PrintInfo *print = (PrintInfo*)data; + const char *cs; + struct stat sb; + + if(print->to_file->value()) + { + cs = print->fname->value(); + if(*cs == 0) + { + fl_message("%s", NO_FILENAME_FOUND_s); + return; + } + if(stat(cs, &sb) == 0) + { + if((sb.st_mode & S_IFMT) == S_IFDIR) + { + fl_message("%s", NAME_IS_DIR_s); + return; + } + if(fl_choice(CONTINUE_PRINT_s, "NO", "YES", NULL) == 0) return; + } + print->fname_s = strdup(cs); + }/* if(print->to_file->value()) */ + else + if(print->to_printer->value()) + { + size_t len = strlen(root_dir) + 20; + + print->printer_s = strdup(print->printer_name->text()); + print->command_s = strdup(printer_info[print->printer_pos].cmd); + + print->fname_s = (char*)malloc(len); +#ifdef _WIN32 + sprintf_s(print->fname_s, len, "%s\\.flimage.ps", root_dir); +#else + snprintf(print->fname_s, len, "%s/.flimage.ps", root_dir); +#endif + print->remove_fname = 1; + }/* if(print->to_printer->value()) */ + + print->format_s = strdup(paper_sizes[print->paper_size_pos].name); + print->media_s = strdup(paper_sizes[print->paper_size_pos].media_s); + print->fpaper_w = paper_sizes[print->paper_size_pos].paper_w; + print->fpaper_h = paper_sizes[print->paper_size_pos].paper_h; + + cs = print->copies->value(); + + if(*cs) + print->nr_copies = atoi(cs); + else + print->nr_copies = 1; + + print->title_s = strdup(print->title->value()); + + print->fmargin_lhs = atof(print->margin_lhs->value()); + print->fmargin_rhs = atof(print->margin_rhs->value()); + print->fmargin_top = atof(print->margin_top->value()); + print->fmargin_bot = atof(print->margin_bot->value()); + + print->center = print->center_image->value(); + if(print->paper_layout[0] == 'L') + print->want_landscape = 1; + else + print->want_portrait = 1; + + if(print-> pcolor[0] == 'C') + print->want_color = 1; + else + print->want_gray = 1; + + if(printer_info) + free_printer_info(); + + delete print->win; + + print->ok = 1; + + print->win_destroy = 1; + +}/* ok_cb() */ + +static void cancel_cb(Fl_Widget *, void *data) +{ + PrintInfo *print = (PrintInfo*)data; + + if(printer_info) + free_printer_info(); + + delete print->win; + + print->ok = 0; + + print->win_destroy = 1; +} + +void Print_gui_create(PrintInfo *print) +{ + Fl_Window* win; + Fl_Group *page1; + int x, y, group_x, group_y, top_y, lhs_x; + int label_x, label_y; + + print->win = win = new Fl_Window(WIN_W, WIN_H); + win->box(FL_FLAT_BOX); + win->color(FL_BACKGROUND_COLOR); + win->begin(); + + group_x = 0; group_y = 20; + + page1 = new Fl_Group(group_x, group_y, GROUP_W, GROUP_H, PRINTERPAGE_s); + page1->box(FL_FLAT_BOX); + page1->color(FL_BACKGROUND_COLOR); + page1->labelfont(FL_HELVETICA_BOLD_ITALIC); + page1->labelsize(13); + page1->labelcolor(FL_BLACK); + page1->begin(); + + group_x += 4; group_y += 12; + { + Fl_Group *format; + + x = group_x; y = group_y; + format = new Fl_Group(x, y, GROUP_W-6, 96); + format->box(FL_EMBOSSED_BOX); + format->begin(); + + x += 10; y -= 10; + label_x = x; label_y = y; + lhs_x = group_x; top_y = group_y + 12; + x = lhs_x; y = top_y; + { + Fl_Round_Button *o; + Fl_Group *g = new Fl_Group(x, y, 150, 40); + g->begin(); + x += 3; y += 0; + + Fl_Round_Button *r1 = new Fl_Round_Button(x, y, 150, 20, COLOR_s); + r1->type(FL_RADIO_BUTTON); + r1->callback(color_cb, print); + r1->clear_visible_focus(); + print->color = r1; + + y += 20; + o = new Fl_Round_Button(x, y, 150, 20, GRAY_s); + o->value(1); + o->type(FL_RADIO_BUTTON); + print->pcolor[0] = 'G'; + o->callback(gray_cb, print); + o->clear_visible_focus(); + print->gray = o; + g->end(); + y = g->y() + g->h(); + } + x = lhs_x; + { + Fl_Round_Button *o; + Fl_Group *g = new Fl_Group(x, y, 150, 40); + g->begin(); + + x += 3; y += 0; + o = new Fl_Round_Button(x, y, 150, 20, LOWRES_s); + o->callback(lowres_cb, print); + o->type(FL_RADIO_BUTTON); + o->value(1); + o->clear_visible_focus(); + print->resolution = 300; + print->lowres = o; + + y += 20; + o = new Fl_Round_Button(x, y, 150, 20, HIRES_s); + o->type(FL_RADIO_BUTTON); + o->callback(hires_cb, print); + o->clear_visible_focus(); + print->hires = o; + + g->end(); + x = g->x() + g->w() + 10; + } + y = top_y; + print->paper_size = new Fl_Choice(x,y,110,23); + print->paper_size->clear_visible_focus(); + fill_paper_size(print); + print->paper_size->callback(paper_size_cb, print); + + y = top_y; x = format->w() - 154; + { + Fl_Round_Button *o; + Fl_Group *g = new Fl_Group(x, y, 150, 40); + g->begin(); + + x += 0; y += 0; + o = new Fl_Round_Button(x, y, 150, 20, PORTRAIT_s); + o->type(FL_RADIO_BUTTON); + o->callback(portrait_cb, print); + o->value(1); + o->clear_visible_focus(); + print->paper_layout[0] = 'P'; + print->portrait = o; + + y += 20; + o = new Fl_Round_Button(x, y, 150, 20, LANDSCAPE_s); + o->type(FL_RADIO_BUTTON); + o->callback(landscape_cb, print); + o->clear_visible_focus(); + print->landscape = o; + + g->end(); + y = g->y() + g->h(); + } + x = format->w() - 150; + print->center_image = new Fl_Check_Button(x, y, 25, 25, CENTER_s); + print->center_image->clear_visible_focus(); + + format->end(); + group_y = format->y() + format->h() + 12; + { + Fl_Group *c = new Fl_Group(label_x, label_y, 100, 20, DOCFORMAT_s); + c->box(FL_EMBOSSED_BOX); + c->align(FL_ALIGN_INSIDE); + c->end(); + } + } + x = group_x; y = group_y; + { + Fl_Group *g; + g = new Fl_Group(x, y, 178, 38); + g->box(FL_EMBOSSED_BOX); + g->begin(); + + label_x = x+10; label_y = y-10; + x += 7; y += 12; + { + Fl_Round_Button *o = new Fl_Round_Button(x, y, 96, 22, PRINTER_s); + o->type(FL_RADIO_BUTTON); + o->callback(to_printer_cb, print); + o->value(1); + o->clear_visible_focus(); + print->to_printer = o; + } + x += 100; + { + Fl_Round_Button *o = new Fl_Round_Button(x, y, 67, 22, FILE_s); + o->type(FL_RADIO_BUTTON); + o->callback(to_file_cb, print); + o->clear_visible_focus(); + print->to_file = o; + } + g->end(); + x = g->x() + g->w() + 1; + { + Fl_Group *c = new Fl_Group(label_x, label_y, 100, 20, PRINTTO_s); + c->box(FL_EMBOSSED_BOX); + c->align(FL_ALIGN_INSIDE); + c->end(); + } + } + y = group_y; + { + Fl_Group *g; + g = new Fl_Group(x, y, GROUP_W-x-4, 40); + g->box(FL_EMBOSSED_BOX); + g->begin(); + + label_x = x+10; label_y = y-10; + x += 70; y += 12; + { + print->copies = new Fl_Int_Input(x, y, 50, 24, COPIES_s); + print->copies->value("1"); + } + x += 130; + { + print->title = new Fl_Input(x, y, g->x() + g->w()-x-4, 24, TITLE_s); + print->title->value("No title"); + } + g->end(); + group_y = g->y() + g->h() + 12; + { + Fl_Group *c = new Fl_Group(label_x, label_y, 100, 20, PRINT_s); + c->box(FL_EMBOSSED_BOX); + c->align(FL_ALIGN_INSIDE); + c->end(); + } + } + x = group_x; y = group_y; + print->printer_group = new Fl_Group(x, y-10, GROUP_W-6, 50); + print->printer_group->begin(); + { + Fl_Choice *o; + Fl_Group *g; + g = new Fl_Group(x, y, GROUP_W-6, 40); + g->box(FL_EMBOSSED_BOX); + g->begin(); + + label_x = x+10; label_y = y-10; + x += 120; y += 12; + o = new Fl_Choice(x, y, 140, 24, PRINTERNAMES_s); + o->align(FL_ALIGN_LEFT); + o->callback(printer_name_cb, print); + print->printer_name = o; + + fill_printer_names(print); + +#ifdef SHOW_PRINTER_LOC + x += 240; + print->loc = new Fl_Output(x, y, 140, 24, LOC_s); + print->loc->value(printer_info[print->printer_pos].loc); + print->loc->clear_visible_focus(); +#endif + g->end(); + { + Fl_Group *c = new Fl_Group(label_x, label_y, 100, 20, PRINTER_s); + c->box(FL_EMBOSSED_BOX); + c->align(FL_ALIGN_INSIDE); + c->end(); + } + } + print->printer_group->end(); + group_y = print->printer_group->y() + print->printer_group->h() + 12; + + x = group_x; y = group_y; + print->file_group = new Fl_Group(x, y-10, GROUP_W-6, 50); + print->file_group->deactivate(); + print->file_group->begin(); + { + Fl_Group *g; + g = new Fl_Group(x, y, GROUP_W-6, 40); + g->box(FL_EMBOSSED_BOX); + g->begin(); + + label_x = x+10; label_y = y-10; + x += 120; y += 12; + print->fname = new Fl_Input(x, y, 280, 24, NAME_s); + + g->end(); + { + Fl_Group *c = new Fl_Group(label_x, label_y, 100, 20, FILE_s); + c->box(FL_EMBOSSED_BOX); + c->align(FL_ALIGN_INSIDE); + c->end(); + } + + } + print->file_group->end(); + group_y = print->file_group->y() + print->file_group->h() + 12; + + x = group_x; y = group_y; + { + Fl_Group *g = new Fl_Group(x, y, GROUP_W-6, 40); + g->box(FL_EMBOSSED_BOX); + g->begin(); + + label_x = x+10; label_y = y-10; + x += 80; y += 12; + print->margin_lhs = new Fl_Float_Input(x, y, 50, 24, LEFT_s); + print->margin_lhs->value("25.51"); + + x += 130; + print->margin_rhs = new Fl_Float_Input(x, y, 50, 24, RIGHT_s); + print->margin_rhs->value("6.35"); + + x += 130; + print->margin_top = new Fl_Float_Input(x, y, 50, 24, TOP_s); + print->margin_top->value("6.35"); + + x += 130; + print->margin_bot = new Fl_Float_Input(x, y, 50, 24, BOTTOM_s); + print->margin_bot->value("6.35"); + + g->end(); + { + Fl_Group *c = new Fl_Group(label_x, label_y, 100, 20, MARGINS_s); + c->box(FL_EMBOSSED_BOX); + c->align(FL_ALIGN_INSIDE); + c->end(); + } + + } + page1->end(); + + y = WIN_H - 35; + int dx = (WIN_W - 200)/3; + x = dx; + { + Fl_Button* o = new Fl_Button(x, y, 100, 30, PRINT_s); + o->callback(ok_cb, print); + } + x += 100 + dx; + { + Fl_Button* o = new Fl_Button(x, y, 100, 30, CANCEL_s); + o->color(FL_YELLOW); + o->callback(cancel_cb, print); + } + win->end(); + win->show(); + + while( !print->win_destroy) + Fl::wait(1.0); + +}/* Print_gui_create() */ diff --git a/src/bin/fltk/flviewer/print_gui.hh b/src/bin/fltk/flviewer/print_gui.hh new file mode 100644 index 00000000..3f78fb96 --- /dev/null +++ b/src/bin/fltk/flviewer/print_gui.hh @@ -0,0 +1,48 @@ +#ifndef _FLVIEWER_PRINT_GUI_HH_ +#define _FLVIEWER_PRINT_GUI_HH_ + +#include +#include +#include + +typedef struct print_info +{ + Fl_Window* win; + + Fl_Choice *paper_size, *printer_name; + Fl_Round_Button *portrait, *landscape; + + Fl_Round_Button *lowres, *hires; + + Fl_Round_Button *color, *gray; + + Fl_Group *printer_group, *file_group; + Fl_Round_Button *to_printer, *to_file; + + Fl_Output *loc; + + Fl_Input *title, *fname; + Fl_Button *center_image; + Fl_Int_Input *copies; + Fl_Float_Input *margin_lhs, *margin_rhs, *margin_top, *margin_bot; + + char ok, remove_fname, center; + char want_portrait, want_landscape, want_color, want_gray; + int resolution, nr_copies; + int paper_size_pos, printer_pos; + int win_destroy; + + char paper_layout[2]; + char pcolor[2]; + + double fmargin_lhs, fmargin_rhs, fmargin_top, fmargin_bot; + double fpaper_w, fpaper_h; + char *fname_s, *command_s, *title_s, *printer_s, *format_s; + char *media_s; + +} PrintInfo; + + +void Print_gui_create(PrintInfo *p); + +#endif /* _FLVIEWER_PRINT_GUI_HH_ */ diff --git a/src/bin/fltk/flviewer/ps_image.cxx b/src/bin/fltk/flviewer/ps_image.cxx new file mode 100644 index 00000000..a8804701 --- /dev/null +++ b/src/bin/fltk/flviewer/ps_image.cxx @@ -0,0 +1,632 @@ +#include +/* + * Author(s): Ameet A. Raval, Frans van Hoesel, Andrew Ford, szukw000 + * + * NOTE: rle16(): files can be sufficiently shorter + * if the image has a small number of colors. + * rle8() : extends the file. +*/ +#include +#include +#include +#include +#include + + +#include "ps_image.hh" + +#define MAX_COL 12 +#define TM_BASE_YEAR 1900 + +/* RLE values */ +#define USHORT_BLOCK_MASK 0x8000 +#define USHORT_BLOCK_LEN 21845 +#define USHORT_MAX_INDEX 21845 + +#define UCHAR_MAX_INDEX 256 + +#define FULLY_TRANSPARENT 0 +#define FULLY_OPAQUE 255 + +static void ps_print_hex(PSInfo *ps, unsigned short val, int flush) +{ + static unsigned char hexline[128]; + static unsigned char digit[] = "0123456789abcdef"; + + if(!flush) + { + hexline[ps->PS_hexi++] = (unsigned char) + digit[((unsigned) val >>(unsigned) 4) & (unsigned) 0x0f]; + hexline[ps->PS_hexi++] = (unsigned char) + digit[(unsigned) val & (unsigned) 0x0f]; + } + if((flush && ps->PS_hexi) || (ps->PS_hexi >77)) + { + hexline[ps->PS_hexi] = '\0'; + ps->PS_hexi = 0; + fprintf(ps->writer, "%s\n", hexline); + } +} + +struct ps_color +{ + unsigned char red, green, blue; + unsigned char dirty; +}; + +static unsigned char *mono_to_rgb(PSInfo *ps) +{ + unsigned char *buf, *d, *s; + unsigned int i, max; + + max = ps->image_w * ps->image_h; + buf = (unsigned char*)malloc(max * 3); + d = buf; s = ps->src_buf; + + for(i = 0; i < max; ++i) + { + *d++ = *s; *d++ = *s; *d++ = *s; ++s; + } + return buf; +} + +/* rgba_to_rgb() uses the alpha_composite()-code from : + * libpng-VERSION/contrib/gregbook/rpng2-x.c +*/ +static unsigned char *rgba_to_rgb(PSInfo *ps) +{ + unsigned char *buf, *d, *s; + unsigned int i, max; + unsigned char bg_red, bg_green, bg_blue; + unsigned short red, green, blue, alpha, c; + + bg_red = ps->bg_red; bg_green = ps->bg_green; bg_blue = ps->bg_blue; + max = ps->image_w * ps->image_h; + buf = (unsigned char*)malloc(max * 3); + d = buf; s = ps->src_buf; + + for(i = 0; i < max; ++i) + { + red = (unsigned short)*s++; + green = (unsigned short)*s++; + blue = (unsigned short)*s++; + alpha = (unsigned short)*s++; + + if(alpha == FULLY_OPAQUE) + { + *d++ = (unsigned char)red; + *d++ = (unsigned char)green; + *d++ = (unsigned char)blue; + continue; + } + if(alpha == FULLY_TRANSPARENT) + { + *d++ = bg_red; + *d++ = bg_green; + *d++ = bg_blue; + continue; + } +/* transition */ + c = red * alpha + + (unsigned short)bg_red * (FULLY_OPAQUE - alpha) + 128; + *d++ = (unsigned char)((c + (c>>8))>>8); + + c = green * alpha + + (unsigned short)bg_green * (FULLY_OPAQUE - alpha) + 128; + *d++ = (unsigned char)((c + (c>>8))>>8); + + c = blue * alpha + + (unsigned short)bg_blue * (FULLY_OPAQUE - alpha) + 128; + *d++ = (unsigned char)((c + (c>>8))>>8); + + }/* for(i ) */ + + return buf; +} + +/* + * Run-Length-Encoding of image. + * RLE is done to reduce the file size and therefore the time to send + * the file to the printer. You get longer processing time instead. + * + * RLE is encoded as such: + * # 'run' of count+1 equal pixels + * # count+1 non-equal pixels + * count can range between 0 and 127 for uchar + * and between 0 and 21845 for ushort + * + * returns the length of the RLE line vector + * + * Implementation Limits of PostScript: 'string' 65535 + * + * max. triple: 21845 + * + * Depending of the image size the encoding is split into: + * + * if len is <= 2^16 - 1: rle16_encode() +*/ + +static int rle16_encode(unsigned short *scanline, + unsigned short *rleline, unsigned short *block, int wide) +{ + int i, j, rlen; + unsigned short blocklen, isrun; + unsigned short pix; + + blocklen = isrun = 0; rlen = 0; + + for(i = 0; i < wide; i++) + { +/* there are 5 possible states: + * 0: block empty. + * 1: block is a run, current pix == previous pix + * 2: block is a run, current pix != previous pix + * 3: block not a run, current pix == previous pix + * 4: block not a run, current pix != previous pix +*/ + pix = scanline[i]; + if(!blocklen) + { +/* case 0: empty +*/ + block[blocklen++] = pix; + isrun = 1; + } + else + if(isrun) + { + if(pix == block[blocklen-1]) + { +/* case 1: isrun, prev == cur +*/ + block[blocklen++] = pix; + } + else + { +/* case 2: isrun, prev != cur +*/ + if(blocklen>1) + { +/* we have a run block to flush */ + rleline[rlen++] = blocklen-1; + rleline[rlen++] = block[0]; +/* start new run block with pix */ + block[0] = pix; + blocklen = 1; + } + else + { +/* blocklen<=1, turn into non-run */ + isrun = 0; + block[blocklen++] = pix; + } + } + } + else + { +/* not a run */ + if(pix == block[blocklen-1]) + { +/* case 3: non-run, prev == cur +*/ + if(blocklen>1) + { +/* have a non-run block to flush */ + rleline[rlen++] = (blocklen-1) | USHORT_BLOCK_MASK; + for(j=0; jwriter, "/cmap %d string def\n\n\n", nc * 3); + +/* load up the colormap */ + fputs("currentfile cmap readhexstring\n", ps->writer); + + for(i=0; i < nc; i++) + { + fprintf(ps->writer, "%02x%02x%02x", ps_colors[i].red, + ps_colors[i].green, ps_colors[i].blue); + + if((i%(MAX_COL+1)) == MAX_COL) fputs("\n", ps->writer); + } +/* lose return values from readhexstring */ + fputs("\npop pop\n", ps->writer); + +}/* write_colormap() */ + +static int create_image_data(PSInfo *ps, unsigned char *src_buf, + struct ps_color **out_colors, unsigned short **out_dst, + int *out_dst_len) +{ + unsigned char *src; + struct ps_color *ps_colors; + unsigned short *dst; + unsigned int src_len, dst_len, i, free_index; + unsigned int r, g, b; + + src = src_buf; + src_len = ps->image_w * ps->image_h * 3; + + i = (src_len/3) * (unsigned int)sizeof(struct ps_color); + + dst = (unsigned short*)calloc(1, i); + + ps_colors = (struct ps_color*)calloc(1, i); + + dst_len = 0; *out_dst = dst; *out_colors = ps_colors; + + ps_colors[0].red = *src++; + ps_colors[0].green = *src++; + ps_colors[0].blue = *src++; + free_index = 1; + src_len -= 3; *dst++ = 0; dst_len = 1; + + while(src_len > 0) + { + r = *src++; g = *src++; b = *src++; src_len -= 3; + i = (r<<3) + (r>>11) + g; + i = (i<<3) + (i>>23) + b; + i %= free_index; + + while(i < free_index) + { + if(ps_colors[i].dirty == 0) + { + ps_colors[i].red = (unsigned char)r; + ps_colors[i].green = (unsigned char)g; + ps_colors[i].blue = (unsigned char)b; + ps_colors[i].dirty = 1; + break; + } + if(r == ps_colors[i].red + && g == ps_colors[i].green + && b == ps_colors[i].blue) + break; + ++i; + } + if(i == free_index) + { + if(++free_index == USHORT_MAX_INDEX) + { +/* no colormap, no ps_colors */ + break; + } + ps_colors[i].red = (unsigned char)r; + ps_colors[i].green = (unsigned char)g; + ps_colors[i].blue = (unsigned char)b; + ps_colors[i].dirty = 1; + } + *dst++ = i; ++dst_len; + }/* while(src_len > 0) */ + + *out_dst_len = dst_len; + + return free_index; +}/* create_image_data() */ + +const char *prolog_open_cs = +"%%!PS-Adobe-3.0\n" +"%%%%Creator: %s\n" +"%%%%Title: %s\n" +"%%%%LanguageLevel: 2\n" +"%%%%CreationDate: %s\n" +"%%%%Pages: 1\n" +"%%%%PageOrder: Ascend\n"; + +const char *rle16_cs = +"/RLECMAPIMAGE16 { /buffer 2 string def /rgbval 3 string def\n" +" /block 65535 string def\n" +" { currentfile buffer readhexstring pop pop\n" +" /bcount buffer 0 get 256 mul buffer 1 get add store\n" +" bcount 32768 ge\n" +" {\n" +" 0 1 bcount 32768 sub\n" +" { currentfile buffer readhexstring pop pop\n" +" /mapidx buffer 0 get 256 mul buffer 1 get add 3 mul store\n" +" /rgbval cmap mapidx 3 getinterval store\n" +" block exch 3 mul rgbval putinterval\n" +" } for\n" +" block 0 bcount 32767 sub 3 mul getinterval\n" +" }\n" +" {\n" +" currentfile buffer readhexstring pop pop\n" +" /mapidx buffer 0 get 256 mul buffer 1 get add 3 mul store\n" +" /rgbval cmap mapidx 3 getinterval store\n" +" 0 1 bcount { block exch 3 mul rgbval putinterval } for\n" +" block 0 bcount 1 add 3 mul getinterval\n" +" } ifelse\n" +" }\n" +" false 3 colorimage\n" +"} bind def\n"; + +const char *ps_date(void) +{ + static char buf[128]; + struct tm *stm; + time_t t; + + t = time(NULL); + stm = localtime(&t); +#ifdef _WIN32 + sprintf_s(buf, 128, "%4d-%02d-%02d", + stm->tm_year + TM_BASE_YEAR, stm->tm_mon+1, stm->tm_mday); +#else + snprintf(buf, 128, "%4d-%02d-%02d", + stm->tm_year + TM_BASE_YEAR, stm->tm_mon+1, stm->tm_mday); +#endif + + return buf; +} + +static void write_header(PSInfo *ps, int max_index) +{ + double lhs, top, rhs, bot, box_w, box_h, x, y; + const char *moveto; + + fprintf(ps->writer, prolog_open_cs, PACKAGE_STRING, ps->title_s, + ps_date()); + + lhs = ps->fmargin_lhs; + top = ps->fmargin_top; + rhs = ps->fmargin_rhs; + bot = ps->fmargin_bot; + + if(ps->portrait) + { + box_w = ps->fmedia_w - lhs - rhs; + box_h = ps->fmedia_h - top - bot; + ps->fscale_w = ps->image_w; ps->fscale_h = ps->image_h; + + if(ps->fscale_w > box_w) + { + ps->fscale_w = box_w; + ps->fscale_h = box_w * (double)ps->image_h/(double)ps->image_w; + } + else + if(ps->fscale_h > box_h) + { + ps->fscale_w = box_h * (double)ps->image_h/(double)ps->image_w; + ps->fscale_h = box_h; + } + x = lhs; y = box_h + bot; + + if(ps->center) + { + if(ps->fscale_h < box_h) y -= (box_h - ps->fscale_h)/2.; + if(ps->fscale_w < box_w) x += (box_w - ps->fscale_w)/2.; + } + fprintf(ps->writer, "%%%%Orientation: Portrait\n" + "%%%%BoundingBox: %d %d %d %d\n" + "%%%%DocumentMedia: %s %d %d 0 () ()\n", + (int)lhs, (int)top, (int)box_w, (int)box_h, + ps->media_s, (int)ps->fmedia_w, (int)ps->fmedia_h); + + moveto = "save\n%.4f %.4f moveto\n"; + } + else + { + assert(ps->landscape); + + box_w = ps->fmedia_w - lhs - rhs; + box_h = ps->fmedia_h - top - bot; + ps->fscale_w = ps->image_w; ps->fscale_h = ps->image_h; + + if(ps->fscale_h > box_w) + { + ps->fscale_w = box_w * (double)ps->image_w/(double)ps->image_h; + ps->fscale_h = box_w; + } + else + if(ps->fscale_w > box_h) + { + ps->fscale_w = box_h; + ps->fscale_h = box_h * (double)ps->image_w/(double)ps->image_h; + } + x = lhs; y = bot; + + if(ps->center) + { + if(ps->fscale_h < box_w) x += (box_w - ps->fscale_h)/2.; + if(ps->fscale_w < box_h) y += (box_h - ps->fscale_w)/2.; + } + fprintf(ps->writer, "%%%%Orientation: Landscape\n" + "%%%%BoundingBox: %d %d %d %d\n" + "%%%%DocumentMedia: %s %d %d 0 () ()\n", + (int)lhs, (int)top, (int)box_w, (int)box_h, + ps->media_s, (int)ps->fmedia_w, (int)ps->fmedia_h); + + moveto = "save\n%.4f %.4f translate 90 rotate 0. 0. moveto\n"; + + } + fputs("%%EndComments\n%%BeginProlog\n", ps->writer); + + if(max_index < USHORT_MAX_INDEX) + fputs(rle16_cs, ps->writer); + + fputs("%%EndProlog\n%%BeginSetup\n%%EndSetup\n%%Page: 1 1\n" + "%%BeginPageSetup\n%%EndPageSetup\n", ps->writer); + + fprintf(ps->writer, moveto, x, y); +#ifdef DEBUG +fprintf(stderr,"%s:%d:write_header\n\tMARGINS(%.4f,%.4f,%.4f,%.4f)\n\t" +"BOX w(%.4f) h(%.4f) SCALE w(%.4f) h(%.4f)\n\tX(%.4f) Y(%.4f)\n", +__FILE__,__LINE__, top,rhs,bot,lhs,box_w,box_h,ps->fscale_w, +ps->fscale_h,x,y); +#endif +}/* write_header() */ + +int PS_image_draw(PSInfo *ps) +{ + struct ps_color *ps_colors; + unsigned short *dst_buf, *src; + unsigned char *rgb_buf; + int i, j, width, height, rle_len, dst_len; + int max_index; + + width = ps->image_w; + height = ps->image_h; + dst_buf = NULL; ps_colors = NULL; + + if(ps->image_channels == 1) + rgb_buf = mono_to_rgb(ps); + else + if(ps->image_channels == 4) + rgb_buf = rgba_to_rgb(ps); + else + rgb_buf = ps->src_buf; + + max_index = + create_image_data(ps, rgb_buf, &ps_colors, &dst_buf, &dst_len); + + if(max_index == 0) + { + if(ps->image_channels != 3) free(rgb_buf); + + if(dst_buf) free(dst_buf); + + return 0; + } +/* small images without colormap: +*/ + if(max_index < UCHAR_MAX_INDEX) + max_index = USHORT_MAX_INDEX; + + write_header(ps, max_index); + + fprintf(ps->writer, "20 dict begin\n/pix %d string def\n\n", width * 3); + +/* position and scaling +*/ + fprintf(ps->writer, "gsave currentpoint %.4f sub translate" + " %.4f %.4f scale\n", ps->fscale_h, ps->fscale_w, ps->fscale_h); + + if(max_index < USHORT_MAX_INDEX) + { + write_colormap(ps, max_index, ps_colors); + } + fprintf(ps->writer, "%d %d 8\n", width, height); + +/* mapping matrix +*/ + fprintf(ps->writer, "[%d 0 0 -%d 0 %d]\n", width, height, height); + + if(max_index < USHORT_MAX_INDEX) + { + unsigned short *rle_line, val; + unsigned short *block; + + fputs("RLECMAPIMAGE16\n", ps->writer); + + rle_line = (unsigned short*) malloc(width * 2 * sizeof(unsigned short)); + block = (unsigned short*) malloc(width * sizeof(unsigned short)); + + src = dst_buf; + + for(i=0; i < height; i++) + { + rle_len = rle16_encode(src, rle_line, block, width); + src += width; + j = -1; + + while(++j < rle_len) + { + val = rle_line[j]; + ps_print_hex(ps, val>>8, 0); + ps_print_hex(ps, val%256, 0); + } + ps_print_hex(ps, '\0', 1); /* Flush the hex buffer */ + } + free(rle_line); free(block); + } + else /* max_index >= USHORT_MAX_INDEX */ + { + unsigned char *src; + int col, src_len; + + fputs("{currentfile pix readhexstring pop}\n" + "false 3 colorimage\n", ps->writer); + + src = rgb_buf; src_len = width * height * 3; + col = 0; + + while(src_len > 0) + { + fprintf(ps->writer, "%02x%02x%02x", src[0], src[1], src[2]); + src += 3; src_len -= 3; + if(++col > MAX_COL) + { + fputs("\n", ps->writer); col = 0; + } + } + } + if(ps->image_channels != 3) + free(rgb_buf); + free(dst_buf); free(ps_colors); + + fputs("end\ngrestore\nrestore\nshowpage\n%%Trailer\n%%EOF\n", ps->writer); + + return 1; +} /* PS_image_write() */ diff --git a/src/bin/fltk/flviewer/ps_image.hh b/src/bin/fltk/flviewer/ps_image.hh new file mode 100644 index 00000000..d09cdc83 --- /dev/null +++ b/src/bin/fltk/flviewer/ps_image.hh @@ -0,0 +1,31 @@ +#ifndef _FLVIEWER_PS_IMAGE_HH_ +#define _FLVIEWER_PS_IMAGE_HH_ + +typedef struct psinfo +{ + char portrait, landscape, center; + char *format; +/* Normally bg_red = bg_green = bg_blue = 255: +*/ + unsigned char bg_red, bg_green, bg_blue; + + unsigned char *src_buf; + char *title_s; + char *media_s; + + int image_channels; + int image_w, image_h; + + double fmedia_w, fmedia_h; + double fmargin_top, fmargin_rhs, fmargin_bot, fmargin_lhs; + double fscale_w, fscale_h; + + int PS_hexi; + + FILE *writer; +} PSInfo; + + +extern int PS_image_draw(PSInfo *psi); + +#endif /* _FLVIEWER_PS_IMAGE_HH_ */ diff --git a/src/bin/fltk/flviewer/read_jpeg2000.cxx b/src/bin/fltk/flviewer/read_jpeg2000.cxx new file mode 100644 index 00000000..74b3238b --- /dev/null +++ b/src/bin/fltk/flviewer/read_jpeg2000.cxx @@ -0,0 +1,3509 @@ +#include +/* + * author(s) and license +*/ +/* + * Part 1 JPEG 2000 Image Core Coding System (J2K, JP2) + * 15444-1annexi.pdf: new JP2 file format +*/ +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#include +#define snprintf sprintf_s +#define strcasecmp _stricmp +#define strncasecmp _strnicmp +#define sprintf _scprintf +#define strdup _strdup +#else /* not _WIN32 */ +#define __STDC_FORMAT_MACROS +#include +#include +#endif /* _WIN32 */ + + +#include +#include +#include +#include + +#include "opj_inttypes.h" +#include "opj_stdint.h" + +#include "viewerdefs.hh" +#include "tree.hh" + +//----------------------------------- +//WARNING: SHOW_PACKETS may need a very long time to be shown: +//#define SHOW_PACKETS + +#define TREE_LABEL_SIZE 11 + +unsigned char box_name[33]; + +//----------------------------------- +//#define DEBUG_MAIN +//#define READ_ALL_SOT_MARKERS +//#define PSOT_LENG_FROM_BUF_END +//#define DEBUG_DEFAULT_TEST +//#define DEBUG_BOXHEADER +//#define DEBUG_BOXHEADER8 +//#define COLLECT_CURV +//#define DEBUG_CURV +//#define DEBUG_XYZ +//#define DEBUG_ICC_PROFILE +//#define DEBUG_DESC +//#define DEBUG_JP2C +//#define SHOW_COM +//#define QUANT_AS_STRING +//#define SHOW_SIZE_VALUE +//#define SHOW_PCLR_ENTRY +//#define DEBUG_JP2C_END +//#define SHOW_XML +//#define SHOW_UUID_DATA + +//---------------- FORWARD ---------------- + +//read_ihdr(), read_bpcc() +static unsigned short nr_components; + +//read_ppt() +static unsigned int ppt, ppt_store, ppt_len; + +//read_ppm() +static unsigned int ppm_prev; +static unsigned int ppm_store; + +//read_poc() +static unsigned char has_POC; +static unsigned int numpocs; + +//read_siz() +static short extended_cap, Csiz; +static int one_tile_only; + +//read_cod() +static short entropy_coder, use_sop_marker, use_eph_marker; +static short max_precincts, user_defined_precincts; + +static unsigned short irreversible_transform, reversible_transform, + transform; + +//-------------- end FORWARD -------------- + +static jp2_color_t jp2_color; +static char item_name[MAX_ITEMBUF+2]; + + static const char *L_document_xpm[] = +{ + "11 11 3 1", + ". c None", + "x c #d8d8f8", + "@ c #202060", + ".@@@@@@....", + ".@xxx@.@...", + ".@xxx@..@..", + ".@xxx@@@@@.", + ".@xxxxxxx@.", + ".@xxxxxxx@.", + ".@xxxxxxx@.", + ".@xxxxxxx@.", + ".@xxxxxxx@.", + ".@xxxxxxx@.", + ".@@@@@@@@@." +}; +static Fl_Pixmap L_documentpixmap(L_document_xpm); + +/*----------------- + COM: Comment and extension marker + COC: Coding style component marker + COD: Coding style default maker + EPH: End of packet marker + EOI: End of image marker (EOC: end of codestream ) + PLM: Packet length, main header marker + PLT: Packet length, tile-part header marker + POD: Progression order change (POC), default marker + PPM: Packed packet headers, main header marker + PPT: Packed packet headers, tile-part header marker + QCC: Quantization component marker + QCD: Quantization default marker + RGN: Region of interest marker + SIZ: Size of image marker + SOC: Start of image (codestream) marker + SOP: Start of packet marker + SOT: Start of tile marker + TLM: Tile length marker + + +Part 2: + + DCO: Variable DC offset + VMS: Visual masking + DFS: Downsampling factor style + ADS: Arbitrary decomposition style + CBD: Component bit depth + MCT: Multiple component transformation definition + MCC: Multiple component collection + MIC: Multiple component intermediate collection + NLT: Non-linearity point transformation + + ARN: Arbitrary region of interest marker: obsolete? + +Part 2, Part 10: + ATK: Arbitrary transformation kernels + +------------------*/ +#define J2K_SOC 0xff4f +#define J2K_SIZ 0xff51 +#define J2K_COD 0xff52 +#define J2K_COC 0xff53 +#define J2K_TLM 0xff55 +#define J2K_PLM 0xff57 +#define J2K_PLT 0xff58 +#define J2K_QCD 0xff5c +#define J2K_QCC 0xff5d +#define J2K_RGN 0xff5e +#define J2K_POC 0xff5f +#define J2K_PPM 0xff60 +#define J2K_PPT 0xff61 +#define J2K_CRG 0xff63 +#define J2K_COM 0xff64 +#define J2K_SEC 0xff65 +#define J2K_EPB 0xff66 +#define J2K_ESD 0xff67 +#define J2K_EPC 0xff68 +#define J2K_RED 0xff69 + +/*------- Part 2 ---------*/ +#define J2K_DCO 0xff70 +#define J2K_VMS 0xff71 +#define J2K_DFS 0xff72 +#define J2K_ADS 0xff73 +#define J2K_MCT 0xff74 +#define J2K_MCC 0xff75 +#define J2K_NLT 0xff76 +#define J2K_MIC 0xff77 +#define J2K_CBD 0xff78 +#define J2K_ATK 0xff79 +//ARN +/*----------------------*/ + +#define J2K_SOT 0xff90 +#define J2K_SOP 0xff91 +#define J2K_EPH 0xff92 +#define J2K_SOD 0xff93 + +#define J2K_INSEC 0xff94 +#define J2K_EOC 0xffd9 + + +static const char *reg_text[]= +{ +" General use (binary values)", +" General use (ISO 8859-1 (latin-1) values)", +" Reserved use", +NULL +}; + +static const char *enumcs_text(int i) +{ + static const char *cs_text[]= + { + "Bi-level", + "YCbCr(1)", + "", + "YCbCr(2)", + "YCbCr(3)", + + "", + "", + "", + "", + "PhotoCD", + + "", + "CMY", + "CMYK", + "YCCK", + "CIELab", + + "Bi-level(2)", + "sRGB", + "greyscale", + "sYCC", + "CIEJab", + + "e-sRGB", + "ROMM-RGB", + "YPbPr(1125/60)", + "YPbPr(1250/50)", + "e-sYCC", + + NULL + }; + + if(i < 0 || i > 24) return "Unknown"; + return cs_text[i]; + +}//enumcs_text() + +static void init() +{ + nr_components = 0; + ppt = ppt_store = ppt_len = 0; + ppm_prev = ppm_store = 0; + has_POC = 0; + numpocs = 0; + extended_cap = 0; + Csiz = 0; + one_tile_only = 0; + + entropy_coder = use_sop_marker = use_eph_marker = 0; + max_precincts = user_defined_precincts = 0; + + irreversible_transform = reversible_transform = transform = 0; +} + +unsigned int get4(const unsigned char *b) +{ + return (b[0]<<24)|(b[1]<<16)|(b[2]<<8)|b[3]; +} + +unsigned int get2(const unsigned char *b) +{ + return (b[0]<<8)|b[1]; +} + +uint64_t get8(const unsigned char *b) +{ + uint64_t v; + unsigned int v2; + v = (uint64_t)get4(b); v2 = get4(b+4); + return ((v<<32) | v2); +} + +unsigned int get_size(const unsigned char *b, unsigned int size) +{ + unsigned int i, v = b[0]; +#ifdef SHOW_SIZE_VALUE +fprintf(stderr,"\n=== get_size(%d) ===\n\n",size); +#endif + for(i = 1; i < size; ++i) + { + v = (v<<8) | b[i]; + } + return v; +} + +static void apply_cdef(jp2_cdef_info_t *info, unsigned short n) +{ + unsigned short i, j, last; + + for(i = 0; i < n; ++i) + { + if(info[i].asoc != 65535 && info[i].typ != 65535) continue; + + last = n - 1; + + for(j = i; j < last; ++j) + { + info[j] = info[j+1]; + } + --n; + } + FLViewer_set_max_components(n); +} + +static void read_curv_type(unsigned char *tag) +{ +#ifdef DEBUG_CURV + unsigned char *start; +#endif +#ifdef COLLECT_CURV + unsigned int i, + unsigned short v; +#endif + unsigned int n; + + tag += 4;//reserved + n = get4(tag); tag += 4; +#ifdef DEBUG_CURV + start = tag; +fprintf(stderr," curv size[%u]\n",n); +#endif + if(n == 1) + { +#ifdef DEBUG_CURV +/* gamma */ + unsigned short v = get2(tag); + +fprintf(stderr," curv[0]gamma(%u.%u)\n",(v>>8),v & 0xff); +#endif + return; + } + + +#ifdef COLLECT_CURV + for(i = 0; i < n; ++i) + { + v = get2(tag); tag += 2; + +fprintf(stderr," curv[%d] %u\n",i,v); + } + + + +#elif DEBUG_CURV + i = 0; + v = get2(tag); tag += 2; +fprintf(stderr," curv[%d] %u\n",i,v); + v = get2(tag); tag += 2; +fprintf(stderr," curv[%d] %u\n",i+1,v); + + i = n/2; tag = start + i*2; + v = get2(tag); tag += 2; +fprintf(stderr," curv[%d] %u\n",i,v); + v = get2(tag); tag += 2; +fprintf(stderr," curv[%d] %u\n",i+1,v); + + i = n - 2; tag = start + i * 2; + v = get2(tag); tag += 2; +fprintf(stderr," curv[%d] %u\n",i,v); + v = get2(tag); tag += 2; +fprintf(stderr," curv[%d] %u\n",i+1,v); +#endif +} + +static void read_XYZ_type(unsigned char *tag) +{ +#ifdef DEBUG_XYZ + unsigned int a,b,c; +#endif + tag += 4;//reserved + +#ifdef DEBUG_XYZ + a = get4(tag); b = get4(tag+4); c = get4(tag+8); +fprintf(stderr," XYZ(%u.%u, %u.%u, %u.%u)", +a>>16,a & 0xff,a>>16,a & 0xff,a>>16,a & 0xff); +#endif +} + +/* Is NOT ascii text, but UTF8 text */ +static void read_desc_type(unsigned char *tag, unsigned int size) +{ +#ifdef DEBUG_DESC + unsigned int i; + +fputs(" DESC(", stderr); + for(i = 0; i < size; ++i) + { + if(tag[i] == '/') fputs("\n/", stderr); + else + if( !iscntrl(tag[i])) fprintf(stderr,"%c",tag[i]); + } +fputs(")", stderr); + +#endif //DEBUG_DESC +} + +static void add_sub_item() +{ + Fl_Tree_Item *sub = tree->add(item_name); + sub->usericon(&L_documentpixmap); +} + +static void read_icc_profile(unsigned char *s, const char *name_src) +{ + char sign[5], proclass[5]; + char cspace[5], pcs[5], platsign[5]; + unsigned char *version; + unsigned char *profile_start, *profile_end, *tag; + int profile_len, siz; + unsigned cmmtype, da0, da1; + unsigned int proflags, rendintent; + unsigned int ciex,ciey,ciez; + unsigned int nt, i; + unsigned short year,month,day,hour,min,sec; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/ICC profile box",name_buf); + add_sub_item(); + + profile_start = s; + profile_len = get4(s); s += 4; + profile_end = s + profile_len; + + cmmtype = get4(s); s += 4; + version = s; s += 4; + proclass[4] = 0; memcpy(proclass, s, 4); s += 4; + cspace[4] = 0; memcpy(cspace, s, 4); s += 4; + pcs[4] = 0; memcpy(pcs, s, 4); s += 4; + year = get2(s); s += 2; month = get2(s); s += 2; day = get2(s); s += 2; + hour = get2(s); s += 2; min = get2(s); s += 2; sec = get2(s); s += 2; + sign[4] = 0; memcpy(sign, s, 4); s += 4; + platsign[4] = 0; memcpy(platsign, s, 4); s += 4; + proflags = get4(s); s += 4; + s += 4;/* device manufacturer */ + s += 4;/* device model */ + da0 = get4(s); s += 4; da1 = get4(s); s += 4; + rendintent = get4(s); s += 4; + ciex = get4(s); s += 4; ciey = get4(s); s += 4; ciez = get4(s); s += 4; + s += 4;/* creator */ + s += 16;/* ID */ + + snprintf(item_name, MAX_ITEMBUF, "%s/cmmtype(%#x)",name_buf,cmmtype); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/version(%u.%u.%u.0)",name_buf, + version[0],version[1],version[2]); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/class(%s)",name_buf,proclass); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/color-space(%s)",name_buf,cspace); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/profile-connection-space(%s)", + name_buf,pcs); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/date(%u.%u.%u) time(%u:%u:%u)", + name_buf, + day,month,year,hour,min,sec); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/signature(%s)",name_buf,sign); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/platform-signature(%s)", + name_buf,platsign); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, + "%s/profile-flags(%#x) [0] %u [1] %u [2:15] %u", + name_buf,proflags,proflags & 1,proflags & 2, proflags & 0xfffc); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/device-attr(%u) white(%u)", + name_buf, da0,(da1&1)); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, + "%s/negative(%u) matte(%u) transparent(%u)", + name_buf,(da1&2),(da1&4),(da1&8)); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/rendering-intent(%#x)",name_buf, + rendintent); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/CIE: x(%d.%u) y(%d.%u) z(%d.%u)", + name_buf, (ciex>>16),ciex&0xffff,(ciey>>16),ciey&0xffff,(ciez>>16), + ciez&0xffff); + add_sub_item(); + + s = profile_start + 128; + nt = get4(s); s += 4; + + for(i = 0; i < nt; ++i) + { + unsigned int off; + + memcpy(sign, s, 4); s += 4; + off = get4(s); s += 4; + siz = get4(s); s += 4; + tag = profile_start + off; + +#ifdef DEBUG_ICC_PROFILE +fprintf(stderr,"[%d] signature(%s) size[%d]\n",i,sign,siz); +#endif +//issue328-Ninja.jp2 : + if(s + siz > profile_end || tag > profile_end) + { + fprintf(stderr, "\nflviewer/read_jpeg2000.cxx:%d:\n" + "\t=== ICC Profile seems to be chopped. RETURN. ===\n\n",__LINE__); + return; + } + if(memcmp(sign, "cprt", 4) == 0) + { +//#ifdef DEBUG_ICC + char buf[32]; + int j, k = 0; + + memset(buf, 0, 32); + + for(j = 4; j < siz; ++j) + { + if(iscntrl(tag[j])) continue; + + buf[k] = tag[j]; ++k; + if(k == 31) break; + } + snprintf(item_name, MAX_ITEMBUF, "%s/%s",name_buf,buf); + add_sub_item(); +//#endif + } + else + if(memcmp(sign, "desc", 4) == 0) + { +//fprintf(stderr,"%s:%d:\n\tTRACE\n",__FILE__,__LINE__); + read_desc_type(tag + 4, siz - 4); + } + else + { + unsigned char buf[5]; + + buf[4] = 0; memcpy(buf, tag, 4); tag += 4; + + if(memcmp(buf, "curv", 4) == 0) + { +//fprintf(stderr,"%s:%d:\n\tTRACE\n",__FILE__,__LINE__); + read_curv_type(tag); + } + else + if(memcmp(buf, "XYZ ", 4) == 0) + { +//fprintf(stderr,"%s:%d:\n\tTRACE\n",__FILE__,__LINE__); + read_XYZ_type(tag); + } + else + if(memcmp(buf, "desc", 4) == 0) + { +//fprintf(stderr,"%s:%d:\n\tTRACE\n",__FILE__,__LINE__); + read_desc_type(tag, siz-4); + } + else + { +/*----------- +fprintf(stderr," %s\n", buf); +-------------*/ + } + } +#ifdef DEBUG_ICC_PROFILE +fprintf(stderr,"\n"); +#endif + } +}/* read_icc_profile() */ + +uint64_t read_boxheader(unsigned char *box, unsigned char *dend, + unsigned int *out_siz) +{ + uint64_t len; + + len = (uint64_t)get4(box); + memcpy(box_name, box + 4, 4); box_name[4] = 0; *out_siz = 8; // 4 + 4 + +#ifdef DEBUG_BOXHEADER + fprintf(stderr,"\tREAD[1]BOX_NAME(%s) BOX_LEN(%" PRIu64 ")\n", + box_name,len); +#endif + + if(len == 0) return (uint64_t)(dend - box);//last box + + if(len > 1) return len; + + if(sizeof(uint64_t) == 8) + { + len = get8(box+8); *out_siz = 16; // 4 + 4 + 8 + } + else + { + fprintf(stderr,"%s:%d:\n\tread_boxheader ==> can not read 8 bytes." + " STOP.\n",__FILE__,__LINE__); + + len = 0; *out_siz = 16; // 4 + 4 + 8 + } +#ifdef DEBUG_BOXHEADER8 + fprintf(stderr,"\tREAD[2] BOX_LEN(%" PRIu64 ")\n", + len); +#endif + + return len; +} + +static unsigned short read_siz(unsigned char *s, const char *name_src) +{ + unsigned int len, x,y,x0,y0,xt,yt, xt0,yt0; + unsigned short r,c,i,xr,yr,prec,depth,sign; + unsigned int tile_w, tile_h, image_w, image_h; + int max_tiles; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Image and tile size marker", + name_buf); + add_sub_item(); + + len = get2(s); s += 2;//Lsiz = 38 + 3 * Csiz + + r = get2(s); s += 2;//Rsiz + snprintf(item_name, MAX_ITEMBUF, "%s/Rsiz(%d)",name_buf,r); + add_sub_item(); + + x = get4(s); s += 4;//Xsiz + snprintf(item_name, MAX_ITEMBUF, "%s/Xsiz(%d)",name_buf,x); + add_sub_item(); + + y = get4(s); s += 4;//Ysiz + snprintf(item_name, MAX_ITEMBUF, "%s/Ysiz(%d)",name_buf,y); + add_sub_item(); + + x0 = get4(s); s += 4;//XOsiz + snprintf(item_name, MAX_ITEMBUF, "%s/X0siz(%d)",name_buf,x0); + add_sub_item(); + + y0 = get4(s); s += 4;//YOsiz + snprintf(item_name, MAX_ITEMBUF, "%s/Y0siz(%d)",name_buf,y0); + add_sub_item(); + + xt = get4(s); s += 4;//XTsiz + snprintf(item_name, MAX_ITEMBUF, "%s/XTsiz(%d)",name_buf,xt); + add_sub_item(); + + yt = get4(s); s += 4;//YTsiz + snprintf(item_name, MAX_ITEMBUF, "%s/YTsiz(%d)",name_buf,yt); + add_sub_item(); + + xt0 = get4(s); s += 4;//XTOsiz + snprintf(item_name, MAX_ITEMBUF, "%s/XT0siz(%d)",name_buf,xt0); + add_sub_item(); + + yt0 = get4(s); s += 4;//YTOsiz + snprintf(item_name, MAX_ITEMBUF, "%s/YT0siz(%d)",name_buf,yt0); + add_sub_item(); + + c = get2(s); s += 2;//Csiz + snprintf(item_name, MAX_ITEMBUF, "%s/Csiz(%d)",name_buf,c); + add_sub_item(); + Csiz = c; + + FLViewer_set_max_components(c); + + image_w = x - x0; image_h = y - y0; + tile_w = xt - xt0; tile_h = yt - yt0; + + if(tile_w <= 0 || tile_h <= 0) + { +//This definitely is a bug. + max_tiles = 0; + } + else + { + int nr; + + max_tiles = image_w/tile_w; + if(image_w%tile_w) ++max_tiles; + + nr = image_h/tile_h; + if(image_h%tile_h) ++nr; + + max_tiles *= nr; + } + FLViewer_set_max_tiles(max_tiles); + + if(r >= 32768) extended_cap = 1; else extended_cap = 0; + + snprintf(item_name, MAX_ITEMBUF, "%s/Ext. Capabilities(%d)", + name_buf,extended_cap); + add_sub_item(); + +#ifdef DEBUG_SIZ +fprintf(stderr,"%s:%d:\n\tread_siz\n\tlen(%u)\n" +"\tcapabilities(%u)[extended: %d]\n\tx(%u : %u) y(%u : %u)" +"\n\txt(%u : %u) yt(%u : %u)\n\tIMAGE w(%d) h(%d) TILE w(%d) h(%d)\n" +"\tCsiz(%hu)\n",len,r, extended_cap, x0,x, y0,y, +xt0,xt, yt0,yt, image_w,image_h,tile_w,tile_h,Csiz); +#endif + + for(i = 0; i < c; ++i) + { + prec = s[0]; ++s; + depth = (prec & 0x7f) + 1; + sign = (prec & 0x80?1:0);//Ssiz + xr = s[0]; ++s;//XRsiz + yr = s[0]; ++s;//YRsiz + + snprintf(item_name, + MAX_ITEMBUF, "%s/comp[%d] signed(%u) prec(%u) hsep(%u) vsep(%u)", + name_buf,i,sign,depth,xr,yr); + add_sub_item(); + } + one_tile_only = (image_w == tile_w && image_h == tile_h); + snprintf(item_name, MAX_ITEMBUF, "%s/OneTileOnly(%d)", + name_buf,one_tile_only); + add_sub_item(); + + ppm_store = 0; ppm_prev = 0; + + return len; +}//read_siz() + +static unsigned short read_cod(unsigned char *s, const char *name_src) +{ + unsigned char *cur; + const char *cs = ""; + unsigned short len, max_len, nr_layers; + unsigned short Scod, prog_order, multi_comp_transform; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Coding style default marker", + name_buf); + add_sub_item(); + + cur = s; + max_len = get2(cur); cur += 2; + Scod = cur[0]; ++cur;//Table A-13 + prog_order = cur[0]; ++cur;//Table A-16 + nr_layers = get2(cur); cur += 2; + multi_comp_transform = cur[0]; ++cur; + + if(nr_layers > 65534) + { + return max_len; + } + FLViewer_set_max_layers(nr_layers); + + entropy_coder = use_sop_marker = use_eph_marker = 0; + + if(Scod & 1) entropy_coder = 1; + if(Scod & 2) use_sop_marker = 1; + if(Scod & 4) use_eph_marker = 1; + + if(prog_order == 0) cs = "LRCP"; + else + if(prog_order == 1) cs = "RLCP"; + else + if(prog_order == 2) cs = "RPCL"; + else + if(prog_order == 3) cs = "PCRL"; + else + if(prog_order == 4) cs = "CPRL"; + else + cs = "Unknown"; + + snprintf(item_name, MAX_ITEMBUF, "%s/prog_order(%hu)%s", name_buf, + prog_order, cs); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/nr_layers(%u)", name_buf, + nr_layers ); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/multi_comp_transform(%hu)", name_buf, + multi_comp_transform ); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/entropy_coder(%u)", name_buf, + entropy_coder ); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/use_sop_marker(%u)", name_buf, + use_sop_marker); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/use_eph_marker(%u)", name_buf, + use_eph_marker); + add_sub_item(); + + max_precincts = user_defined_precincts = 0; + + if(max_len < 13) + { + max_precincts = 1; // A.2 + + snprintf(item_name, MAX_ITEMBUF, "%s/max_precincts(1)", name_buf); + add_sub_item(); + } + else + { + user_defined_precincts = 1; + + snprintf(item_name, MAX_ITEMBUF, "%s/user_defined_precincts(1)", name_buf); + add_sub_item(); + } + { + unsigned int i; + unsigned char code_block_width ,code_block_height, + code_block_style, nr_decomp_levels; + +/*-------------------------------------------------- + + A -- Progression order + B-- Number of layers + C -- Multiple component transformation +A B C | D E F G H Ii .. In D -- Number of decomposition levels + | E -- Code-block width + SGcod | SPcod F -- Code-block height + G -- Code-block style + H -- Transformation + Ii through In -- Precinct size +----------------------------------------------------*/ +/* SPcod: +*/ + nr_decomp_levels = cur[0] + 1; ++cur; + code_block_width = cur[0]; ++cur; + code_block_height = cur[0]; ++cur; + code_block_style = cur[0]; ++cur; + transform = cur[0]; ++cur; + + if(nr_decomp_levels == 0 || code_block_width == 0 || code_block_height == 0) + { + return max_len; + } + FLViewer_set_max_reduction((int)nr_decomp_levels); + + snprintf(item_name, MAX_ITEMBUF, "%s/nr_decomp_levels(%hu)", name_buf, + nr_decomp_levels); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/code_block_width(%d)", name_buf, + code_block_width); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/code_block_height(%u)", name_buf, + code_block_height); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/code_block_style(%d)", name_buf, + code_block_style); + add_sub_item(); + + irreversible_transform = reversible_transform = 0; + if(transform == 0) + { + irreversible_transform = 1; + + snprintf(item_name, MAX_ITEMBUF, "%s/transformation(0) (9-7 irreversible)", + name_buf); + add_sub_item(); + } + else + if(transform == 1) + { + reversible_transform = 1; + + snprintf(item_name, MAX_ITEMBUF, "%s/transformation(1) (5-3 reversible)", + name_buf); + add_sub_item(); + } + else + { + + snprintf(item_name, MAX_ITEMBUF, "%s/transformation(%hu)", name_buf, + transform); + add_sub_item(); + } + + if(max_len == 12) + { + unsigned short j; + for(j = 0; j < nr_decomp_levels; ++j) + { + snprintf(item_name, MAX_ITEMBUF, "%s/[%d] precinct w(%hu) h(%hu)", + name_buf, j,15,15); + add_sub_item(); + } + return max_len; + } + len = 12; + + i = 0; + while(len < max_len && (len + nr_decomp_levels) < max_len) + { + len += nr_decomp_levels; + + if(len > max_len) + { + return max_len; + } + if((Scod & 1))// Table A-21 + { + unsigned short j, v; + + for(j = 0; j < nr_decomp_levels; ++j) + { + v = cur[0]; ++cur; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%d] precinct w(%hu) h(%hu)", + name_buf, j,(v&0xf), (v>>4)); + add_sub_item(); + } + } + else + { + unsigned short j; + for(j = 0; j < nr_decomp_levels; ++j) + { + snprintf(item_name, MAX_ITEMBUF, "%s/[%d] precinct w(%hu) h(%hu)", + name_buf,j,15,15); + add_sub_item(); + } + } + ++i; + } + } + + return max_len; + +}// read_cod() + +static unsigned short read_coc(unsigned char *s, const char *name_src) +{ + unsigned short len, Scoc; + unsigned short A, B, C, D, E; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Coding style component marker", + name_buf); + add_sub_item(); + + len = get2(s); s += 2; + + Scoc = s[0]; ++s;//csty + snprintf(item_name, MAX_ITEMBUF, "%s/Scoc(%hu)", name_buf,Scoc); + add_sub_item(); + + A = s[0] + 1; ++s; + snprintf(item_name, MAX_ITEMBUF, "%s/nr_decomp_levels(%hu)", name_buf,A); + add_sub_item(); + + B = s[0] + 2; ++s; + snprintf(item_name, MAX_ITEMBUF, "%s/code-block-width(%hu)", name_buf,B); + add_sub_item(); + + C = s[0] + 2; ++s; + snprintf(item_name, MAX_ITEMBUF, "%s/code-block-height(%hu)", name_buf,C); + add_sub_item(); + + D = s[0]; ++s; + snprintf(item_name, MAX_ITEMBUF, "%s/code-block-style(%hu)", name_buf,D); + add_sub_item(); + + E = s[0]; ++s; + snprintf(item_name, MAX_ITEMBUF, "%s/transformation(%hu)", name_buf,E); + add_sub_item(); + + if(Scoc == 0) + { + unsigned short i; + + for(i = 0; i < A; ++i) + { + snprintf(item_name, MAX_ITEMBUF, "%s/Precinct[%d] Width(15) Height(15)", + name_buf,i ); + add_sub_item(); + } + } + else + if(Scoc & 1) + { + unsigned short i, K; + + for(i = 0; i < A; ++i) + { + K = s[0]; ++s; + + snprintf(item_name, MAX_ITEMBUF, "%s/Precinct[%d] Width(%hu) Height(%hu)", + name_buf,i,(K & 0xf), (K >> 4) ); + add_sub_item(); + } + } + return len; + +}//read_coc() + +static unsigned short read_rgn(unsigned char *s, const char *name_src) +{ + unsigned short len, Crgn, Srgn, SPrgn; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Region-of-interest marker",name_buf); + add_sub_item(); + + len = get2(s); s += 2; + Crgn = get_size(s, (Csiz < 257?1:2) ); + snprintf(item_name, MAX_ITEMBUF, "%s/Component Index(%hu)",name_buf,Crgn); + add_sub_item(); + + Srgn = s[0]; ++s; + snprintf(item_name, MAX_ITEMBUF, "%s/ROI style(%hu)",name_buf,Srgn); + add_sub_item(); + + SPrgn = s[0]; ++s; + snprintf(item_name, MAX_ITEMBUF, "%s/Implicit ROI shift(%hu)", + name_buf,SPrgn); + add_sub_item(); + + return len; + +}//read_rgn() + +static unsigned short read_plm(unsigned char *s, const char *name_src) +{ + unsigned short len; + short siz; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Packet length marker",name_buf); + add_sub_item(); + + len = get2(s); s += 2; + siz = (short)len; + ++s; //Zplm + + siz -= 3; + while(siz > 0) + { + unsigned int i, Nplm, packet_len = 0; + unsigned short v; + + Nplm = get4(s); s += 4; siz -= 4; + snprintf(item_name, MAX_ITEMBUF, "%s/Index of marker segment(%u)", + name_buf,Nplm); + add_sub_item(); + + for(i = 0; i < Nplm; ++i) + { + v = s[0]; ++s; --siz; + packet_len = (packet_len << 7) + v; + +// if((v & 0x80) == 0) packet_len = 0; //New packet + + snprintf(item_name, MAX_ITEMBUF, "%s/Packet[%d] length(%u)", + name_buf,i,packet_len); + add_sub_item(); + + if((v & 0x80) == 0) packet_len = 0; //New packet + } + } + return len; + +}//read_plm() + +static unsigned short read_qcc(unsigned char *s, const char *name_src) +{ + unsigned short len, Cqcc, Sqcc; + unsigned short header_size, num_bands; + unsigned short qntsty; +// unsigned short numgbits; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Quantization component marker", + name_buf); + add_sub_item(); + + len = get2(s); s += 2; + header_size = len - 2 - 1; + + if(Csiz < 257) + { + Cqcc = s[0]; ++s; + } + else + { + Cqcc = get2(s); s += 2; + } + + Sqcc = s[0]; ++s; + + qntsty = Sqcc & 0x1f; //numgbits = Sqcc >> 5; + + if(qntsty == 1) + { + num_bands = 1; + } + else + if(qntsty == 0) + { + num_bands = header_size; + } + else + { + num_bands = header_size/2; + } + snprintf(item_name, MAX_ITEMBUF, "%s/Cqcc(%d) Sqcc(%d) numbands(%d)", + name_buf, Cqcc, Sqcc, num_bands); + add_sub_item(); + + if(qntsty == 0) + { + unsigned short i, v; + + for(i = 0; i < num_bands; ++i) + { + v = s[0]; ++s; + + snprintf(item_name, MAX_ITEMBUF, "%s/Band[%d] Exponent(%hu) Mantissa(%hu)", + name_buf,i,(v>>3), 0); + add_sub_item(); + } + } + else + { + unsigned short i, v; + + for(i = 0; i < num_bands; ++i) + { + v = get2(s); s += 2; + + snprintf(item_name, MAX_ITEMBUF, "%s/Band[%d] Exponent(%hu) Mantissa(%hu)", + name_buf,i,(v>>11), (v & 0x7ff)); + add_sub_item(); + } + } + return len; +}//read_qcc() + +static unsigned short read_poc(unsigned char *s, const char *name_src) +{ + unsigned short len, numpchgs, i, old_poc; + unsigned short RSpoc, CSpoc; + unsigned short LYEpoc, REpoc, CEpoc; + unsigned short Ppoc; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Progression order change marker", + name_buf); + add_sub_item(); + + len = get2(s); s += 2; + + old_poc = has_POC ? numpocs + 1 : 0; + has_POC = 1; + + numpchgs = (len - 2) / (5 + 2 * (Csiz < 257 ? 1 : 2)); + + if( numpchgs >= 32 ) numpchgs = 0; + + for(i = old_poc; i < numpchgs + old_poc; ++i) + { + RSpoc = s[0]; ++s; + snprintf(item_name, MAX_ITEMBUF, "%s/poc[%i] RSpoc(%hu)",name_buf,i,RSpoc); + add_sub_item(); + + if(Csiz < 257) + { + CSpoc = s[0]; ++s; + } + else + { + CSpoc = get2(s); s += 2; + } + snprintf(item_name, MAX_ITEMBUF, "%s/poc[%i] CSpoc(%hu)",name_buf,i,CSpoc); + add_sub_item(); + + LYEpoc = get2(s); s += 2; + snprintf(item_name, MAX_ITEMBUF, "%s/poc[%i] LYEpoc(%hu)",name_buf,i,LYEpoc); + add_sub_item(); + + REpoc = s[0]; ++s; + snprintf(item_name, MAX_ITEMBUF, "%s/poc[%i] REpoc(%hu)",name_buf,i,REpoc); + add_sub_item(); + + if(Csiz < 257) + { + CEpoc = s[0]; ++s; + } + else + { + CEpoc = get2(s); s += 2; + } + snprintf(item_name, MAX_ITEMBUF, "%s/poc[%i] CEpoc(%hu)",name_buf,i,CEpoc); + add_sub_item(); + + Ppoc = s[0]; ++s; + snprintf(item_name, MAX_ITEMBUF, "%s/poc[%i] Ppoc(%hu)",name_buf,i,Ppoc); + add_sub_item(); + } + numpocs = numpchgs + old_poc - 1; + + return len; + +}//read_poc() + +static unsigned short read_tlm(unsigned char *s, const char *name_src) +{ + unsigned short len; + unsigned short Ztlm, Stlm; + unsigned int ST, SP, dSP, i, tile_tlm, Ttlm, Ptlm; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Tile-part lengths marker",name_buf); + add_sub_item(); + + len = get2(s); s += 2; + Ztlm = s[0]; ++s; + snprintf(item_name, MAX_ITEMBUF, "%s/Ztlm(%hu)",name_buf,Ztlm); + add_sub_item(); + + Stlm = s[0]; ++s; + snprintf(item_name, MAX_ITEMBUF, "%s/Stlm(%hu)",name_buf,Stlm); + add_sub_item(); + + ST = ((Stlm >> 4) & 0x01) + ((Stlm >> 4) & 0x02); + SP = (Stlm >> 6) & 0x01; + dSP = (SP ? 4 : 2); + tile_tlm = (len - 4) / ((SP + 1) * 2 + ST); + + for(i = 0; i < tile_tlm; ++i) + { + Ttlm = get_size(s, ST); s += ST; + Ptlm = get_size(s, dSP); s += dSP; + + snprintf(item_name, MAX_ITEMBUF, "%s/Tlm[%i] Ttlm(%u) Ptlm(%u)", + name_buf,i,Ttlm,Ptlm); + add_sub_item(); + } + + return len; + +}//read_tlm() + +unsigned char *read_resc(unsigned char *s, unsigned char *box_end, + const char *name_src) +{ + char name_buf[MAX_ITEMBUF]; + unsigned short vcn, vcd, hcn, hcd, vce, hce; + + strcpy(name_buf, (char*)name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Capture resolution box",name_buf); + add_sub_item(); + + vcn = get2(s); s += 2; + vcd = get2(s); s += 2; + hcn = get2(s); s += 2; + hcd = get2(s); s += 2; + vce = s[0]; ++s; + hce = s[0]; ++s; + + snprintf(item_name, MAX_ITEMBUF, "%s/vcn(%hu) vcd(%hu)", name_buf,vcn,vcd); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/hcn(%hu) hcd(%hu)", name_buf,hcn,hcd); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/vce(%hu) hce(%hu)", name_buf,vce,hce); + add_sub_item(); + + return s; +}//read_resc() + +unsigned char *read_resd(unsigned char *s, unsigned char *box_end, + const char *name_src) +{ + char name_buf[MAX_ITEMBUF]; + unsigned short vdn, vdd, hdn, hdd, vde, hde; + + strcpy(name_buf, (char*)name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Default display resolution box", + name_buf); + add_sub_item(); + + vdn = get2(s); s += 2; + vdd = get2(s); s += 2; + hdn = get2(s); s += 2; + hdd = get2(s); s += 2; + vde = s[0]; ++s; + hde = s[0]; ++s; + + snprintf(item_name, MAX_ITEMBUF, "%s/vdn(%hu) vdd(%hu)", name_buf,vdn,vdd); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/hdn(%hu) hdd(%hu)", name_buf,hdn,hdd); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/vde(%hu) hde(%hu)", name_buf,vde,hde); + add_sub_item(); + + return s; +}//read_resd() + +unsigned char *read_res(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const unsigned char *name_src) +{ + char name_buf[MAX_ITEMBUF]; + uint64_t box_len; + unsigned int hstep; + + strcpy(name_buf, (char*)name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Resolution box",name_buf); + add_sub_item(); + + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + + snprintf(item_name, MAX_ITEMBUF, "%s/%s", name_buf,(char*)box_name); + + if(memcmp(box_name, "resc", 4) == 0) + { + Fl_Tree_Item *sup = tree->add(item_name); + + s = read_resc(s + hstep, s + box_len, item_name); + + sup->close(); + + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + + snprintf(item_name, MAX_ITEMBUF, "%s/%s", name_buf,(char*)box_name); + } + if(memcmp(box_name, "resd", 4) == 0) + { + Fl_Tree_Item *sup = tree->add(item_name); + + s = read_resd(s + hstep, s + box_len, item_name); + + sup->close(); + } + return s; +} + +unsigned char *read_ftyp(unsigned char *s, unsigned char *box_end, + const char *name_src) +{ + int i, n; + char name_buf[MAX_ITEMBUF]; + char buf[5], brand[5]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/File type box", name_buf); + add_sub_item(); + + brand[4] = 0; buf[4] = 0; + memcpy(brand, s, 4); s += 4; +// minv = get4(s); + s += 4; + + snprintf(item_name, MAX_ITEMBUF, "%s/brand(%s)", name_buf,brand); + add_sub_item(); + + n = (int)((box_end - s)/4); + + for(i = 0; i < n; ++i) + { + memcpy(buf, s, 4); s += 4; + + if(*buf == 0) memset(buf, ' ', 4); + + snprintf(item_name, MAX_ITEMBUF, "%s/CL(%s)", name_buf,buf); + add_sub_item(); + } + return s; +} + +unsigned char *read_ihdr(unsigned char *s, unsigned char *box_end, + const char *name_src) +{ + char name_buf[MAX_ITEMBUF]; + int w, h; + unsigned short nc, bpc, c, unkc, ipr, depth, sign; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Image header box",name_buf); + add_sub_item(); + + h = get4(s); s += 4; + w = get4(s); s += 4; + nc = get2(s); s += 2; + bpc = s[0]; ++s; + depth = (bpc & 0x7f) + 1; + sign = (bpc & 0x80)?1:0; + c = s[0]; ++s; + unkc = s[0]; ++s; + ipr = s[0]; ++s; + +#ifdef DEBUG_IHDR +fprintf(stderr,"read_ihdr\n\tw(%u) h(%u) nc(%u) bpc(%u)\n\tsigned(%u) " +"depth(%u)\n\tcompress(%u) unknown_c(%u) ipr(%u)\n",w, h, +nc,bpc, sign,depth,c, unkc, ipr); +#endif + + snprintf(item_name, MAX_ITEMBUF, "%s/w(%d)", name_buf, w); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/h(%d)", name_buf, h); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/numcomps(%d)", name_buf, nc); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/bpc(%d)", name_buf, bpc); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/depth(%d)", name_buf, depth); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/signed(%d)", name_buf, sign); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/compress(%d)", name_buf, c); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/unkc(%d)", name_buf, unkc); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/ipr(%d)", name_buf, ipr); + add_sub_item(); + + nr_components = nc; + + return s; +}/* read_ihdr() */ + +unsigned char *read_bpcc(unsigned char *s, unsigned char *box_end, + const char *name_src) +{ + unsigned char *v; + char name_buf[MAX_ITEMBUF]; + unsigned short i; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Bits per component box",name_buf); + add_sub_item(); + + v = s; + + for(i = 0; i < nr_components; ++i) + { + snprintf(item_name, MAX_ITEMBUF, "%s/[%d]bpcc(%d)", name_buf, + i,v[0]); + add_sub_item(); + + ++v; + } + return (s + nr_components); +} + +unsigned char *read_colr(unsigned char *s, unsigned char *box_end, + const char *name_src) +{ + char name_buf[MAX_ITEMBUF]; + unsigned int meth, prec, approx, enumcs = 0; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Colour specification box",name_buf); + add_sub_item(); + + meth = s[0]; ++s; + prec = s[0]; ++s; + approx = s[0]; ++s; + + snprintf(item_name, MAX_ITEMBUF, "%s/meth(%d)",name_buf,meth); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/prec(%d)",name_buf,prec); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/approx(%d)",name_buf,approx); + add_sub_item(); + + if(meth == 1)/* enumerated colorspace */ + { + const char *cs = ""; + + enumcs = get4(s); s += 4; + cs = enumcs_text(enumcs); + + snprintf(item_name, MAX_ITEMBUF, "%s/enumcs(%d: %s)", + name_buf,enumcs,cs); + add_sub_item(); + + if(enumcs == 14) //CIELab + { + s = box_end; + } + } + else /* Profile */ + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/ICC",name_buf); + sup = tree->add(item_name); + + read_icc_profile(s, item_name); + + sup->close(); + s = box_end;//skip ICC Profile + } + assert(box_end == s); + + if( !jp2_color.has_colr) + { + jp2_color.meth = meth; + jp2_color.precedence = prec; + jp2_color.approx = approx; + jp2_color.enumcs = enumcs; + jp2_color.has_colr = 1; + } + + return s; +}//read_colr() + +unsigned char *read_cdef(unsigned char *s, unsigned char *box_end, + const char *name_src) +{ + jp2_cdef_info_t *cdef_info; + char name_buf[MAX_ITEMBUF]; + unsigned short i, n, c, typ, asoc; +// +// Part 1, I.5.3.6: 'There shall be at most one Channel Definition box +// inside a JP2 Header box.' +// + if(jp2_color.has_cdef) + { + return box_end; + } + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Channel definition box",name_buf); + add_sub_item(); + + n = get2(s); s += 2; + + cdef_info = (jp2_cdef_info_t*)malloc(n * sizeof(jp2_cdef_info_t)); + if(cdef_info == NULL) return box_end; + + jp2_color.has_cdef = 1; + + for(i = 0; i < n; ++i) + { + c = get2(s); s += 2; + typ = get2(s); s += 2; + asoc = get2(s); s += 2; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%d] c(%d) typ(%d) asoc(%d)", + name_buf, i, c, typ, asoc); + add_sub_item(); + + cdef_info[i].cn = c; cdef_info[i].typ = typ; cdef_info[i].asoc = asoc; + } + + apply_cdef(cdef_info, n); + + free(cdef_info); + + return s; + +}//read_cdef() + +unsigned char *read_pclr(unsigned char *s, unsigned char *box_end, + unsigned int *out_channels, const char *name_src) +{ + char name_buf[MAX_ITEMBUF]; + unsigned char *prec; + unsigned int *entries; + int size; + unsigned short nr_entries, nr_channels; + unsigned short i, j; + int count; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Palette box",name_buf); + add_sub_item(); + + nr_entries = get2(s); s += 2; /* NE */ + nr_channels = s[0]; ++s; /* NPC */ + count = 11;//8+3 + + *out_channels = nr_channels; + + i = nr_channels * nr_entries; + entries = (unsigned int*)calloc(i, sizeof(unsigned int)); + if(entries == NULL) return box_end; + + prec = (unsigned char*)calloc(nr_channels, 1); + if(prec == NULL) + { + free(entries); + return box_end; + } + + for(i = 0; i < nr_channels; ++i) + { + prec[i] = s[0]; ++s; /* Bi */ + ++count; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%d] signed(%u) depth(%u)", + name_buf, i, (prec[i]&0x80?1:0), (prec[i]&0x7f) + 1 ); + add_sub_item(); + } + + for(j = 0; j < nr_entries; ++j) + { +#ifdef SHOW_PCLR_ENTRY +fprintf(stderr," entry[%03u]",j); +#endif + for(i = 0; i < nr_channels; ++i) + { + size = ((prec[i]&0x7f) + 1 + 7)/8; + + entries[j*nr_channels + i] = get_size(s, size); s += size; /* Cji */ + count += size; + +#ifdef SHOW_PCLR_ENTRY +fprintf(stderr,"%u ", entries[j*nr_channels + i]); +#endif + } +#ifdef SHOW_PCLR_ENTRY +fputs("\n",stderr); +#endif + } + free(prec); free(entries); + + return box_end; +}/* read_pclr() */ + +unsigned char *read_cmap(unsigned char *s, unsigned char *box_end, + unsigned int nr_channels, const char *name_src) +{ + char name_buf[MAX_ITEMBUF]; + unsigned short i, cmp; + unsigned char mtyp, pcol; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Component mapping box",name_buf); + add_sub_item(); + + for(i = 0; i < nr_channels; ++i) + { + cmp = get2(s); s += 2; + mtyp = s[0]; ++s; + pcol = s[0]; ++s; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%d] cmp(%u) mtyp(%u) pcol(%u)", + name_buf, i,cmp,mtyp,pcol); + add_sub_item(); + } + + return s; +}/* read_cmap() */ + +unsigned char *read_jp2h(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + uint64_t box_len; + unsigned int hstep, nr_channels = 0; + int pos = -1; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/JP2 header box",name_buf); + add_sub_item(); + + while(s < box_end) + { + ++pos; + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] %s",name_buf,pos, + (char*)box_name); + + if(memcmp(box_name, "ihdr", 4) == 0) + { + Fl_Tree_Item *sup; + sup = tree->add(item_name); + + s = read_ihdr(s + hstep, s + box_len, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "bpcc", 4) == 0) + { + Fl_Tree_Item *sup; + sup = tree->add(item_name); + + s = read_bpcc(s + hstep, s + box_len, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "colr", 4) == 0) + { + Fl_Tree_Item *sup; + sup = tree->add(item_name); + + s = read_colr(s + hstep, s + box_len, item_name); + + sup->close(); + continue; + } + if(memcmp(box_name, "cdef", 4) == 0) + { + Fl_Tree_Item *sup; + sup = tree->add(item_name); + + s = read_cdef(s + hstep, s + box_len, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "pclr", 4) == 0) + { + Fl_Tree_Item *sup; + sup = tree->add(item_name); + + s = read_pclr(s + hstep, s + box_len, &nr_channels, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "cmap", 4) == 0) + { + Fl_Tree_Item *sup; + sup = tree->add(item_name); + + s = read_cmap(s + hstep, s + box_len, nr_channels, item_name); + + sup->close(); + continue; + } + if(memcmp(box_name, "res ", 4) == 0) + { + Fl_Tree_Item *sup; + sup = tree->add(item_name); + + s = read_res(s + hstep, s + box_len, dend, (unsigned char*)item_name); + + sup->close(); + continue; + } + if(memcmp(box_name, "xml ", 4) == 0 + || memcmp(box_name, "XML ", 4) == 0) + { + Fl_Tree_Item *sup, *sub; + char *buf = NULL; + char iname[MAX_ITEMBUF]; + + snprintf(iname, MAX_ITEMBUF, "[%03d] XML", ++pos); + sup = tree->add(iname); + + snprintf(item_name, MAX_ITEMBUF, "%s/xml1", iname); + sub = tree->add(item_name); + + s = read_xml(s + hstep, s + box_len, dend, &buf); + + sub->label(buf); + + sup->close(); + free(buf); --pos; + continue; + } + { + Fl_Tree_Item *sup; + char iname[MAX_ITEMBUF]; + + snprintf(iname, MAX_ITEMBUF, "[%03d] %s", ++pos, (char*)box_name); + sup = tree->add(iname); + + snprintf(item_name, MAX_ITEMBUF, "%s/Not handled. Skipped.", iname); + add_sub_item(); + + sup->close(); + } + + s += box_len; + } + + return box_end; +}//read_jp2h() + +unsigned short read_plt(unsigned char *s, const char *name_src) +{ + unsigned short len, Zplt; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, + "%s/Packet length, tile-part header marker", name_buf); + add_sub_item(); + + len = get2(s); s += 2; + Zplt = s[0]; ++s; + + snprintf(item_name, MAX_ITEMBUF, + "%s/Zplt(%hu) len(%hu)", name_buf,Zplt,len); + add_sub_item(); + + return len; +}// read_plt() + +static unsigned short read_ppm(unsigned char *s, const char *name_src) +{ + unsigned short max_len, len, Zppm; + unsigned int Nppm, i, j; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Packed packet headers marker (Main)", name_buf); + add_sub_item(); + + max_len = get2(s); s += 2; + len = max_len - 3; + Zppm = s[0]; ++s; + snprintf(item_name, MAX_ITEMBUF, "%s/Zppm(%hu)", name_buf,Zppm); + add_sub_item(); + + while(len > 0) + { + if(ppm_prev) + { + Nppm = ppm_prev; + } + else + { + Nppm = get4(s); s += 4; + + snprintf(item_name, MAX_ITEMBUF, "%s/Nppm(%u)", name_buf,Nppm); + add_sub_item(); + } + j = ppm_store; + + for(i = Nppm; i > 0; --i) + { + ++s; ++j; + + if(--len == 0) break; + } + ppm_prev = i - 1; + ppm_store = j; + + }//while(len > 0) + + return max_len; +}//read_ppm() + +static unsigned short read_ppt(unsigned char *s, const char *name_src) +{ + unsigned short len, Zppt; + unsigned int i, j; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Packed packet headers marker (Tile part)", name_buf); + add_sub_item(); + + len = get2(s); s += 2; + Zppt = s[0]; ++s; + snprintf(item_name, MAX_ITEMBUF, "%s/Zppt(%hu)", name_buf,Zppt); + add_sub_item(); + + ppt = 1; + + if(Zppt == 0)//First marker + { + ppt_store = 0; ppt_len = len - 3; + } + else + { + ppt_len = len - 3 + ppt_store; + } + j = ppt_store; + for(i = len - 3; i > 0; --i) + { + ++s; + ++j; + } + ppt_store = j; + + return len; +}//read_ppt() + +#ifdef SHOW_PACKETS + +static unsigned short read_sop(unsigned char *s, const char *name_src) +{ + unsigned short len, Nsop; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Start of packet marker", name_buf); + add_sub_item(); + + len = get2(s); s += 2; + + Nsop = get2(s); s += 2; + snprintf(item_name, MAX_ITEMBUF, "%s/Packet sequence number(%hu)", name_buf,Nsop); + add_sub_item(); + + return len; +}//read_sop() + +#endif //SHOW_PACKETS + +static unsigned short read_crg(unsigned char *s, const char *name_src) +{ + unsigned short len, i, v; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Component registration marker", name_buf); + add_sub_item(); + + len = get2(s); s += 2; + for(i = 0; i < Csiz; ++i) + { + v = get2(s); s += 2; + snprintf(item_name, MAX_ITEMBUF, "%s/Xcrg[%d] %hu", name_buf,i,v); + add_sub_item(); + } + for(i = 0; i < Csiz; ++i) + { + v = get2(s); s += 2; + snprintf(item_name, MAX_ITEMBUF, "%s/YXcrg[%d] %hu", name_buf,i,v); + add_sub_item(); + } + return len; +}//read_crg() + +static unsigned short read_com(unsigned char *s, const char *name_src) +{ + Fl_Tree_Item *sub; + char *txt; + unsigned short len; + unsigned int r, i, n; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Comment marker", name_buf); + add_sub_item(); + + len = get2(s); s += 2; + r = get2(s); s += 2; + n = len - 4; + txt = (char*)malloc(n + 8); + if(txt == NULL) return len; + + memset(txt, 0, n+8); + strcpy(txt, " "); + memcpy(txt+4, s, n); + + if(r > 1) i = 2; else i = r; + + snprintf(item_name, MAX_ITEMBUF, "%s/com1", name_buf); + sub = tree->add(item_name); + sub->label(reg_text[i]); + + snprintf(item_name, MAX_ITEMBUF, "%s/com2", name_buf); + sub = tree->add(item_name); + sub->label(txt); + +#ifdef SHOW_COM +fprintf(stderr,"%s:%d:\n\tCOM\n\tR[%d]%s\n\tT(%s)\n",__FILE__,__LINE__, +i,reg_text[i],txt); +#endif + free(txt); + + return len; +}//read_com() + +static unsigned char *read_sot(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + unsigned char *start; + unsigned short tile_nr; +#ifdef READ_ALL_SOT_MARKERS + unsigned short len; +#endif + uint64_t Psot; + unsigned char TPsot, TNsot; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Start of tile-part marker",name_buf); + add_sub_item(); + + start = s; +#ifdef READ_ALL_SOT_MARKERS + len = get2(s); s += 2; +#else + s += 2; +#endif + tile_nr = get2(s); s += 2; + + snprintf(item_name, MAX_ITEMBUF,"%s/TileNr(%d)",name_buf,tile_nr); + add_sub_item(); + + Psot = (uint64_t)get4(s); s += 4; + TPsot = s[0]; ++s; + TNsot = s[0]; ++s; + +#ifdef PSOT_LENG_FROM_BUF_END + if(Psot == 0) + { + Psot = (uint64_t)(dend - s); + + snprintf(item_name, MAX_ITEMBUF,"%s/Psot(%" PRIu64 ")",name_buf,Psot); + add_sub_item(); +/*--------------- +fprintf(stderr,"%s:%d:\n\tbuf_end(%p) - s(%p) ==> Psot(%lu)\n" +"\tbox_end(%p) - s(%p) ==> Psot(%lu)\n",__FILE__,__LINE__, +(void*)dend,(void*)s,Psot, +(void*)box_end,(void*)s,(uint64_t)(box_end - s) ); +---------------*/ + }//EOC, EOI +#else /* not PSOT_LENG_FROM_BUF_END */ + if(Psot == 0) + { + Psot = (uint64_t)(box_end - s); + + snprintf(item_name, MAX_ITEMBUF,"%s/Psot(%" PRIu64 ")",name_buf,Psot); + add_sub_item(); +/*------------------ +fprintf(stderr,"%s:%d:\n\tbuf_end(%p) - s(%p) ==> Psot(%lu):not used\n" +"\tbox_end(%p) - s(%p) ==> Psot(%lu)\n",__FILE__,__LINE__, +(void*)dend,(void*)s,(uint64_t)(dend - s), +(void*)box_end,(void*)s,Psot); +------------------*/ + } +#endif /* PSOT_LENG_FROM_BUF_END */ + +#ifdef READ_ALL_SOT_MARKERS + s = start + len; +#else + s = start + Psot - 2; +#endif + + snprintf(item_name, MAX_ITEMBUF,"%s/TPsot(%d)",name_buf, TPsot); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF,"%s/TNsot(%d)",name_buf, TNsot); + add_sub_item(); + + return s; +}//read_sot() + +static unsigned short read_qcd(unsigned char *s, const char *name_src) +{ +#ifdef QUANT_AS_STRING + const char *cs = ""; +#endif + unsigned short max_len, i; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Quantization default marker",name_buf); + add_sub_item(); + + max_len = get2(s); s += 2; + + for(i = 0; i < Csiz; ++i) + { + unsigned short sqcd, v, bits; + + sqcd = s[0]; ++s; + v = (sqcd & 0x1f); bits = (sqcd>>5); + +#ifdef QUANT_AS_STRING + if(v == 0) cs = "no";//No quantization + else + if(v == 1) cs = "implicit";//Scalar derived + else + if(v == 2) cs = "explicit";//Scalar expounded + else + cs = "unknown"; + + snprintf(item_name, MAX_ITEMBUF, "%s/Sqcd[%d] quant(%s) bits(%hu)", name_buf, + i,cs,bits); +#else + snprintf(item_name, MAX_ITEMBUF, "%s/Sqcd[%d] q(%hu) b(%hu)", name_buf, + i,v,bits); +#endif + + add_sub_item(); + } + + return max_len; +}//read_qcd(); + +static unsigned short read_epb(unsigned char *s, const char *name_src) +{ + unsigned int ldp, p; + unsigned short len, v; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + len = get2(s); s += 2; + + snprintf(item_name, MAX_ITEMBUF, "%s/Error protection block", name_buf); + add_sub_item(); + + v = s[0]; ++s; + snprintf(item_name, MAX_ITEMBUF, "%s/style(%hu)", name_buf, v); + add_sub_item(); + + ldp = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/length_of_data(%u)", name_buf, ldp); + add_sub_item(); + + p = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/parameters(%u)", name_buf, p); + add_sub_item(); + + + + return len; +}//read_epb() + +static unsigned short read_epc(unsigned char *s, const char *name_src) +{ + unsigned int cl; + unsigned short len, crc, epc; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + len = get2(s); s += 2; + + snprintf(item_name, MAX_ITEMBUF, "%s/Error protection capacity", name_buf); + add_sub_item(); + + crc = get2(s); s += 2; + snprintf(item_name, MAX_ITEMBUF, "%s/Parity crc(%hu)", name_buf, crc); + add_sub_item(); + + cl = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/codestrem_len(%u)", name_buf, cl); + add_sub_item(); + + epc = s[0]; ++s; + snprintf(item_name, MAX_ITEMBUF, "%s/parameter(%hu)", name_buf, epc); + add_sub_item(); + + return len; + +}//read_epc() + +static unsigned short read_esd(unsigned char *s, const char *name_src) +{ + unsigned short len, v; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + len = get2(s); s += 2; + + snprintf(item_name, MAX_ITEMBUF, "%s/Error sensitivity descriptor", name_buf); + add_sub_item(); + + if(Csiz < 257) + { + v = s[0]; ++s; + } + else + { + v = get2(s); s += 2; + } + snprintf(item_name, MAX_ITEMBUF, "%s/component(%hu)", name_buf, v); + add_sub_item(); + + v = s[0]; ++s; + snprintf(item_name, MAX_ITEMBUF, "%s/usage(%hu)", name_buf, v); + add_sub_item(); + + return len; + +}//read_esd() + +static unsigned short read_red(unsigned char *s, const char *name_src) +{ + unsigned short len, v; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + len = get2(s); s += 2; + + snprintf(item_name, MAX_ITEMBUF, "%s/Residual errors descriptor", name_buf); + add_sub_item(); + + v = s[0]; ++s; + snprintf(item_name, MAX_ITEMBUF, "%s/usage(%hu)", name_buf, v); + add_sub_item(); + + return len; + +}//read_red() + + +unsigned char *test_marker(unsigned char *s, unsigned char *box_end, + unsigned int type) +{ + unsigned int len; + unsigned char prefix, suffix; + + suffix = type & 0xff; + s += 2; + +/* 0x30 : 0x3f ==> reserved, no parameters */ + if(suffix >= 0x30 && suffix <= 0x3f) return s; + + len = get2(s); s += len; + if(s >= box_end) + { + fprintf(stderr,"\t1:MARKER %#x is unknown.\n",type); + return s;//box_end; + } + type = get2(s); + + if(s + 2 >= box_end) + { + fprintf(stderr,"\t2:MARKER %#x is unknown. STOP.\n",type); + return box_end; + } + prefix = (type>>8) & 0xff; suffix = type & 0xff; + + if(prefix == 0xff) return s; + + fprintf(stderr,"\t3:NEXT MARKER %#x is unknown. STOP.\n",type); + return box_end; +} + +unsigned char *read_jp2c(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + unsigned char *stop; +#ifdef DEBUG_JP2C + unsigned char *start0 = s; +#endif + unsigned int type, next_type, len; + int pos = -1; + int eoc_found = 0, sod_found = 0; + char name_buf[MAX_ITEMBUF]; + char iname[MAX_ITEMBUF+2]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Contiguous codestream box",name_buf); + add_sub_item(); + + + while(s < box_end) + { + type = get2(s); + ++pos; + +#ifdef DEBUG_JP2C +fprintf(stderr,"[%03d] marker(%#x) position(%ld)\n",pos,type,(long)(s-start0)); +#endif + s += 2; len = 0; + + switch(type) + { + case J2K_SOC: + { + Fl_Tree_Item *sup; + + snprintf(iname, MAX_ITEMBUF,"%s/[%03d] SOC",name_buf,pos); + sup = tree->add(iname); + + snprintf(item_name, + MAX_ITEMBUF, "%s/Start of codestream marker", iname); + add_sub_item(); + + sup->close(); + continue; + } + + case J2K_SOT: + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] SOT", name_buf,pos); + sup = tree->add(item_name); + + s = read_sot(s, box_end, dend, item_name); + + sup->close(); + continue; + } + + case J2K_SOD: + { + Fl_Tree_Item *sup; + + snprintf(iname, MAX_ITEMBUF,"%s/[%03d] SOD",name_buf,pos); + sup = tree->add(iname); + + snprintf(item_name, MAX_ITEMBUF, "%s/Start of data marker",iname); + add_sub_item(); + + sup->close(); + sod_found = 1; + + next_type = get2(s); + + if(next_type == J2K_SOT || next_type == J2K_SOP) + { + continue; + } + s = dend - 2; + continue; + } + + case J2K_EOC: + { + Fl_Tree_Item *sup; + + snprintf(iname, MAX_ITEMBUF,"%s/[%03d] EOC",name_buf,pos); + sup = tree->add(iname); + + snprintf(item_name, MAX_ITEMBUF,"%s/End of codestream marker",iname); + add_sub_item(); + + sup->close(); + eoc_found = 1; + continue; + } + + case J2K_SIZ: + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF,"%s/[%03d] SIZ",name_buf,pos); + sup = tree->add(item_name); + + s += read_siz(s, item_name); + + sup->close(); + continue; + } + + case J2K_COD: + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF,"%s/[%03d] COD", name_buf,pos); + sup = tree->add(item_name); + + s += read_cod(s, item_name); + + sup->close(); + continue; + } + + case J2K_COC: + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] COC", name_buf,pos); + sup = tree->add(item_name); + + s += read_coc(s, item_name); + + sup->close(); + + continue; + } + case J2K_RGN: + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] RGN", name_buf,pos); + sup = tree->add(item_name); + + s += read_rgn(s, item_name); + + sup->close(); + continue; + } + + case J2K_QCD: + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF,"%s/[%03d] QCD", name_buf,pos); + sup = tree->add(item_name); + + s += read_qcd(s, item_name); + + sup->close(); + continue; + } + + case J2K_QCC: + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] QCC", name_buf,pos); + sup = tree->add(item_name); + + s += read_qcc(s, item_name); + + sup->close(); + continue; + } + + case J2K_POC://POD + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] POC", name_buf,pos); + sup = tree->add(item_name); + + s += read_poc(s, item_name); + + sup->close(); + continue; + } + + case J2K_TLM: + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] COC", name_buf,pos); + sup = tree->add(item_name); + + s += read_tlm(s, item_name); + + sup->close(); + continue; + } + + case J2K_PLM: + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] PLM", name_buf,pos); + sup = tree->add(item_name); + + s += read_plm(s, item_name); + + sup->close(); + continue; + } + + case J2K_PLT: + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] PLT", name_buf,pos); + sup = tree->add(item_name); + + s += read_plt(s, item_name); + + sup->close(); + continue; + } + + case J2K_PPM: + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] PPM", name_buf,pos); + sup = tree->add(item_name); + + s += read_ppm(s, item_name); + + sup->close(); + continue; + } + + case J2K_PPT: + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] PPT", name_buf,pos); + sup = tree->add(item_name); + + s += read_ppt(s, item_name); + + sup->close(); + continue; + } + + case J2K_SOP: + { +#ifdef SHOW_PACKETS + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] SOP", name_buf,pos); + sup = tree->add(item_name); + + s += read_sop(s, item_name); + + sup->close(); +#endif + stop = box_end - 2; + next_type = 0; + while(s < stop) + { + if(s[0] == 0xff) + { + next_type = get2(s); + + if(next_type == J2K_EPH) break; + } + ++s; + } + continue; + } + + case J2K_EPH: + { +#ifdef SHOW_PACKETS + Fl_Tree_Item *sup; + + snprintf(iname, MAX_ITEMBUF, "%s/[%03d] EPH", name_buf,pos); + sup = tree->add(iname); + + snprintf(item_name, MAX_ITEMBUF, "%s/End of packet marker", iname); + add_sub_item(); + + sup->close(); +#endif + stop = box_end - 2; next_type = 0; + while(s < stop) + { + if(s[0] == 0xff) + { + next_type = get2(s); + if(next_type == J2K_SOP || next_type == J2K_SOT) break; + } + ++s; + } + continue; + } + + case J2K_CRG: + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] CRG", name_buf,pos); + sup = tree->add(item_name); + + s += read_crg(s, item_name); + + sup->close(); + continue; + } + + case J2K_COM://CME + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] COM", name_buf,pos); + sup = tree->add(item_name); + + s += read_com(s, item_name); + + sup->close(); + continue; + } + + case J2K_EPC://JPWL + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] EPC", name_buf,pos); + sup = tree->add(item_name); + + s += read_epc(s, item_name); + + sup->close(); + continue; + } + + case J2K_EPB://JPWL + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] EPB", name_buf,pos); + sup = tree->add(item_name); + + s += read_epb(s, item_name); + + sup->close(); + continue; + } + + case J2K_ESD://JPWL + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] ESD", name_buf,pos); + sup = tree->add(item_name); + + s += read_esd(s, item_name); + + sup->close(); + continue; + } + + case J2K_RED://JPWL + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] RED", name_buf,pos); + sup = tree->add(item_name); + + s += read_red(s, item_name); + + sup->close(); + continue; + } + + case J2K_SEC://JPSEC + { + Fl_Tree_Item *item; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] SEC", name_buf,pos); + item = tree->add(item_name); + item->usericon(&L_documentpixmap); + + len = get2(s); s += len; + + continue; + } + + case J2K_INSEC://JPSEC + { + Fl_Tree_Item *item; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] INSEC", name_buf,pos); + item = tree->add(item_name); + item->usericon(&L_documentpixmap); + + len = get2(s); s += len; + + continue; + } +/*---------- Part 2, Extensions ---------------*/ + case J2K_DCO: + { + Fl_Tree_Item *item; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] dco", name_buf,pos); + item = tree->add(item_name); + item->usericon(&L_documentpixmap); + + len = get2(s); s += len; + + continue; + } + + case J2K_VMS: + { + Fl_Tree_Item *item; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] vms", name_buf,pos); + item = tree->add(item_name); + item->usericon(&L_documentpixmap); + + len = get2(s); s += len; + + continue; + } + + case J2K_DFS: + { + Fl_Tree_Item *item; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] dfs", name_buf,pos); + item = tree->add(item_name); + item->usericon(&L_documentpixmap); + + len = get2(s); s += len; + + continue; + } + + case J2K_ADS: + { + Fl_Tree_Item *item; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] ads", name_buf,pos); + item = tree->add(item_name); + item->usericon(&L_documentpixmap); + + len = get2(s); s += len; + + continue; + } + + case J2K_MCT: + { + Fl_Tree_Item *item; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] mct", name_buf,pos); + item = tree->add(item_name); + item->usericon(&L_documentpixmap); + + len = get2(s); s += len; + + continue; + } + + case J2K_MCC: + { + Fl_Tree_Item *item; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] mcc", name_buf,pos); + item = tree->add(item_name); + item->usericon(&L_documentpixmap); + + len = get2(s); s += len; + + continue; + } + + case J2K_NLT: + { + Fl_Tree_Item *item; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] nlt", name_buf,pos); + item = tree->add(item_name); + item->usericon(&L_documentpixmap); + + len = get2(s); s += len; + + continue; + } + + case J2K_CBD: + { + Fl_Tree_Item *item; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] cbd", name_buf,pos); + item = tree->add(item_name); + item->usericon(&L_documentpixmap); + + len = get2(s); s += len; + + continue; + } + + case J2K_ATK://jp3d + { + Fl_Tree_Item *item; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] atk", name_buf,pos); + item = tree->add(item_name); + item->usericon(&L_documentpixmap); + + len = get2(s); s += len; + + continue; + } + + case J2K_MIC: + { + Fl_Tree_Item *item; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] mic", name_buf,pos); + item = tree->add(item_name); + item->usericon(&L_documentpixmap); + + len = get2(s); s += len; + + continue; + } + +/*--------------- end Part 2 ----------------*/ + + default: + { + Fl_Tree_Item *item; + + snprintf(iname, MAX_ITEMBUF, "%s/[%03d] Unknown marker 0x%x", + name_buf,pos,type); + item = tree->add(iname); + item->usericon(&L_documentpixmap); + +#ifdef DEBUG_DEFAULT_TEST +fprintf(stderr,"test_marker:box_end(%p) - s(%p) ==> %ld\n", +(void*)box_end,(void*)s,(long)(box_end - s)); +#endif + s = test_marker(s, box_end, type); + } + break; + } + } + + if(sod_found && ! eoc_found) + { + Fl_Tree_Item *sup; + + snprintf(iname, MAX_ITEMBUF,"%s/[%03d] EOC",name_buf,pos); + sup = tree->add(iname); + + snprintf(item_name, MAX_ITEMBUF,"%s/End of codestream marker",iname); + add_sub_item(); + + sup->close(); + } + + if((box_end - s) == 0) return box_end; + +#ifdef DEBUG_JP2C_END +fprintf(stderr,"\n%s:%d:END OF READ_JP2C\n" +"\ts(%p) - box_end(%p) ==> %d\n",__FILE__,__LINE__, +(void*)s,(void*)box_end, (int)(s - box_end) ); + + +fprintf(stderr,"\tBOX_END[-1:-7] %02x,%02x,%02x,%02x,%02x,%02x,%02x\n", +box_end[-1],box_end[-2],box_end[-3],box_end[-4], +box_end[-5],box_end[-6],box_end[-7]); + +fprintf(stderr,"\tDEND[-1:-7] %02x,%02x,%02x,%02x,%02x,%02x,%02x\n", +dend[-1],dend[-2],dend[-3],dend[-4],dend[-5],dend[-6],dend[-7]); +#endif + + if(s <= box_end) + { +#ifdef DEBUG_JP2C_END + fprintf(stderr,"EXIT read_jp2c\n\tbox_end - s ==> %lu\n", + (unsigned long)(box_end - s)); + fprintf(stderr,"\tbox_end(%p)\n\tbuf_end(%p)\n",(void*)box_end, + (void*)dend); +#endif + return box_end; + } +#ifdef DEBUG_JP2C_END + fprintf(stderr,"EXIT read_jp2c\n\tdend(%p) - s(%p) ==> %lu\n", + (void*)dend,(void*)s,(unsigned long)(dend - s)); + fprintf(stderr,"\tWARNING: s(%p) > box_end(%p) ==> %lu\n", + (void*)s,(void*)box_end,(unsigned long)(s - box_end)); +#endif + return box_end; + +}// read_jp2c() + +unsigned char *read_jp2i(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + snprintf(item_name, MAX_ITEMBUF, "%s/Intellectual property box", name_src); + add_sub_item(); + + return box_end; +}//read_jp2i() + +unsigned char *read_xml(unsigned char *s, unsigned char *box_end, + unsigned char *dend, char **out_buf) +{ + char *b; + size_t len; + + assert(box_end <= dend); + + len = (box_end - s); + b = (char*)calloc(1, len+8); + if(b == NULL) return box_end; + +//FIXME memcpy(b, (char*)s, len); b[len] = 0; + fl_utf8toa((char*)s, (unsigned int)len, b, (unsigned int)len); +#ifdef SHOW_XML +fprintf(stderr,"\n%s:%d:\n\tXML(%s)\n\n",__FILE__,__LINE__,b); +#endif +//FIXME to short output + b[32] = 0; + *out_buf = b; + + return box_end; +}//read_xml() + +unsigned char *read_url(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + unsigned int flag, src_len, dst_len; + unsigned short vers; + char name_buf[MAX_ITEMBUF]; + char dst[2048]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Data Entry URL box",name_buf); + add_sub_item(); + + vers = (unsigned short)s[0]; ++s; + flag = get_size(s, 3); s += 3; + src_len = (unsigned int)strlen((char*)s); + dst_len = fl_utf8toa((char*)s, src_len, dst, 2047); + + snprintf(item_name, MAX_ITEMBUF,"%s/DE vers(%hu) flag(%u) url[%u](%s)", + name_buf, vers,flag,dst_len,dst); + add_sub_item(); + + return box_end; +} + +unsigned char *read_ulst(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + char name_buf[MAX_ITEMBUF]; + unsigned char buf[13]; + unsigned int i, n, id; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/UUID List box",name_buf); + + buf[12] = 0; + n = get2(s); s += 2; + + for(i = 0; i < n; ++i) + { + id = get4(s); s += 4; memcpy(buf, s, 12); s += 12; + snprintf(item_name, MAX_ITEMBUF, "%s/[%u]ID(%u%s)",name_buf,i,id,buf); + add_sub_item(); + } + return box_end; +} + +unsigned char *read_uuid(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + unsigned int len; + char name_buf[MAX_ITEMBUF]; + char data[2048]; + char dst[2048]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, + "%s/Universal unique identifier box", name_buf); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, + "%s/ID(%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x)", + name_buf, + s[0], s[1], s[2], s[3], + s[4], s[5], + s[6], s[7], + s[8], s[9], + s[10], s[11], s[12], s[13], s[14], s[15] ); + s += 16; + add_sub_item(); + + memset(data, 0, 2048); + memset(dst, 0, 2048); + + len = (unsigned int)(box_end - s); + if(len > 2047) len = 2047; + memcpy(data, s, len); data[len] = 0; + fl_utf8toa((char*)data, len, dst, len); +#ifdef SHOW_UUID_DATA + dst[len] = 0; +fprintf(stderr,"%s:%d:\n\tDATA(%s)\n",__FILE__,__LINE__,dst); +#else + dst[32] = 0; +#endif + snprintf(item_name, MAX_ITEMBUF, "%s/data(%s)",name_buf,dst); + add_sub_item(); + + return box_end; +} + +unsigned char *read_uinf(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + uint64_t box_len; + unsigned int hstep; + char name_buf[MAX_ITEMBUF]; + int pos = -1; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/UUID Info box",name_buf); + add_sub_item(); + + box_len = read_boxheader(s, dend, &hstep); + + if(memcmp(box_name, "ulst", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] uinf", name_buf, ++pos); + sup = tree->add(item_name); + + s = read_ulst(s + hstep, s + box_len, dend, item_name); + + sup->close(); + + box_len = read_boxheader(s, dend, &hstep); + } + + if(memcmp(box_name, "url ", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] url", name_buf, ++pos); + sup = tree->add(item_name); + + s = read_url(s + hstep, s + box_len, dend, item_name); + + sup->close(); + } + + return box_end; +} + +static void test_ftyp(FTYPInfo *info, unsigned char *s, + unsigned char *box_end) +{ + int i, n; + unsigned char buf[5]; + + buf[4] = 0; + memcpy(buf, s, 4); s += 4; + +#ifdef DEBUG_TEST_FTYP +fprintf(stderr,"%s:%d:\n\tFTYP BRAND(%s)\n",__FILE__,__LINE__,(char*)buf); +#endif + + if(strcasecmp((char*)buf, "jp2 ") == 0) + info->brand_jp2 = 1; + else + if(strcasecmp((char*)buf, "jpx ") == 0) + info->brand_jpx = 1; + else + if(strcasecmp((char*)buf, "jpm ") == 0) + info->brand_jpm = 1; + + info->minv = get4(s); s += 4; + + n = (int)((box_end - s)/4); + + for(i = 0; i < n; ++i) + { + memcpy(buf, s, 4); s += 4; +#ifdef DEBUG_TEST_FTYP +fprintf(stderr,"%s:%d:\n\tFTYP CL[%d]%s\n",__FILE__,__LINE__,i,(char*)buf); +#endif + + if(strcasecmp((char*)buf, "jp2 ") == 0) + info->compat_jp2 = 1; + else + if(strcasecmp((char*)buf, "jp21") == 0) + info->compat_jp21 = 1; + else + if(strcasecmp((char*)buf, "jpx ") == 0) + info->compat_jpx = 1; + else + if(strcasecmp((char*)buf, "jpxb") == 0) + info->compat_jpxb = 1; + else + if(strcasecmp((char*)buf, "jpm ") == 0) + info->compat_jpm = 1; + + } +}/* test_ftyp() */ + +int JPEG2000_test_ftyp(const char *fname, unsigned char *s, uint64_t size, + FTYPInfo *info) +{ + unsigned char *dend; + const char *cs; + uint64_t box_len; + unsigned int hstep, found = 0; + + memset(info, 0, sizeof(struct ftyp_info)); + + dend = s + size; + + if(memcmp(s, JP2_RFC3745_MAGIC, 12) == 0) + { + info->magic_len = 12; + } + else + if(memcmp(s, JP2_MAGIC, 4) == 0) + { + info->magic_len = 4; + } + else + if(memcmp(s, J2K_CODESTREAM_MAGIC, 4) == 0) + { + info->is_j2k = 1; + info->decod_format = J2K_CFMT; + + return 1; + } + else + return 0; + + s += info->magic_len; + + while(s < dend) + { + box_len = read_boxheader(s, dend, &hstep); + + if( box_len == 0) break; + + if(memcmp(box_name, "ftyp", 4) == 0) + { + test_ftyp(info, s + hstep, s + box_len); + + found = 1; + break; + } + s += box_len; + + }//while( + + if(found == 0) + { + fprintf(stderr,"\nJPX_read_ftyp: no ftyp box found. STOP.\n\n"); + return 0; + } + + if((cs = strrchr(fname, '.')) != NULL) + { + ++cs; + + if(strncasecmp(cs, "jpt", 3) == 0) + { + info->decod_format = JPT_CFMT; + info->is_jpt = 1; + + return 1; + } + } + info->decod_format = JP2_CFMT; + + if(info->brand_jpx) + { + info->is_jpx = 1; + + return 1; + } + + if(info->brand_jp2) + { + info->is_jp2 = 1; + + return 1; + } + + if(info->brand_jpm) + { + info->is_jpm = 1; + + return 1; + } + return 0; +}//JPEG2000_test_ftyp() + +int JPEG2000_build_tree(const char *read_idf) +{ + unsigned char *src, *s, *box_end, *dend; + const char *basename; + uint64_t box_len; +#ifdef HAVE_FSEEKO + off_t src_len; +#elif HAVE_FSEEKI64 + int64_t src_len; +#else + long src_len; +#endif + unsigned int hstep; + int pos = -1; + unsigned short is_codestream = 0, is_mj2 = 0, is_jpx = 0, is_jpm = 0; + FILE *reader; + char sup_name[MAX_ITEMBUF+2]; + + if((reader = fopen(read_idf, "rb")) == NULL) return 0; + + (void)fread(box_name, 1, 12, reader); + rewind(reader); + + if(memcmp(box_name, JP2_RFC3745_MAGIC, 12) == 0) + { + box_len = (uint64_t)12; + strcpy((char*)box_name, "jP "); + } + else + if(memcmp(box_name, JP2_MAGIC, 4) == 0) + { + box_len = (uint64_t)4; + strcpy((char*)box_name, "jP "); + } + else + if(memcmp(box_name, J2K_CODESTREAM_MAGIC, 4) == 0) + { + box_len = (uint64_t)0; *box_name = 0; + is_codestream = 1; + } + else + { + fprintf(stderr, "NOT A JPEG2000 FILE: %s\n",read_idf); + fclose(reader); + return 0; + } +#ifdef _WIN32 + basename = strrchr(read_idf, '\\'); +#else + basename = strrchr(read_idf, '/'); +#endif + if(basename) ++basename; else basename = read_idf; + + if(tree != NULL) + { + tree->clear(); + } + box_name[4] = 0; + +#ifdef HAVE_FSEEKO + fseeko(reader, 0, SEEK_END); +#elif HAVE_FSEEKI64 + _fseeki64(reader, 0, SEEK_END); +#else + fseek(reader, 0, SEEK_END); +#endif + +#ifdef HAVE_FSEEKO + src_len = ftello(reader); +#elif HAVE_FSEEKI64 + src_len = _ftelli64(reader); +#else + src_len = ftell(reader); +#endif + +#ifdef HAVE_FSEEKO + fseeko(reader, 0, SEEK_SET); +#elif HAVE_FSEEKI64 + _fseeki64(reader, 0, SEEK_SET); +#else + fseek(reader, 0, SEEK_SET); +#endif + + src = (unsigned char*) malloc(src_len+4); + + if(src == NULL) + { + fclose(reader); + return 0; + } + (void)fread(src, 1, src_len, reader); + + fclose(reader); + reader = NULL; + + init(); + + memset(&jp2_color, 0, sizeof(jp2_color_t)); + + s = src + (ptrdiff_t)box_len; + dend = src + (ptrdiff_t)src_len; + memset(src+(ptrdiff_t)src_len,'1',4); + + if(is_codestream) + { + Fl_Tree_Item *sup; + + snprintf(sup_name, MAX_ITEMBUF, "[%03d] jp2c", ++pos); + sup = tree->add(sup_name); + +//-------------- J2K ----------------- + s = read_jp2c(s, dend, dend, sup_name); +//-------------- J2K ----------------- + sup->close(); + } + else + { + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) { s = dend; goto end_mark; } + + box_end = s + (ptrdiff_t)box_len; + + if(box_end >= dend) { s = dend; goto end_mark; } + + if(memcmp(box_name, "ftyp", 4) == 0) + { + unsigned char brand[5]; + + brand[4] = 0; + memcpy(brand, s+hstep, 4); + + if(memcmp(brand, "mjp2", 4) == 0) + is_mj2 = 1; + else + if(memcmp(brand, "jpx ", 4) == 0) + is_jpx = 1; + else + if(memcmp(brand, "jpm ", 4) == 0) + is_jpm = 1; + } + if(is_mj2) + { +//------------------------ + read_mj2(s, dend); +//------------------------ + goto end_mark; + } + + if(is_jpx) + { +//------------------------ + read_jpx(src, s, dend); +//------------------------ + goto end_mark; + } + + if(is_jpm) + { +//------------------------ + read_jpm(src, s, dend); +//------------------------ + goto end_mark; + } +//------- JP2, JPM ------- + while(s < dend) + { + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) { s = dend; break; } + + if((uint64_t)(dend - s) < box_len) + box_end = dend; + else + box_end = s + (ptrdiff_t)box_len; + + if(memcmp(box_name, "ftyp", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(sup_name, MAX_ITEMBUF, "[%03d] ftyp", ++pos); + sup = tree->add(sup_name); + + s = read_ftyp(s + hstep, s + box_len, sup_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "jp2h", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(sup_name, MAX_ITEMBUF, "[%03d] jp2h", ++pos); + sup = tree->add(sup_name); + + s = read_jp2h(s + hstep, s + box_len, dend, sup_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "jp2c", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(sup_name, MAX_ITEMBUF, "[%03d] jp2c", ++pos); + sup = tree->add(sup_name); +/*----------------------------------------------------------*/ + s = read_jp2c(s + hstep, s + box_len, dend, sup_name); +/*----------------------------------------------------------*/ + assert(s == box_end); + + sup->close(); + continue; + } + + if(memcmp(box_name, "jp2i", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(sup_name, MAX_ITEMBUF, "[%03d] jp2i", ++pos); + sup = tree->add(sup_name); + + s = read_jp2i(s + hstep, s + box_len, dend, sup_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "xml ", 4) == 0 + || memcmp(box_name, "XML ", 4) == 0) + { + Fl_Tree_Item *sup, *sub; + char *buf = NULL; + + snprintf(sup_name, MAX_ITEMBUF, "[%03d] XML", ++pos); + sup = tree->add(sup_name); + + snprintf(sup_name, MAX_ITEMBUF, "%s/xml1", sup_name); + sub = tree->add(sup_name); + + s = read_xml(s + hstep, s + box_len, dend, &buf); + + sub->label(buf); + + sup->close(); + + free(buf); + continue; + } + + if(memcmp(box_name, "uuid", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(sup_name, MAX_ITEMBUF, "[%03d] uuid", ++pos); + sup = tree->add(sup_name); + + s = read_uuid(s + hstep, s + box_len, dend, sup_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "uinf", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(sup_name, MAX_ITEMBUF, "[%03d] uinf", ++pos); + sup = tree->add(sup_name); + + s = read_uinf(s + hstep, s + box_len, dend, sup_name); + + sup->close(); + continue; + } + { + Fl_Tree_Item *sup; + + snprintf(sup_name, MAX_ITEMBUF, "[%03d] %s", ++pos, (char*)box_name); + sup = tree->add(sup_name); + + snprintf(item_name, MAX_ITEMBUF, "%s/Not handled. Skipped.", sup_name); + add_sub_item(); + + sup->close(); + + } +#ifdef PRINTF_UNKNOWN_BOX +fprintf(stderr,"%s:%d:\n\tTRACE Unknown Box name(%s) len(%ld)\n" +"\tbox_end - s(%ld) dend - s(%ld)\n",__FILE__,__LINE__, +(char*)box_name,box_len,(box_end - s),(dend - s) ); +#endif + s = box_end; + + }//while( + + } +end_mark: + + free(src); + snprintf(sup_name, MAX_ITEMBUF, "%s (%" PRId64 " Byte)", basename, + (int64_t)src_len); + tree->root_label(sup_name); + tree->labelsize(TREE_LABEL_SIZE); + tree->redraw(); + + return 1; + +}// JPEG2000_build_tree() diff --git a/src/bin/fltk/flviewer/read_jpm.cxx b/src/bin/fltk/flviewer/read_jpm.cxx new file mode 100644 index 00000000..f9892182 --- /dev/null +++ b/src/bin/fltk/flviewer/read_jpm.cxx @@ -0,0 +1,2021 @@ +/* + * Part 6 Compound image file format, Mixed raster content JPM + * + * Problem: Shall 'scal' and 'jp2h' be shown even if 'no_codestream == 1'? + * There should not be scal/jp2h boxes. But could be. +*/ +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#include +#define strcasecmp _stricmp +#define strncasecmp _strnicmp +#define snprintf _snprintf +#define sprintf _scprintf +#define strdup _strdup +#else /* not _WIN32 */ +#define __STDC_FORMAT_MACROS +#include +#endif /* _WIN32 */ + +#include +#include +#include +#include + +#include "opj_inttypes.h" +#include "opj_stdint.h" + +#include "viewerdefs.hh" +#include "tree.hh" + + +//#define DEBUG_JPM +//#define DEBUG_JPM_JPX + +//--------- FORWARD +static unsigned char *jpm_start; + +static int has_thumbnail_jp2h; +static uint64_t thumbnail_jp2hpos; +static uint64_t thumbnail_jp2hlen; +static unsigned int thumbnail_jp2hstep; + +static int has_thumbnail_jp2c; +static uint64_t thumbnail_jp2cpos; +static uint64_t thumbnail_jp2clen; +static unsigned int thumbnail_jp2cstep; + +static unsigned char *read_lbl(unsigned char *s, unsigned char *box_end, + const char *name_src); +static unsigned char *read_phdr(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src, unsigned short *out_nrid); + +static unsigned char *read_lobj(unsigned short cur_id, unsigned short max_id, + unsigned char *s, unsigned char *box_end, unsigned char *dend, + const char *name_src); + +static unsigned char *read_flst(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src); +static unsigned char *read_ppcl(unsigned char *s, unsigned char *box_end, + const char *name_src); + + +#define LOG(s) fprintf(stderr,"%s:%d:%s\n",__FILE__,__LINE__,s) + +static const char *otype_values[]={ +"The object contains the mask of a layout object", +"The object contains the image of a layout object", +"The object contains the image and mask of a layout object", +"Reserved value" +}; + +static const char *lhdr_styles[]={ +"Separate objects for image and mask components", +"Single object for image and mask components", +"Single object for image only components", +"Single object for mask only components", +"Vendor specific layout object"// 255 +}; + +static const char *pcolor_values[]={ +"Page is transparent", +"Page is white", +"Page is black", +"Page color is specified in Base Color box", +"Reserved for ISO use" +}; + +static const char *or_values[]={ +"Orientation not specified", +"Rotate 0 degr clockwise for a right reading image", +"Rotate 90 degr clockwise for a right reading image", +"Rotate 180 degr clockwise for a right reading image", +"Rotate 270 degr clockwise for a right reading image", +"Reserved for ISO use" +}; + +//--------- END FORWARD + + static const char *L_document_xpm[] = +{ + "11 11 3 1", + ". c None", + "x c #d8d8f8", + "@ c #202060", + ".@@@@@@....", + ".@xxx@.@...", + ".@xxx@..@..", + ".@xxx@@@@@.", + ".@xxxxxxx@.", + ".@xxxxxxx@.", + ".@xxxxxxx@.", + ".@xxxxxxx@.", + ".@xxxxxxx@.", + ".@xxxxxxx@.", + ".@@@@@@@@@." +}; +static Fl_Pixmap L_documentpixmap(L_document_xpm); + +static char item_name[MAX_ITEMBUF+2]; + +static void add_sub_item() +{ + Fl_Tree_Item *sub = tree->add(item_name); + sub->usericon(&L_documentpixmap); +} + +static const char *pagt_flag_values(unsigned short fl) +{ + if(fl == 0) return "'Offset to PCOL box'"; + if(fl & 1) return "'Offset to PAGE box'"; + if(fl & 3) return "'Offset to PAGE box containing thumbnail'"; + if(fl & 4) return "'Offset to auxPCOL box'"; + if(fl & 8) return "'Offset to PAGE or PCOL box containing metadata'"; + if(fl & 9) return "'Offset to PAGE box with meta'"; + if(fl & 12) return "'Offset to auxPCOL box with meta'"; + + return "'Unknown'"; +} + +static unsigned char *read_sdat(unsigned char *s, unsigned char *box_end, + const char *name_src) +{ + uint64_t len, l; + unsigned short id; + char name_buf[MAX_ITEMBUF]; + char data[MAX_ITEMBUF+1]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/SDAT box", name_buf); + add_sub_item(); + + id = get2(s); s += 2; + len = (box_end - s); + + snprintf(item_name, MAX_ITEMBUF, "%s/id %hu", name_buf, id); + add_sub_item(); + + l = len; if(l > MAX_ITEMBUF) l = MAX_ITEMBUF; + + memcpy(data, s, l); data[l] = 0; + snprintf(item_name, MAX_ITEMBUF, "%s/data[%lu](%s)", name_buf, + len,data); + add_sub_item(); + + return box_end; +} + +static unsigned char *read_sref(unsigned char *s, unsigned char *box_end, + const char *name_src) +{ + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/SREF box", name_buf); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/id %hu", name_buf, get2(s)); + add_sub_item(); + s += 2; + + return box_end; +} + +static unsigned char *read_mhdr(unsigned char *s, unsigned char *box_end, + const char *name_src) +{ + uint64_t mpcoff; + unsigned int np, mpclen; + unsigned short p, sc, c0, c1; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Compound Image Header box", name_buf); + add_sub_item(); + + np = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/nr_pages(%u)",name_buf,np); + add_sub_item(); + + p = (unsigned short)s[0]; ++s; + snprintf(item_name, MAX_ITEMBUF, "%s/profile(%hu)",name_buf,p); + add_sub_item(); + + sc = (unsigned short)s[0]; ++s; + snprintf(item_name, MAX_ITEMBUF, "%s/self-contained(%hu)",name_buf,sc); + add_sub_item(); + + mpcoff = get8(s); s += 8; + mpclen = get4(s); s += 4; + + snprintf(item_name, MAX_ITEMBUF, "%s/mpcoff(%lu)",name_buf,mpcoff); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/mpclen(%u)",name_buf,mpclen); + add_sub_item(); + + c0 = s[0]; ++s; c1 = 0; + if(c0&128) { c1 = s[0]; ++s; } + + snprintf(item_name, MAX_ITEMBUF, "%s/MaskCoder(%hu)",name_buf, + (c1<<8)|(c0&0xff)); + add_sub_item(); + + c0 = s[0]; ++s; c1 = 0; + if(c0&128) { c1 = s[0]; ++s; } + + snprintf(item_name, MAX_ITEMBUF, "%s/ImgCoder(%hu)",name_buf, + (c1<<8)|(c0&0xff)); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/ip_rights(%hu)",name_buf, + (unsigned short)s[0]); + add_sub_item(); + + +#ifdef DEBUG_JPM +fprintf(stderr,"EXIT read_mhdr (s - box_end) ==> %ld\n", +(long)(s - box_end)); +#endif + + return box_end; +}// read_mhdr() + +unsigned char *read_dtbl(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + unsigned char *start; + uint64_t box_len; + unsigned int flag, src_len, dst_len, hstep; + unsigned short i, n, vers; + char name_buf[MAX_ITEMBUF]; + char dst[2048]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Data Reference box", name_buf); + add_sub_item(); + + n = get2(s); s += 2; + snprintf(item_name, MAX_ITEMBUF, "%s/nr_ref(%u)",name_buf,n); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, + "%s/DR[0]version(0) flag(0)\n\t loc[0]''",name_buf); + add_sub_item(); + + for(i = 1; i <= n; ++i) + { + start = s; + box_len = read_boxheader(s, dend, &hstep); + + if(memcmp(box_name, "url ", 4) == 0) + { + s += hstep; + + vers = (unsigned short)s[0]; ++s; + flag = get_size(s, 3); s += 3; + src_len = (unsigned int)strlen((char*)s); + dst_len = fl_utf8toa((char*)s, src_len, dst, 2047); + + snprintf(item_name, MAX_ITEMBUF, + "%s/DR[%u]version(%u) flag(%u) loc[%u]'%s'", + name_buf,i,vers,flag,dst_len,dst); + add_sub_item(); + } + s = start + box_len; + } +#ifdef DEBUG_JPM_JPX +fprintf(stderr,"\tEXIT read_dtbl (s - box_end) ==> %ld\n",(long)(s - box_end)); +#endif + return box_end; +}//read_dtbl() + +static unsigned char *read_pagt(unsigned char *s, unsigned char *box_end, + const char *name_src) +{ + unsigned short dr, flag; + unsigned int i, len, ne; + uint64_t off; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Page Table box", name_buf); + add_sub_item(); + + ne = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/ne(%u)",name_buf,ne); + add_sub_item(); + + for(i = 0; i < ne; ++i) + { + off = get8(s); s += 8; + len = get4(s); s += 4; + dr = get2(s); s += 2; + flag = (unsigned short)s[0]; ++s; + + snprintf(item_name, MAX_ITEMBUF, + "%s/[%2u] off(%lu) len(%u)", name_buf,i,off,len); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, + "%s/[%2u] dr(%hu)",name_buf,i,dr); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, + "%s/[%2u] flag[%hu]%s", name_buf,i,flag,pagt_flag_values(flag)); + add_sub_item(); + } +#ifdef DEBUG_JPM +fprintf(stderr,"\tEXIT read_pagt(s - box_end) ==> %ld\n",(long)(s - box_end)); +#endif + return box_end; + +}/* read_pagt() */ + +static unsigned char *read_pcol(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src, uint64_t offset, + uint64_t len) +{ + uint64_t box_len; + unsigned int hstep, has_pagt = 0; + char name_buf[MAX_ITEMBUF]; + char iname[MAX_ITEMBUF]; + int pos = -1; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Page Collection box", name_buf); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/offset(%ld) len(%ld)", + name_buf, offset, len); + add_sub_item(); + + while(s < box_end) + { + box_len = read_boxheader(s, dend, &hstep); + + if(memcmp(box_name, "ppcl", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] ppcl",name_buf,++pos); + sup = tree->add(item_name); +//pcol + s = read_ppcl(s + hstep, s + box_len, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "lbl ", 4) == 0) + { + Fl_Tree_Item *sup; + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] lbl ",name_buf,++pos); + + sup = tree->add(item_name); + + s = read_lbl(s + hstep, s + box_len, item_name); + + sup->close(); + continue; + } + if(memcmp(box_name, "xml ", 4) == 0 + || memcmp(box_name, "XML ", 4) == 0) + { + Fl_Tree_Item *sup, *sub; + char *buf = NULL; + + snprintf(iname, MAX_ITEMBUF, "%s/[%03d] xml", name_buf, ++pos); + sup = tree->add(iname); + + snprintf(item_name, MAX_ITEMBUF, "%s/xml1", iname); + sub = tree->add(item_name); + + s = read_xml(s + hstep, s + box_len, dend, &buf); + + sub->label(buf); + + sup->close(); + free(buf); --pos; + continue; + } + if(memcmp(box_name, "uuid", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] uuid", name_buf, ++pos); + sup = tree->add(item_name); + + s = read_uuid(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + if(memcmp(box_name, "uinf", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] uinf", name_buf, ++pos); + sup = tree->add(item_name); + + s = read_uinf(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } +//pcol + if(memcmp(box_name, "pagt", 4) == 0) + { + Fl_Tree_Item *sup; + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] pagt",name_buf,++pos); + + sup = tree->add(item_name); + + s = read_pagt(s + hstep, s + box_len, item_name); + + sup->close(); + has_pagt = 1; + continue; + } + { + Fl_Tree_Item *sup; + char iname[MAX_ITEMBUF+2]; + + snprintf(iname, MAX_ITEMBUF, "%s/[%03d] %s", + name_buf, ++pos, (char*)box_name); + sup = tree->add(iname); + + snprintf(item_name, MAX_ITEMBUF, "%s/Not handled. Skipped.", iname); + add_sub_item(); + + sup->close(); + + } + +#ifdef DEBUG_JPM +fprintf(stderr,"read_pcol: UNKNOWN BOX name(%s) len(%lu)\n", +(char*)box_name,box_len); +#endif + + s += box_len; + + } + + if(has_pagt == 0) + { +LOG("pagt missing. STOP."); + return dend; + } + + return box_end; +}//read_pcol() + +static unsigned char *read_bcvl(unsigned char *s, unsigned char *box_end, + const char *name_src) +{ + unsigned short i, nc, bpc, value, dr, depth, sign; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Base Color Value box", name_buf); + add_sub_item(); + + + nc = get2(s); s += 2; + bpc = (unsigned short)s[0]; ++s; + depth = (bpc & 0x7f) + 1; + sign = (bpc & 0x80)?1:0; + + snprintf(item_name, MAX_ITEMBUF, "%s/numcomps(%d)", name_buf, nc); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/bpc(%d)", name_buf, bpc); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/depth(%d)", name_buf, depth); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/signed(%d)", name_buf, sign); + add_sub_item(); + + for(i = 0; i < nc; ++i) + { + value = get2(s); s += 2; + dr = get2(s); s += 2; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%hu]value(%hu) dr(%hu)", + name_buf,i,value,dr); + add_sub_item(); + + } +#ifdef DEBUG_JPM +fprintf(stderr,"\n\t\tEXIT read_bcvl (s - box_end) ==> %ld\n", +(long)(s - box_end)); +#endif + + return box_end; +} + +//no_codestream == 1 +static unsigned char *read_bclr(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + uint64_t box_len; + unsigned int hstep; + unsigned short bcvl_found = 0;; + char name_buf[MAX_ITEMBUF]; + int pos = -1; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Base Color box", name_buf); + add_sub_item(); + + while(s < box_end) + { + box_len = read_boxheader(s, dend, &hstep); + + if(memcmp(box_name, "bcvl", 4) == 0) + { + Fl_Tree_Item *sup; + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] bcvl",name_buf,++pos); + + sup = tree->add(item_name); + + s = read_bcvl(s + hstep, s + box_len, item_name); + + sup->close(); + ++bcvl_found; + continue; + } + if(memcmp(box_name, "colr", 4) == 0) + { + Fl_Tree_Item *sup; + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] colr",name_buf,++pos); + + sup = tree->add(item_name); + + s = read_colr(s + hstep, s + box_len, item_name); + + sup->close(); + continue; + } + if(memcmp(box_name, "bpcc", 4) == 0) + { + Fl_Tree_Item *sup; + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] bpcc",name_buf,++pos); + + sup = tree->add(item_name); + + s = read_bpcc(s + hstep, s + box_len, item_name); + + sup->close(); + continue; + } + { + Fl_Tree_Item *sup; + char iname[MAX_ITEMBUF+2]; + + snprintf(iname, MAX_ITEMBUF, "%s/[%03d] %s", + name_buf, ++pos, (char*)box_name); + sup = tree->add(iname); + + snprintf(item_name, MAX_ITEMBUF, "%s/Not handled. Skipped.", iname); + add_sub_item(); + + sup->close(); + } + +#ifdef DEBUG_JPM +fprintf(stderr,"read_pcol: UNKNOWN BOX name(%s) len(%lu)\n", +(char*)box_name,box_len); +#endif + + s += box_len; + + }//while(s < box_end + + if(bcvl_found == 0) + { +LOG("bcvl not found. STOP."); + return dend; + } +#ifdef DEBUG_JPM +fprintf(stderr,"\t EXIT read_bclr (s - box_end) ==> %ld\n", +(long)(s-box_end)); +#endif + + return box_end; + +}/* read_bclr() */ + +static unsigned char *read_ppcl(unsigned char *s, unsigned char *box_end, + const char *name_src) +{ + uint64_t ppcoff; + unsigned int ppclen, pix; + unsigned short ppcdr; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, + "%s/Primary Page Collection Locator box", name_buf); + add_sub_item(); + + + ppcoff = get8(s); s += 8; + snprintf(item_name, MAX_ITEMBUF, "%s/ppcoff(%lu)",name_buf,ppcoff); + add_sub_item(); + + ppclen = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/ppclen(%u)",name_buf,ppclen); + add_sub_item(); + + ppcdr = get2(s); s += 2; + snprintf(item_name, MAX_ITEMBUF, "%s/ppcdr(%hu)",name_buf,ppcdr); + add_sub_item(); + + pix = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/pix(%u)",name_buf,pix); + add_sub_item(); + + return box_end; + +}//read_ppcl() + +static unsigned char *read_htxb(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + uint64_t box_len; + unsigned int hstep; + char name_buf[MAX_ITEMBUF]; + int pos = -1; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Hidden Text Metadata box", name_buf); + add_sub_item(); + + while(s < box_end) + { + box_len = read_boxheader(s, dend, &hstep); + + if(memcmp(box_name, "lbl ", 4) == 0) + { + Fl_Tree_Item *sup; + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] lbl ",name_buf,++pos); + + sup = tree->add(item_name); + + s = read_lbl(s + hstep, s + box_len, item_name); + + sup->close(); + + box_len = read_boxheader(s, dend, &hstep); + + if(memcmp(box_name, "xml ", 4) == 0 + || memcmp(box_name, "XML ", 4) == 0) + { + Fl_Tree_Item *sup, *sub; + char *buf = NULL; + char iname[MAX_ITEMBUF]; + + snprintf(iname, MAX_ITEMBUF, "%s/[%03d] xml", name_buf, ++pos); + sup = tree->add(iname); + + snprintf(item_name, MAX_ITEMBUF, "%s/xml1", iname); + sub = tree->add(item_name); + + s = read_xml(s + hstep, s + box_len, dend, &buf); + + sub->label(buf); + + sup->close(); + free(buf); --pos; + continue; + } + + if(memcmp(box_name, "uuid", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] uuid", name_buf, ++pos); + sup = tree->add(item_name); + + s = read_uuid(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + + } //if(memcmp(box_name, "lbl ", 4) == 0) + + { + Fl_Tree_Item *sup; + char iname[MAX_ITEMBUF+2]; + + snprintf(iname, MAX_ITEMBUF, "%s/[%03d] %s", + name_buf, ++pos, (char*)box_name); + sup = tree->add(iname); + + snprintf(item_name, MAX_ITEMBUF, "%s/Not handled. Skipped.", iname); + add_sub_item(); + + sup->close(); + } + +#ifdef DEBUG_JPM +fprintf(stderr,"read_pcol: UNKNOWN BOX name(%s) len(%lu)\n", +(char*)box_name,box_len); +#endif + + s += box_len; + + }//while(s < box_end) + + return box_end; + +}// read_htxb() + +static unsigned char *read_phtx(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + uint64_t box_len; + unsigned int hstep; + unsigned char rtyp[5]; + char name_buf[MAX_ITEMBUF]; + int pos = -1; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/HTX Reference box", name_buf); + add_sub_item(); + + memcpy(rtyp, s, 4); s += 4; rtyp[4] = 0; + snprintf(item_name, MAX_ITEMBUF, "%s/phtx_rtyp(%s)",name_buf,rtyp); + add_sub_item(); + + while(s < box_end) + { + box_len = read_boxheader(s, dend, &hstep); + + if(memcmp(box_name, "flst", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] flst", name_buf, ++pos); + sup = tree->add(item_name); + + s = read_flst(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "lbl ", 4) == 0) + { + Fl_Tree_Item *sup; + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] lbl ",name_buf,++pos); + + sup = tree->add(item_name); + + s = read_lbl(s + hstep, s + box_len, item_name); + + sup->close(); + continue; + } + + { + Fl_Tree_Item *sup; + char iname[MAX_ITEMBUF+2]; + + snprintf(iname, MAX_ITEMBUF, "%s/[%03d] %s", + name_buf, ++pos, (char*)box_name); + sup = tree->add(iname); + + snprintf(item_name, MAX_ITEMBUF, "%s/Not handled. Skipped.", iname); + add_sub_item(); + + sup->close(); + + } + +#ifdef DEBUG_JPM +fprintf(stderr,"read_pcol: UNKNOWN BOX name(%s) len(%lu)\n", +(char*)box_name,box_len); +#endif + + s += box_len; + + } + + return box_end; + +}// read_phtx() + +static unsigned char *read_page(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src, uint64_t offset, + uint64_t len) +{ + uint64_t box_len; + unsigned int hstep; + unsigned short nr_id = 0, cur_id = 0, has_phdr = 0, has_res = 0; + char name_buf[MAX_ITEMBUF]; + char iname[MAX_ITEMBUF+2]; + int pos = -1; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Page box", name_buf); + add_sub_item(); + snprintf(item_name, MAX_ITEMBUF, "%s/offset(%ld) len(%ld)", + name_buf, offset, len); + add_sub_item(); + + + while(s < box_end) + { + box_len = read_boxheader(s, dend, &hstep); + + if(memcmp(box_name, "phdr", 4) == 0) + { + Fl_Tree_Item *sup; + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] phdr",name_buf,++pos); + sup = tree->add(item_name); + + has_phdr = 1; + nr_id = 0; + + s = read_phdr(s + hstep, s + box_len, dend, item_name, &nr_id); + + sup->close(); + continue; + } + + if(memcmp(box_name, "res ", 4) == 0) + { + Fl_Tree_Item *sup; + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] res ",name_buf,++pos); + sup = tree->add(item_name); + + has_res = 1; + + s = read_res(s + hstep, s + box_len, dend, + (unsigned char*)item_name); + + sup->close(); + continue; + } + if(memcmp(box_name, "lbl ", 4) == 0) + { + Fl_Tree_Item *sup; + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] lbl ",name_buf,++pos); + sup = tree->add(item_name); + + s = read_lbl(s + hstep, s + box_len, item_name); + + sup->close(); + continue; + } + if(memcmp(box_name, "bclr", 4) == 0) + { + Fl_Tree_Item *sup; + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] bclr",name_buf,++pos); + sup = tree->add(item_name); + + s = read_bclr(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "xml ", 4) == 0 + || memcmp(box_name, "XML ", 4) == 0) + { + Fl_Tree_Item *sup, *sub; + char *buf = NULL; + + snprintf(iname, MAX_ITEMBUF, "%s/[%03d] xml", name_buf, ++pos); + sup = tree->add(iname); + + snprintf(item_name, MAX_ITEMBUF, "%s/xml1", iname); + sub = tree->add(item_name); + + s = read_xml(s + hstep, s + box_len, dend, &buf); + + sub->label(buf); + + sup->close(); + + free(buf); + + continue; + } + if(memcmp(box_name, "uuid", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] uuid", name_buf, ++pos); + sup = tree->add(item_name); + + s = read_uuid(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + if(memcmp(box_name, "uinf", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] uinf", name_buf, ++pos); + sup = tree->add(item_name); + + s = read_uinf(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "lobj", 4) == 0) + { + Fl_Tree_Item *sup; + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] lobj",name_buf,++pos); + sup = tree->add(item_name); + + s = read_lobj(cur_id, nr_id, s + hstep, s + box_len, dend, item_name); + + ++cur_id; + sup->close(); + continue; + } + + if(memcmp(box_name, "ppcl", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] ppcl",name_buf,++pos); + sup = tree->add(item_name); +//page + s = read_ppcl(s + hstep, s + box_len, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "htxb", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] htxb", name_buf, ++pos); + sup = tree->add(item_name); + + s = read_htxb(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "phtx", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] phtx", name_buf, ++pos); + sup = tree->add(item_name); + + s = read_phtx(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + + { + Fl_Tree_Item *sup; + + snprintf(iname, MAX_ITEMBUF, "%s/[%03d] %s", + name_buf, ++pos, (char*)box_name); + sup = tree->add(iname); + + snprintf(item_name, MAX_ITEMBUF, "%s/Not handled. Skipped.", iname); + add_sub_item(); + + sup->close(); + + } +#ifdef DEBUG_JPM +fprintf(stderr,"read_page: UNKNOWN BOX FOUND name(%s) len(%lu)\n", +(char*)box_name,box_len); +#endif + + s += box_len; + } + + if(has_phdr == 0) + { +LOG("phdr missing. STOP."); + return dend; + } + if(has_res == 0) + { +LOG("res missing. STOP."); + return dend; + } +#ifdef DEBUG_JPM +fprintf(stderr,"EXIT read_page (s - box_end) ==> %ld\n\n",(long)(s - box_end)); +#endif + + return box_end; + +}/* read_page() */ + +static unsigned char *read_phdr(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src, unsigned short *out_nrid) +{ + unsigned int pheight, pwidth; + unsigned short nr_lobj, orient, pcolor, v; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Page Header box", name_buf); + add_sub_item(); + + nr_lobj = get2(s); s += 2; *out_nrid = nr_lobj; + snprintf(item_name, MAX_ITEMBUF, + "%s/nr_layout_objects(%u)",name_buf,nr_lobj); + add_sub_item(); + + pheight = get4(s); s += 4; + pwidth = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/pwidth(%u) pheight(%u)",name_buf, + pwidth,pheight); + add_sub_item(); + + orient = get2(s); s += 2; + + if(orient > 4) v = 5; else v = orient; + + snprintf(item_name, MAX_ITEMBUF, "%s/orientation[%u]'%s'", + name_buf,orient,or_values[v]); + add_sub_item(); + + pcolor = get2(s); s += 2; + + if(pcolor > 3) v = 4; else v = pcolor; + + snprintf(item_name, MAX_ITEMBUF, "%s/color[%u]'%s'", + name_buf,pcolor,pcolor_values[v]); + add_sub_item(); + +#ifdef DEBUG_JPM +fprintf(stderr,"\tEXIT read_phdr (s - box_end) ==> %ld\n",(long)(s - box_end)); +#endif + return box_end; +}//read_phdr() + +static unsigned char *read_ohdr(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src, + unsigned short *out_no_codestream) +{ + uint64_t off; + unsigned int voff, hoff, len; + unsigned short otype, no_cs, dr, o; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Object Header box", name_buf); + add_sub_item(); + + otype = (unsigned short)s[0]; ++s; + no_cs = (unsigned short)s[0]; ++s; + + if(otype > 2) o = 3; else o = otype; + snprintf(item_name, MAX_ITEMBUF, "%s/otype(%hu)'%s'", + name_buf,otype,otype_values[o]); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/no_codestream(%hu)", + name_buf,no_cs); + add_sub_item(); + + *out_no_codestream = no_cs; + + if(no_cs == 0) + { + voff = get4(s); s += 4; + hoff = get4(s); s += 4; + off = get8(s); s += 8; + len = get4(s); s += 4; + + snprintf(item_name, MAX_ITEMBUF, "%s/hoff(%u) voff(%u)", + name_buf,hoff,voff); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/off(%lu) len(%u)", + name_buf,off,len); + add_sub_item(); + + dr = get2(s); s += 2; + + snprintf(item_name, MAX_ITEMBUF, "%s/data_reference(%hu)",name_buf, + dr); + add_sub_item(); + + } + +#ifdef DEBUG_JPM +fprintf(stderr,"\tEXIT read_ohdr(s - box_end) ==> %ld\n",(long)(s - box_end)); +#endif + + return box_end; +}/* read_ohdr() */ + +static unsigned char *read_scal(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + unsigned short vrn, vrd, hrn, hrd; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Object Scale box", name_buf); + add_sub_item(); + + vrn = get2(s); s += 2; + vrd = get2(s); s += 2; + hrn = get2(s); s += 2; + hrd = get2(s); s += 2; + + snprintf(item_name, MAX_ITEMBUF, "%s/hrn(%hu) hrd(%hu)",name_buf, + hrn,hrd); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/vrn(%hu) vrd(%hu)",name_buf, + vrn,vrd); + add_sub_item(); + +#ifdef DEBUG_JPM +fprintf(stderr,"\tEXIT read_scal (s - box_end) ==> %ld\n",(long)(s - box_end)); +#endif + + return box_end; +}//read_scal() + +static unsigned char *read_objc(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + uint64_t box_len; + unsigned int hstep; + unsigned short has_ohdr = 0, no_codestream = 1; + char name_buf[MAX_ITEMBUF]; + char iname[MAX_ITEMBUF]; + int pos = -1; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Object box", name_buf); + add_sub_item(); + + while(s < box_end) + { + box_len = read_boxheader(s, dend, &hstep); + + if(memcmp(box_name, "ohdr", 4) == 0) + { + Fl_Tree_Item *sup; + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] ohdr",name_buf,++pos); + sup = tree->add(item_name); + + has_ohdr = 1; + s = read_ohdr(s + hstep, s + box_len, dend, item_name, &no_codestream); + + sup->close(); + continue; + } + if(no_codestream == 1) + { + if(memcmp(box_name, "bclr", 4) == 0) + { + Fl_Tree_Item *sup; + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] bclr",name_buf,++pos); + sup = tree->add(item_name); + + s = read_bclr(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + } + if(memcmp(box_name, "xml ", 4) == 0 + || memcmp(box_name, "XML ", 4) == 0) + { + Fl_Tree_Item *sup, *sub; + char *buf = NULL; + + snprintf(iname, MAX_ITEMBUF, "%s/[%03d] xml", name_buf, ++pos); + sup = tree->add(iname); + + snprintf(item_name, MAX_ITEMBUF, "%s/xml1", iname); + sub = tree->add(item_name); + + s = read_xml(s + hstep, s + box_len, dend, &buf); + + sub->label(buf); + + sup->close(); + free(buf); --pos; + continue; + } + if(memcmp(box_name, "uuid", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] uuid", name_buf, ++pos); + sup = tree->add(item_name); + + s = read_uuid(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + if(memcmp(box_name, "uinf", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] uinf", name_buf, ++pos); + sup = tree->add(item_name); + + s = read_uinf(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "scal", 4) == 0) + { + if(no_codestream == 0)//Mandatory + { + Fl_Tree_Item *sup; + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] scal",name_buf,++pos); + sup = tree->add(item_name); + + s = read_scal(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + s += box_len; + continue; + } + + if(memcmp(box_name, "jp2h", 4) == 0) + { + if(no_codestream == 0)//Mandatory + { + Fl_Tree_Item *sup; + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] jp2h",name_buf,++pos); + sup = tree->add(item_name); + + s = read_jp2h(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + s += box_len; + continue; + } + + { + Fl_Tree_Item *sup; + char iname[MAX_ITEMBUF+2]; + + snprintf(iname, MAX_ITEMBUF, "%s/[%03d] %s", + name_buf, ++pos, (char*)box_name); + sup = tree->add(iname); + + snprintf(item_name, MAX_ITEMBUF, "%s/Not handled. Skipped.", iname); + add_sub_item(); + + sup->close(); + + } + +#ifdef DEBUG_JPM +fprintf(stderr,"read_objc: UNKNOWN BOX FOUND name(%s) len(%lu)\n", +(char*)box_name,box_len); +#endif + + s += box_len; + } + if(has_ohdr == 0) + { +LOG("ohdr missing. STOP."); + return dend; + } +#ifdef DEBUG_JPM +fprintf(stderr,"\tEXIT read_objc (s - box_end) ==> %ld\n",(long)(s - box_end)); +#endif + return box_end; + +}/* read_objc() */ + +static unsigned char *read_lhdr(unsigned char *s, unsigned char *box_end, + const char *name_src) +{ + unsigned int h, w, voff, hoff; + unsigned short ID, style, v; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Layout Object Header box", + name_buf); + add_sub_item(); + + ID = get2(s); s += 2; + h = get4(s); s += 4; + w = get4(s); s += 4; + voff = get4(s); s += 4; + hoff = get4(s); s += 4; + style = (unsigned short)s[0]; ++s; + + if(style == 255) v = 4; else v = style; + + snprintf(item_name, MAX_ITEMBUF, "%s/ID(%hu)",name_buf,ID); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/style(%hu)'%s'", + name_buf,style,lhdr_styles[v] ); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/hoff(%u) voff(%u)", + name_buf,hoff,voff); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/w(%u) h(%u)", + name_buf,w,h); + add_sub_item(); + +#ifdef DEBUG_JPM +fprintf(stderr,"\tEXIT read_lhdr (s - box_end) ==> %ld\n",(long)(s - box_end)); +#endif + return box_end; +}/* read_lhdr() */ + +static unsigned char *read_lobj(unsigned short cur_id, unsigned short max_id, + unsigned char *s, unsigned char *box_end, unsigned char *dend, + const char *name_src) +{ + uint64_t box_len; + unsigned int hstep; + short has_lhdr = 0, has_objc = 0; + char name_buf[MAX_ITEMBUF]; + char iname[MAX_ITEMBUF+2]; + int pos = -1; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Layout Object box", name_buf); + add_sub_item(); + + if(cur_id >= max_id) return box_end; + + while(s < box_end) + { + box_len = read_boxheader(s, dend, &hstep); + + if(memcmp(box_name, "lhdr", 4) == 0) + { + Fl_Tree_Item *sup; + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] lhdr",name_buf,++pos); + sup = tree->add(item_name); + + has_lhdr = 1; + + s = read_lhdr(s + hstep, s + box_len, item_name); + + sup->close(); + continue; + } + if(memcmp(box_name, "xml ", 4) == 0 + || memcmp(box_name, "XML ", 4) == 0) + { + Fl_Tree_Item *sup, *sub; + char *buf = NULL; + + snprintf(iname, MAX_ITEMBUF, "%s/[%03d] xml", name_buf, ++pos); + sup = tree->add(iname); + + snprintf(item_name, MAX_ITEMBUF, "%s/xml1", iname); + sub = tree->add(item_name); + + s = read_xml(s + hstep, s + box_len, dend, &buf); + + sub->label(buf); + + sup->close(); + free(buf); --pos; + continue; + } + if(memcmp(box_name, "uuid", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] uuid", name_buf, ++pos); + sup = tree->add(item_name); + + s = read_uuid(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + if(memcmp(box_name, "uinf", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] uinf", name_buf, ++pos); + sup = tree->add(item_name); + + s = read_uinf(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "objc", 4) == 0) + { + Fl_Tree_Item *sup; + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] objc",name_buf,++pos); + sup = tree->add(item_name); + + has_objc = 1; + + s = read_objc(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + { + Fl_Tree_Item *sup; + char iname[MAX_ITEMBUF+2]; + + snprintf(iname, MAX_ITEMBUF, "%s/[%03d] %s", + name_buf, ++pos, (char*)box_name); + sup = tree->add(iname); + + snprintf(item_name, MAX_ITEMBUF, "%s/Not handled. Skipped.", iname); + add_sub_item(); + + sup->close(); + + } + +#ifdef DEBUG_JPM +fprintf(stderr,"read_lobj: UNKNOWN BOX FOUND name(%s) len(%lu)\n", +(char*)box_name,box_len); +#endif + + s += box_len; + } + if(has_objc == 0 || has_lhdr == 0) + { + fprintf(stderr,"%s:%d:\n\tFAILURE: objc(%d) or lhdr(%d) missing." + " STOP.\n",__FILE__,__LINE__,has_objc,has_lhdr); + return dend; + } + + +#ifdef DEBUG_JPM +fprintf(stderr,"\tEXIT read_lobj(s - box_end) ==> %ld\n",(long)(s - box_end)); +#endif + + return box_end; + +}/* read_lobj() */ + +static unsigned char *read_flst(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + uint64_t off; + unsigned int len; + unsigned short i, n, dr; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Fragment List box",name_buf); + add_sub_item(); + + n = get2(s); s += 2; + snprintf(item_name, MAX_ITEMBUF, "%s/nr_fragments %u",name_buf,n); + add_sub_item(); + + for(i = 0; i < n; ++i) + { + off = get8(s); s += 8; + len = get4(s); s += 4; + dr = get2(s); s += 2; + + snprintf(item_name, MAX_ITEMBUF,"%s/[%2u] off(%lu) len(%u)", + name_buf, i,(unsigned long)off,len); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF,"%s/ dr(%u)",name_buf,dr); + add_sub_item(); + } + + assert(s == box_end); + return box_end; +}/* read_flst() */ + +static unsigned char *read_cref(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + uint64_t box_len; + unsigned int hstep, rtyp; + char name_buf[MAX_ITEMBUF]; + int pos = -1; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Cross-Reference box",name_buf); + add_sub_item(); + + rtyp = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/cref_rtyp(%d)",name_buf,rtyp); + add_sub_item(); + + assert(s == box_end); + + box_len = read_boxheader(s, dend, &hstep); + + if(memcmp(box_name, "flst", 4) != 0) + { +LOG("flst missing. STOP."); + + return dend; + } + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] flst", name_buf, ++pos); + sup = tree->add(item_name); + + s = read_flst(s + hstep, s + box_len, dend, item_name); + + sup->close(); + } + assert(s == box_end); + return box_end; +}/* read_cref() */ + +static unsigned char *read_lbl(unsigned char *s, unsigned char *box_end, + const char *name_src) +{ + size_t n; + unsigned char *buf; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Label box", name_buf); + add_sub_item(); + + n = (size_t)(box_end - s); + buf = (unsigned char*)malloc(n+1); buf[n] = 0; + + if(buf) + { + memcpy(buf, s, n); + + snprintf(item_name, MAX_ITEMBUF, "%s/text(%s)",name_buf,buf); + add_sub_item(); + + free(buf); + } + return box_end; +} + +static unsigned char *read_mdat(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Media Data box",name_buf); + add_sub_item(); + + return box_end; +}//read_mdat() + +static unsigned char *read_ftbl(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + uint64_t box_len; + unsigned int hstep; + char name_buf[MAX_ITEMBUF]; + int pos = -1; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Fragment Table box",name_buf); + add_sub_item(); + + box_len = read_boxheader(s, dend, &hstep); + + if(memcmp(box_name, "flst", 4) != 0) + { +LOG("flst missing. STOP."); + return dend; + } + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] flst", name_buf, ++pos); + sup = tree->add(item_name); + + s = read_flst(s + hstep, s + box_len, dend, item_name); + + sup->close(); + } + return box_end; +}//read_ftbl() + +int read_jpm(unsigned char *src, unsigned char *parse_start, + unsigned char *dend) +{ + uint64_t box_len; + unsigned char *box_end, *s; + unsigned int hstep; + int pos = -1; + short ftyp_found = 0, mhdr_found = 0, sdat_found = 0; + + jpm_start = src; + s = parse_start; + has_thumbnail_jp2h = has_thumbnail_jp2c = 0; + +//--- HEAD + + while(s < dend) + { + box_len = read_boxheader(s, dend, &hstep); + + if( box_len == 0) return 0; + + if(memcmp(box_name, "ftyp", 4) == 0)//Mandatory + { + s += box_len; + ftyp_found = 1; + continue; + } + + if(memcmp(box_name, "jp2h", 4) == 0)//Optional + { + if(ftyp_found == 0) return 0; + + has_thumbnail_jp2h = 1; + s += box_len; + continue; + } + + if(memcmp(box_name, "jp2c", 4) == 0)//Mandatory if 'jp2' found + { + if(has_thumbnail_jp2h == 0) return 0; + + has_thumbnail_jp2c = 1; + s += box_len; + continue; + } + + if(memcmp(box_name, "mhdr", 4) == 0)//Mandatory + { + s += box_len; + mhdr_found = 1; + + break; + } + + }//while(s < dend) + + if(ftyp_found == 0 || mhdr_found == 0) + { +fprintf(stderr,"%s:%d:\n\tFAILURE: ftyp_found(%d) mhdr_found(%d).STOP.\n", +__FILE__,__LINE__,ftyp_found,mhdr_found); + + return 0; + } + if(has_thumbnail_jp2h == 1 && has_thumbnail_jp2c == 0) + { +fprintf(stderr,"%s:%d:\n\tFAILURE: has_thumbnail_jp2h(%d) " +"has_thumbnail_jp2c(%d).STOP.\n", +__FILE__,__LINE__,has_thumbnail_jp2h,has_thumbnail_jp2c); + + return 0; + + } + s = parse_start; + + box_len = read_boxheader(s, dend, &hstep); + + if(memcmp(box_name, "ftyp", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "[%03d] ftyp", ++pos); + sup = tree->add(item_name); + + s = read_ftyp(s + hstep, s + box_len, item_name); + + sup->close(); + box_len = read_boxheader(s, dend, &hstep); + } + + if(memcmp(box_name, "jp2h", 4) == 0) + { + Fl_Tree_Item *sup; + + has_thumbnail_jp2h = 1; + thumbnail_jp2hpos = (s - jpm_start); + thumbnail_jp2hstep = hstep; + thumbnail_jp2hlen = box_len; + + snprintf(item_name, MAX_ITEMBUF, "[%03d] jp2h (doc. thumbnail)", ++pos); + sup = tree->add(item_name); + + s = read_jp2h(s + hstep, s + box_len, dend, item_name); + + sup->close(); + box_len = read_boxheader(s, dend, &hstep); + } + if(memcmp(box_name, "jp2c", 4) == 0) + { + Fl_Tree_Item *sup; + + has_thumbnail_jp2c = 1; + thumbnail_jp2cpos = (s - jpm_start); + thumbnail_jp2cstep = hstep; + thumbnail_jp2clen = box_len; + + snprintf(item_name, MAX_ITEMBUF, "[%03d] jp2c (doc. thumbnail)", ++pos); + sup = tree->add(item_name); + + s = read_jp2c(s + hstep, s + box_len, dend, item_name); + + sup->close(); + box_len = read_boxheader(s, dend, &hstep); + } + + if(memcmp(box_name, "mhdr", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "[%03d] mhdr", ++pos); + sup = tree->add(item_name); + + s = read_mhdr(s + hstep, s + box_len, item_name); + + sup->close(); + } + +//--- BODY + + while(s < dend) + { + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) { s = dend; break; } + + if((uint64_t)(dend - s) < box_len) + box_end = dend; + else + box_end = s + (ptrdiff_t)box_len; + + + if(memcmp(box_name, "dtbl", 4) == 0) + { + Fl_Tree_Item *sup; + char iname[MAX_ITEMBUF+2]; + + snprintf(iname, MAX_ITEMBUF, "[%03d] dtbl", ++pos); + sup = tree->add(iname); + + s = read_dtbl(s + hstep, box_end, dend, iname); + + sup->close(); + continue; + } + + if(memcmp(box_name, "jp2h", 4) == 0) + { + Fl_Tree_Item *sup; + char iname[MAX_ITEMBUF+2]; + + snprintf(iname, MAX_ITEMBUF, "[%03d] jp2h", ++pos); + sup = tree->add(iname); + + s = read_jp2h(s + hstep, box_end, dend, iname); + + sup->close(); + continue; + } + + if(memcmp(box_name, "jp2c", 4) == 0) + { + Fl_Tree_Item *sup; + char iname[MAX_ITEMBUF+2]; + + snprintf(iname, MAX_ITEMBUF, "[%03d] jp2c", ++pos); + sup = tree->add(iname); + + s = read_jp2c(s + hstep, box_end, dend, iname); + + sup->close(); + continue; + } + + if(memcmp(box_name, "pcol", 4) == 0) + { + Fl_Tree_Item *sup; + char iname[MAX_ITEMBUF+2]; + + snprintf(iname, MAX_ITEMBUF, "[%03d] pcol", ++pos); + sup = tree->add(iname); + + s = read_pcol(s + hstep, box_end, dend, iname, s - jpm_start, box_len); + + sup->close(); + continue; + } + + if(memcmp(box_name, "uuid", 4) == 0) + { + Fl_Tree_Item *sup; + char iname[MAX_ITEMBUF+2]; + + snprintf(iname, MAX_ITEMBUF, "[%03d] uuid", ++pos); + sup = tree->add(iname); + + s = read_uuid(s + hstep, box_end, dend, iname); + + sup->close(); + continue; + } + + if(memcmp(box_name, "uinf", 4) == 0) + { + Fl_Tree_Item *sup; + char iname[MAX_ITEMBUF+2]; + + snprintf(iname, MAX_ITEMBUF, "[%03d] uinf", ++pos); + sup = tree->add(iname); + + s = read_uinf(s + hstep, box_end, dend, iname); + + sup->close(); + continue; + } + if(memcmp(box_name, "page", 4) == 0) + { + Fl_Tree_Item *sup; + char iname[MAX_ITEMBUF+2]; + + snprintf(iname, MAX_ITEMBUF, "[%03d] page", ++pos); + sup = tree->add(iname); + + s = read_page(s + hstep, box_end, dend, iname, s - jpm_start, box_len); + + sup->close(); + continue; + } + + if(memcmp(box_name, "ftbl", 4) == 0) + { + Fl_Tree_Item *sup; + char iname[MAX_ITEMBUF+2]; + + snprintf(iname, MAX_ITEMBUF, "[%03d] ftbl", ++pos); + sup = tree->add(iname); + + s = read_ftbl(s + hstep, box_end, dend, iname); + + sup->close(); + continue; + } + + if(memcmp(box_name, "mdat", 4) == 0) + { + Fl_Tree_Item *sup; + char iname[MAX_ITEMBUF+2]; + + snprintf(iname, MAX_ITEMBUF, "[%03d] mdat", ++pos); + sup = tree->add(iname); + + s = read_mdat(s + hstep, box_end, dend, iname); + + sup->close(); + continue; + } + + if(memcmp(box_name, "cref", 4) == 0) + { + Fl_Tree_Item *sup; + char iname[MAX_ITEMBUF+2]; + + snprintf(iname, MAX_ITEMBUF, "[%03d] cref", ++pos); + sup = tree->add(iname); + + s = read_cref(s + hstep, s + box_len, dend, iname); + + sup->close(); + continue; + } + + if(memcmp(box_name, "htxb", 4) == 0) + { + Fl_Tree_Item *sup; + char iname[MAX_ITEMBUF+2]; + + snprintf(iname, MAX_ITEMBUF, "[%03d] htxb", ++pos); + sup = tree->add(iname); + + s = read_htxb(s + hstep, s + box_len, dend, iname); + + sup->close(); + continue; + } + if(memcmp(box_name, "sdat", 4) == 0) + { + Fl_Tree_Item *sup; + char iname[MAX_ITEMBUF+2]; + + snprintf(iname, MAX_ITEMBUF, "[%03d] sdat", ++pos); + sup = tree->add(iname); + + s = read_sdat(s + hstep, s + box_len, iname); + + sup->close(); + + sdat_found = 1; + continue; + } + if(memcmp(box_name, "sref", 4) == 0) + { + Fl_Tree_Item *sup; + char iname[MAX_ITEMBUF+2]; + + if(!sdat_found) + { + fprintf(stderr,"File not correct: sref found but no sdat found.\n"); + s += box_len; + continue; + } + snprintf(iname, MAX_ITEMBUF, "[%03d] sref", ++pos); + sup = tree->add(iname); + + s = read_sref(s + hstep, s + box_len, iname); + + sup->close(); + continue; + } + if(memcmp(box_name, "xml ", 4) == 0 + || memcmp(box_name, "XML ", 4) == 0) + { + Fl_Tree_Item *sup, *sub; + char *buf = NULL; + char iname[MAX_ITEMBUF+2]; + + snprintf(iname, MAX_ITEMBUF, "[%03d] xml", ++pos); + sup = tree->add(iname); + + snprintf(item_name, MAX_ITEMBUF, "%s/xml1", iname); + sub = tree->add(item_name); + + s = read_xml(s + hstep, box_end, dend, &buf); + + sub->label(buf); + + sup->close(); + free(buf); + continue; + } + { + Fl_Tree_Item *sup; + char iname[MAX_ITEMBUF+2]; + + snprintf(iname, MAX_ITEMBUF, "[%03d] %s", ++pos, (char*)box_name); + sup = tree->add(iname); + + snprintf(item_name, MAX_ITEMBUF, "%s/Not handled. Skipped.", iname); + add_sub_item(); + + sup->close(); + + } + + +#ifdef DEBUG_JPM +fprintf(stderr,"read_jpm: UNKNOWN BOX FOUND name(%s) len(%lu)\n", +(char*)box_name,box_len); +#endif + s = box_end; + + } + +#ifdef DEBUG_JPM +fprintf(stderr,"EXIT with (dend - s) ==> %ld\n",(long)(dend-s)); +#endif + + return 0; + +}//read_jpm() diff --git a/src/bin/fltk/flviewer/read_jpx.cxx b/src/bin/fltk/flviewer/read_jpx.cxx new file mode 100644 index 00000000..eb7178ac --- /dev/null +++ b/src/bin/fltk/flviewer/read_jpx.cxx @@ -0,0 +1,1395 @@ +/* + * Part 2 Extensions (JPX) + * fcd15444-2-JPX-2000.pdf + * fcd15444-2annexm-JPX-2004.pdf + * fcd15444-2annexn-JPX-2004.pdf +*/ +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#include +#define strcasecmp _stricmp +#define strncasecmp _strnicmp +#define snprintf _snprintf +#define sprintf _scprintf +#define strdup _strdup +#else /* not _WIN32 */ +#define __STDC_FORMAT_MACROS +#include +#include +#endif /* _WIN32 */ + +#include +#include +#include +#include + +#include "opj_inttypes.h" +#include "opj_stdint.h" + +#include "viewerdefs.hh" +#include "tree.hh" + + static const char *L_document_xpm[] = +{ + "11 11 3 1", + ". c None", + "x c #d8d8f8", + "@ c #202060", + ".@@@@@@....", + ".@xxx@.@...", + ".@xxx@..@..", + ".@xxx@@@@@.", + ".@xxxxxxx@.", + ".@xxxxxxx@.", + ".@xxxxxxx@.", + ".@xxxxxxx@.", + ".@xxxxxxx@.", + ".@xxxxxxx@.", + ".@@@@@@@@@." +}; +static Fl_Pixmap L_documentpixmap(L_document_xpm); + + +//FORWARD + +static unsigned char *jpx_start; + +#define LOG(s) fprintf(stderr,"%s:%d:%s\n",__FILE__,__LINE__,s) + +static int cur_composition_layer_w = 100; +static int cur_composition_layer_h = 100; + +static char item_name[MAX_ITEMBUF+2]; + +//--------- end FORWARD + +static void add_sub_item() +{ + Fl_Tree_Item *sub = tree->add(item_name); + sub->usericon(&L_documentpixmap); +} + +static unsigned char *read_flst(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + uint64_t off; + unsigned int len; + unsigned short i, n, dr; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Fragment List box",name_buf); + add_sub_item(); + + n = get2(s); s += 2; + snprintf(item_name, MAX_ITEMBUF, "%s/nr_fragments %u",name_buf,n); + add_sub_item(); + + for(i = 0; i < n; ++i) + { + off = get8(s); s += 8; + len = get4(s); s += 4; + dr = get2(s); s += 2; + + snprintf(item_name, MAX_ITEMBUF, + "%s/frag[%u] off(%"PRIu64") len(%u) dr(%u)", name_buf, i,off,len,dr); + add_sub_item(); + } + + assert(s == box_end); + return box_end; +}/* read_flst() */ + +static unsigned char *read_cref(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + uint64_t box_len; + unsigned int hstep, rtyp; + char name_buf[MAX_ITEMBUF]; + int pos = -1; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Cross-Reference box",name_buf); + add_sub_item(); + + rtyp = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/rtyp(%d)",name_buf,rtyp); + add_sub_item(); + + assert(s == box_end); + + box_len = read_boxheader(s, dend, &hstep); + + if(memcmp(box_name, "flst", 4) != 0) + { +LOG("flst missing. STOP."); + + return dend; + } + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] flst", name_buf, ++pos); + sup = tree->add(item_name); + + s = read_flst(s + hstep, s + box_len, dend, item_name); + + sup->close(); + } + assert(s == box_end); + return box_end; +}/* read_cref() */ + +static unsigned char *read_lbl(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + unsigned int n; + unsigned char *buf; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Label box",name_buf); + add_sub_item(); + + n = (unsigned int)(box_end - s); + buf = (unsigned char*)malloc(n+1); + if(buf) + { + buf[n] = 0; + memcpy(buf, s, n); + + snprintf(item_name, MAX_ITEMBUF, "%s/text(%s)",name_buf,(char*)buf); + add_sub_item(); + + free(buf); + } + s += n; + return box_end; +} + +static unsigned char *read_roid(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + unsigned int x, y, w, h; + unsigned short i, nr, r, typ, prio; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/ROI Description box",name_buf); + add_sub_item(); + +/*----------------- +//JUNK +//annexm, page 199: Rcp is mentioned +//annexm, page 200: + +Rcpi: Region of Interest coding priority. + This value describes the coding priority of the Region of Interest. + The value 0 means low coding priority and 255 means maximum coding + priority. This value is + encoded as a 1-byte unsigned integer. In transcoding applications, + bits should be allocated with + respect to the coding priority of each ROI. + +Some lines below in Table M.49, Rcp is missing +---------------------*/ + nr = s[0]; ++s; + snprintf(item_name, MAX_ITEMBUF, "%s/nr_regions %d",name_buf,nr); + add_sub_item(); + + for(i = 0; i < nr; ++i) + { + r = s[0]; ++s; + typ = s[0]; ++s; + prio = s[0]; ++s; + x = get4(s); s += 4; + y = get4(s); s += 4; + w = get4(s); s += 4; + h = get4(s); s += 4; + + snprintf(item_name, MAX_ITEMBUF, "%s/roi[%u] present(%u) typ(%u) prio(%u) " + "x(%d) y(%d) w(%d) h(%d)", + name_buf, i,r,typ,prio,x,y,w,h); + add_sub_item(); + } + assert(s == box_end);// JUNK TEST + return box_end; +}/* read_roid() */ + +static unsigned char *read_jpch(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + uint64_t box_len; + unsigned int hstep, nr_channels = 0; + char name_buf[MAX_ITEMBUF]; + int pos = -1; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Codestream Header box",name_buf); + add_sub_item(); + + while(s < box_end) + { + box_len = read_boxheader(s, dend, &hstep); + + if(memcmp(box_name, "lbl ", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] lbl ", name_buf, ++pos); + sup = tree->add(item_name); + + s = read_lbl(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "ihdr", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] ihdr", name_buf, ++pos); + sup = tree->add(item_name); + + s = read_ihdr(s + hstep, s + box_len, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "bpcc", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] bpcc", name_buf, ++pos); + sup = tree->add(item_name); + + s = read_bpcc(s + hstep, s + box_len, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "pclr", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] pclr", name_buf, ++pos); + sup = tree->add(item_name); + + s = read_pclr(s + hstep, s + box_len, &nr_channels, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "cmap", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] cmap", name_buf, ++pos); + sup = tree->add(item_name); + + s = read_cmap(s + hstep, s + box_len, nr_channels, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "roid", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] roid", name_buf, ++pos); + sup = tree->add(item_name); + + s = read_roid(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + } + assert(s == box_end); + return box_end; + +}/* read_jpch() */ + +static unsigned char *read_cgrp(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + uint64_t box_len; + unsigned int hstep; + char name_buf[MAX_ITEMBUF]; + int pos = -1; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Colour Group box",name_buf); + add_sub_item(); + + while(s < box_end) + { + Fl_Tree_Item *sup; + + box_len = read_boxheader(s, dend, &hstep); + + if(memcmp(box_name, "colr", 4) != 0) break; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] colr", name_buf, ++pos); + sup = tree->add(item_name); + + s = read_colr(s + hstep, s + box_len, item_name); + + sup->close(); + } + assert(s == box_end); + return box_end; + +}/* read_cgrp() */ + +static unsigned char *read_opct(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + unsigned short typ, n, i; + unsigned int siz; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Opacity box",name_buf); + add_sub_item(); + + typ = s[0]; ++s; + n = s[0]; ++s; + if(n > 0) + siz = (unsigned int)(box_end - s); + else + siz = 0; + + snprintf(item_name, MAX_ITEMBUF, "%s/typ(%u) nr(%u) size(%u)",name_buf,typ,n,siz); + add_sub_item(); + + for(i = 0; i < n; ++i) + { +/*---------------- +CVi: Chroma-key value. This field specifies the value of channel i + for the chroma-key colour. Samples + that match the chroma-key value for all channels shall be + considered fully transparent. + The size of + this field is specified by the bit depth of the corresponding + channel. + If the value is not a multiple + of 8, then each CVi value shall be padded to a multiple of 8 bits + with bits equal to the sign bit and + the actual value shall be stored in the low-order bits of the + padded value. + For example, if the depth + of a channel is a signed 10-bit value, then the CVi value shall + be stored in the low 10 bits of a 16-bit + field and the high-order 6 bits shall be all equal to the sign + bit of the value in this CVi field. + +-----------------*/ + snprintf(item_name, MAX_ITEMBUF, "%s/chroma-key[%u]%u",name_buf,i,get_size(s, siz)); + add_sub_item(); + + s += siz; + } + assert(s == box_end); + return box_end; + +}/* read_opct() */ + +static unsigned char *read_creg(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + unsigned short xs, ys, n, i, cdn, xr, yr, xo, yo; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Codestream Registration box",name_buf); + add_sub_item(); + + xs = get2(s); s += 2; + ys = get2(s); s += 2; + n = (unsigned short)((box_end - s)/6); + + snprintf(item_name, MAX_ITEMBUF, "%s/xs(%d) ys(%d) n(%d)",name_buf,xs,ys,n); + add_sub_item(); + + for(i = 0; i < n; ++i) + { + cdn = get2(s); s += 2; + xr = s[0]; ++s; + yr = s[0]; ++s; + xo = s[0]; ++s; + yo = s[0]; ++s; + + snprintf(item_name, MAX_ITEMBUF, "%s/stream[%u]cdn(%u) xr(%u) yr(%u) xo(%u) yo(%u)", + name_buf,i,cdn,xr,yr,xo,yo); + add_sub_item(); + } + assert(s == box_end); + return box_end; + +}/* read_creg() */ + + +static unsigned char *read_jplh(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + uint64_t box_len; + unsigned int hstep; + char name_buf[MAX_ITEMBUF]; + int pos = -1; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Compositing Layer Header box",name_buf); + add_sub_item(); + + while(s < box_end) + { + box_len = read_boxheader(s, dend, &hstep); + + if(memcmp(box_name, "lbl ", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] lbl ", name_buf, ++pos); + sup = tree->add(item_name); + + s = read_lbl(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "cgrp", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] cgrp", name_buf, ++pos); + sup = tree->add(item_name); + + s = read_cgrp(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "opct", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] opct", name_buf, ++pos); + sup = tree->add(item_name); + + s = read_opct(s + hstep, s + box_len, dend, item_name); + + sup->close(); + + box_len = read_boxheader(s, dend, &hstep); + } + + if(memcmp(box_name, "cdef", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] cdef", name_buf, ++pos); + sup = tree->add(item_name); + + s = read_cdef(s + hstep, s + box_len, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "creg", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] creg", name_buf, ++pos); + sup = tree->add(item_name); + + s = read_creg(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "res ", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] res ", name_buf, ++pos); + sup = tree->add(item_name); + + s = read_res(s + hstep, s + box_len, dend, (unsigned char*)item_name); + + sup->close(); + continue; + } + } + assert(s == box_end); + return box_end; + +}/* read_jplh() */ + +static unsigned char *read_inst(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + unsigned int tick, x0, y0, w, h, life, next_use,xc,yc,wc,hc; + unsigned short typ, rept, persist, has_xy, has_wh, has_life, has_crop; + int i; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Instruction Set box",name_buf); + add_sub_item(); + + typ = get2(s); s += 2; + rept = get2(s); s += 2; + tick = get4(s); s += 4; + has_xy = (typ>>0)&1; + has_wh = (typ>>1)&1; + has_life = (typ>>2)&1; + has_crop = (typ>>5)&1; + +#ifdef DEBUG_INST +fprintf(stderr,"read_inst\n\t typ(%d)(%d,%d,%d,%d, %d,%d,%d,%d)\n" +"\ttyp(%d) rept(%d) tick(%d)\n",typ, (typ>>7)&1,(typ>>6)&1, +has_crop,(typ>>4)&1,(typ>>3)&1,has_life,has_wh,has_xy, +rept,tick); +#endif + snprintf(item_name, MAX_ITEMBUF, "%s/typ(%d) rept(%d) tick(%d)",name_buf, + typ,rept,tick); + add_sub_item(); + + i = -1; + while(s < box_end) + { + ++i; + + if(has_xy) + { + x0 = get4(s); s += 4; + y0 = get4(s); s += 4; + } + else + { + x0 = y0 = 0; + } + + if(has_wh) + { + w = get4(s); s += 4; + h = get4(s); s += 4; + } + else + { + w = cur_composition_layer_w; + h = cur_composition_layer_h; + } + if(has_life) + { + life = get4(s); s += 4; + persist = (life>>31)&1; + life = (life>>31)&0; + next_use = get4(s); s += 4; + } + else + { + persist = 1; + life = 0; + next_use = 0; + } + if(has_crop) + { + xc = get4(s); s += 4; + yc = get4(s); s += 4; + wc = get4(s); s += 4; + hc = get4(s); s += 4; + } + else + { + xc = yc = 0; + wc = cur_composition_layer_w; + hc = cur_composition_layer_h; + } + +/*------------- +fprintf(stderr,"inst[%d]\n\tx0(%d) y0(%d) w(%d) h(%d)\n" +"\tlife(%d) persist(%d) next-use(%d)\n" +"\txc(%d) yc(%d) wc(%d) hc(%d)\n",i,x0,y0,w,h,life,persist,next_use, + xc,yc,wc,hc); +---------------*/ + snprintf(item_name, MAX_ITEMBUF, "%s/inst[%d] x0(%d) y0(%d) w(%d) h(%d) " + "life(%d) persist(%d) next-use(%d) " + "xc(%d) yc(%d) wc(%d) hc(%d)",name_buf,i,x0,y0,w,h,life,persist, + next_use,xc,yc,wc,hc); + add_sub_item(); + + } + return s; + +}/* read_inst() */ + +static unsigned char *read_copt(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + unsigned int h, w; unsigned short loop; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Composition Options box",name_buf); + add_sub_item(); + + h = get4(s); s += 4; + w = get4(s); s += 4; + loop = s[0]; ++s; + + snprintf(item_name, MAX_ITEMBUF, "%s/height(%d) width(%d) loop(%d)", + name_buf,h,w,loop); + add_sub_item(); + + assert(s == box_end); + return box_end; +}/* read_copt() */ + +static unsigned char *read_comp(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + uint64_t box_len; + unsigned int hstep; + char name_buf[MAX_ITEMBUF]; + int pos = -1; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Composition box",name_buf); + add_sub_item(); + + box_len = read_boxheader(s, dend, &hstep); + + if(memcmp(box_name, "copt", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] copt", name_buf, ++pos); + sup = tree->add(item_name); + + s = read_copt(s + hstep, s + box_len, dend, item_name); + + sup->close(); + + box_len = read_boxheader(s, dend, &hstep); + } + if(memcmp(box_name, "inst", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] inst", name_buf, ++pos); + sup = tree->add(item_name); + + s = read_inst(s + hstep, s + box_len, dend, item_name); + + sup->close(); + } + + return box_end; +}/* read_comp() */ + +static unsigned char *read_chck(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ +/* Digital Signatur Box */ + uint64_t off, len; + unsigned short styp, ptyp; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Digital Signature box",name_buf); + add_sub_item(); + + off = len = 0; + styp = s[0]; ++s; + ptyp = s[0]; ++s; + + if(ptyp == 1) + { + off = get8(s); s += 8; + len = get8(s); s += 8; + } + + snprintf(item_name, MAX_ITEMBUF, + "%s/styp(%u) ptyp(%u) off(%"PRIu64") len(%"PRIu64") data size[%lu]", + name_buf,styp,ptyp,off,len,(unsigned long)(box_end-s)); + add_sub_item(); + + assert(box_end == s); + return box_end; + +}/* read_chck() */ + +static unsigned char *read_gtso(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Graphics Technology Standard Output box",name_buf); + add_sub_item(); + +/*--------- +OUTP: This field shall be a valid Output ICC profile + as defined by the ICC Profile format specification + ICC-1. Version information is embedded within the + profile itself. Applications that only support + specific versions of the ICC Profile Format Specifications + can extract the version number from bytes 8-11 of the profile + (bytes 8­11 of the contents of the Output ICC Profile box). +------------*/ + + + return box_end; +}/* read_gtso() */ + +static unsigned char *read_drep(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + uint64_t box_len; + unsigned int hstep; + char name_buf[MAX_ITEMBUF]; + int pos = -1; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Desired Reproductions box",name_buf); + add_sub_item(); + + box_len = read_boxheader(s, dend, &hstep); + + if(memcmp(box_name, "gtso", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] gtso", name_buf, ++pos); + sup = tree->add(item_name); + + s = read_gtso(s + hstep, s + box_len, dend, item_name); + + sup->close(); + } + return box_end; +}/* read_drep() */ + +static unsigned char *read_bfil(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + unsigned int id, n; + unsigned char buf[13]; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Binary Filter box",name_buf); + add_sub_item(); + + buf[12] = 0; + id = get4(s); s += 4; + memcpy(buf, s, 12); s += 12; +/*--------------------------------------------------------------- + ID | UUID-suffix +--------|----------------------------- +EC340B04-74C5-11D4-A729-879EA3548F0E + Compressed with GZIP. + The contents of the DATA field have been compressed using the + DEFLATE algorithm (as specified in RFC 1951). + The compressed data is stored in the binary structure + defined by the GZIP file format, as specified in RFC 1952. + +EC340B04-74C5-11D4-A729-879EA3548F0F + Encrypted using DES. + The contents of the DATA field has been encrypted using DES as + defined in ISO 10126-2. + + + All other values reserved. + + +---------------------------------------------------------------*/ + n = (unsigned int)(box_end - s); + + snprintf(item_name, MAX_ITEMBUF, "%s/bfil(%u%s) data[%u]",name_buf,id,buf,n); + add_sub_item(); + + + return box_end; +}/* read_bfil() */ + +static unsigned char *read_nlst(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + unsigned int n, i, an; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Number List box",name_buf); + add_sub_item(); + + n = (unsigned int)((box_end - s)/4); + for(i = 0; i < n; ++i) + { + an = get4(s); s += 4; + + snprintf(item_name, MAX_ITEMBUF, "%s/nlst[%u]%u",name_buf,i,an); + add_sub_item(); + + } + assert(s == box_end); + return box_end; + +}/* read_nlst() */ + +static unsigned char *read_asoc(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + uint64_t box_len; + unsigned int hstep; + char name_buf[MAX_ITEMBUF]; + int pos = -1; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Association box",name_buf); + add_sub_item(); + + while(s < box_end) + { + box_len = read_boxheader(s, dend, &hstep); + + if(memcmp(box_name, "nlst", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] nlst", name_buf, ++pos); + sup = tree->add(item_name); + + s = read_nlst(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + if(memcmp(box_name, "lbl ", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] lbl ", name_buf, ++pos); + sup = tree->add(item_name); + + s = read_lbl(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + if(memcmp(box_name, "asoc", 4) == 0) + { + Fl_Tree_Item *sup; + ++pos; + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] asoc", name_buf, pos); + + sup = tree->add(item_name); + s = read_asoc(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + if(memcmp(box_name, "xml ", 4) == 0 + || memcmp(box_name, "XML ", 4) == 0) + { + Fl_Tree_Item *sup, *sub; + char *buf = NULL; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] xml ", name_buf, ++pos); + sup = tree->add(item_name); + + snprintf(item_name, MAX_ITEMBUF, "%s/xml1", item_name); + sub = tree->add(item_name); + + s = read_xml(s + hstep, s + box_len, dend, &buf); + + sub->label(buf); + + sup->close(); + free(buf); + continue; + } + { + Fl_Tree_Item *sup; + char iname[MAX_ITEMBUF+2]; + + snprintf(iname, MAX_ITEMBUF, "%s/[%03d] %s", + name_buf, ++pos, (char*)box_name); + sup = tree->add(iname); + + snprintf(item_name, MAX_ITEMBUF, "%s/Not handled. Skipped.", iname); + add_sub_item(); + + sup->close(); + + } + s = box_end; + } + assert(box_end == s); + return box_end; + +}/* read_asoc() */ + +static unsigned char *read_mdat(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Media Data box",name_buf); + add_sub_item(); + + return box_end; +}//read_mdat() + +static unsigned char *read_ftbl(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + uint64_t box_len; + unsigned int hstep; + char name_buf[MAX_ITEMBUF]; + int pos = -1; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Fragment Table box",name_buf); + add_sub_item(); + + box_len = read_boxheader(s, dend, &hstep); + + if(memcmp(box_name, "flst", 4) != 0) + { + +LOG("flst missing. STOP."); + + return dend; + } + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%03d] flst", name_buf, ++pos); + sup = tree->add(item_name); + + s = read_flst(s + hstep, s + box_len, dend, item_name); + + sup->close(); + } + return box_end; +}//read_ftbl() + +static unsigned char *read_rreq(unsigned char *s, unsigned char *box_end, + const char *name_src) +{ + unsigned int fuam, dcm, vm; + unsigned short ml, nsf, i, sf, sm, nvf; + unsigned char uuid[17]; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Data Reference box",name_buf); + add_sub_item(); + + ml = s[0]; ++s; + fuam = get_size(s, ml); s += ml; + dcm = get_size(s, ml); s += ml; + nsf = get2(s); s += 2; + + snprintf(item_name, MAX_ITEMBUF, "%s/ml(%u) fuam(%u) dcm(%u) nsf(%hu)", + name_buf, ml,fuam, dcm, nsf); + add_sub_item(); + + for(i = 0; i < nsf; ++i) + { + sf = get2(s); s += 2; + sm = get_size(s, ml); s += ml; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%hd] sf(%hu) sm(%hu)", + name_buf,i,sf,sm); + add_sub_item(); + } + + nvf = get2(s); s += 2; + snprintf(item_name, MAX_ITEMBUF, "%s/nvf(%hu)",name_buf, nvf); + add_sub_item(); + + uuid[16] = 0; + for(i = 0; i < nvf; ++i) + { + memcpy(uuid, s, 16); s += 16; + + vm = get_size(s, ml); s += ml; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%hu] vm(%u)",name_buf,i,vm); + add_sub_item(); + } + + return box_end; + +}//read_rreq() + +int read_jpx(unsigned char *src, unsigned char *parse_start, + unsigned char *dend) +{ + uint64_t box_len; + unsigned char *box_end, *s; + unsigned int hstep; + int pos = -1; + + jpx_start = src; + s = parse_start; + + for(;;) + { + box_len = read_boxheader(s, dend, &hstep); + + if( box_len == 0) { s = dend; break; } + + if(memcmp(box_name, "ftyp", 4) != 0) + { + + LOG("ftyp missing. STOP."); + + return 0; + } + s += box_len; + + box_len = read_boxheader(s, dend, &hstep); + + if(memcmp(box_name, "rreq", 4) != 0) + { + LOG("rreq missing. STOP."); + + return 0; + } + break; + }/* for(;;) */ + + s = parse_start; + + while(s < dend) + { + box_len = read_boxheader(s, dend, &hstep); + + if((uint64_t)(dend - s) < box_len) + box_end = dend; + else + box_end = s + (ptrdiff_t)box_len; + + if(memcmp(box_name, "ftyp", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "[%03d] ftyp", ++pos); + sup = tree->add(item_name); + + s = read_ftyp(s + hstep, s + box_len, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "rreq", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "[%03d] rreq", ++pos); + sup = tree->add(item_name); + + s = read_rreq(s + hstep, s + box_len, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "jp2h", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "[%03d] jp2h", ++pos); + sup = tree->add(item_name); + + s = read_jp2h(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "jpch", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "[%03d] jpch", ++pos); + sup = tree->add(item_name); + + s = read_jpch(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "jplh", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "[%03d] jplh", ++pos); + sup = tree->add(item_name); + + s = read_jplh(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "dtbl", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "[%03d] dtbl", ++pos); + sup = tree->add(item_name); + + s = read_dtbl(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "ftbl", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "[%03d] ftbl", ++pos); + sup = tree->add(item_name); + + s = read_ftbl(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "jp2c", 4) == 0) + { + char iname[MAX_ITEMBUF+2]; + Fl_Tree_Item *sup; + + snprintf(iname, MAX_ITEMBUF, "[%03d] jp2c", ++pos); + sup = tree->add(iname); + + s = read_jp2c(s + hstep, s + box_len, dend, iname); + + sup->close(); + continue; + } + + if(memcmp(box_name, "comp", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "[%03d] comp", ++pos); + sup = tree->add(item_name); + + s = read_comp(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "drep", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "[%03d] drep", ++pos); + sup = tree->add(item_name); + + s = read_drep(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "roid", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "[%03d] roid", ++pos); + sup = tree->add(item_name); + + s = read_roid(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "cref", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "[%03d] cref", ++pos); + sup = tree->add(item_name); + + s = read_cref(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "asoc", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "[%03d] asoc", ++pos); + sup = tree->add(item_name); + + s = read_asoc(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "bfil", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "[%03d] bfil", ++pos); + sup = tree->add(item_name); + + s = read_bfil(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "chck", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "[%03d] chck", ++pos); + sup = tree->add(item_name); + + s = read_chck(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "xml ", 4) == 0 + || memcmp(box_name, "XML ", 4) == 0) + { + Fl_Tree_Item *sup, *sub; + char *buf = NULL; + + snprintf(item_name, MAX_ITEMBUF, "[%03d] xml ", ++pos); + sup = tree->add(item_name); + + snprintf(item_name, MAX_ITEMBUF, "%s/xml1", item_name); + sub = tree->add(item_name); + + s = read_xml(s + hstep, s + box_len, dend, &buf); + + sub->label(buf); + + sup->close(); + free(buf); + continue; + } + + if(memcmp(box_name, "uuid", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "[%03d] uuid", ++pos); + sup = tree->add(item_name); + + s = read_uuid(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "uinf", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "[%03d] uinf", ++pos); + sup = tree->add(item_name); + + s = read_uinf(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "ftbl", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "[%03d] ftbl", ++pos); + sup = tree->add(item_name); + + s = read_ftbl(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "mdat", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "[%03d] mdat", ++pos); + sup = tree->add(item_name); + + s = read_mdat(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "jp2i", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "[%03d] jp2i", ++pos); + sup = tree->add(item_name); + + s = read_jp2i(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + + { + Fl_Tree_Item *sup; + char iname[MAX_ITEMBUF]; + + snprintf(iname, MAX_ITEMBUF, "[%03d] %s", ++pos, (char*)box_name); + sup = tree->add(iname); + + snprintf(item_name, MAX_ITEMBUF, "%s/Not handled. Skipped.", iname); + add_sub_item(); + + sup->close(); + + } + s = box_end; + + }//while(s < dend) + + return 1; + +}//read_jpx() diff --git a/src/bin/fltk/flviewer/read_mj2.cxx b/src/bin/fltk/flviewer/read_mj2.cxx new file mode 100644 index 00000000..da3e9747 --- /dev/null +++ b/src/bin/fltk/flviewer/read_mj2.cxx @@ -0,0 +1,2474 @@ +#include +/* + * author(s) and license +*/ +/* + * Part 3 Motion JPEG 2000 (MJ2) +*/ +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#include +#define strcasecmp _stricmp +#define strncasecmp _strnicmp +#define snprintf _snprintf +#define sprintf _scprintf +#define strdup _strdup +#else /* not _WIN32 */ +#define __STDC_FORMAT_MACROS +#include +#endif /* _WIN32 */ + +#include +#include +#include +#include + +#include "opj_inttypes.h" +#include "opj_stdint.h" + +#include "viewerdefs.hh" +#include "tree.hh" + +//----------------------------- +track_t *Tracks; +//----------------------------- +/*------------------------------*/ + +//#define MAX_ITEMBUF 256 +static char item_name[MAX_ITEMBUF+2]; + +/*------------------------------*/ + +static unsigned char handler_type[5]; +static char has_vmhd, has_smhd, has_hmhd; + + static const char *L_document_xpm[] = +{ + "11 11 3 1", + ". c None", + "x c #d8d8f8", + "@ c #202060", + ".@@@@@@....", + ".@xxx@.@...", + ".@xxx@..@..", + ".@xxx@@@@@.", + ".@xxxxxxx@.", + ".@xxxxxxx@.", + ".@xxxxxxx@.", + ".@xxxxxxx@.", + ".@xxxxxxx@.", + ".@xxxxxxx@.", + ".@@@@@@@@@." +}; +static Fl_Pixmap L_documentpixmap(L_document_xpm); + +static sample_t *new_track_samples(int max_samples) +{ + sample_t *samples; + int i; + + assert(Tracks); + i = Tracks[0].nr_tracks; +#ifdef DEBUG_MJ2 +fprintf(stderr,"%s:%d:\n\tENTER tracks nr(%d) max(%d) samples nr(%d)\n", +__FILE__,__LINE__,i,Tracks[0].max_tracks, max_samples); +#endif + + samples = (sample_t*)calloc(1, (max_samples+1)*sizeof(sample_t)); + + Tracks[i].samples = samples; + Tracks[i].max_samples = max_samples; + + Tracks[0].nr_tracks += 1; +#ifdef DEBUG_MJ2 +fprintf(stderr,"%s:%d:\n\tEXIT nr_tracks(%d)\n", +__FILE__,__LINE__,i+1); +#endif + + return samples; +} + +#define LOG(s) fprintf(stderr,"%s:%d:\n\t%s\n",__FILE__,__LINE__,s) + +static void add_sub_item() +{ + Fl_Tree_Item *sub = tree->add(item_name); + sub->usericon(&L_documentpixmap); +} + +static unsigned char *read_cprt(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src, uint64_t len) +{ + unsigned int vf; + unsigned short lang; + char name_buf[MAX_ITEMBUF]; + char *txt; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Copyright box", name_buf); + add_sub_item(); + + vf = get4(s); s += 4; len -= 4; + snprintf(item_name, MAX_ITEMBUF, "%s/version(%d) flags(0x%x)", name_buf, + (vf>>24) & 0xff,(vf & 0x00ffffff)); + add_sub_item(); + + lang = get2(s); s += 2; len -= 2; + { + char a, b, c; + + if(lang) + { + c = (lang>>1)&0x37; b = (lang>>6)&0x37; a = (lang>>11)&0x37; + snprintf(item_name, MAX_ITEMBUF, "%s/language(%c%c%c)",name_buf, a, b, c); + } + else + snprintf(item_name, MAX_ITEMBUF, "%s/language(0)",name_buf); + + add_sub_item(); + } + txt = (char*)malloc(len + 1); + + if(memcmp(s, "\xfe\xff", 2) == 0) + { +//UTF16BE FIXME + memcpy(txt, s, len); + } + else + { +//UTF8 + fl_utf8toa((char*)s, (unsigned int)len, txt, (unsigned int)len); + } + snprintf(item_name, MAX_ITEMBUF, "%s/notice(%s)", name_buf,txt); + add_sub_item(); + + free(txt); s += len; + + return box_end; + +}//read_cprt() +// +// Container: Movie Box (`moov') or Track Box (`trak') +// +static unsigned char *read_udta(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + uint64_t box_len; + unsigned int hstep; + int pos = -1; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/User data box", name_buf); + add_sub_item(); + + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + + while(memcmp(box_name, "cprt", 4) == 0)//zero or more + { + Fl_Tree_Item *sup; + char sup_buf[MAX_ITEMBUF]; + + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%03d] cprt", name_buf, ++pos); + sup = tree->add(sup_buf); + + s = read_cprt(s + hstep, s + box_len, dend, sup_buf, box_len); + + sup->close(); + + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + } + + return box_end; +}//read_udta() + +static unsigned char *read_tfhd(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src, int len) +{ + unsigned int vf, tID; + int tf_flags; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Track fragment header box", name_buf); + add_sub_item(); + + vf = get4(s); s += 4; + tf_flags = (vf & 0x00ffffff); + tID = get4(s); s += 4; + + snprintf(item_name, MAX_ITEMBUF, "%s/version(%d) flags(0x%x)", name_buf, + (vf>>24) & 0xff,tf_flags); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/track-ID(%u)", name_buf,tID); + add_sub_item(); + + if(len > 7) + { + uint64_t off; + + if(sizeof(uint64_t) == 4) return dend; + + off = get8(s); s += 8; len -= 8; + + snprintf(item_name, MAX_ITEMBUF, "%s/base-data-offset(%" PRIu64 ")", + name_buf, off); + add_sub_item(); + } + if(len > 3) + { + unsigned int index = get4(s); s += 4; len -= 4; + + snprintf(item_name, MAX_ITEMBUF, "%s/sample-description-index(%u)", name_buf,index); + add_sub_item(); + } + + if(len > 3) + { + unsigned int dur = get4(s); s += 4; len -= 4; + + snprintf(item_name, MAX_ITEMBUF, "%s/default-sample-duration(%u)", name_buf,dur); + add_sub_item(); + } + + if(len > 3) + { + unsigned int size = get4(s); s += 4; len -= 4; + + snprintf(item_name, MAX_ITEMBUF, "%s/default-sample-size(%u)", name_buf,size); + add_sub_item(); + } + + if(len > 3) + { + unsigned int flags = get4(s); s += 4; len -= 4; + + snprintf(item_name, MAX_ITEMBUF, "%s/default-sample-flags(%u)", name_buf,flags); + add_sub_item(); + } + +//fprintf(stderr,"%s:%d:\n\tEXIT tfhd len(%d)\n",__FILE__,__LINE__,len); +//-------------------------------- + return box_end; + +}//read_tfhd() + +static unsigned char *read_trun(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + unsigned int sc, f, i, vf; + int off, tr_flags; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Track fragment run box", name_buf); + add_sub_item(); + + vf = get4(s); s += 4; + tr_flags = (vf & 0x00ffffff); + snprintf(item_name, MAX_ITEMBUF, "%s/version(%d) tr_flags(0x%x)", name_buf, + (vf>>24) & 0xff,tr_flags); + add_sub_item(); + + sc = get4(s); s += 4; + off = get4(s); s += 4; + f = get4(s); s += 4; + + snprintf(item_name, MAX_ITEMBUF, "%s/sample-count(%u)", name_buf,sc); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/data-offset(%d)", name_buf,off); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/first-sample-flags(%u)", name_buf,f); + add_sub_item(); + + for(i = 0; i < sc; ++i) + { + unsigned int dur, size, f, off; + + dur = get4(s); s += 4; + size = get4(s); s += 4; + f = get4(s); s += 4; + off = get4(s); s += 4; + + snprintf(item_name, MAX_ITEMBUF, "%s/Sample[%u] duration(%u) size(%u)" + " flags(%u) offset(%u)", name_buf,i,dur,size,f,off); + add_sub_item(); + } + return box_end; +}//read_trun() + +static unsigned char *read_traf(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + Fl_Tree_Item *sup; + uint64_t box_len; + unsigned int hstep; + int len; + int pos = -1; + char name_buf[MAX_ITEMBUF]; + char sup_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Track fragment box", name_buf); + add_sub_item(); + + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + + if(memcmp(box_name, "tfhd", 4) != 0) + { + +LOG("tfhd missing. STOP."); + + return dend; + } + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%3d] tfhd", name_buf, ++pos); + sup = tree->add(sup_buf); + + len = (int)(box_len - hstep - 8); + + s = read_tfhd(s + hstep, s + box_len, dend, sup_buf, len); + + sup->close(); + + if(s >= dend) return dend; + + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + + if(memcmp(box_name, "trun", 4) == 0) + { + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%3d] trun", name_buf, ++pos); + sup = tree->add(sup_buf); + + s = read_trun(s + hstep, s + box_len, dend, sup_buf); + + sup->close(); + + if(s >= dend) return dend; + } + + return box_end; +}//read_traf() + +static unsigned char *read_mfhd(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + unsigned int vf, n; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Movie fragment header box", name_buf); + add_sub_item(); + + vf = get4(s); s += 4; + n = get4(s); s += 4; + + snprintf(item_name, MAX_ITEMBUF, "%s/version(%d) flags(%d)", item_name, + (vf>>24) & 0xff,(vf & 0x00ffffff)); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/sequence-number(%u)", item_name,n); + add_sub_item(); + + return box_end; +}//read_mfhd() + +static unsigned char *read_moof(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + Fl_Tree_Item *sup; + uint64_t box_len; + unsigned int hstep; + int pos = -1; + char name_buf[MAX_ITEMBUF]; + char sup_buf[MAX_ITEMBUF]; + + strcpy(name_buf, (char*)name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Movie fragment box", name_buf); + add_sub_item(); + + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + + if(memcmp(box_name, "mfhd", 4) != 0) + { + +LOG("mfhd missing. STOP."); + + return dend; + } + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%03d] mfhd", name_buf, ++pos); + sup = tree->add(sup_buf); + + s = read_mfhd(s + hstep, s + box_len, dend, sup_buf); + + sup->close(); + + if(s >= dend) return dend; + + for(;;) + { + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + + if(memcmp(box_name, "traf", 4) != 0) break; + + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%d] traf", name_buf, ++pos); + sup = tree->add(sup_buf); + + s = read_traf(s + hstep, s + box_len, dend, sup_buf); + + sup->close(); + + if(s >= dend) return dend; + + }/* for() */ + + return box_end; + +}//read_moof() + +static unsigned char *read_tfra(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + unsigned int vf, tID, v, i; + unsigned short version, traf_num, trun_num, sample_num; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, + "%s/Track fragment random access box", name_buf); + add_sub_item(); + + vf = get4(s); s += 4; + version = (vf>>24) & 0xff; + snprintf(item_name, MAX_ITEMBUF, "%s/version(%hu) flags(%d)", name_buf, + version,(vf & 0x00ffffff)); + add_sub_item(); + + tID = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/track_ID(%u)", name_buf, tID); + add_sub_item(); + + v = get4(s); s += 4;//reserved 26 Bit + traf_num = (((v>>26)&0x3) + 1) * 8; + trun_num = (((v>>28)&0x3) + 1) * 8; + sample_num = (((v>>30)&0x3) + 1) * 8; + + v = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/Number of entries(%u)", name_buf, v); + add_sub_item(); + + for(i = 0; i < v; ++i) + { + if(version == 1) + { + uint64_t t, o; + + if(sizeof(uint64_t) == 4) return dend; + + t = get8(s); s += 8; + o = get8(s); s += 8; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%hu] time(%" PRIu64 ")", + name_buf, i,t); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/[%hu] moof_offset(%" PRIu64 ")", + name_buf, i,o); + add_sub_item(); + } + else + { + unsigned int t, o; + + t = get4(s); s += 4; + o = get4(s); s += 4; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%hu] time(%u)", name_buf, i,t); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/[%hu] moof_offset(%u)", name_buf, i,o); + add_sub_item(); + } + snprintf(item_name, MAX_ITEMBUF, "%s/[%hu] traf_num(%hu)", + name_buf,i,traf_num); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/[%hu] trun_num(%hu)", + name_buf,i,trun_num); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/[%hu] sample_num(%hu)", + name_buf,i,sample_num); + add_sub_item(); + }//for(i + + return box_end; +}//read_tfra() + +static unsigned char *read_mfro(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + unsigned int vf, v; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, + "%s/Movie fragment random access box", name_buf); + add_sub_item(); + + vf = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/version(%d) flags(%d)", name_buf, + (vf>>24) & 0xff,(vf & 0x00ffffff)); + add_sub_item(); + + v = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/size(%u)", name_buf, v); + add_sub_item(); + + return box_end; +}//read_mfro() + +static unsigned char *read_mfra(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + uint64_t box_len; + unsigned int hstep; + int pos = -1; + char name_buf[MAX_ITEMBUF]; + char sup_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Movie fragment random access box", + name_buf); + add_sub_item(); + + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + + if(memcmp(box_name, "tfra", 4) == 0)//option, > 1 + { + Fl_Tree_Item *sup; + + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%03d] tfra", name_buf, ++pos); + sup = tree->add(sup_buf); + + s = read_tfra(s + hstep, s + box_len, dend, sup_buf); + + sup->close(); + + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + } + + if(memcmp(box_name, "mfro", 4) == 0)//mandatory, 1 + { + Fl_Tree_Item *sup; + + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%03d] mfro", name_buf, ++pos); + sup = tree->add(sup_buf); + + s = read_mfro(s + hstep, s + box_len, dend, sup_buf); + + sup->close(); + } + else + { + +LOG("mfro missing. STOP."); + + s = dend; + } + return s; +}//read_mfra() + +static unsigned char *read_vmhd(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + const char *cs = ""; + unsigned int vf; + unsigned short gmode, opcolor[3]; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Video media header box", name_buf); + add_sub_item(); + + vf = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/version(%d) flags(%d)", name_buf, + (vf>>24) & 0xff,(vf & 0x00ffffff)); + add_sub_item(); + + gmode = get2(s); s += 2; + + if(gmode == 0) cs = "copy"; + else + if(gmode == 0x24) cs = "transparent"; + else + if(gmode == 0x100) cs = "alpha"; + else + if(gmode == 0x101) cs = "whitealpha"; + else + if(gmode == 0x102) cs = "blackalpha"; + + snprintf(item_name, MAX_ITEMBUF, "%s/graphicsmode(%s)", name_buf, cs); + add_sub_item(); + + opcolor[0] = get2(s); s += 2; + opcolor[1] = get2(s); s += 2; + opcolor[2] = get2(s); s += 2; + + snprintf(item_name, MAX_ITEMBUF, "%s/opcolor(0x%x 0x%x 0x%x)", name_buf, + opcolor[0],opcolor[1],opcolor[2]); + add_sub_item(); + + return box_end; +}/* read_vmhd() */ + +static unsigned char *read_smhd(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + char name_buf[MAX_ITEMBUF]; + unsigned int vf; + int bal; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Sound media header box", name_buf); + add_sub_item(); + + vf = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/version(%d) flags(%d)", name_buf, + (vf>>24) & 0xff,(vf & 0x00ffffff)); + add_sub_item(); + + bal = get2(s); s += 2; + snprintf(item_name, MAX_ITEMBUF, "%s/balance(%u)", name_buf, bal); + add_sub_item(); + + s += 2;//reserved + + return s; +} + +static unsigned char *read_hmhd(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + char name_buf[MAX_ITEMBUF]; + unsigned int vf, maxbit, avgbit, slideavgbit; + unsigned short maxpdu, avgpdu; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Hint media header box", name_buf); + add_sub_item(); + + vf = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/version(%d) flags(%d)", name_buf, + (vf>>24) & 0xff,(vf & 0x00ffffff)); + add_sub_item(); + + maxpdu = get2(s); s += 2; + snprintf(item_name, MAX_ITEMBUF, "%s/max-pdu(%u)", name_buf, maxpdu); + add_sub_item(); + + avgpdu = get2(s); s += 2; + snprintf(item_name, MAX_ITEMBUF, "%s/average-pdu(%u)", name_buf, avgpdu); + add_sub_item(); + + maxbit = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/max-bitrate(%u)", name_buf, maxbit); + add_sub_item(); + + avgbit = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/average-bitrate(%u)", + name_buf, avgbit); + add_sub_item(); + + slideavgbit = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/sliding-average-bitrate(%u)", + name_buf,slideavgbit); + add_sub_item(); + + return box_end; +} + +static unsigned char *read_dref(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + Fl_Tree_Item *sub; + uint64_t box_len; + unsigned int hstep; + unsigned int vers, en, i; + unsigned short flag; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Data reference box", name_buf); + add_sub_item(); + + vers = s[0]; ++s; + flag = get_size(s, 3); s += 3; + en = get4(s); s += 4; + + snprintf(item_name, MAX_ITEMBUF, "%s/version(%hu) flag(%u)", + name_buf, vers,flag); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/Entries(%d)", name_buf, en); + add_sub_item(); + ++en; + + for(i = 1; i < en; ++i) + { + unsigned char *eend, *ename; + char ebuf[MAX_ITEMBUF*2]; + + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + + eend = s + box_len; + s += hstep; + + if(memcmp(box_name, "url ", 4) == 0) + { + vers = s[0]; ++s; + flag = get_size(s, 3); s += 3; + + snprintf(ebuf, MAX_ITEMBUF, + "%s/[%d] url: version(%hu) flag(%u)", name_buf, i, vers, flag); + sub = tree->add(ebuf); + sub->usericon(&L_documentpixmap); + } + else + if(memcmp(box_name, "urn ", 4) == 0) + { + vers = s[0]; ++s; + flag = get_size(s, 3); s += 3; + ename = s; + + snprintf(ebuf, MAX_ITEMBUF, + "%s/[%d] urn: version(%hu) flag(%u) ename(%s)", + name_buf, i, vers, flag, ename); + sub = tree->add(ebuf); + sub->usericon(&L_documentpixmap); + } + else + { + fprintf(stderr,"[%u] wrong entry name(%s)\n",i,box_name); + } + s = eend; + + } + + return s; +}//read_dref() + +static unsigned char *read_dinf(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + Fl_Tree_Item *sup; + uint64_t box_len; + unsigned int hstep; + int pos = -1; + char name_buf[MAX_ITEMBUF]; + char sup_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Data information box", name_buf); + add_sub_item(); + + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + + if(memcmp(box_name, "dref", 4) != 0) + { + +LOG("dref missing. STOP."); + + return dend; + } + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%03d] dref", name_buf, ++pos); + sup = tree->add(sup_buf); + + s = read_dref(s + hstep, s + box_len, dend, sup_buf); + + sup->close(); + + return s; + +}/* read_dinf() */ + +static unsigned char *read_stts(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + unsigned int vf, en, i, sc; + int sd; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Time-to-sample box", name_buf); + add_sub_item(); + + vf = get4(s); s += 4; + en = get4(s); s += 4; + + snprintf(item_name, MAX_ITEMBUF, "%s/version(%u) flag(%u)",name_buf, + (vf>>24)&0xff, vf&0xffffff); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/entry-count(%u)",name_buf,en); + add_sub_item(); + + for(i = 0; i < en; ++i) + { + sc = get4(s); s += 4; + sd = get4(s); s += 4; + + snprintf(item_name, MAX_ITEMBUF, + "%s/[%u] sample-count(%u) sample-delta(%d)", name_buf,i,sc,sd); + add_sub_item(); + } +//mj2.c : mj2_tts_decompact(tk); + + return box_end; +}//read_stts() + +static unsigned char *read_stsc(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + unsigned int vf, en, i; + unsigned int fc, spc, sdi; + char name_buf[MAX_ITEMBUF]; + + strcpy((char*)name_buf, (char*)name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Sample-to-chunk data box", name_buf); + add_sub_item(); + + vf = get4(s); s += 4; + en = get4(s); s += 4; + + snprintf(item_name, MAX_ITEMBUF, "%s/version(%u) flag(%u)",name_buf, + (vf>>24)&0xff, vf&0xffffff); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/entry-count(%u)",name_buf,en); + add_sub_item(); + + ++en; + + for(i = 1; i < en; ++i) + { + fc = get4(s); s += 4; + spc = get4(s); s += 4; + sdi = get4(s); s += 4; + + snprintf(item_name, MAX_ITEMBUF, + "%s/[%u] first-chunk(%u) samples-per-chunk(%u)" + " sample-index(%u)",name_buf, i, fc,spc,sdi); + add_sub_item(); + } + return box_end; +}//read_stsc() + +static unsigned char *read_stsz(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + sample_t *TrackSamples; + unsigned int vf, en,sample_size; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Sample sizes box", name_buf); + add_sub_item(); + + vf = get4(s); s += 4; + sample_size = get4(s); s += 4; + en = get4(s); s += 4; + + snprintf(item_name, MAX_ITEMBUF, "%s/version(%u) flag(%u)",name_buf, + (vf>>24)&0xff, vf&0xffffff); + add_sub_item(); +#ifdef USE_LONG_NAME + snprintf(item_name, MAX_ITEMBUF, "%s/sample-size(%u) sample-count(%u)", +#else + snprintf(item_name, MAX_ITEMBUF, "%s/siz(%u) cnt(%u)", +#endif + name_buf,sample_size,en); + add_sub_item(); + + ++en; // 1:en + + TrackSamples = new_track_samples(en); + + if(sample_size == 0) + { + unsigned int i, esize; + + for(i = 1; i < en; ++i) + { + esize = get4(s); s += 4; + + TrackSamples[i].size = esize; +#ifdef USE_LONG_NAME + snprintf(item_name, MAX_ITEMBUF, "%s/[%04d] entry-size(%u)", +#else + snprintf(item_name, MAX_ITEMBUF, "%s/[%04d] size(%u)", +#endif + name_buf,i,esize); + add_sub_item(); + } + } + else // all tracks have same size + { + unsigned int i; + + for(i = 1; i < en; ++i) + { + TrackSamples[i].size = sample_size; +#ifdef USE_LONG_NAME + snprintf(item_name, MAX_ITEMBUF, "%s/[%04d] entry-size(%u)", +#else + snprintf(item_name, MAX_ITEMBUF, "%s/[%04d] size(%u)", +#endif + name_buf,i,sample_size); + add_sub_item(); + + } + } + return box_end; +}//read_stsz() + +static unsigned char *read_stz2(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + sample_t *TrackSamples; + unsigned int vf, en, v, i; + unsigned short bits, val; + char name_buf[MAX_ITEMBUF]; + + strcpy((char*)name_buf, (char*)name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Compact sample sizes box", name_buf); + add_sub_item(); + + vf = get4(s); s += 4; + v = get4(s); s += 4; + bits = (v>>24)&0xff;//24 Bit reserved, 8 Bit field-size + en = get4(s); s += 4; + + if(bits != 4 && bits != 8 && bits != 16) + { + fprintf(stderr,"%s:%d:\n\tstz2 has wrong bits size(%hu). STOP.\n", + __FILE__,__LINE__,bits); + + return dend; + } + snprintf(item_name, MAX_ITEMBUF, "%s/version(%u) flag(%u)",name_buf, + (vf>>24)&0xff, vf&0xffffff); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/field-size(%hu) sample-count(%u)", + name_buf,bits,en); + add_sub_item(); + + ++en; + TrackSamples = new_track_samples(en); + + for(i = 1; i < en; ++i) + { + if(bits == 4) + { + val = (s[0]<<4) |( s[1]&0x0f); s += 2; + } + else + if(bits == 8) + { + val = s[0]; ++s; + } + else +// if(bits == 16) + { + val = get2(s); s += 2; + } + snprintf(item_name, MAX_ITEMBUF, "%s/[%04d] size(%hu)", + name_buf,i,val); + add_sub_item(); + + TrackSamples[i].size = val; + }//for(i + + return box_end; +}//read_stz2() + +static unsigned char *read_stco(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + sample_t *TrackSamples; + unsigned int vf, en, co, i; + int nr_tracks; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Chunk offset box", name_buf); + add_sub_item(); + + vf = get4(s); s += 4; + en = get4(s); s += 4; + + snprintf(item_name, MAX_ITEMBUF, "%s/version(%u) flag(%u)",name_buf, + (vf>>24)&0xff, vf&0xffffff); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/entry-count(%u)",name_buf,en); + add_sub_item(); + + assert(Tracks); + nr_tracks = Tracks[0].nr_tracks; + TrackSamples = Tracks[nr_tracks-1].samples; + assert(TrackSamples); + + ++en; + for(i = 1; i < en; ++i) + { + co = get4(s); s += 4; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%04d] offset(%u)", + name_buf,i,co); + add_sub_item(); + + TrackSamples[i].pos = (int64_t)co; + } + + return box_end; +}//read_stco() + +static unsigned char *read_co64(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + sample_t *TrackSamples; + uint64_t co; + unsigned int vf, en, i; + int nr_tracks; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Chunk offset box", name_buf); + add_sub_item(); + + vf = get4(s); s += 4; + en = get4(s); s += 4; + + snprintf(item_name, MAX_ITEMBUF, "%s/version(%u) flag(%u)",name_buf, + (vf>>24)&0xff, vf&0xffffff); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/entry-count(%u)",name_buf,en); + add_sub_item(); + + assert(Tracks); + nr_tracks = Tracks[0].nr_tracks; + TrackSamples = Tracks[nr_tracks-1].samples; + assert(TrackSamples); + + ++en; + + for(i = 1; i < en; ++i) + { + co = get8(s); s += 8; + + TrackSamples[i].pos = (int64_t)co; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%04d] offset(%" PRIu64 ")", + name_buf,i,co); + add_sub_item(); + } + return box_end; +}//read_co64() + +static unsigned char *read_fiel(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + unsigned short fcount, forder; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Field Coding box", name_buf); + add_sub_item(); + + fcount = (unsigned short)s[0]; ++s; + forder = (unsigned short)s[0]; ++s; + + snprintf(item_name, MAX_ITEMBUF, + "%s/fieldcount(%hu)",name_buf, fcount); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, + "%s/fieldorder(%hu)",name_buf, forder); + add_sub_item(); + + return box_end; +} + +static unsigned char *read_jp2p(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src, uint64_t box_len) +{ + unsigned int i, n, vf; + unsigned char brand[5]; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/MJP2 profile box", name_buf); + add_sub_item(); + + vf = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/version(%u) flag(%u)",name_buf, + (vf>>24)&0xff, vf&0xffffff); + add_sub_item(); + + n = (unsigned int)((box_len - 12)/4); brand[4] = 0; + snprintf(item_name, MAX_ITEMBUF, "%s/entry-count(%u)",name_buf,n); + add_sub_item(); + + for(i = 0; i < n; ++i) + { + memcpy(brand, s, 4); s += 4; + + if(*brand == 0) memset(brand,' ', 4); + + snprintf(item_name, MAX_ITEMBUF, "%s/CL(%s)", name_buf,(char*)brand); + add_sub_item(); + } + return box_end; +} + +static unsigned char *read_mjp2(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + uint64_t box_len; + unsigned int hstep, vf; + int hres, vres; + unsigned short w, h, nlen, depth; + int pos = -1; + char name_buf[MAX_ITEMBUF]; + char sup_buf[MAX_ITEMBUF]; + char name32[33]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/MJP2 sample entry box", name_buf); + add_sub_item(); + + vf = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/version(%d) flags(%d)", name_buf, + (vf>>24) & 0xff,(vf & 0xffffff)); + add_sub_item(); + + s += 4; // FIXME: not clear Part 3, 6.2.16.1 + s += 2;//predef + s += 2;//res + s += 12;//predef + + w = get2(s); s += 2; + snprintf(item_name, MAX_ITEMBUF, "%s/width(%hu)",name_buf,w); + add_sub_item(); + + h = get2(s); s += 2; + snprintf(item_name, MAX_ITEMBUF, "%s/height(%hu)",name_buf,h); + add_sub_item(); + + hres = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/hres(%hi.%hi)",name_buf, + (hres>>16),(hres&0xffff)); + add_sub_item(); + + vres = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/vres(%hi.%hi)",name_buf, + (vres>>16),(vres&0xffff)); + add_sub_item(); + + s += 4;//res + s += 2;//predef + nlen = s[0]; + memcpy(name32, s+1, nlen); name32[nlen] = 0; + snprintf(item_name, MAX_ITEMBUF, "%s/name[%hu](%s)",name_buf,nlen,name32); + add_sub_item(); + + s += 32; + depth = get2(s); s += 2; + snprintf(item_name, MAX_ITEMBUF, "%s/depth(%hu)",name_buf,depth); + add_sub_item(); + + s += 2;//predef + + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + +//JP2HeaderBox required: + if(memcmp(box_name, "jp2h", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%03d] jp2h", name_buf, ++pos); + sup = tree->add(sup_buf); + + s = read_jp2h(s + hstep, s + box_len, dend, sup_buf); + + sup->close(); + + if(s >= dend) return s; + + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + } + +//FieldCodingBox optional: + if(memcmp(box_name, "fiel", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%03d] fiel", name_buf, ++pos); + sup = tree->add(sup_buf); + + s = read_fiel(s + hstep, s + box_len, dend, sup_buf); + + sup->close(); + + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + } + +//MJP2ProfileBox optional: + if(memcmp(box_name, "jp2p", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%03d] jp2p", name_buf, ++pos); + sup = tree->add(sup_buf); + + s = read_jp2p(s + hstep, s + box_len, dend, sup_buf, box_len); + + sup->close(); + + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + } + +//MJP2PrefixBox optional: + if(memcmp(box_name, "jp2x", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%03d] jp2x", name_buf, ++pos); + sup = tree->add(sup_buf); + + snprintf(item_name, MAX_ITEMBUF, "%s/data[%" PRIu64 "]", sup_buf, + (box_len-8)); + add_sub_item(); + + sup->close(); + + s += box_len; + + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + } + +//MJP2SubSamplingBox optional: + if(memcmp(box_name, "jsub", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%03d] jsub", name_buf, ++pos); + sup = tree->add(sup_buf); + + s += hstep; + + snprintf(item_name, MAX_ITEMBUF, + "%s/hsub(%hu) vsub(%hu)", sup_buf, s[0],s[1]); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, + "%s/hoff(%hu) voff(%hu)", sup_buf, s[2],s[3]); + add_sub_item(); + + sup->close(); + + s += 4; + + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + } + +//MJP2OriginalFormatBox optional: + if(memcmp(box_name, "orfo", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%03d] orfo", name_buf, ++pos); + sup = tree->add(sup_buf); + + s += hstep; + + snprintf(item_name, MAX_ITEMBUF, + "%s/original-fieldcount(%hu)", sup_buf, (unsigned short)s[0]); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, + "%s/original-fieldorder(%hu)", sup_buf, (unsigned short)s[1]); + add_sub_item(); + + s += 2; + + sup->close(); + } + + return box_end; + +}//read_mjp2( + +static unsigned char *read_stsd(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + uint64_t box_len; + unsigned int hstep, vf, en, i; + int pos; + char name_buf[MAX_ITEMBUF]; + char sup_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Sample description box", name_buf); + add_sub_item(); + + vf = get4(s); s += 4; + en = get4(s); s += 4; + + snprintf(item_name, MAX_ITEMBUF, "%s/version(%u) flag(%u)",name_buf, + (vf>>24)&0xff, vf&0xffffff); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/entry-count(%u)",name_buf,en); + add_sub_item(); + + ++en; pos = 0; + + for(i = 1; i < en; ++i) + { + unsigned char *bend; + + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + + bend = s + box_len; + +#ifdef DEBUG_MJ2 +fprintf(stderr,"%s:%d:handler_type(%s) <==> box_name(%s)\n",__FILE__,__LINE__, +handler_type,box_name); +#endif + + if(memcmp(handler_type, "soun", 4) == 0) + { + +fprintf(stderr,"%s:%d:\n\tAUDIO TRACK IGNORED\n",__FILE__,__LINE__); + + s = bend; + continue; + } + + if(memcmp(handler_type, "vide", 4) == 0) + { + Fl_Tree_Item *sup; + + if(memcmp(box_name, "mjp2", 4) != 0)//mj2.c : mj2_read_smj2() + { + +fprintf(stderr,"[%d]'vide' has wrong box name:(%s)\n",i,box_name); + + s = bend; + continue; + } + + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%3d] mjp2", name_buf, ++pos); + sup = tree->add(sup_buf); + + s = read_mjp2(s + hstep, s + box_len, dend, sup_buf); + + sup->close(); + + if(s != bend) return dend; + + s = bend; + + continue; + } /* vide */ + + if(memcmp(handler_type, "hint", 4) == 0) + { + fprintf(stderr,"%s:%d:\n\tHINT TRACK IGNORED\n",__FILE__,__LINE__); + s = bend; + continue; + } + s = bend; + }/* for(i) */ + + return s; + +}//read_stsd() + +static unsigned char *read_stbl(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + Fl_Tree_Item *sup; + uint64_t box_len; + unsigned int hstep; + int pos = -1; + char name_buf[MAX_ITEMBUF]; + char sup_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Sample table box", name_buf); + add_sub_item(); + + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + + if(memcmp(box_name, "stsd", 4) != 0) + { + +LOG("stsd missing. STOP."); + + return dend; + } + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%03d] stsd", name_buf, ++pos); + sup = tree->add(sup_buf); + + s = read_stsd(s + hstep, s + box_len, dend, sup_buf); + + sup->close(); + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + + if(memcmp(box_name, "stts", 4) != 0) + { + +LOG("stts missing. STOP."); + + return dend; + } + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%03d] stts", name_buf, ++pos); + sup = tree->add(sup_buf); + + s = read_stts(s + hstep, s + box_len, dend, sup_buf); + + sup->close(); + + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + + if(memcmp(box_name, "stsc", 4) != 0) + { + +LOG("stsc missing. STOP."); + + return dend; + } + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%03d] stsc", name_buf, ++pos); + sup = tree->add(sup_buf); + + s = read_stsc(s + hstep, s + box_len, dend, sup_buf); + sup->close(); + + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + + if(memcmp(box_name, "stsz", 4) == 0) + { + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%03d] stsz", name_buf, ++pos); + sup = tree->add(sup_buf); + + s = read_stsz(s + hstep, s + box_len, dend, sup_buf); + + sup->close(); + + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + } + else + if(memcmp(box_name, "stz2", 4) == 0) + { + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%03d] stz2", name_buf, ++pos); + sup = tree->add(sup_buf); + + s = read_stz2(s + hstep, s + box_len, dend, sup_buf); + + sup->close(); + + if(s == dend) return s; + + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + } + else + { + +LOG("stsz/stz2 missing. STOP."); + + return dend; + + } + + if(memcmp(box_name, "stco", 4) == 0) + { + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%03d] stco", name_buf, ++pos); + sup = tree->add(sup_buf); + + s = read_stco(s + hstep, s + box_len, dend, sup_buf); + + sup->close(); + } + else + if(memcmp(box_name, "co64", 4) == 0) + { + if(sizeof(uint64_t) == 4) return dend; + + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%03d] co64", name_buf, ++pos); + sup = tree->add(sup_buf); + + s = read_co64(s + hstep, s + box_len, dend, sup_buf); + + sup->close(); + } + else + { + +LOG("stco/co64 missing. STOP."); + + return dend; + } + return box_end; +}/* read_stbl() */ + +static unsigned char *read_elst(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + char name_buf[MAX_ITEMBUF]; + unsigned int vf, en,i; + unsigned short version, irate, frate; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Edit list box", name_buf); + add_sub_item(); + + vf = get4(s); s += 4; + version = (vf>>24) & 0xff; + en = get4(s); s += 4; + + snprintf(item_name, MAX_ITEMBUF, "%s/version(%d) flags(0x%x)", name_buf, + version, (vf & 0xffffff) ); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/entry-count(%u)", name_buf,en); + add_sub_item(); + + for(i = 0; i < en; ++i) + { + if(version == 1) + { + uint64_t d, t; + + if(sizeof(uint64_t) == 4) return dend; + + d = get8(s); s += 8; + t = get8(s); s += 8; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%u] segment-duration(%" PRIu64 ")", + name_buf,i,d); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/[%u] media-time(%" PRIu64 ")", + name_buf,i,t); + add_sub_item(); + } + else + { + unsigned int d, t; + + d = get4(s); s += 4; + t = get4(s); s += 4; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%u] segment-duration(%u)", + name_buf,i,d); + add_sub_item(); + + snprintf(item_name, MAX_ITEMBUF, "%s/[%u] media-time(%d)", name_buf,i,t); + add_sub_item(); + } + irate = get2(s); s += 2; + frate = get2(s); s += 2; + + snprintf(item_name, MAX_ITEMBUF, "%s/[%u] media-rate(%hu.%hu)", name_buf, + i,irate,frate); + add_sub_item(); + }//for(i + + return box_end; +}//read_elst() + +static unsigned char *read_mdhd(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + unsigned int vf; + unsigned short lang, version; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Media header box", name_buf); + add_sub_item(); + + vf = get4(s); s += 4; + version = (vf>>24)&0xff; + snprintf(item_name, MAX_ITEMBUF, "%s/version(%hu) flags(%u)", name_buf, + version,(vf&0xffffff)); + add_sub_item(); + + if(version == 0) + { + unsigned int v; + + v = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/creation-time(%u)", name_buf, v); + add_sub_item(); + + v = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/modification-time(%u)", name_buf, v); + add_sub_item(); + + v = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/timescale(%u)",name_buf, v); + add_sub_item(); + + v = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/duration(%u)",name_buf, v); + add_sub_item(); + } + else + { + uint64_t v; + + if(sizeof(uint64_t) == 4) return dend; + + v = get8(s); s += 8; + snprintf(item_name, MAX_ITEMBUF, "%s/creation-time(%" PRIu64 ")", + name_buf, v); + add_sub_item(); + + v = get8(s); s += 8; + snprintf(item_name, MAX_ITEMBUF, "%s/modification-time(%" PRIu64 ")", + name_buf, v); + add_sub_item(); + + v = get8(s); s += 8; + snprintf(item_name, MAX_ITEMBUF, "%s/timescale(%" PRIu64 ")",name_buf, v); + add_sub_item(); + + v = get8(s); s += 8; + snprintf(item_name, MAX_ITEMBUF, "%s/duration(%" PRIu64 ")",name_buf, v); + add_sub_item(); + } + + lang = get2(s); s += 2; + { + char a, b, c; + + if(lang) + { + c = (lang>>1)&0x37; b = (lang>>6)&0x37; a = (lang>>11)&0x37; + snprintf(item_name, MAX_ITEMBUF, "%s/language(%c%c%c)",name_buf, a, b, c); + } + else + snprintf(item_name, MAX_ITEMBUF, "%s/language(0)",name_buf); + + add_sub_item(); + } + s += 2;//pre-defined + + return box_end; +}//read_mdhd() + +static unsigned char *read_hdlr(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + char *hname; + unsigned int vf; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Handler reference box", name_buf); + add_sub_item(); + + vf = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/version(%d) flags(%d)", name_buf, + (vf>>24) & 0xff,(vf & 0x00ffffff)); + add_sub_item(); + + s += 4;//pre-defined + + handler_type[4] = 0; memcpy(handler_type, s, 4); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/handler-type(%s)", + name_buf, (char*)handler_type); + add_sub_item(); + + s += 12;//reserved + + hname = strdup((char*)s); s += strlen(hname) + 1; + snprintf(item_name, MAX_ITEMBUF, "%s/name(%s)", name_buf, hname); + add_sub_item(); + + free(hname); + + return box_end; +}//read_hdlr() + +static unsigned char *read_minf(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + Fl_Tree_Item *sup; + uint64_t box_len; + unsigned int hstep; + int pos = -1; + char name_buf[MAX_ITEMBUF]; + char sup_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Media information box", name_buf); + add_sub_item(); + + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + + has_vmhd = has_smhd = has_hmhd = 0; + + if(memcmp(box_name, "vmhd", 4) == 0) + { + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%03d] vmhd", name_buf, ++pos); + sup = tree->add(sup_buf); + + s = read_vmhd(s + hstep, s + box_len, dend, sup_buf); + + sup->close(); + has_vmhd = 1; + } + else + if(memcmp(box_name, "smhd", 4) == 0) + { + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%03d] smhd", name_buf, ++pos); + sup = tree->add(sup_buf); + + s = read_smhd(s + hstep, s + box_len, dend, sup_buf); + + sup->close(); + has_smhd = 1; + } + else + if(memcmp(box_name, "hmhd", 4) == 0) + { + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%03d] hmhd", name_buf, ++pos); + sup = tree->add(sup_buf); + + s = read_hmhd(s + hstep, s + box_len, dend, sup_buf); + + sup->close(); + has_hmhd = 1; + } + else + { + +LOG("neither vmhd nor smhd nor hmhd found. STOP."); + + return dend; + } + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + + if(memcmp(box_name, "dinf", 4) != 0) + { + +LOG("dinf missing. STOP."); + + return dend; + } + + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%03d] dinf", name_buf, ++pos); + sup = tree->add(sup_buf); + + s = read_dinf(s + hstep, s + box_len, dend, sup_buf); + + sup->close(); + + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + + if(memcmp(box_name, "stbl", 4) != 0) + { + +LOG("stbl missing. STOP."); + + return dend; + } + + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%03d] stbl", name_buf, ++pos); + sup = tree->add(sup_buf); + + s = read_stbl(s + hstep, s + box_len, dend, sup_buf); + + sup->close(); + + return s; +} + +static unsigned char *read_mdia(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + Fl_Tree_Item *sup; + uint64_t box_len; + unsigned int hstep; + char name_buf[MAX_ITEMBUF]; + char sup_buf[MAX_ITEMBUF]; + int pos = -1; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Media box", name_buf); + add_sub_item(); + + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + + if(memcmp(box_name, "mdhd", 4) != 0) + { +LOG("mdhd missing. STOP."); + + return dend; + } + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%03d] mdhd", name_buf, ++pos); + sup = tree->add(sup_buf); + + s = read_mdhd(s + hstep, s + box_len, dend, sup_buf); + + sup->close(); + + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + + if(memcmp(box_name, "hdlr", 4) != 0) + { + +LOG("hdrl missing. STOP."); + + return dend; + } + + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%03d] hdlr", name_buf, ++pos); + sup = tree->add(sup_buf); + + s = read_hdlr(s + hstep, s + box_len, dend, sup_buf); + + sup->close(); + + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + + if(memcmp(box_name, "minf", 4) != 0) + { +LOG("minf missing. STOP."); + + return dend; + } + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%03d] minf", name_buf, ++pos); + sup = tree->add(sup_buf); + + s = read_minf(s + hstep, s + box_len, dend, sup_buf); + + sup->close(); + + return s; + +}/* read_mdia() */ + +static unsigned char *read_tkhd(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) + +{ + unsigned int vf, val; + unsigned int ct, mt, curID, dur, max_w, max_h; + short layer, vol, i; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Track header box", name_buf); + add_sub_item(); + + vf = get4(s); s += 4; + + snprintf(item_name, MAX_ITEMBUF, "%s/version(%d) flags(%d)", name_buf, + (vf>>24) & 0xff,(vf & 0x00ffffff)); + add_sub_item(); + + ct = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/creation-time(%u)", name_buf, ct); + add_sub_item(); + + mt = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/modification-time(%u)", name_buf, mt); + add_sub_item(); + + curID = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/track-ID(%u)", name_buf, curID); + add_sub_item(); + + s += 4;//reserved + + dur = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/duration(%u)", name_buf, dur); + add_sub_item(); + + s += 8;//reserved + + layer = get2(s); s += 2; + snprintf(item_name, MAX_ITEMBUF, "%s/layer(%d)", name_buf, layer); + add_sub_item(); + + s += 2;//pre-defined + + vol = get2(s); s += 2; + snprintf(item_name, MAX_ITEMBUF, "%s/volume(%d.%d)", name_buf, + (vol>>8), (vol & 0xff)); + add_sub_item(); + + s += 2;//reserved + + for(i = 0; i < 9; ++i) + { + val = get4(s); s += 4; + + snprintf(item_name, MAX_ITEMBUF, "%s/matrix[%d](%d)",name_buf, i,val); + add_sub_item(); + } + + max_w = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/width(%u.%u)", name_buf, + (max_w>>16),(max_w & 0xffff)); + add_sub_item(); + + max_h = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/height(%u.%u)", name_buf, + (max_h>>16),(max_h & 0xffff)); + add_sub_item(); + + if(Tracks == NULL) + { + Tracks = (track_t*)calloc(1, 4 * sizeof(track_t)); + Tracks[0].max_tracks = 4; + } + i = curID - 1; + assert(i < Tracks[0].max_tracks); + Tracks[i].duration = dur; + Tracks[i].width = (unsigned int)(max_w>>16); + Tracks[i].height = (unsigned int)(max_h>>16); + + return box_end; + +}//read_tkhd() + +static unsigned char *read_trak(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + Fl_Tree_Item *sup; + uint64_t box_len; + unsigned int hstep; + char name_buf[MAX_ITEMBUF]; + char sup_buf[MAX_ITEMBUF]; + int pos = -1; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Track box", name_buf); + add_sub_item(); + + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + + if(memcmp(box_name, "tkhd", 4) != 0) + { +LOG("tkhd missing. STOP."); + + return dend; + } + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%03d] tkhd", name_buf, ++pos); + sup = tree->add(sup_buf); + + s = read_tkhd(s + hstep, s + box_len, dend, sup_buf); + + sup->close(); + + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + + if(memcmp(box_name, "tref", 4) == 0) + { + unsigned char *boxend = s + box_len; + int val; + + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%03d] tref", name_buf, ++pos); + sup = tree->add(sup_buf); + + val = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/reference-type(%d)", + sup_buf, val); + add_sub_item(); + + sup->close(); + + s = boxend; + + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + } + + if(memcmp(box_name, "edts", 4) == 0) + { + Fl_Tree_Item *edts_sub; + unsigned char *boxend = s + box_len; + + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%03d] edts",name_buf, ++pos); + edts_sub = tree->add(sup_buf); + + s = boxend; + + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + + if(memcmp(box_name, "elst", 4) == 0) + { + Fl_Tree_Item *elst_sub; + unsigned char *boxend = s + box_len; + char sub_buf[MAX_ITEMBUF]; + + snprintf(sub_buf, MAX_ITEMBUF, "%s/[%03d] elst", sup_buf,++pos); + elst_sub = tree->add(sub_buf); + + s = read_elst(s, box_end, dend, sub_buf); + + elst_sub->close(); + + s = boxend; + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + } + edts_sub->close(); + } + + if(memcmp(box_name, "mdia", 4) != 0) + { + +LOG("mdia missing. STOP."); + + return dend; + } + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%03d] mdia", name_buf, ++pos); + sup = tree->add(sup_buf); + + s = read_mdia(s + hstep, s + box_len, dend, sup_buf); + + sup->close(); + + return s; +}/* read_trak() */ + +static unsigned char *read_mvex(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + uint64_t box_len; + unsigned int hstep; + unsigned int vf, tID, di, dur, size, flags; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Movie extends box", name_buf); + add_sub_item(); + + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + + if(memcmp(box_name, "mehd", 4) == 0) + { +fputs("--- FOUND mehd ---\n", stderr); + s += box_len; + + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + } + if(memcmp(box_name, "trex", 4) != 0) + { + +LOG("trex missing. STOP."); + + return dend; + } + s += hstep; + vf = get4(s); s += 4; + tID = get4(s); s += 4; + di = get4(s); s += 4; + dur = get4(s); s += 4; + size = get4(s); s += 4; + flags = get4(s); s += 4; + +fprintf(stderr,"trex\n\t" +"vf(%hi,%hi) trackID(%u) index(%u) dur(%u) size(%u) flags(%u)\n", +(vf>>16),(vf&0xffff),tID,di,dur,size,flags); + + return box_end; +}//read_mvex() + +static unsigned char *read_mvhd(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + unsigned int vf, ct, mt, ts, dur, rate, nextID, val; + short vol, i; + char name_buf[MAX_ITEMBUF]; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Movie header box", name_buf); + add_sub_item(); + + vf = get4(s); s += 4; + + snprintf(item_name, MAX_ITEMBUF, "%s/version(%d) flags(%d)",name_buf, + (vf>>24) & 0xff,(vf & 0x00ffffff)); + add_sub_item(); + + ct = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/creation-time(%u)",name_buf, ct); + add_sub_item(); + + mt = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/modification-time(%u)",name_buf, mt); + add_sub_item(); + + ts = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/timescale(%u)",name_buf, ts); + add_sub_item(); + + dur = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/duration(%u)",name_buf, dur); + add_sub_item(); + + rate = get4(s); s += 4; + snprintf(item_name, MAX_ITEMBUF, "%s/rate(%u.%u)",name_buf, + (rate>>16),(rate & 0xffff)); + add_sub_item(); + + vol = get2(s); s += 2; + snprintf(item_name, MAX_ITEMBUF, "%s/volume(%u.%u)",name_buf, + (vol>>8),(vol & 0xff)); + add_sub_item(); + + s += 10;//reserved(2) + reserved(8) + + for(i = 0; i < 9; ++i) + { + val = get4(s); s += 4; + + snprintf(item_name, MAX_ITEMBUF, "%s/matrix[%d](%d)",name_buf, i,val); + add_sub_item(); + } + + s += 24; //uint32 predefined[6] + nextID = get4(s); s += 4; + + snprintf(item_name, MAX_ITEMBUF, "%s/next-track-ID(%u)",name_buf,nextID); + add_sub_item(); + + if(Tracks == NULL) + { + Tracks = (track_t*)calloc(1, nextID * sizeof(track_t)); + Tracks[0].max_tracks = nextID; + } + Tracks[0].duration = dur; + + return box_end; + +}//read_mvhd() + +static unsigned char *read_moov(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src) +{ + Fl_Tree_Item *sup; + uint64_t box_len; + unsigned int hstep; + char name_buf[MAX_ITEMBUF]; + char sup_buf[MAX_ITEMBUF]; + int pos = -1; + + strcpy(name_buf, name_src); + snprintf(item_name, MAX_ITEMBUF, "%s/Movie box", name_buf); + add_sub_item(); + + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + + if(memcmp(box_name, "mvhd", 4) != 0) + { + +LOG("mvhd missing. STOP."); + + return dend; + } + + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%03d] mvhd", name_buf, ++pos); + sup = tree->add(sup_buf); + + s = read_mvhd(s + hstep, s + box_len, dend, sup_buf); + + sup->close(); + + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + + if(memcmp(box_name, "udta", 4) == 0)//optional + { + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%03d] udta", name_buf,++pos); + sup = tree->add(sup_buf); + + s = read_udta(s + hstep, s + box_len, dend, sup_buf); + + sup->close(); + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + } + + if(memcmp(box_name, "trak", 4) != 0) + { + +LOG("trak missing. STOP."); + + return dend; + } + + for(;;) + { + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%03d] trak", name_buf, ++pos); + sup = tree->add(sup_buf); + + s = read_trak(s + hstep, s + box_len, dend, sup_buf); + + sup->close(); + + if(s >= dend) break; + + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + + if(memcmp(box_name, "mvex", 4) == 0) + { + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%03d] mvex", name_buf, ++pos); + sup = tree->add(sup_buf); + + s = read_mvex(s + hstep, s + box_len, dend, sup_buf); + + sup->close(); + } + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + + if(memcmp(box_name, "udta", 4) == 0)//optional + { + snprintf(sup_buf, MAX_ITEMBUF, "%s/[%03d] udta", name_buf, ++pos); + sup = tree->add(sup_buf); + + s = read_udta(s + hstep, s + box_len, dend, sup_buf); + + sup->close(); + box_len = read_boxheader(s, dend, &hstep); + + if(box_len == 0) return dend; + } + + if(memcmp(box_name, "trak", 4) != 0) break; + + } + return s; +}/* read_moov() */ + +int read_mj2(unsigned char *s, unsigned char *dend) +{ + unsigned char *box_end; + uint64_t box_len; + unsigned int hstep, nr_moov; + int pos = -1; + + Tracks = NULL; + nr_moov = 0; + + while(s < dend) + { + ++pos; + box_len = read_boxheader(s, dend, &hstep); + + if( box_len == 0) { s = dend; break; } + + if((uint64_t)(dend - s) < box_len) + box_end = dend; + else + box_end = s + (ptrdiff_t)box_len; + + if(memcmp(box_name, "ftyp", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "[%03d] ftyp", pos); + sup = tree->add(item_name); + + s = read_ftyp(s + hstep, s + box_len, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "moov", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "[%03d] moov", pos); + sup = tree->add(item_name); + + s = read_moov(s + hstep, s + box_len, dend, item_name); + + sup->close(); + ++nr_moov; + continue; + } + + if(memcmp(box_name, "moof", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "[%03d] moof", pos); + sup = tree->add(item_name); + + s = read_moof(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "mfra", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "[%03d] mfra", pos); + sup = tree->add(item_name); + + s = read_mfra(s + hstep, s + box_len, dend, item_name); + + sup->close(); + continue; + } + + if(memcmp(box_name, "mdat", 4) == 0) + { + Fl_Tree_Item *sup; + + snprintf(item_name, MAX_ITEMBUF, "[%03d] mdat", pos); + sup = tree->add(item_name); + + snprintf(item_name, MAX_ITEMBUF, "[%03d] mdat/Media data box", pos); + add_sub_item(); + + sup->close(); + + s = box_end; + continue; + } + + if((memcmp(box_name, "free", 4) == 0) + || (memcmp(box_name, "skip", 4) == 0)) + { + Fl_Tree_Item *sup; + + sup = tree->add((char*)box_name); + + snprintf(item_name, MAX_ITEMBUF, "%s/%" PRIu64 " Byte skipped", + box_name, box_len); + add_sub_item(); + + sup->close(); + s = box_end; + continue; + } + { + snprintf(item_name, MAX_ITEMBUF, "Unknown box %s", (char*)box_name); + add_sub_item(); + } + s = box_end; + } + + { + long delta = (long)(dend-s); + + if(delta != 0) + { + fprintf(stderr,"EXIT read_mj2 with delta ==> %" PRId64 "\n",delta ); + } + } + + return 1; +}/* read_mj2() */ diff --git a/src/bin/fltk/flviewer/rgb_color.cxx b/src/bin/fltk/flviewer/rgb_color.cxx new file mode 100644 index 00000000..4e1a8666 --- /dev/null +++ b/src/bin/fltk/flviewer/rgb_color.cxx @@ -0,0 +1,807 @@ +#include +/* + * author(s) and license +*/ +#include +#include +#include +#include + +#include "rgb_color.hh" + +static struct rgb_and_name{unsigned char r, g, b; const char *cname;} + rgb_names[] = { +{0xf0,0xf8,0xff,"alice blue"}, +{0xf0,0xf8,0xff,"aliceblue"}, +{0xfa,0xeb,0xd7,"antique white"}, +{0xfa,0xeb,0xd7,"antiquewhite"}, +{0xff,0xef,0xdb,"antiquewhite1"}, +{0xee,0xdf,0xcc,"antiquewhite2"}, +{0xcd,0xc0,0xb0,"antiquewhite3"}, +{0x8b,0x83,0x78,"antiquewhite4"}, +{0x7f,0xff,0xd4,"aquamarine"}, +{0x7f,0xff,0xd4,"aquamarine1"}, +{0x76,0xee,0xc6,"aquamarine2"}, +{0x66,0xcd,0xaa,"aquamarine3"}, +{0x45,0x8b,0x74,"aquamarine4"}, +{0xf0,0xff,0xff,"azure"}, +{0xf0,0xff,0xff,"azure1"}, +{0xe0,0xee,0xee,"azure2"}, +{0xc1,0xcd,0xcd,"azure3"}, +{0x83,0x8b,0x8b,"azure4"}, +{0xf5,0xf5,0xdc,"beige"}, +{0xff,0xe4,0xc4,"bisque"}, +{0xff,0xe4,0xc4,"bisque1"}, +{0xee,0xd5,0xb7,"bisque2"}, +{0xcd,0xb7,0x9e,"bisque3"}, +{0x8b,0x7d,0x6b,"bisque4"}, +{0x00,0x00,0x00,"black"}, +{0xff,0xeb,0xcd,"blanched almond"}, +{0xff,0xeb,0xcd,"blanchedalmond"}, +{0x00,0x00,0xff,"blue"}, +{0x8a,0x2b,0xe2,"blue violet"}, +{0x00,0x00,0xff,"blue1"}, +{0x00,0x00,0xee,"blue2"}, +{0x00,0x00,0xcd,"blue3"}, +{0x00,0x00,0x8b,"blue4"}, +{0x8a,0x2b,0xe2,"blueviolet"}, +{0xa5,0x2a,0x2a,"brown"}, +{0xff,0x40,0x40,"brown1"}, +{0xee,0x3b,0x3b,"brown2"}, +{0xcd,0x33,0x33,"brown3"}, +{0x8b,0x23,0x23,"brown4"}, +{0xde,0xb8,0x87,"burlywood"}, +{0xff,0xd3,0x9b,"burlywood1"}, +{0xee,0xc5,0x91,"burlywood2"}, +{0xcd,0xaa,0x7d,"burlywood3"}, +{0x8b,0x73,0x55,"burlywood4"}, +{0x5f,0x9e,0xa0,"cadet blue"}, +{0x5f,0x9e,0xa0,"cadetblue"}, +{0x98,0xf5,0xff,"cadetblue1"}, +{0x8e,0xe5,0xee,"cadetblue2"}, +{0x7a,0xc5,0xcd,"cadetblue3"}, +{0x53,0x86,0x8b,"cadetblue4"}, +{0x7f,0xff,0x00,"chartreuse"}, +{0x7f,0xff,0x00,"chartreuse1"}, +{0x76,0xee,0x00,"chartreuse2"}, +{0x66,0xcd,0x00,"chartreuse3"}, +{0x45,0x8b,0x00,"chartreuse4"}, +{0xd2,0x69,0x1e,"chocolate"}, +{0xff,0x7f,0x24,"chocolate1"}, +{0xee,0x76,0x21,"chocolate2"}, +{0xcd,0x66,0x1d,"chocolate3"}, +{0x8b,0x45,0x13,"chocolate4"}, +{0xff,0x7f,0x50,"coral"}, +{0xff,0x72,0x56,"coral1"}, +{0xee,0x6a,0x50,"coral2"}, +{0xcd,0x5b,0x45,"coral3"}, +{0x8b,0x3e,0x2f,"coral4"}, +{0x64,0x95,0xed,"cornflower blue"}, +{0x64,0x95,0xed,"cornflowerblue"}, +{0xff,0xf8,0xdc,"cornsilk"}, +{0xff,0xf8,0xdc,"cornsilk1"}, +{0xee,0xe8,0xcd,"cornsilk2"}, +{0xcd,0xc8,0xb1,"cornsilk3"}, +{0x8b,0x88,0x78,"cornsilk4"}, +{0x00,0xff,0xff,"cyan"}, +{0x00,0xff,0xff,"cyan1"}, +{0x00,0xee,0xee,"cyan2"}, +{0x00,0xcd,0xcd,"cyan3"}, +{0x00,0x8b,0x8b,"cyan4"}, +{0x00,0x00,0x8b,"dark blue"}, +{0x00,0x8b,0x8b,"dark cyan"}, +{0xb8,0x86,0x0b,"dark goldenrod"}, +{0xa9,0xa9,0xa9,"dark gray"}, +{0x00,0x64,0x00,"dark green"}, +{0xa9,0xa9,0xa9,"dark grey"}, +{0xbd,0xb7,0x6b,"dark khaki"}, +{0x8b,0x00,0x8b,"dark magenta"}, +{0x55,0x6b,0x2f,"dark olive green"}, +{0xff,0x8c,0x00,"dark orange"}, +{0x99,0x32,0xcc,"dark orchid"}, +{0x8b,0x00,0x00,"dark red"}, +{0xe9,0x96,0x7a,"dark salmon"}, +{0x8f,0xbc,0x8f,"dark sea green"}, +{0x48,0x3d,0x8b,"dark slate blue"}, +{0x2f,0x4f,0x4f,"dark slate gray"}, +{0x2f,0x4f,0x4f,"dark slate grey"}, +{0x00,0xce,0xd1,"dark turquoise"}, +{0x94,0x00,0xd3,"dark violet"}, +{0x00,0x00,0x8b,"darkblue"}, +{0x00,0x8b,0x8b,"darkcyan"}, +{0xb8,0x86,0x0b,"darkgoldenrod"}, +{0xff,0xb9,0x0f,"darkgoldenrod1"}, +{0xee,0xad,0x0e,"darkgoldenrod2"}, +{0xcd,0x95,0x0c,"darkgoldenrod3"}, +{0x8b,0x65,0x08,"darkgoldenrod4"}, +{0xa9,0xa9,0xa9,"darkgray"}, +{0x00,0x64,0x00,"darkgreen"}, +{0xa9,0xa9,0xa9,"darkgrey"}, +{0xbd,0xb7,0x6b,"darkkhaki"}, +{0x8b,0x00,0x8b,"darkmagenta"}, +{0x55,0x6b,0x2f,"darkolivegreen"}, +{0xca,0xff,0x70,"darkolivegreen1"}, +{0xbc,0xee,0x68,"darkolivegreen2"}, +{0xa2,0xcd,0x5a,"darkolivegreen3"}, +{0x6e,0x8b,0x3d,"darkolivegreen4"}, +{0xff,0x8c,0x00,"darkorange"}, +{0xff,0x7f,0x00,"darkorange1"}, +{0xee,0x76,0x00,"darkorange2"}, +{0xcd,0x66,0x00,"darkorange3"}, +{0x8b,0x45,0x00,"darkorange4"}, +{0x99,0x32,0xcc,"darkorchid"}, +{0xbf,0x3e,0xff,"darkorchid1"}, +{0xb2,0x3a,0xee,"darkorchid2"}, +{0x9a,0x32,0xcd,"darkorchid3"}, +{0x68,0x22,0x8b,"darkorchid4"}, +{0x8b,0x00,0x00,"darkred"}, +{0xe9,0x96,0x7a,"darksalmon"}, +{0x8f,0xbc,0x8f,"darkseagreen"}, +{0xc1,0xff,0xc1,"darkseagreen1"}, +{0xb4,0xee,0xb4,"darkseagreen2"}, +{0x9b,0xcd,0x9b,"darkseagreen3"}, +{0x69,0x8b,0x69,"darkseagreen4"}, +{0x48,0x3d,0x8b,"darkslateblue"}, +{0x2f,0x4f,0x4f,"darkslategray"}, +{0x97,0xff,0xff,"darkslategray1"}, +{0x8d,0xee,0xee,"darkslategray2"}, +{0x79,0xcd,0xcd,"darkslategray3"}, +{0x52,0x8b,0x8b,"darkslategray4"}, +{0x2f,0x4f,0x4f,"darkslategrey"}, +{0x00,0xce,0xd1,"darkturquoise"}, +{0x94,0x00,0xd3,"darkviolet"}, +{0xff,0x14,0x93,"deep pink"}, +{0x00,0xbf,0xff,"deep sky blue"}, +{0xff,0x14,0x93,"deeppink"}, +{0xff,0x14,0x93,"deeppink1"}, +{0xee,0x12,0x89,"deeppink2"}, +{0xcd,0x10,0x76,"deeppink3"}, +{0x8b,0x0a,0x50,"deeppink4"}, +{0x00,0xbf,0xff,"deepskyblue"}, +{0x00,0xbf,0xff,"deepskyblue1"}, +{0x00,0xb2,0xee,"deepskyblue2"}, +{0x00,0x9a,0xcd,"deepskyblue3"}, +{0x00,0x68,0x8b,"deepskyblue4"}, +{0x69,0x69,0x69,"dim gray"}, +{0x69,0x69,0x69,"dim grey"}, +{0x69,0x69,0x69,"dimgray"}, +{0x69,0x69,0x69,"dimgrey"}, +{0x1e,0x90,0xff,"dodger blue"}, +{0x1e,0x90,0xff,"dodgerblue"}, +{0x1e,0x90,0xff,"dodgerblue1"}, +{0x1c,0x86,0xee,"dodgerblue2"}, +{0x18,0x74,0xcd,"dodgerblue3"}, +{0x10,0x4e,0x8b,"dodgerblue4"}, +{0xb2,0x22,0x22,"firebrick"}, +{0xff,0x30,0x30,"firebrick1"}, +{0xee,0x2c,0x2c,"firebrick2"}, +{0xcd,0x26,0x26,"firebrick3"}, +{0x8b,0x1a,0x1a,"firebrick4"}, +{0xff,0xfa,0xf0,"floral white"}, +{0xff,0xfa,0xf0,"floralwhite"}, +{0x22,0x8b,0x22,"forest green"}, +{0x22,0x8b,0x22,"forestgreen"}, +{0xdc,0xdc,0xdc,"gainsboro"}, +{0xf8,0xf8,0xff,"ghost white"}, +{0xf8,0xf8,0xff,"ghostwhite"}, +{0xff,0xd7,0x00,"gold"}, +{0xff,0xd7,0x00,"gold1"}, +{0xee,0xc9,0x00,"gold2"}, +{0xcd,0xad,0x00,"gold3"}, +{0x8b,0x75,0x00,"gold4"}, +{0xda,0xa5,0x20,"goldenrod"}, +{0xff,0xc1,0x25,"goldenrod1"}, +{0xee,0xb4,0x22,"goldenrod2"}, +{0xcd,0x9b,0x1d,"goldenrod3"}, +{0x8b,0x69,0x14,"goldenrod4"}, +{0xbe,0xbe,0xbe,"gray"}, +{0x00,0x00,0x00,"gray0"}, +{0x03,0x03,0x03,"gray1"}, +{0x1a,0x1a,0x1a,"gray10"}, +{0xff,0xff,0xff,"gray100"}, +{0x1c,0x1c,0x1c,"gray11"}, +{0x1f,0x1f,0x1f,"gray12"}, +{0x21,0x21,0x21,"gray13"}, +{0x24,0x24,0x24,"gray14"}, +{0x26,0x26,0x26,"gray15"}, +{0x29,0x29,0x29,"gray16"}, +{0x2b,0x2b,0x2b,"gray17"}, +{0x2e,0x2e,0x2e,"gray18"}, +{0x30,0x30,0x30,"gray19"}, +{0x05,0x05,0x05,"gray2"}, +{0x33,0x33,0x33,"gray20"}, +{0x36,0x36,0x36,"gray21"}, +{0x38,0x38,0x38,"gray22"}, +{0x3b,0x3b,0x3b,"gray23"}, +{0x3d,0x3d,0x3d,"gray24"}, +{0x40,0x40,0x40,"gray25"}, +{0x42,0x42,0x42,"gray26"}, +{0x45,0x45,0x45,"gray27"}, +{0x47,0x47,0x47,"gray28"}, +{0x4a,0x4a,0x4a,"gray29"}, +{0x08,0x08,0x08,"gray3"}, +{0x4d,0x4d,0x4d,"gray30"}, +{0x4f,0x4f,0x4f,"gray31"}, +{0x52,0x52,0x52,"gray32"}, +{0x54,0x54,0x54,"gray33"}, +{0x57,0x57,0x57,"gray34"}, +{0x59,0x59,0x59,"gray35"}, +{0x5c,0x5c,0x5c,"gray36"}, +{0x5e,0x5e,0x5e,"gray37"}, +{0x61,0x61,0x61,"gray38"}, +{0x63,0x63,0x63,"gray39"}, +{0x0a,0x0a,0x0a,"gray4"}, +{0x66,0x66,0x66,"gray40"}, +{0x69,0x69,0x69,"gray41"}, +{0x6b,0x6b,0x6b,"gray42"}, +{0x6e,0x6e,0x6e,"gray43"}, +{0x70,0x70,0x70,"gray44"}, +{0x73,0x73,0x73,"gray45"}, +{0x75,0x75,0x75,"gray46"}, +{0x78,0x78,0x78,"gray47"}, +{0x7a,0x7a,0x7a,"gray48"}, +{0x7d,0x7d,0x7d,"gray49"}, +{0x0d,0x0d,0x0d,"gray5"}, +{0x7f,0x7f,0x7f,"gray50"}, +{0x82,0x82,0x82,"gray51"}, +{0x85,0x85,0x85,"gray52"}, +{0x87,0x87,0x87,"gray53"}, +{0x8a,0x8a,0x8a,"gray54"}, +{0x8c,0x8c,0x8c,"gray55"}, +{0x8f,0x8f,0x8f,"gray56"}, +{0x91,0x91,0x91,"gray57"}, +{0x94,0x94,0x94,"gray58"}, +{0x96,0x96,0x96,"gray59"}, +{0x0f,0x0f,0x0f,"gray6"}, +{0x99,0x99,0x99,"gray60"}, +{0x9c,0x9c,0x9c,"gray61"}, +{0x9e,0x9e,0x9e,"gray62"}, +{0xa1,0xa1,0xa1,"gray63"}, +{0xa3,0xa3,0xa3,"gray64"}, +{0xa6,0xa6,0xa6,"gray65"}, +{0xa8,0xa8,0xa8,"gray66"}, +{0xab,0xab,0xab,"gray67"}, +{0xad,0xad,0xad,"gray68"}, +{0xb0,0xb0,0xb0,"gray69"}, +{0x12,0x12,0x12,"gray7"}, +{0xb3,0xb3,0xb3,"gray70"}, +{0xb5,0xb5,0xb5,"gray71"}, +{0xb8,0xb8,0xb8,"gray72"}, +{0xba,0xba,0xba,"gray73"}, +{0xbd,0xbd,0xbd,"gray74"}, +{0xbf,0xbf,0xbf,"gray75"}, +{0xc2,0xc2,0xc2,"gray76"}, +{0xc4,0xc4,0xc4,"gray77"}, +{0xc7,0xc7,0xc7,"gray78"}, +{0xc9,0xc9,0xc9,"gray79"}, +{0x14,0x14,0x14,"gray8"}, +{0xcc,0xcc,0xcc,"gray80"}, +{0xcf,0xcf,0xcf,"gray81"}, +{0xd1,0xd1,0xd1,"gray82"}, +{0xd4,0xd4,0xd4,"gray83"}, +{0xd6,0xd6,0xd6,"gray84"}, +{0xd9,0xd9,0xd9,"gray85"}, +{0xdb,0xdb,0xdb,"gray86"}, +{0xde,0xde,0xde,"gray87"}, +{0xe0,0xe0,0xe0,"gray88"}, +{0xe3,0xe3,0xe3,"gray89"}, +{0x17,0x17,0x17,"gray9"}, +{0xe5,0xe5,0xe5,"gray90"}, +{0xe8,0xe8,0xe8,"gray91"}, +{0xeb,0xeb,0xeb,"gray92"}, +{0xed,0xed,0xed,"gray93"}, +{0xf0,0xf0,0xf0,"gray94"}, +{0xf2,0xf2,0xf2,"gray95"}, +{0xf5,0xf5,0xf5,"gray96"}, +{0xf7,0xf7,0xf7,"gray97"}, +{0xfa,0xfa,0xfa,"gray98"}, +{0xfc,0xfc,0xfc,"gray99"}, +{0x00,0xff,0x00,"green"}, +{0xad,0xff,0x2f,"green yellow"}, +{0x00,0xff,0x00,"green1"}, +{0x00,0xee,0x00,"green2"}, +{0x00,0xcd,0x00,"green3"}, +{0x00,0x8b,0x00,"green4"}, +{0xad,0xff,0x2f,"greenyellow"}, +{0xbe,0xbe,0xbe,"grey"}, +{0x00,0x00,0x00,"grey0"}, +{0x03,0x03,0x03,"grey1"}, +{0x1a,0x1a,0x1a,"grey10"}, +{0xff,0xff,0xff,"grey100"}, +{0x1c,0x1c,0x1c,"grey11"}, +{0x1f,0x1f,0x1f,"grey12"}, +{0x21,0x21,0x21,"grey13"}, +{0x24,0x24,0x24,"grey14"}, +{0x26,0x26,0x26,"grey15"}, +{0x29,0x29,0x29,"grey16"}, +{0x2b,0x2b,0x2b,"grey17"}, +{0x2e,0x2e,0x2e,"grey18"}, +{0x30,0x30,0x30,"grey19"}, +{0x05,0x05,0x05,"grey2"}, +{0x33,0x33,0x33,"grey20"}, +{0x36,0x36,0x36,"grey21"}, +{0x38,0x38,0x38,"grey22"}, +{0x3b,0x3b,0x3b,"grey23"}, +{0x3d,0x3d,0x3d,"grey24"}, +{0x40,0x40,0x40,"grey25"}, +{0x42,0x42,0x42,"grey26"}, +{0x45,0x45,0x45,"grey27"}, +{0x47,0x47,0x47,"grey28"}, +{0x4a,0x4a,0x4a,"grey29"}, +{0x08,0x08,0x08,"grey3"}, +{0x4d,0x4d,0x4d,"grey30"}, +{0x4f,0x4f,0x4f,"grey31"}, +{0x52,0x52,0x52,"grey32"}, +{0x54,0x54,0x54,"grey33"}, +{0x57,0x57,0x57,"grey34"}, +{0x59,0x59,0x59,"grey35"}, +{0x5c,0x5c,0x5c,"grey36"}, +{0x5e,0x5e,0x5e,"grey37"}, +{0x61,0x61,0x61,"grey38"}, +{0x63,0x63,0x63,"grey39"}, +{0x0a,0x0a,0x0a,"grey4"}, +{0x66,0x66,0x66,"grey40"}, +{0x69,0x69,0x69,"grey41"}, +{0x6b,0x6b,0x6b,"grey42"}, +{0x6e,0x6e,0x6e,"grey43"}, +{0x70,0x70,0x70,"grey44"}, +{0x73,0x73,0x73,"grey45"}, +{0x75,0x75,0x75,"grey46"}, +{0x78,0x78,0x78,"grey47"}, +{0x7a,0x7a,0x7a,"grey48"}, +{0x7d,0x7d,0x7d,"grey49"}, +{0x0d,0x0d,0x0d,"grey5"}, +{0x7f,0x7f,0x7f,"grey50"}, +{0x82,0x82,0x82,"grey51"}, +{0x85,0x85,0x85,"grey52"}, +{0x87,0x87,0x87,"grey53"}, +{0x8a,0x8a,0x8a,"grey54"}, +{0x8c,0x8c,0x8c,"grey55"}, +{0x8f,0x8f,0x8f,"grey56"}, +{0x91,0x91,0x91,"grey57"}, +{0x94,0x94,0x94,"grey58"}, +{0x96,0x96,0x96,"grey59"}, +{0x0f,0x0f,0x0f,"grey6"}, +{0x99,0x99,0x99,"grey60"}, +{0x9c,0x9c,0x9c,"grey61"}, +{0x9e,0x9e,0x9e,"grey62"}, +{0xa1,0xa1,0xa1,"grey63"}, +{0xa3,0xa3,0xa3,"grey64"}, +{0xa6,0xa6,0xa6,"grey65"}, +{0xa8,0xa8,0xa8,"grey66"}, +{0xab,0xab,0xab,"grey67"}, +{0xad,0xad,0xad,"grey68"}, +{0xb0,0xb0,0xb0,"grey69"}, +{0x12,0x12,0x12,"grey7"}, +{0xb3,0xb3,0xb3,"grey70"}, +{0xb5,0xb5,0xb5,"grey71"}, +{0xb8,0xb8,0xb8,"grey72"}, +{0xba,0xba,0xba,"grey73"}, +{0xbd,0xbd,0xbd,"grey74"}, +{0xbf,0xbf,0xbf,"grey75"}, +{0xc2,0xc2,0xc2,"grey76"}, +{0xc4,0xc4,0xc4,"grey77"}, +{0xc7,0xc7,0xc7,"grey78"}, +{0xc9,0xc9,0xc9,"grey79"}, +{0x14,0x14,0x14,"grey8"}, +{0xcc,0xcc,0xcc,"grey80"}, +{0xcf,0xcf,0xcf,"grey81"}, +{0xd1,0xd1,0xd1,"grey82"}, +{0xd4,0xd4,0xd4,"grey83"}, +{0xd6,0xd6,0xd6,"grey84"}, +{0xd9,0xd9,0xd9,"grey85"}, +{0xdb,0xdb,0xdb,"grey86"}, +{0xde,0xde,0xde,"grey87"}, +{0xe0,0xe0,0xe0,"grey88"}, +{0xe3,0xe3,0xe3,"grey89"}, +{0x17,0x17,0x17,"grey9"}, +{0xe5,0xe5,0xe5,"grey90"}, +{0xe8,0xe8,0xe8,"grey91"}, +{0xeb,0xeb,0xeb,"grey92"}, +{0xed,0xed,0xed,"grey93"}, +{0xf0,0xf0,0xf0,"grey94"}, +{0xf2,0xf2,0xf2,"grey95"}, +{0xf5,0xf5,0xf5,"grey96"}, +{0xf7,0xf7,0xf7,"grey97"}, +{0xfa,0xfa,0xfa,"grey98"}, +{0xfc,0xfc,0xfc,"grey99"}, +{0xf0,0xff,0xf0,"honeydew"}, +{0xf0,0xff,0xf0,"honeydew1"}, +{0xe0,0xee,0xe0,"honeydew2"}, +{0xc1,0xcd,0xc1,"honeydew3"}, +{0x83,0x8b,0x83,"honeydew4"}, +{0xff,0x69,0xb4,"hot pink"}, +{0xff,0x69,0xb4,"hotpink"}, +{0xff,0x6e,0xb4,"hotpink1"}, +{0xee,0x6a,0xa7,"hotpink2"}, +{0xcd,0x60,0x90,"hotpink3"}, +{0x8b,0x3a,0x62,"hotpink4"}, +{0xcd,0x5c,0x5c,"indian red"}, +{0xcd,0x5c,0x5c,"indianred"}, +{0xff,0x6a,0x6a,"indianred1"}, +{0xee,0x63,0x63,"indianred2"}, +{0xcd,0x55,0x55,"indianred3"}, +{0x8b,0x3a,0x3a,"indianred4"}, +{0xff,0xff,0xf0,"ivory"}, +{0xff,0xff,0xf0,"ivory1"}, +{0xee,0xee,0xe0,"ivory2"}, +{0xcd,0xcd,0xc1,"ivory3"}, +{0x8b,0x8b,0x83,"ivory4"}, +{0xf0,0xe6,0x8c,"khaki"}, +{0xff,0xf6,0x8f,"khaki1"}, +{0xee,0xe6,0x85,"khaki2"}, +{0xcd,0xc6,0x73,"khaki3"}, +{0x8b,0x86,0x4e,"khaki4"}, +{0xe6,0xe6,0xfa,"lavender"}, +{0xff,0xf0,0xf5,"lavender blush"}, +{0xff,0xf0,0xf5,"lavenderblush"}, +{0xff,0xf0,0xf5,"lavenderblush1"}, +{0xee,0xe0,0xe5,"lavenderblush2"}, +{0xcd,0xc1,0xc5,"lavenderblush3"}, +{0x8b,0x83,0x86,"lavenderblush4"}, +{0x7c,0xfc,0x00,"lawn green"}, +{0x7c,0xfc,0x00,"lawngreen"}, +{0xff,0xfa,0xcd,"lemon chiffon"}, +{0xff,0xfa,0xcd,"lemonchiffon"}, +{0xff,0xfa,0xcd,"lemonchiffon1"}, +{0xee,0xe9,0xbf,"lemonchiffon2"}, +{0xcd,0xc9,0xa5,"lemonchiffon3"}, +{0x8b,0x89,0x70,"lemonchiffon4"}, +{0xad,0xd8,0xe6,"light blue"}, +{0xf0,0x80,0x80,"light coral"}, +{0xe0,0xff,0xff,"light cyan"}, +{0xee,0xdd,0x82,"light goldenrod"}, +{0xfa,0xfa,0xd2,"light goldenrod yellow"}, +{0xd3,0xd3,0xd3,"light gray"}, +{0x90,0xee,0x90,"light green"}, +{0xd3,0xd3,0xd3,"light grey"}, +{0xff,0xb6,0xc1,"light pink"}, +{0xff,0xa0,0x7a,"light salmon"}, +{0x20,0xb2,0xaa,"light sea green"}, +{0x87,0xce,0xfa,"light sky blue"}, +{0x84,0x70,0xff,"light slate blue"}, +{0x77,0x88,0x99,"light slate gray"}, +{0x77,0x88,0x99,"light slate grey"}, +{0xb0,0xc4,0xde,"light steel blue"}, +{0xff,0xff,0xe0,"light yellow"}, +{0xad,0xd8,0xe6,"lightblue"}, +{0xbf,0xef,0xff,"lightblue1"}, +{0xb2,0xdf,0xee,"lightblue2"}, +{0x9a,0xc0,0xcd,"lightblue3"}, +{0x68,0x83,0x8b,"lightblue4"}, +{0xf0,0x80,0x80,"lightcoral"}, +{0xe0,0xff,0xff,"lightcyan"}, +{0xe0,0xff,0xff,"lightcyan1"}, +{0xd1,0xee,0xee,"lightcyan2"}, +{0xb4,0xcd,0xcd,"lightcyan3"}, +{0x7a,0x8b,0x8b,"lightcyan4"}, +{0xee,0xdd,0x82,"lightgoldenrod"}, +{0xff,0xec,0x8b,"lightgoldenrod1"}, +{0xee,0xdc,0x82,"lightgoldenrod2"}, +{0xcd,0xbe,0x70,"lightgoldenrod3"}, +{0x8b,0x81,0x4c,"lightgoldenrod4"}, +{0xfa,0xfa,0xd2,"lightgoldenrodyellow"}, +{0xd3,0xd3,0xd3,"lightgray"}, +{0x90,0xee,0x90,"lightgreen"}, +{0xd3,0xd3,0xd3,"lightgrey"}, +{0xff,0xb6,0xc1,"lightpink"}, +{0xff,0xae,0xb9,"lightpink1"}, +{0xee,0xa2,0xad,"lightpink2"}, +{0xcd,0x8c,0x95,"lightpink3"}, +{0x8b,0x5f,0x65,"lightpink4"}, +{0xff,0xa0,0x7a,"lightsalmon"}, +{0xff,0xa0,0x7a,"lightsalmon1"}, +{0xee,0x95,0x72,"lightsalmon2"}, +{0xcd,0x81,0x62,"lightsalmon3"}, +{0x8b,0x57,0x42,"lightsalmon4"}, +{0x20,0xb2,0xaa,"lightseagreen"}, +{0x87,0xce,0xfa,"lightskyblue"}, +{0xb0,0xe2,0xff,"lightskyblue1"}, +{0xa4,0xd3,0xee,"lightskyblue2"}, +{0x8d,0xb6,0xcd,"lightskyblue3"}, +{0x60,0x7b,0x8b,"lightskyblue4"}, +{0x84,0x70,0xff,"lightslateblue"}, +{0x77,0x88,0x99,"lightslategray"}, +{0x77,0x88,0x99,"lightslategrey"}, +{0xb0,0xc4,0xde,"lightsteelblue"}, +{0xca,0xe1,0xff,"lightsteelblue1"}, +{0xbc,0xd2,0xee,"lightsteelblue2"}, +{0xa2,0xb5,0xcd,"lightsteelblue3"}, +{0x6e,0x7b,0x8b,"lightsteelblue4"}, +{0xff,0xff,0xe0,"lightyellow"}, +{0xff,0xff,0xe0,"lightyellow1"}, +{0xee,0xee,0xd1,"lightyellow2"}, +{0xcd,0xcd,0xb4,"lightyellow3"}, +{0x8b,0x8b,0x7a,"lightyellow4"}, +{0x32,0xcd,0x32,"lime green"}, +{0x32,0xcd,0x32,"limegreen"}, +{0xfa,0xf0,0xe6,"linen"}, +{0xff,0x00,0xff,"magenta"}, +{0xff,0x00,0xff,"magenta1"}, +{0xee,0x00,0xee,"magenta2"}, +{0xcd,0x00,0xcd,"magenta3"}, +{0x8b,0x00,0x8b,"magenta4"}, +{0xb0,0x30,0x60,"maroon"}, +{0xff,0x34,0xb3,"maroon1"}, +{0xee,0x30,0xa7,"maroon2"}, +{0xcd,0x29,0x90,"maroon3"}, +{0x8b,0x1c,0x62,"maroon4"}, +{0x66,0xcd,0xaa,"medium aquamarine"}, +{0x00,0x00,0xcd,"medium blue"}, +{0xba,0x55,0xd3,"medium orchid"}, +{0x93,0x70,0xdb,"medium purple"}, +{0x3c,0xb3,0x71,"medium sea green"}, +{0x7b,0x68,0xee,"medium slate blue"}, +{0x00,0xfa,0x9a,"medium spring green"}, +{0x48,0xd1,0xcc,"medium turquoise"}, +{0xc7,0x15,0x85,"medium violet red"}, +{0x66,0xcd,0xaa,"mediumaquamarine"}, +{0x00,0x00,0xcd,"mediumblue"}, +{0xba,0x55,0xd3,"mediumorchid"}, +{0xe0,0x66,0xff,"mediumorchid1"}, +{0xd1,0x5f,0xee,"mediumorchid2"}, +{0xb4,0x52,0xcd,"mediumorchid3"}, +{0x7a,0x37,0x8b,"mediumorchid4"}, +{0x93,0x70,0xdb,"mediumpurple"}, +{0xab,0x82,0xff,"mediumpurple1"}, +{0x9f,0x79,0xee,"mediumpurple2"}, +{0x89,0x68,0xcd,"mediumpurple3"}, +{0x5d,0x47,0x8b,"mediumpurple4"}, +{0x3c,0xb3,0x71,"mediumseagreen"}, +{0x7b,0x68,0xee,"mediumslateblue"}, +{0x00,0xfa,0x9a,"mediumspringgreen"}, +{0x48,0xd1,0xcc,"mediumturquoise"}, +{0xc7,0x15,0x85,"mediumvioletred"}, +{0x19,0x19,0x70,"midnight blue"}, +{0x19,0x19,0x70,"midnightblue"}, +{0xf5,0xff,0xfa,"mint cream"}, +{0xf5,0xff,0xfa,"mintcream"}, +{0xff,0xe4,0xe1,"misty rose"}, +{0xff,0xe4,0xe1,"mistyrose"}, +{0xff,0xe4,0xe1,"mistyrose1"}, +{0xee,0xd5,0xd2,"mistyrose2"}, +{0xcd,0xb7,0xb5,"mistyrose3"}, +{0x8b,0x7d,0x7b,"mistyrose4"}, +{0xff,0xe4,0xb5,"moccasin"}, +{0xff,0xde,0xad,"navajo white"}, +{0xff,0xde,0xad,"navajowhite"}, +{0xff,0xde,0xad,"navajowhite1"}, +{0xee,0xcf,0xa1,"navajowhite2"}, +{0xcd,0xb3,0x8b,"navajowhite3"}, +{0x8b,0x79,0x5e,"navajowhite4"}, +{0x00,0x00,0x80,"navy"}, +{0x00,0x00,0x80,"navy blue"}, +{0x00,0x00,0x80,"navyblue"}, +{0xfd,0xf5,0xe6,"old lace"}, +{0xfd,0xf5,0xe6,"oldlace"}, +{0x6b,0x8e,0x23,"olive drab"}, +{0x6b,0x8e,0x23,"olivedrab"}, +{0xc0,0xff,0x3e,"olivedrab1"}, +{0xb3,0xee,0x3a,"olivedrab2"}, +{0x9a,0xcd,0x32,"olivedrab3"}, +{0x69,0x8b,0x22,"olivedrab4"}, +{0xff,0xa5,0x00,"orange"}, +{0xff,0x45,0x00,"orange red"}, +{0xff,0xa5,0x00,"orange1"}, +{0xee,0x9a,0x00,"orange2"}, +{0xcd,0x85,0x00,"orange3"}, +{0x8b,0x5a,0x00,"orange4"}, +{0xff,0x45,0x00,"orangered"}, +{0xff,0x45,0x00,"orangered1"}, +{0xee,0x40,0x00,"orangered2"}, +{0xcd,0x37,0x00,"orangered3"}, +{0x8b,0x25,0x00,"orangered4"}, +{0xda,0x70,0xd6,"orchid"}, +{0xff,0x83,0xfa,"orchid1"}, +{0xee,0x7a,0xe9,"orchid2"}, +{0xcd,0x69,0xc9,"orchid3"}, +{0x8b,0x47,0x89,"orchid4"}, +{0xee,0xe8,0xaa,"pale goldenrod"}, +{0x98,0xfb,0x98,"pale green"}, +{0xaf,0xee,0xee,"pale turquoise"}, +{0xdb,0x70,0x93,"pale violet red"}, +{0xee,0xe8,0xaa,"palegoldenrod"}, +{0x98,0xfb,0x98,"palegreen"}, +{0x9a,0xff,0x9a,"palegreen1"}, +{0x90,0xee,0x90,"palegreen2"}, +{0x7c,0xcd,0x7c,"palegreen3"}, +{0x54,0x8b,0x54,"palegreen4"}, +{0xaf,0xee,0xee,"paleturquoise"}, +{0xbb,0xff,0xff,"paleturquoise1"}, +{0xae,0xee,0xee,"paleturquoise2"}, +{0x96,0xcd,0xcd,"paleturquoise3"}, +{0x66,0x8b,0x8b,"paleturquoise4"}, +{0xdb,0x70,0x93,"palevioletred"}, +{0xff,0x82,0xab,"palevioletred1"}, +{0xee,0x79,0x9f,"palevioletred2"}, +{0xcd,0x68,0x89,"palevioletred3"}, +{0x8b,0x47,0x5d,"palevioletred4"}, +{0xff,0xef,0xd5,"papaya whip"}, +{0xff,0xef,0xd5,"papayawhip"}, +{0xff,0xda,0xb9,"peach puff"}, +{0xff,0xda,0xb9,"peachpuff"}, +{0xff,0xda,0xb9,"peachpuff1"}, +{0xee,0xcb,0xad,"peachpuff2"}, +{0xcd,0xaf,0x95,"peachpuff3"}, +{0x8b,0x77,0x65,"peachpuff4"}, +{0xcd,0x85,0x3f,"peru"}, +{0xff,0xc0,0xcb,"pink"}, +{0xff,0xb5,0xc5,"pink1"}, +{0xee,0xa9,0xb8,"pink2"}, +{0xcd,0x91,0x9e,"pink3"}, +{0x8b,0x63,0x6c,"pink4"}, +{0xdd,0xa0,0xdd,"plum"}, +{0xff,0xbb,0xff,"plum1"}, +{0xee,0xae,0xee,"plum2"}, +{0xcd,0x96,0xcd,"plum3"}, +{0x8b,0x66,0x8b,"plum4"}, +{0xb0,0xe0,0xe6,"powder blue"}, +{0xb0,0xe0,0xe6,"powderblue"}, +{0xa0,0x20,0xf0,"purple"}, +{0x9b,0x30,0xff,"purple1"}, +{0x91,0x2c,0xee,"purple2"}, +{0x7d,0x26,0xcd,"purple3"}, +{0x55,0x1a,0x8b,"purple4"}, +{0xff,0x00,0x00,"red"}, +{0xff,0x00,0x00,"red1"}, +{0xee,0x00,0x00,"red2"}, +{0xcd,0x00,0x00,"red3"}, +{0x8b,0x00,0x00,"red4"}, +{0xbc,0x8f,0x8f,"rosy brown"}, +{0xbc,0x8f,0x8f,"rosybrown"}, +{0xff,0xc1,0xc1,"rosybrown1"}, +{0xee,0xb4,0xb4,"rosybrown2"}, +{0xcd,0x9b,0x9b,"rosybrown3"}, +{0x8b,0x69,0x69,"rosybrown4"}, +{0x41,0x69,0xe1,"royal blue"}, +{0x41,0x69,0xe1,"royalblue"}, +{0x48,0x76,0xff,"royalblue1"}, +{0x43,0x6e,0xee,"royalblue2"}, +{0x3a,0x5f,0xcd,"royalblue3"}, +{0x27,0x40,0x8b,"royalblue4"}, +{0x8b,0x45,0x13,"saddle brown"}, +{0x8b,0x45,0x13,"saddlebrown"}, +{0xfa,0x80,0x72,"salmon"}, +{0xff,0x8c,0x69,"salmon1"}, +{0xee,0x82,0x62,"salmon2"}, +{0xcd,0x70,0x54,"salmon3"}, +{0x8b,0x4c,0x39,"salmon4"}, +{0xf4,0xa4,0x60,"sandy brown"}, +{0xf4,0xa4,0x60,"sandybrown"}, +{0x2e,0x8b,0x57,"sea green"}, +{0x2e,0x8b,0x57,"seagreen"}, +{0x54,0xff,0x9f,"seagreen1"}, +{0x4e,0xee,0x94,"seagreen2"}, +{0x43,0xcd,0x80,"seagreen3"}, +{0x2e,0x8b,0x57,"seagreen4"}, +{0xff,0xf5,0xee,"seashell"}, +{0xff,0xf5,0xee,"seashell1"}, +{0xee,0xe5,0xde,"seashell2"}, +{0xcd,0xc5,0xbf,"seashell3"}, +{0x8b,0x86,0x82,"seashell4"}, +{0xa0,0x52,0x2d,"sienna"}, +{0xff,0x82,0x47,"sienna1"}, +{0xee,0x79,0x42,"sienna2"}, +{0xcd,0x68,0x39,"sienna3"}, +{0x8b,0x47,0x26,"sienna4"}, +{0x87,0xce,0xeb,"sky blue"}, +{0x87,0xce,0xeb,"skyblue"}, +{0x87,0xce,0xff,"skyblue1"}, +{0x7e,0xc0,0xee,"skyblue2"}, +{0x6c,0xa6,0xcd,"skyblue3"}, +{0x4a,0x70,0x8b,"skyblue4"}, +{0x6a,0x5a,0xcd,"slate blue"}, +{0x70,0x80,0x90,"slate gray"}, +{0x70,0x80,0x90,"slate grey"}, +{0x6a,0x5a,0xcd,"slateblue"}, +{0x83,0x6f,0xff,"slateblue1"}, +{0x7a,0x67,0xee,"slateblue2"}, +{0x69,0x59,0xcd,"slateblue3"}, +{0x47,0x3c,0x8b,"slateblue4"}, +{0x70,0x80,0x90,"slategray"}, +{0xc6,0xe2,0xff,"slategray1"}, +{0xb9,0xd3,0xee,"slategray2"}, +{0x9f,0xb6,0xcd,"slategray3"}, +{0x6c,0x7b,0x8b,"slategray4"}, +{0x70,0x80,0x90,"slategrey"}, +{0xff,0xfa,0xfa,"snow"}, +{0xff,0xfa,0xfa,"snow1"}, +{0xee,0xe9,0xe9,"snow2"}, +{0xcd,0xc9,0xc9,"snow3"}, +{0x8b,0x89,0x89,"snow4"}, +{0x00,0xff,0x7f,"spring green"}, +{0x00,0xff,0x7f,"springgreen"}, +{0x00,0xff,0x7f,"springgreen1"}, +{0x00,0xee,0x76,"springgreen2"}, +{0x00,0xcd,0x66,"springgreen3"}, +{0x00,0x8b,0x45,"springgreen4"}, +{0x46,0x82,0xb4,"steel blue"}, +{0x46,0x82,0xb4,"steelblue"}, +{0x63,0xb8,0xff,"steelblue1"}, +{0x5c,0xac,0xee,"steelblue2"}, +{0x4f,0x94,0xcd,"steelblue3"}, +{0x36,0x64,0x8b,"steelblue4"}, +{0xd2,0xb4,0x8c,"tan"}, +{0xff,0xa5,0x4f,"tan1"}, +{0xee,0x9a,0x49,"tan2"}, +{0xcd,0x85,0x3f,"tan3"}, +{0x8b,0x5a,0x2b,"tan4"}, +{0xd8,0xbf,0xd8,"thistle"}, +{0xff,0xe1,0xff,"thistle1"}, +{0xee,0xd2,0xee,"thistle2"}, +{0xcd,0xb5,0xcd,"thistle3"}, +{0x8b,0x7b,0x8b,"thistle4"}, +{0xff,0x63,0x47,"tomato"}, +{0xff,0x63,0x47,"tomato1"}, +{0xee,0x5c,0x42,"tomato2"}, +{0xcd,0x4f,0x39,"tomato3"}, +{0x8b,0x36,0x26,"tomato4"}, +{0x40,0xe0,0xd0,"turquoise"}, +{0x00,0xf5,0xff,"turquoise1"}, +{0x00,0xe5,0xee,"turquoise2"}, +{0x00,0xc5,0xcd,"turquoise3"}, +{0x00,0x86,0x8b,"turquoise4"}, +{0xee,0x82,0xee,"violet"}, +{0xd0,0x20,0x90,"violet red"}, +{0xd0,0x20,0x90,"violetred"}, +{0xff,0x3e,0x96,"violetred1"}, +{0xee,0x3a,0x8c,"violetred2"}, +{0xcd,0x32,0x78,"violetred3"}, +{0x8b,0x22,0x52,"violetred4"}, +{0xf5,0xde,0xb3,"wheat"}, +{0xff,0xe7,0xba,"wheat1"}, +{0xee,0xd8,0xae,"wheat2"}, +{0xcd,0xba,0x96,"wheat3"}, +{0x8b,0x7e,0x66,"wheat4"}, +{0xff,0xff,0xff,"white"}, +{0xf5,0xf5,0xf5,"white smoke"}, +{0xf5,0xf5,0xf5,"whitesmoke"}, +{0xff,0xff,0x00,"yellow"}, +{0x9a,0xcd,0x32,"yellow green"}, +{0xff,0xff,0x00,"yellow1"}, +{0xee,0xee,0x00,"yellow2"}, +{0xcd,0xcd,0x00,"yellow3"}, +{0x8b,0x8b,0x00,"yellow4"}, +{0x9a,0xcd,0x32,"yellowgreen"} +} +; + + + +static int max_rgb_names = (int) + (sizeof(rgb_names)/sizeof(struct rgb_and_name) ); + +int rgb_color_values(char *name, unsigned char &r, + unsigned char &g, unsigned char &b) +{ + int lwb, upb, mid, found, c; + + if( !isalpha(name[0])) return 0; + + mid = 0; + while((c = name[mid])) { name[mid] = tolower(c); ++mid; } + lwb = 0; + upb = max_rgb_names - 1; + + while (lwb <= upb) + { + mid = (lwb + upb)>>1; + + found = strcmp(name, rgb_names[mid].cname); + + if(found == 0) + { + r = rgb_names[mid].r; + g = rgb_names[mid].g; + b = rgb_names[mid].b; + return 1; + } + if(found < 0) + upb = mid - 1; + else + lwb = mid + 1; + } + r = 0; g = 0; b = 0; + return 0; + +}// rgb_color_values() diff --git a/src/bin/fltk/flviewer/rgb_color.hh b/src/bin/fltk/flviewer/rgb_color.hh new file mode 100644 index 00000000..ec681023 --- /dev/null +++ b/src/bin/fltk/flviewer/rgb_color.hh @@ -0,0 +1,7 @@ +#ifndef _FLVIEWER_RGB_COLOR_HH_ +#define _FLVIEWER_RGB_COLOR_HH_ + +extern int rgb_color_values(char *name, unsigned char &r, + unsigned char &g, unsigned char &b); + +#endif //_FLVIEWER_RGB_COLOR_HH_ diff --git a/src/bin/fltk/flviewer/tree.hh b/src/bin/fltk/flviewer/tree.hh new file mode 100644 index 00000000..2e0be1b4 --- /dev/null +++ b/src/bin/fltk/flviewer/tree.hh @@ -0,0 +1,184 @@ +#ifndef _FLVIEWER_TREE_HH_ +#define _FLVIEWER_TREE_HH_ + +#include + +#define MAX_ITEMBUF 254 + +class UserTree : public Fl_Tree +{ +public: + UserTree(int xx, int yy, int ww, int hh) + : Fl_Tree(xx, yy, ww, hh, NULL) + { } + virtual int handle(int event); +}; + +extern UserTree *tree; + +extern unsigned char box_name[33]; + +typedef struct jp2_cdef_info +{ + unsigned short cn, typ, asoc; +} jp2_cdef_info_t; + +typedef struct jp2_cdef +{ + jp2_cdef_info_t *info; + unsigned short n; +} jp2_cdef_t; + +typedef struct jp2_cmap_comp +{ + unsigned short cmp; + unsigned char mtyp, pcol; +} jp2_cmap_comp_t; + +typedef struct jp2_pclr +{ + unsigned int *entries; + unsigned char *channel_sign; + unsigned char *channel_size; + jp2_cmap_comp_t *cmap; + unsigned short nr_entries; + unsigned char nr_channels; +} jp2_pclr_t; + +typedef struct jp2_color +{ + unsigned char *icc_profile_buf; + unsigned int icc_profile_len; + + jp2_cdef_t *jp2_cdef; + jp2_pclr_t *jp2_pclr; + unsigned short has_colr, has_cdef; + unsigned int enumcs, meth, precedence, approx; +} jp2_color_t; + +typedef struct sample +{ + int64_t pos; + unsigned int size; +} sample_t; + +typedef struct track +{ + sample_t *samples; + int max_samples; + int nr_tracks; + int max_tracks; + + unsigned int duration; + unsigned int width; + unsigned int height; +} track_t; + +extern track_t *Tracks; + +typedef struct ftyp_info +{ + unsigned int magic_len; + int decod_format; + unsigned int minv; + unsigned char is_j2k, is_jp2, is_jpx, is_jpm, is_jpt; + + unsigned char brand_jp2, brand_jpx, brand_jpm; + + unsigned char compat_jp2, compat_jp21; + + unsigned char compat_jpx, compat_jpxb; + + unsigned char compat_jpm; + +}FTYPInfo; + +//--- PROTOTYPES + +extern int JPEG2000_test_ftyp(const char *fname, unsigned char *s, + uint64_t size, FTYPInfo *info); +extern int JPEG2000_build_tree(const char *read_idf); + +extern int read_mj2(unsigned char *parse_start, unsigned char *dend); +extern int read_jpx(unsigned char *src, unsigned char *parse_start, + unsigned char *dend); +extern int read_jpm(unsigned char *src, unsigned char *parse_start, + unsigned char *dend); + +extern uint64_t read_boxheader(unsigned char *box, unsigned char *dend, + unsigned int *out_siz); + +extern uint64_t get8(const unsigned char *b); +extern unsigned int get4(const unsigned char *b); +extern unsigned int get2(const unsigned char *b); +extern unsigned int get_size(const unsigned char *b, unsigned int size); + +extern unsigned char *read_resc(unsigned char *s, unsigned char *box_end, + const unsigned char *name_src); +extern unsigned char *read_resd(unsigned char *s, unsigned char *box_end, + const unsigned char *name_src); +extern unsigned char *read_res(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const unsigned char *name_src); + +extern unsigned char *read_ftyp(unsigned char *s, unsigned char *box_end, + const char *name_src); +extern unsigned char *read_jp2h(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src); + +extern unsigned char *read_ihdr(unsigned char *s, unsigned char *box_end, + const char *name_src); +extern unsigned char *read_bpcc(unsigned char *s, unsigned char *box_end, + const char *name_src); + +extern unsigned char *read_pclr(unsigned char *s, unsigned char *box_end, + unsigned int *out_channels, const char *name_src); +extern unsigned char *read_cmap(unsigned char *s, unsigned char *box_end, + unsigned int nr_channels, const char *name_src); +extern unsigned char *read_colr(unsigned char *s, unsigned char *box_end, + const char *name_src); + +extern unsigned char *read_cdef(unsigned char *s, unsigned char *box_end, + const char *name_src); +extern unsigned char *read_xml(unsigned char *s, unsigned char *box_end, + unsigned char *dend, char **out_buf); + +extern unsigned char *read_uuid(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src); +extern unsigned char *read_uinf(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src); +extern unsigned char *read_url(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src); + +extern unsigned char *read_ulst(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src); + + +extern unsigned char *read_jp2c(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src); +extern unsigned char *read_jp2i(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src); +extern unsigned char *read_dtbl(unsigned char *s, unsigned char *box_end, + unsigned char *dend, const char *name_src); + + +extern void FLViewer_set_max_mj2_samples(unsigned int n); +extern void FLViewer_set_max_components(unsigned int n); +extern void FLViewer_set_max_layers(unsigned int n); + +extern int FLViewer_max_mj2_samples(); +extern void FLViewer_set_max_mj2_tracks(unsigned int n); + +extern int FLViewer_max_layers(); +extern int FLViewer_layers(); + +extern int FLViewer_max_components(); +extern int FLViewer_component(); + +extern void FLViewer_set_max_tiles(int mx_tiles); +extern void FLViewer_set_max_reduction(int mx_reduct); + +extern unsigned char *OPENJPEG_mj2_decode(const char *read_idf, + unsigned char *src, uint64_t size, int *out_selected); + + +#endif /* _FLVIEWER_TREE_HH_ */ diff --git a/src/bin/fltk/flviewer/viewerdefs.hh b/src/bin/fltk/flviewer/viewerdefs.hh new file mode 100644 index 00000000..10dad2c8 --- /dev/null +++ b/src/bin/fltk/flviewer/viewerdefs.hh @@ -0,0 +1,72 @@ +#ifndef _FLVIEWER_DEFS_HH_ +#define _FLVIEWER_DEFS_HH_ + +//----------------------------------------- +#define LABEL_SIZE 14 +#define BAR_SIZE 17 + +#ifdef _WIN32 +#define WIN_X 30 +#define WIN_Y 35 +#else +#define WIN_X 80 +#define WIN_Y 130 +#endif + +#define BORDER_SIZE 5 +#define FRAMES_W 80 +#define TRACKS_W 60 + +#define BUTTON_W 80 +#define BUTTON_H 25 + +#define STEP_GROUP_W BUTTON_W*2 + +#define HEADER_H 160 + +#define MIN_SCROLLER_W BAR_SIZE +#define MIN_SCROLLER_H BAR_SIZE + +// Only if(movie_runs == 0); still images only: +// +#define MAX_SCROLLER_W 640 //500 // 590 +#define MAX_SCROLLER_H 480 + +#define SCROLLER_X 210 +#define SCROLLER_Y HEADER_H + +#define TREE_X BORDER_SIZE +#define TREE_Y SCROLLER_Y +#define TREE_W 200 +#define TREE_H MAX_SCROLLER_H + +#define HEADER_W TREE_W + BORDER_SIZE + MAX_SCROLLER_W -130 + +#define WINDOW_MIN_W BORDER_SIZE + HEADER_W + BORDER_SIZE +#define WINDOW_MIN_H BORDER_SIZE + HEADER_H + TREE_H + BORDER_SIZE +//----------------------------------------- +#define PNG_MAGIC "\x89PNG\x0d\x0a\x1a\x0a" + +/* JPEG2000 */ +#define JP2_RFC3745_MAGIC "\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a" +#define JP2_MAGIC "\x0d\x0a\x87\x0a" +/* position 45: "\xff\x52" */ +#define J2K_CODESTREAM_MAGIC "\xff\x4f\xff\x51" + +#define J2K_CFMT 0 +#define JP2_CFMT 1 +#define JPT_CFMT 2 + +#define PXM_DFMT 10 +#define PGX_DFMT 11 +#define BMP_DFMT 12 +#define YUV_DFMT 13 +#define TIF_DFMT 14 +#define RAW_DFMT 15 +#define TGA_DFMT 16 +#define PNG_DFMT 17 +#define RAWL_DFMT 18 + +/* PROTOTYPES */ + +#endif /* _FLVIEWER_DEFS_HH_ */