From d577d991b97ae2b5ee1af23641bcffc3f83af5b2 Mon Sep 17 00:00:00 2001 From: Pixel Date: Wed, 4 Nov 2009 11:56:41 -0800 Subject: Initial import. Contains the im, cd and iup librairies, and a "working" Makefile for them under linux. --- im/dox/im.dox | 1528 ++++++++++++++++ im/include/im.h | 287 +++ im/include/im_attrib.h | 120 ++ im/include/im_attrib_flat.h | 39 + im/include/im_binfile.h | 224 +++ im/include/im_capture.h | 365 ++++ im/include/im_color.h | 465 +++++ im/include/im_colorhsi.h | 56 + im/include/im_complex.h | 180 ++ im/include/im_convert.h | 142 ++ im/include/im_counter.h | 69 + im/include/im_dib.h | 195 ++ im/include/im_file.h | 115 ++ im/include/im_format.h | 97 + im/include/im_format_all.h | 360 ++++ im/include/im_format_avi.h | 88 + im/include/im_format_ecw.h | 93 + im/include/im_format_jp2.h | 79 + im/include/im_format_raw.h | 74 + im/include/im_format_wmv.h | 101 ++ im/include/im_image.h | 411 +++++ im/include/im_kernel.h | 315 ++++ im/include/im_lib.h | 191 ++ im/include/im_math.h | 368 ++++ im/include/im_math_op.h | 214 +++ im/include/im_palette.h | 172 ++ im/include/im_plus.h | 73 + im/include/im_process.h | 36 + im/include/im_process_ana.h | 222 +++ im/include/im_process_glo.h | 170 ++ im/include/im_process_loc.h | 606 +++++++ im/include/im_process_pon.h | 720 ++++++++ im/include/im_raw.h | 34 + im/include/im_util.h | 277 +++ im/include/imlua.h | 83 + im/include/old_im.h | 59 + im/mak.vc8/im.sln | 177 ++ im/mak.vc8/im.vcproj | 1224 +++++++++++++ im/mak.vc8/im_avi.vcproj | 120 ++ im/mak.vc8/im_capture.vcproj | 120 ++ im/mak.vc8/im_copy.vcproj | 116 ++ im/mak.vc8/im_ecw.vcproj | 120 ++ im/mak.vc8/im_fftw.vcproj | 425 +++++ im/mak.vc8/im_info.vcproj | 116 ++ im/mak.vc8/im_jp2.vcproj | 444 +++++ im/mak.vc8/im_process.vcproj | 224 +++ im/mak.vc8/im_view.vcproj | 116 ++ im/mak.vc8/im_wmv.vcproj | 120 ++ im/mak.vc8/imlua3.vcproj | 120 ++ im/mak.vc8/imlua5.vcproj | 164 ++ im/mak.vc8/imlua_capture5.vcproj | 111 ++ im/mak.vc8/imlua_fftw5.vcproj | 115 ++ im/mak.vc8/imlua_process5.vcproj | 119 ++ im/mak.vc9/im.sln | 177 ++ im/mak.vc9/im.vcproj | 1224 +++++++++++++ im/mak.vc9/im_avi.vcproj | 120 ++ im/mak.vc9/im_capture.vcproj | 120 ++ im/mak.vc9/im_copy.vcproj | 116 ++ im/mak.vc9/im_ecw.vcproj | 120 ++ im/mak.vc9/im_fftw.vcproj | 425 +++++ im/mak.vc9/im_info.vcproj | 116 ++ im/mak.vc9/im_jp2.vcproj | 444 +++++ im/mak.vc9/im_process.vcproj | 224 +++ im/mak.vc9/im_view.vcproj | 116 ++ im/mak.vc9/im_wmv.vcproj | 120 ++ im/mak.vc9/imlua3.vcproj | 120 ++ im/mak.vc9/imlua5.vcproj | 164 ++ im/mak.vc9/imlua_capture5.vcproj | 111 ++ im/mak.vc9/imlua_fftw5.vcproj | 115 ++ im/mak.vc9/imlua_process5.vcproj | 119 ++ im/src/COPYRIGHT | 32 + im/src/Makefile | 15 + im/src/README | 11 + im/src/config.mak | 89 + im/src/im.def | 200 +++ im/src/im.dep | 121 ++ im/src/im.rc | 19 + im/src/im_attrib.cpp | 319 ++++ im/src/im_bin.cpp | 111 ++ im/src/im_binfile.cpp | 710 ++++++++ im/src/im_capture.def | 27 + im/src/im_capture.mak | 73 + im/src/im_capture.wlib | 22 + im/src/im_capture_dx.cpp | 2255 +++++++++++++++++++++++ im/src/im_colorhsi.cpp | 265 +++ im/src/im_colormode.cpp | 87 + im/src/im_colorutil.cpp | 27 + im/src/im_convertbitmap.cpp | 284 +++ im/src/im_convertcolor.cpp | 985 +++++++++++ im/src/im_converttype.cpp | 555 ++++++ im/src/im_counter.cpp | 151 ++ im/src/im_datatype.cpp | 54 + im/src/im_dib.cpp | 1136 ++++++++++++ im/src/im_dibxbitmap.cpp | 181 ++ im/src/im_ecw.def | 2 + im/src/im_ecw.mak | 16 + im/src/im_file.cpp | 465 +++++ im/src/im_filebuffer.cpp | 695 ++++++++ im/src/im_fileraw.cpp | 66 + im/src/im_format.cpp | 299 ++++ im/src/im_format_all.cpp | 34 + im/src/im_format_bmp.cpp | 949 ++++++++++ im/src/im_format_ecw.cpp | 385 ++++ im/src/im_format_gif.cpp | 1510 ++++++++++++++++ im/src/im_format_ico.cpp | 660 +++++++ im/src/im_format_krn.cpp | 325 ++++ im/src/im_format_led.cpp | 341 ++++ im/src/im_format_pcx.cpp | 711 ++++++++ im/src/im_format_pnm.cpp | 483 +++++ im/src/im_format_ras.cpp | 608 +++++++ im/src/im_format_raw.cpp | 366 ++++ im/src/im_format_sgi.cpp | 616 +++++++ im/src/im_format_tga.cpp | 1113 ++++++++++++ im/src/im_format_wmv.cpp | 1633 +++++++++++++++++ im/src/im_image.cpp | 695 ++++++++ im/src/im_lib.cpp | 38 + im/src/im_lua3.c | 1297 ++++++++++++++ im/src/im_palette.cpp | 551 ++++++ im/src/im_process.def | 165 ++ im/src/im_process.dep | 84 + im/src/im_process.mak | 36 + im/src/im_rgb2map.cpp | 964 ++++++++++ im/src/im_str.cpp | 67 + im/src/im_sysfile_unix.cpp | 211 +++ im/src/im_sysfile_win32.cpp | 207 +++ im/src/im_wmv.def | 2 + im/src/im_wmv.mak | 23 + im/src/imlua3.def | 2 + im/src/imlua3.mak | 12 + im/src/imlua5.mak | 18 + im/src/imlua51.dep | 38 + im/src/imlua_capture5.mak | 18 + im/src/imlua_process5.mak | 19 + im/src/imlua_process51.dep | 17 + im/src/imlua_wmv.mak | 17 + im/src/jas_binfile.c | 97 + im/src/lua5/im_convert.lua | 18 + im/src/lua5/im_fftw.lua | 57 + im/src/lua5/im_image.lua | 24 + im/src/lua5/im_process.lua | 329 ++++ im/src/lua5/imlua.c | 252 +++ im/src/lua5/imlua.def | 24 + im/src/lua5/imlua_aux.c | 256 +++ im/src/lua5/imlua_aux.h | 82 + im/src/lua5/imlua_avi.c | 44 + im/src/lua5/imlua_avi.def | 4 + im/src/lua5/imlua_capture.c | 443 +++++ im/src/lua5/imlua_capture.def | 5 + im/src/lua5/imlua_convert.c | 96 + im/src/lua5/imlua_fftw.c | 162 ++ im/src/lua5/imlua_fftw.def | 4 + im/src/lua5/imlua_file.c | 661 +++++++ im/src/lua5/imlua_image.c | 1083 ++++++++++++ im/src/lua5/imlua_image.h | 38 + im/src/lua5/imlua_jp2.c | 44 + im/src/lua5/imlua_jp2.def | 4 + im/src/lua5/imlua_kernel.c | 182 ++ im/src/lua5/imlua_palette.c | 399 +++++ im/src/lua5/imlua_palette.h | 32 + im/src/lua5/imlua_process.c | 3143 +++++++++++++++++++++++++++++++++ im/src/lua5/imlua_process.def | 4 + im/src/lua5/imlua_util.c | 279 +++ im/src/lua5/imlua_wmv.c | 44 + im/src/lua5/imlua_wmv.def | 4 + im/src/lua5/loh/im_convert.loh | 87 + im/src/lua5/loh/im_convert_be32.loh | 87 + im/src/lua5/loh/im_convert_be64.loh | 95 + im/src/lua5/loh/im_convert_le64.loh | 95 + im/src/lua5/loh/im_fftw.loh | 110 ++ im/src/lua5/loh/im_fftw_be32.loh | 110 ++ im/src/lua5/loh/im_fftw_be64.loh | 122 ++ im/src/lua5/loh/im_fftw_le64.loh | 122 ++ im/src/lua5/loh/im_fftw_le64w.loh | 115 ++ im/src/lua5/loh/im_image.loh | 63 + im/src/lua5/loh/im_image_be32.loh | 63 + im/src/lua5/loh/im_image_be64.loh | 68 + im/src/lua5/loh/im_image_le64.loh | 68 + im/src/lua5/loh/im_process.loh | 817 +++++++++ im/src/lua5/loh/im_process_be32.loh | 817 +++++++++ im/src/lua5/loh/im_process_be64.loh | 897 ++++++++++ im/src/lua5/loh/im_process_le64.loh | 897 ++++++++++ im/src/lua5/loh/im_process_le64w.loh | 890 ++++++++++ im/src/make_uname | 13 + im/src/make_uname.bat | 74 + im/src/old_im.cpp | 440 +++++ im/src/old_imcolor.c | 75 + im/src/old_imresize.c | 117 ++ im/src/process/im_analyze.cpp | 1268 +++++++++++++ im/src/process/im_arithmetic_bin.cpp | 587 ++++++ im/src/process/im_arithmetic_un.cpp | 256 +++ im/src/process/im_canny.cpp | 254 +++ im/src/process/im_color.cpp | 255 +++ im/src/process/im_convolve.cpp | 1594 +++++++++++++++++ im/src/process/im_convolve_rank.cpp | 701 ++++++++ im/src/process/im_distance.cpp | 512 ++++++ im/src/process/im_effects.cpp | 86 + im/src/process/im_fft.cpp | 198 +++ im/src/process/im_geometric.cpp | 724 ++++++++ im/src/process/im_histogram.cpp | 105 ++ im/src/process/im_houghline.cpp | 435 +++++ im/src/process/im_kernel.cpp | 293 +++ im/src/process/im_logic.cpp | 136 ++ im/src/process/im_morphology_bin.cpp | 317 ++++ im/src/process/im_morphology_gray.cpp | 231 +++ im/src/process/im_quantize.cpp | 64 + im/src/process/im_render.cpp | 532 ++++++ im/src/process/im_resize.cpp | 332 ++++ im/src/process/im_statistics.cpp | 341 ++++ im/src/process/im_threshold.cpp | 391 ++++ im/src/process/im_tonegamut.cpp | 322 ++++ im/src/tecmake_compact.mak | 1170 ++++++++++++ im/test/glut_capture.c | 415 +++++ im/test/im_copy.cpp | 145 ++ im/test/im_info.cpp | 211 +++ im/test/im_info.mak | 11 + im/test/im_view.c | 182 ++ im/test/im_view.mak | 14 + im/test/iupglview.c | 237 +++ 218 files changed, 66392 insertions(+) create mode 100755 im/dox/im.dox create mode 100755 im/include/im.h create mode 100755 im/include/im_attrib.h create mode 100755 im/include/im_attrib_flat.h create mode 100755 im/include/im_binfile.h create mode 100755 im/include/im_capture.h create mode 100755 im/include/im_color.h create mode 100755 im/include/im_colorhsi.h create mode 100755 im/include/im_complex.h create mode 100755 im/include/im_convert.h create mode 100755 im/include/im_counter.h create mode 100755 im/include/im_dib.h create mode 100755 im/include/im_file.h create mode 100755 im/include/im_format.h create mode 100755 im/include/im_format_all.h create mode 100755 im/include/im_format_avi.h create mode 100755 im/include/im_format_ecw.h create mode 100755 im/include/im_format_jp2.h create mode 100755 im/include/im_format_raw.h create mode 100755 im/include/im_format_wmv.h create mode 100755 im/include/im_image.h create mode 100755 im/include/im_kernel.h create mode 100755 im/include/im_lib.h create mode 100755 im/include/im_math.h create mode 100755 im/include/im_math_op.h create mode 100755 im/include/im_palette.h create mode 100755 im/include/im_plus.h create mode 100755 im/include/im_process.h create mode 100755 im/include/im_process_ana.h create mode 100755 im/include/im_process_glo.h create mode 100755 im/include/im_process_loc.h create mode 100755 im/include/im_process_pon.h create mode 100755 im/include/im_raw.h create mode 100755 im/include/im_util.h create mode 100755 im/include/imlua.h create mode 100755 im/include/old_im.h create mode 100755 im/mak.vc8/im.sln create mode 100755 im/mak.vc8/im.vcproj create mode 100755 im/mak.vc8/im_avi.vcproj create mode 100755 im/mak.vc8/im_capture.vcproj create mode 100755 im/mak.vc8/im_copy.vcproj create mode 100755 im/mak.vc8/im_ecw.vcproj create mode 100755 im/mak.vc8/im_fftw.vcproj create mode 100755 im/mak.vc8/im_info.vcproj create mode 100755 im/mak.vc8/im_jp2.vcproj create mode 100755 im/mak.vc8/im_process.vcproj create mode 100755 im/mak.vc8/im_view.vcproj create mode 100755 im/mak.vc8/im_wmv.vcproj create mode 100755 im/mak.vc8/imlua3.vcproj create mode 100755 im/mak.vc8/imlua5.vcproj create mode 100755 im/mak.vc8/imlua_capture5.vcproj create mode 100755 im/mak.vc8/imlua_fftw5.vcproj create mode 100755 im/mak.vc8/imlua_process5.vcproj create mode 100755 im/mak.vc9/im.sln create mode 100755 im/mak.vc9/im.vcproj create mode 100755 im/mak.vc9/im_avi.vcproj create mode 100755 im/mak.vc9/im_capture.vcproj create mode 100755 im/mak.vc9/im_copy.vcproj create mode 100755 im/mak.vc9/im_ecw.vcproj create mode 100755 im/mak.vc9/im_fftw.vcproj create mode 100755 im/mak.vc9/im_info.vcproj create mode 100755 im/mak.vc9/im_jp2.vcproj create mode 100755 im/mak.vc9/im_process.vcproj create mode 100755 im/mak.vc9/im_view.vcproj create mode 100755 im/mak.vc9/im_wmv.vcproj create mode 100755 im/mak.vc9/imlua3.vcproj create mode 100755 im/mak.vc9/imlua5.vcproj create mode 100755 im/mak.vc9/imlua_capture5.vcproj create mode 100755 im/mak.vc9/imlua_fftw5.vcproj create mode 100755 im/mak.vc9/imlua_process5.vcproj create mode 100755 im/src/COPYRIGHT create mode 100755 im/src/Makefile create mode 100755 im/src/README create mode 100755 im/src/config.mak create mode 100755 im/src/im.def create mode 100644 im/src/im.dep create mode 100755 im/src/im.rc create mode 100755 im/src/im_attrib.cpp create mode 100755 im/src/im_bin.cpp create mode 100755 im/src/im_binfile.cpp create mode 100755 im/src/im_capture.def create mode 100755 im/src/im_capture.mak create mode 100644 im/src/im_capture.wlib create mode 100755 im/src/im_capture_dx.cpp create mode 100755 im/src/im_colorhsi.cpp create mode 100755 im/src/im_colormode.cpp create mode 100755 im/src/im_colorutil.cpp create mode 100755 im/src/im_convertbitmap.cpp create mode 100755 im/src/im_convertcolor.cpp create mode 100755 im/src/im_converttype.cpp create mode 100755 im/src/im_counter.cpp create mode 100755 im/src/im_datatype.cpp create mode 100755 im/src/im_dib.cpp create mode 100755 im/src/im_dibxbitmap.cpp create mode 100755 im/src/im_ecw.def create mode 100755 im/src/im_ecw.mak create mode 100755 im/src/im_file.cpp create mode 100755 im/src/im_filebuffer.cpp create mode 100755 im/src/im_fileraw.cpp create mode 100755 im/src/im_format.cpp create mode 100755 im/src/im_format_all.cpp create mode 100755 im/src/im_format_bmp.cpp create mode 100755 im/src/im_format_ecw.cpp create mode 100755 im/src/im_format_gif.cpp create mode 100755 im/src/im_format_ico.cpp create mode 100755 im/src/im_format_krn.cpp create mode 100755 im/src/im_format_led.cpp create mode 100755 im/src/im_format_pcx.cpp create mode 100755 im/src/im_format_pnm.cpp create mode 100755 im/src/im_format_ras.cpp create mode 100755 im/src/im_format_raw.cpp create mode 100755 im/src/im_format_sgi.cpp create mode 100755 im/src/im_format_tga.cpp create mode 100755 im/src/im_format_wmv.cpp create mode 100755 im/src/im_image.cpp create mode 100755 im/src/im_lib.cpp create mode 100755 im/src/im_lua3.c create mode 100755 im/src/im_palette.cpp create mode 100755 im/src/im_process.def create mode 100644 im/src/im_process.dep create mode 100755 im/src/im_process.mak create mode 100755 im/src/im_rgb2map.cpp create mode 100755 im/src/im_str.cpp create mode 100755 im/src/im_sysfile_unix.cpp create mode 100755 im/src/im_sysfile_win32.cpp create mode 100755 im/src/im_wmv.def create mode 100755 im/src/im_wmv.mak create mode 100755 im/src/imlua3.def create mode 100755 im/src/imlua3.mak create mode 100755 im/src/imlua5.mak create mode 100644 im/src/imlua51.dep create mode 100755 im/src/imlua_capture5.mak create mode 100755 im/src/imlua_process5.mak create mode 100644 im/src/imlua_process51.dep create mode 100755 im/src/imlua_wmv.mak create mode 100755 im/src/jas_binfile.c create mode 100755 im/src/lua5/im_convert.lua create mode 100755 im/src/lua5/im_fftw.lua create mode 100755 im/src/lua5/im_image.lua create mode 100755 im/src/lua5/im_process.lua create mode 100755 im/src/lua5/imlua.c create mode 100755 im/src/lua5/imlua.def create mode 100755 im/src/lua5/imlua_aux.c create mode 100755 im/src/lua5/imlua_aux.h create mode 100755 im/src/lua5/imlua_avi.c create mode 100755 im/src/lua5/imlua_avi.def create mode 100755 im/src/lua5/imlua_capture.c create mode 100755 im/src/lua5/imlua_capture.def create mode 100755 im/src/lua5/imlua_convert.c create mode 100755 im/src/lua5/imlua_fftw.c create mode 100755 im/src/lua5/imlua_fftw.def create mode 100755 im/src/lua5/imlua_file.c create mode 100755 im/src/lua5/imlua_image.c create mode 100755 im/src/lua5/imlua_image.h create mode 100755 im/src/lua5/imlua_jp2.c create mode 100755 im/src/lua5/imlua_jp2.def create mode 100755 im/src/lua5/imlua_kernel.c create mode 100755 im/src/lua5/imlua_palette.c create mode 100755 im/src/lua5/imlua_palette.h create mode 100755 im/src/lua5/imlua_process.c create mode 100755 im/src/lua5/imlua_process.def create mode 100755 im/src/lua5/imlua_util.c create mode 100755 im/src/lua5/imlua_wmv.c create mode 100755 im/src/lua5/imlua_wmv.def create mode 100644 im/src/lua5/loh/im_convert.loh create mode 100755 im/src/lua5/loh/im_convert_be32.loh create mode 100644 im/src/lua5/loh/im_convert_be64.loh create mode 100755 im/src/lua5/loh/im_convert_le64.loh create mode 100755 im/src/lua5/loh/im_fftw.loh create mode 100755 im/src/lua5/loh/im_fftw_be32.loh create mode 100644 im/src/lua5/loh/im_fftw_be64.loh create mode 100755 im/src/lua5/loh/im_fftw_le64.loh create mode 100755 im/src/lua5/loh/im_fftw_le64w.loh create mode 100644 im/src/lua5/loh/im_image.loh create mode 100755 im/src/lua5/loh/im_image_be32.loh create mode 100644 im/src/lua5/loh/im_image_be64.loh create mode 100755 im/src/lua5/loh/im_image_le64.loh create mode 100755 im/src/lua5/loh/im_process.loh create mode 100755 im/src/lua5/loh/im_process_be32.loh create mode 100644 im/src/lua5/loh/im_process_be64.loh create mode 100755 im/src/lua5/loh/im_process_le64.loh create mode 100755 im/src/lua5/loh/im_process_le64w.loh create mode 100755 im/src/make_uname create mode 100755 im/src/make_uname.bat create mode 100755 im/src/old_im.cpp create mode 100755 im/src/old_imcolor.c create mode 100755 im/src/old_imresize.c create mode 100755 im/src/process/im_analyze.cpp create mode 100755 im/src/process/im_arithmetic_bin.cpp create mode 100755 im/src/process/im_arithmetic_un.cpp create mode 100755 im/src/process/im_canny.cpp create mode 100755 im/src/process/im_color.cpp create mode 100755 im/src/process/im_convolve.cpp create mode 100755 im/src/process/im_convolve_rank.cpp create mode 100755 im/src/process/im_distance.cpp create mode 100755 im/src/process/im_effects.cpp create mode 100755 im/src/process/im_fft.cpp create mode 100755 im/src/process/im_geometric.cpp create mode 100755 im/src/process/im_histogram.cpp create mode 100755 im/src/process/im_houghline.cpp create mode 100755 im/src/process/im_kernel.cpp create mode 100755 im/src/process/im_logic.cpp create mode 100755 im/src/process/im_morphology_bin.cpp create mode 100755 im/src/process/im_morphology_gray.cpp create mode 100755 im/src/process/im_quantize.cpp create mode 100755 im/src/process/im_render.cpp create mode 100755 im/src/process/im_resize.cpp create mode 100755 im/src/process/im_statistics.cpp create mode 100755 im/src/process/im_threshold.cpp create mode 100755 im/src/process/im_tonegamut.cpp create mode 100755 im/src/tecmake_compact.mak create mode 100644 im/test/glut_capture.c create mode 100755 im/test/im_copy.cpp create mode 100644 im/test/im_info.cpp create mode 100755 im/test/im_info.mak create mode 100644 im/test/im_view.c create mode 100644 im/test/im_view.mak create mode 100644 im/test/iupglview.c (limited to 'im') diff --git a/im/dox/im.dox b/im/dox/im.dox new file mode 100755 index 0000000..5188237 --- /dev/null +++ b/im/dox/im.dox @@ -0,0 +1,1528 @@ +# Doxyfile 1.6.1 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = IM + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = 3.5 + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = ../html + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = NO + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = NO + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = YES + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it parses. +# With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this tag. +# The format is ext=language, where ext is a file extension, and language is one of +# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, +# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat +# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), +# use: inc=Fortran f=C. Note that for custom extensions you also need to set +# FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen to replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = YES + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penality. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will rougly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols + +SYMBOL_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = NO + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = YES + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = NO + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = NO + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = NO + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = NO + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= NO + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by +# doxygen. The layout file controls the global structure of the generated output files +# in an output format independent way. The create the layout file that represents +# doxygen's defaults, run doxygen with the -l option. You can optionally specify a +# file name after the option, if omitted DoxygenLayout.xml will be used as the name +# of the layout file. + +LAYOUT_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = NO + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = ../include + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 + +FILE_PATTERNS = *.h \ + iup.c + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = YES + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = NO + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = en/doxygen/ + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER +# are set, an additional index file will be generated that can be used as input for +# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated +# HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. +# For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's +# filter section matches. +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = YES + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list. + +USE_INLINE_TREES = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# When the SEARCHENGINE tag is enable doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP) or Qt help (GENERATE_QHP) +# there is already a search function so this one should typically +# be disabled. + +SEARCHENGINE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = ../include/ + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = LUA_TNONE + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = NO + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = YES + +# By default doxygen will write a font called FreeSans.ttf to the output +# directory and reference it in all dot files that doxygen generates. This +# font does not include all possible unicode characters however, so when you need +# these (or just want a differently looking font) you can specify the font name +# using DOT_FONTNAME. You need need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. + +DOT_FONTNAME = FreeSans + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 1000 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/im/include/im.h b/im/include/im.h new file mode 100755 index 0000000..a324199 --- /dev/null +++ b/im/include/im.h @@ -0,0 +1,287 @@ +/** \file + * \brief Main API + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_H +#define __IM_H + +#if defined(__cplusplus) +extern "C" { +#endif + + +/** Image data type descriptors. \n + * See also \ref datatypeutl. + * \ingroup imagerep */ +enum imDataType +{ + IM_BYTE, /**< "unsigned char". 1 byte from 0 to 255. */ + IM_USHORT, /**< "unsigned short". 2 bytes from 0 to 65,535. */ + IM_INT, /**< "int". 4 bytes from -2,147,483,648 to 2,147,483,647. */ + IM_FLOAT, /**< "float". 4 bytes single precision IEEE floating point. */ + IM_CFLOAT /**< complex "float". 2 float values in sequence, real and imaginary parts. */ +}; + +/** Image color mode color space descriptors (first byte). \n + * See also \ref colormodeutl. + * \ingroup imagerep */ +enum imColorSpace +{ + IM_RGB, /**< Red, Green and Blue (nonlinear). */ + IM_MAP, /**< Indexed by RGB color map (data_type=IM_BYTE). */ + IM_GRAY, /**< Shades of gray, luma (nonlinear Luminance), or an intensity value that is not related to color. */ + IM_BINARY, /**< Indexed by 2 colors: black (0) and white (1) (data_type=IM_BYTE). */ + IM_CMYK, /**< Cian, Magenta, Yellow and Black (nonlinear). */ + IM_YCBCR, /**< ITU-R 601 Y'CbCr. Y' is luma (nonlinear Luminance). */ + IM_LAB, /**< CIE L*a*b*. L* is Lightness (nonlinear Luminance, nearly perceptually uniform). */ + IM_LUV, /**< CIE L*u*v*. L* is Lightness (nonlinear Luminance, nearly perceptually uniform). */ + IM_XYZ /**< CIE XYZ. Linear Light Tristimulus, Y is linear Luminance. */ +}; + +/** Image color mode configuration/extra descriptors (1 bit each in the second byte). \n + * See also \ref colormodeutl. + * \ingroup imagerep */ +enum imColorModeConfig +{ + IM_ALPHA = 0x100, /**< adds an Alpha channel */ + IM_PACKED = 0x200, /**< packed components (rgbrgbrgb...) */ + IM_TOPDOWN = 0x400 /**< orientation from top down to bottom */ +}; + + + +/** File Access Error Codes + * \ingroup file */ +enum imErrorCodes +{ + IM_ERR_NONE, /**< No error. */ + IM_ERR_OPEN, /**< Error while opening the file (read or write). */ + IM_ERR_ACCESS, /**< Error while accessing the file (read or write). */ + IM_ERR_FORMAT, /**< Invalid or unrecognized file format. */ + IM_ERR_DATA, /**< Invalid or unsupported data. */ + IM_ERR_COMPRESS, /**< Invalid or unsupported compression. */ + IM_ERR_MEM, /**< Insuficient memory */ + IM_ERR_COUNTER /**< Interrupted by the counter */ +}; + +/* Internal Image File Structure. */ +typedef struct _imFile imFile; + +/** Opens the file for reading. It must exists. Also reads file header. + * It will try to identify the file format. + * See also \ref imErrorCodes. \n + * In Lua the IM file metatable name is "imFile". + * When converted to a string will return "imFile(%p)" where %p is replaced by the userdata address. + * If the file is already closed by im.FileClose, then it will return also the suffix "-closed". + * + * \verbatim im.FileOpen(file_name: string) -> ifile: imFile, error: number [in Lua 5] \endverbatim + * \ingroup file */ +imFile* imFileOpen(const char* file_name, int *error); + +/** Opens the file for reading using a specific format. It must exists. Also reads file header. + * See also \ref imErrorCodes and \ref format. + * + * \verbatim im.FileOpenAs(file_name, format: string) -> ifile: imFile, error: number [in Lua 5] \endverbatim + * \ingroup file */ +imFile* imFileOpenAs(const char* file_name, const char* format, int *error); + +/** Creates a new file for writing using a specific format. If the file exists will be replaced. \n + * It will only initialize the format driver and create the file, no data is actually written. + * See also \ref imErrorCodes and \ref format. + * + * \verbatim im.FileNew(file_name: string, format: string) -> ifile: imFile, error: number [in Lua 5] \endverbatim + * \ingroup file */ +imFile* imFileNew(const char* file_name, const char* format, int *error); + +/** Closes the file. \n + * In Lua if this function is not called, the file is closed by the garbage collector. + * + * \verbatim im.FileClose(ifile: imFile) [in Lua 5] \endverbatim + * \verbatim ifile:Close() [in Lua 5] \endverbatim + * \ingroup file */ +void imFileClose(imFile* ifile); + +/** Returns an internal handle. + * index=0 returns always an imBinFile* handle, + * but for some formats returns NULL because they do not use imBinFile (like AVI and WMV). + * index=1 return an internal structure used by the format, usually is a handle + * to a third party library structure. This is file format dependent. + * + * \verbatim ifile:Handle() -> handle: userdata [in Lua 5] \endverbatim + * \ingroup file */ +void* imFileHandle(imFile* ifile, int index); + +/** Returns file information. + * image_count is the number of images in a stack or + * the number of frames in a video/animation or the depth of a volume data. \n + * compression and image_count can be NULL. \n + * These informations are also available as attributes: + * \verbatim FileFormat (string) \endverbatim + * \verbatim FileCompression (string) \endverbatim + * \verbatim FileImageCount IM_INT (1) \endverbatim + * See also \ref format. + * + * \verbatim ifile:GetInfo() -> format: string, compression: string, image_count: number [in Lua 5] \endverbatim + * \ingroup file */ +void imFileGetInfo(imFile* ifile, char* format, char* compression, int *image_count); + +/** Changes the write compression method. \n + * If the compression is not supported will return an error code when writting. \n + * Use NULL to set the default compression. You can use the imFileGetInfo to retrieve the actual compression + * but only after \ref imFileWriteImageInfo. Only a few formats allow you to change the compression between frames. + * + * \verbatim ifile:SetInfo(compression: string) [in Lua 5] \endverbatim + * \ingroup file */ +void imFileSetInfo(imFile* ifile, const char* compression); + +/** Changes an extended attribute. \n + * The data will be internally duplicated. \n + * If data is NULL the attribute is removed. + * If data_type is BYTE then count can be -1 to indicate a NULL terminated string. + * See also \ref imDataType. + * + * \verbatim ifile:SetAttribute(attrib: string, data_type: number, data: table of numbers or string) [in Lua 5] \endverbatim + * If data_type is IM_BYTE, as_string can be used as data. + * \ingroup file */ +void imFileSetAttribute(imFile* ifile, const char* attrib, int data_type, int count, const void* data); + +/** Returns an extended attribute. \n + * Returns NULL if not found. data_type and count can be NULL. + * See also \ref imDataType. + * + * \verbatim ifile:GetAttribute(attrib: string, [as_string: boolean]) -> data: table of numbers or string, data_type: number [in Lua 5] \endverbatim + * If data_type is IM_BYTE, as_string can be used to return a string instead of a table. + * \ingroup file */ +const void* imFileGetAttribute(imFile* ifile, const char* attrib, int *data_type, int *count); + +/** Returns a list of the attribute names. \n + * "attrib" must contain room enough for "attrib_count" names. Use "attrib=NULL" to return only the count. + * + * \verbatim ifile:GetAttributeList() -> data: table of strings [in Lua 5] \endverbatim + * \ingroup file */ +void imFileGetAttributeList(imFile* ifile, char** attrib, int *attrib_count); + +/** Returns the pallete if any. \n + * "palette" must be a 256 colors alocated array. \n + * Returns zero in "palette_count" if there is no palette. "palette_count" is >0 and <=256. + * + * \verbatim ifile:GetPalette() -> palette: imPalette [in Lua 5] \endverbatim + * \ingroup file */ +void imFileGetPalette(imFile* ifile, long* palette, int *palette_count); + +/** Changes the pallete. \n + * "palette_count" is >0 and <=256. + * + * \verbatim ifile:SetPalette(palette: imPalette) [in Lua 5] \endverbatim + * \ingroup file */ +void imFileSetPalette(imFile* ifile, long* palette, int palette_count); + +/** Reads the image header if any and returns image information. \n + * Reads also the extended image attributes, so other image attributes will be available only after calling this function. \n + * Returns an error code. + * index specifies the image number between 0 and image_count-1. \n + * Some drivers reads only in sequence, so "index" can be ignored by the format driver. \n + * Any parameters can be NULL. This function must be called at least once, check each format documentation. + * See also \ref imErrorCodes, \ref imDataType, \ref imColorSpace and \ref imColorModeConfig. + * + * \verbatim ifile:ReadImageInfo([index: number]) -> error: number, width: number, height: number, file_color_mode: number, file_data_type: number [in Lua 5] \endverbatim + * Default index is 0. + * \ingroup file */ +int imFileReadImageInfo(imFile* ifile, int index, int *width, int *height, int *file_color_mode, int *file_data_type); + +/** Writes the image header. Writes the file header at the first time it is called. + * Writes also the extended image attributes. \n + * Must call imFileSetPalette and set other attributes before calling this function. \n + * In some formats the color space will be converted to match file format specification. \n + * Returns an error code. This function must be called at least once, check each format documentation. + * See also \ref imErrorCodes, \ref imDataType, \ref imColorSpace and \ref imColorModeConfig. + * + * \verbatim ifile:WriteImageInfo(width: number, height: number, user_color_mode: number, user_data_type: number) -> error: number [in Lua 5] \endverbatim + * \ingroup file */ +int imFileWriteImageInfo(imFile* ifile, int width, int height, int user_color_mode, int user_data_type); + +/** Reads the image data with or without conversion. \n + * The data can be converted to bitmap when reading. + * Data type conversion to byte will always scan for min-max then scale to 0-255, + * except integer values that min-max are already between 0-255. Complex to real conversions will use the magnitude. \n + * Color mode flags contains packed, alpha and top-botttom information. + * If flag is 0 means unpacked, no alpha and bottom up. If flag is -1 the file original flags are used. \n + * Returns an error code. + * See also \ref imErrorCodes, \ref imDataType, \ref imColorSpace and \ref imColorModeConfig. + * + * \verbatim ifile:ReadImageData(data: userdata, convert2bitmap: boolean, color_mode_flags: number) -> error: number [in Lua 5] \endverbatim + * \ingroup file */ +int imFileReadImageData(imFile* ifile, void* data, int convert2bitmap, int color_mode_flags); + +/** Writes the image data. \n + * Returns an error code. + * + * \verbatim ifile:WriteImageData(data: userdata) -> error: number [in Lua 5] \endverbatim + * \ingroup file */ +int imFileWriteImageData(imFile* ifile, void* data); + + + + +/** Registers all the internal formats. \n + * It is automatically called internally when a format is accessed, + * but can be called to force the internal formats to be registered before other formats. + * Notice that additional formats when registered will be registered before the internal formats + * if imFormatRegisterInternal is not called yet. \n + * To control the register order is usefull when two format drivers handle the same format. + * The first registered format will always be used first. + * \ingroup format */ +void imFormatRegisterInternal(void); + +/** Remove all registered formats. + * \ingroup format */ +void imFormatRemoveAll(void); + +/** Returns a list of the registered formats. \n + * format_list is an array of format identifiers. + * Each format identifier is 10 chars max, maximum of 50 formats. + * You can use "char* format_list[50]". + * + * \verbatim im.FormatList() -> format_list: table of strings [in Lua 5] \endverbatim + * \ingroup format */ +void imFormatList(char** format_list, int *format_count); + +/** Returns the format description. \n + * Format description is 50 chars max. \n + * Extensions are separated like "*.tif;*.tiff;", 50 chars max. \n + * Returns an error code. The parameters can be NULL, except format. + * See also \ref format. + * + * \verbatim im.FormatInfo(format: string) -> error: number, desc: string, ext: string, can_sequence: boolean [in Lua 5] \endverbatim + * \ingroup format */ +int imFormatInfo(const char* format, char* desc, char* ext, int *can_sequence); + +/** Returns the format compressions. \n + * Compressions are 20 chars max each, maximum of 50 compressions. You can use "char* comp[50]". \n + * color_mode and data_type are optional, use -1 to ignore them. \n + * If you use them they will select only the allowed compressions checked like in \ref imFormatCanWriteImage. \n + * Returns an error code. + * See also \ref format, \ref imErrorCodes, \ref imDataType, \ref imColorSpace and \ref imColorModeConfig. + * + * \verbatim im.FormatCompressions(format: string, [color_mode: number], [data_type: number]) -> error: number, comp: table of strings [in Lua 5] \endverbatim + * \ingroup format */ +int imFormatCompressions(const char* format, char** comp, int *comp_count, int color_mode, int data_type); + +/** Checks if the format suport the given image class at the given compression. \n + * Returns an error code. + * See also \ref format, \ref imErrorCodes, \ref imDataType, \ref imColorSpace and \ref imColorModeConfig. + * + * \verbatim im.FormatCanWriteImage(format: string, compression: string, color_mode: number, data_type: number) -> can_write: boolean [in Lua 5] \endverbatim + * \ingroup format */ +int imFormatCanWriteImage(const char* format, const char* compression, int color_mode, int data_type); + + +#if defined(__cplusplus) +} +#endif + +#include "old_im.h" + +#endif diff --git a/im/include/im_attrib.h b/im/include/im_attrib.h new file mode 100755 index 0000000..76302ef --- /dev/null +++ b/im/include/im_attrib.h @@ -0,0 +1,120 @@ +/** \file + * \brief Attributes Table. + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_ATTRIB_H_ +#define __IM_ATTRIB_H_ + +#include "im_attrib_flat.h" + +/** \brief Attributes Table. + * + * \par + * All the attributes have a name, a type, a count and the data.\n + * Names are usually strings with less that 30 chars. + * \par + * Attributes are stored in a hash table for fast access. \n + * We use the hash function described in "The Pratice of Programming" of Kernighan & Pike. + * \ingroup util */ +class imAttribTable +{ + imAttribTablePrivate* ptable; +public: + + /** Creates an empty table. + * If size is zero the default size of 101 is used. Size must be a prime number. + * Other common values are 67, 599 and 1499.*/ + imAttribTable(int hash_size) + { ptable = imAttribTableCreate(hash_size); } + + /** Destroys the table and all the attributes. */ + ~imAttribTable() + { imAttribTableDestroy(ptable); ptable = 0; } + + /** Returns the number of elements in the table. */ + int Count() const + { return imAttribTableCount(ptable); } + + /** Removes all the attributes in the table */ + void RemoveAll() + { imAttribTableRemoveAll(ptable); } + + /** Copies the contents of the given table into this table. */ + void CopyFrom(const imAttribTable& table) + { imAttribTableCopyFrom(ptable, table.ptable); } + + /** Inserts an attribute into the table. \n + * If data_type is BYTE then count can be -1 to indicate a NULL terminated string. + * Data is duplicated if not NULL, else data is initialized with zeros. + * See also \ref imDataType. */ + void Set(const char* name, int data_type, int count, const void* data) + { imAttribTableSet(ptable, name, data_type, count, data); } + + /** Removes an attribute from the table given its name. */ + void UnSet(const char *name) + { imAttribTableUnSet(ptable, name); } + + /** Finds an attribute in the table. + * Returns the attribute if found, NULL otherwise. + * See also \ref imDataType. */ + const void* Get(const char *name, int *data_type = 0, int *count = 0) const + { return imAttribTableGet(ptable, name, data_type, count); } + + /** For each attribute calls the user callback. If the callback returns 0 the function returns. */ + void ForEach(void* user_data, imAttribTableCallback attrib_func) const + { imAttribTableForEach(ptable, user_data, attrib_func); } +}; + +/** \brief Attributes Table. + * + * \par + * Same as \ref imAttribTable, but uses an array of fixed size. + * \ingroup util */ +class imAttribArray +{ + imAttribTablePrivate* ptable; +public: + + /** Creates an empty array. */ + imAttribArray(int count) + { ptable = imAttribArrayCreate(count); } + + /** Destroys the array and all the attributes. */ + ~imAttribArray() + { imAttribTableDestroy(ptable); ptable = 0; } + + /** Returns the number of elements in the array. */ + int Count() const + { return imAttribTableCount(ptable); } + + /** Removes all the attributes in the array */ + void RemoveAll() + { imAttribTableRemoveAll(ptable); } + + /** Copies the contents of the given table into this table. */ + void CopyFrom(const imAttribArray& table) + { imAttribArrayCopyFrom(ptable, table.ptable); } + + /** Inserts one attribute into the array. + * The attribute data is a simple array of data_type elements of count length. \n + * Data is duplicated if not NULL, else data is initialized with zeros. + * When NULL is specified use the Get method to retrieve a pointer to the data + * so you can initialize it with other values. + * See also \ref imDataType. */ + void Set(int index, const char* name, int data_type, int count, const void* data) + { imAttribArraySet(ptable, index, name, data_type, count, data); } + + /** Finds one attribute in the array. + * Returns the attribute if found, NULL otherwise. + * See also \ref imDataType. */ + const void* Get(int index, char *name = 0, int *data_type = 0, int *count = 0) const + { return imAttribArrayGet(ptable, index, name, data_type, count); } + + /** For each attribute calls the user callback. If the callback returns 0 the function returns. */ + void ForEach(void* user_data, imAttribTableCallback attrib_func) const + { imAttribTableForEach(ptable, user_data, attrib_func); } +}; + +#endif diff --git a/im/include/im_attrib_flat.h b/im/include/im_attrib_flat.h new file mode 100755 index 0000000..db6c2d8 --- /dev/null +++ b/im/include/im_attrib_flat.h @@ -0,0 +1,39 @@ +/** \file + * \brief Attributes Table Flat API. + * This will simplify the DLL export, and can be used for C aplications. + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_ATTRIB_FLAT_H_ +#define __IM_ATTRIB_FLAT_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +struct imAttribTablePrivate; + +/** Definition of the callback used in ForEach function. */ +typedef int (*imAttribTableCallback)(void* user_data, int index, const char* name, int data_type, int count, const void* data); + +imAttribTablePrivate* imAttribTableCreate(int hash_size); +void imAttribTableDestroy(imAttribTablePrivate* ptable); +int imAttribTableCount(imAttribTablePrivate* ptable); +void imAttribTableRemoveAll(imAttribTablePrivate* ptable); +const void* imAttribTableGet(const imAttribTablePrivate* ptable, const char *name, int *data_type, int *count); +void imAttribTableSet(imAttribTablePrivate* ptable, const char* name, int data_type, int count, const void* data); +void imAttribTableUnSet(imAttribTablePrivate* ptable, const char *name); +void imAttribTableCopyFrom(imAttribTablePrivate* ptable_dst, const imAttribTablePrivate* ptable_src); +void imAttribTableForEach(const imAttribTablePrivate* ptable, void* user_data, imAttribTableCallback attrib_func); + +imAttribTablePrivate* imAttribArrayCreate(int hash_size); +const void* imAttribArrayGet(const imAttribTablePrivate* ptable, int index, char *name, int *data_type, int *count); +void imAttribArraySet(imAttribTablePrivate* ptable, int index, const char* name, int data_type, int count, const void* data); +void imAttribArrayCopyFrom(imAttribTablePrivate* ptable_dst, const imAttribTablePrivate* ptable_src); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/im/include/im_binfile.h b/im/include/im_binfile.h new file mode 100755 index 0000000..08af47a --- /dev/null +++ b/im/include/im_binfile.h @@ -0,0 +1,224 @@ +/** \file + * \brief Binary File Access. + * + * See Copyright Notice in im_lib.h + */ + +#include "im_util.h" + +#ifndef __IM_BINFILE_H +#define __IM_BINFILE_H + +#if defined(__cplusplus) +extern "C" { +#endif + + +/** \defgroup binfile Binary File Access + * + * \par + * These functions are very usefull for reading/writing binary files + * that have headers or data that have to be converted depending on + * the current CPU byte order. It can invert 2, 4 or 8 bytes numbers to/from little/big-endian orders. + * \par + * It will process the data only if the file format is diferent from the current CPU. + * \par + * Can read from disk or memory. In case of a memory buffer, the file name must be the \ref imBinMemoryFileName structure. + * \par + * See \ref im_binfile.h + * \ingroup util */ + +typedef struct _imBinFile imBinFile; + +/** Opens an existant binary file for reading. + * The default file byte order is the CPU byte order. + * Returns NULL if failed. + * \ingroup binfile */ +imBinFile* imBinFileOpen(const char* pFileName); + +/** Creates a new binary file for writing. + * The default file byte order is the CPU byte order. + * Returns NULL if failed. + * \ingroup binfile */ +imBinFile* imBinFileNew(const char* pFileName); + +/** Closes the file. + * \ingroup binfile */ +void imBinFileClose(imBinFile* bfile); + +/** Indicates that was an error on the last operation. + * \ingroup binfile */ +int imBinFileError(imBinFile* bfile); + +/** Returns the file size in bytes. + * \ingroup binfile */ +unsigned long imBinFileSize(imBinFile* bfile); + +/** Changes the file byte order. Returns the old one. + * \ingroup binfile */ +int imBinFileByteOrder(imBinFile* bfile, int pByteOrder); + +/** Reads an array of count values with byte sizes: 1, 2, 4, or 8. And invert the byte order if necessary after read. + * \ingroup binfile */ +unsigned long imBinFileRead(imBinFile* bfile, void* pValues, unsigned long pCount, int pSizeOf); + +/** Writes an array of values with sizes: 1, 2, 4, or 8. And invert the byte order if necessary before write.\n + * ATENTION: The function will not make a temporary copy of the values to invert the byte order.\n + * So after the call the values will be invalid, if the file byte order is diferent from the CPU byte order. + * \ingroup binfile */ +unsigned long imBinFileWrite(imBinFile* bfile, void* pValues, unsigned long pCount, int pSizeOf); + +/** Writes a string without the NULL terminator. The function uses sprintf to compose the string. \n + * The internal buffer is fixed at 4096 bytes. + * \ingroup binfile */ +unsigned long imBinFilePrintf(imBinFile* bfile, char *format, ...); + +/** Reads an integer number from the current position until found a non integer character. + * Returns a non zero value if sucessfull. + * \ingroup binfile */ +int imBinFileReadInteger(imBinFile* handle, int *value); + +/** Reads an floating point number from the current position until found a non number character. + * Returns a non zero value if sucessfull. + * \ingroup binfile */ +int imBinFileReadFloat(imBinFile* handle, float *value); + +/** Moves the file pointer from the begining of the file.\n + * When writing to a file seeking can go beyond the end of the file. + * \ingroup binfile */ +void imBinFileSeekTo(imBinFile* bfile, unsigned long pOffset); + +/** Moves the file pointer from current position.\n + * If the offset is a negative value the pointer moves backwards. + * \ingroup binfile */ +void imBinFileSeekOffset(imBinFile* bfile, long pOffset); + +/** Moves the file pointer from the end of the file.\n + * The offset is usually a negative value. + * \ingroup binfile */ +void imBinFileSeekFrom(imBinFile* bfile, long pOffset); + +/** Returns the current offset position. + * \ingroup binfile */ +unsigned long imBinFileTell(imBinFile* bfile); + +/** Indicates that the file pointer is at the end of the file. + * \ingroup binfile */ +int imBinFileEndOfFile(imBinFile* bfile); + +/** Predefined I/O Modules. + * \ingroup binfile */ +enum imBinFileModule +{ + IM_RAWFILE, /**< System dependent file I/O Rotines. */ + IM_STREAM, /**< Standard Ansi C Stream I/O Rotines. */ + IM_MEMFILE, /**< Uses a memory buffer (see \ref imBinMemoryFileName). */ + IM_SUBFILE, /**< It is a sub file. FileName is a imBinFile* pointer from any other module. */ + IM_FILEHANDLE,/**< System dependent file I/O Rotines, but FileName is a system file handle ("int" in UNIX and "HANDLE" in Windows). */ + IM_IOCUSTOM0 /**< Other registered modules starts from here. */ +}; + +/** Sets the current I/O module. + * \returns the previous function set, or -1 if failed. + * See also \ref imBinFileModule. + * \ingroup binfile */ +int imBinFileSetCurrentModule(int pModule); + +/** \brief Memory File I/O Filename + * + * \par + * Fake file name for the memory I/O module. + * \ingroup binfile */ +typedef struct _imBinMemoryFileName +{ + unsigned char *buffer; /**< The memory buffer. If you are reading the buffer must exists. + * If you are writing the buffer can be internally allocated to the given size. The buffer is never free. + * The buffer is allocated using "malloc", and reallocated using "realloc". Use "free" to release it. + * To avoid RTL conflicts use the function imBinMemoryRelease. */ + int size; /**< Size of the buffer. */ + float reallocate; /**< Reallocate factor for the memory buffer when writing (size += reallocate*size). + * Set reallocate to 0 to disable reallocation, in this case buffer must not be NULL. */ +}imBinMemoryFileName; + +/** Release the internal memory allocated when writing a Memory File (see \ref imBinMemoryFileName). + * \ingroup binfile */ +void imBinMemoryRelease(unsigned char *buffer); + + +#if defined(__cplusplus) +} +#endif + + +#if defined(__cplusplus) + +/** Base class to help the creation of new modules.\n + * It handles the read/write operations with byte order correction if necessary. + * \ingroup binfile */ +class imBinFileBase +{ + friend class imBinSubFile; + +protected: + int IsNew, + FileByteOrder, + DoByteOrder; // to speed up byte order checking + + // These will actually read/write the data + virtual unsigned long ReadBuf(void* pValues, unsigned long pSize) = 0; + virtual unsigned long WriteBuf(void* pValues, unsigned long pSize) = 0; + +public: + + int InitByteOrder(int ByteOrder) + { + int old_byte_order = this->FileByteOrder; + this->FileByteOrder = ByteOrder; + + if (ByteOrder != imBinCPUByteOrder()) + this->DoByteOrder = 1; + else + this->DoByteOrder = 0; + return old_byte_order; + } + + // These will take care of byte swap if needed. + + unsigned long Read(void* pValues, unsigned long pCount, int pSizeOf) + { + unsigned long rSize = ReadBuf(pValues, pCount * pSizeOf); + if (pSizeOf != 1 && DoByteOrder) imBinSwapBytes(pValues, pCount, pSizeOf); + return rSize/pSizeOf; + } + + unsigned long Write(void* pValues, unsigned long pCount, int pSizeOf) + { + if (pSizeOf != 1 && DoByteOrder) imBinSwapBytes(pValues, pCount, pSizeOf); + return WriteBuf(pValues, pCount * pSizeOf)/pSizeOf; + } + + virtual void Open(const char* pFileName) = 0; + virtual void New(const char* pFileName) = 0; + virtual void Close() = 0; + virtual unsigned long FileSize() = 0; + virtual int HasError() const = 0; + virtual void SeekTo(unsigned long pOffset) = 0; + virtual void SeekOffset(long pOffset) = 0; + virtual void SeekFrom(long pOffset) = 0; + virtual unsigned long Tell() const = 0; + virtual int EndOfFile() const = 0; +}; + +/** File I/O module creation callback. + * \ingroup binfile */ +typedef imBinFileBase* (*imBinFileNewFunc)(); + +/** Register a user I/O module.\n + * Returns the new function set id.\n + * Accepts up to 10 modules. + * \ingroup binfile */ +int imBinFileRegisterModule(imBinFileNewFunc pNewFunc); + +#endif + +#endif diff --git a/im/include/im_capture.h b/im/include/im_capture.h new file mode 100755 index 0000000..bc5f732 --- /dev/null +++ b/im/include/im_capture.h @@ -0,0 +1,365 @@ +/** \file + * \brief Video Capture + * + * See Copyright Notice in im.h + */ + +#ifndef __IM_CAPTURE_H +#define __IM_CAPTURE_H + +#if defined(__cplusplus) +extern "C" { +#endif + +/* declarations to create an export library for Watcom. */ +#if ! defined (IM_DECL) + #if defined (__WATCOMC__) + #define IM_DECL __cdecl + #elif defined(__WATCOM_CPLUSPLUS__) + #define IM_DECL __cdecl + #else + #define IM_DECL + #endif +#endif + +/** \defgroup capture Image Capture + * \par + * Functions to capture images from live video devices. + * \par + * See \ref im_capture.h + */ + +typedef struct _imVideoCapture imVideoCapture; + +/** Returns the number of available devices. + * + * \verbatim im.VideoCaptureDeviceCount() -> count: number [in Lua 5] \endverbatim + * \ingroup capture */ +int IM_DECL imVideoCaptureDeviceCount(void); + +/** Returns the device description. Returns NULL only if it is an invalid device. + * + * \verbatim im.VideoCaptureDeviceDesc(device: number) -> desc: string [in Lua 5] \endverbatim + * \ingroup capture */ +const char* IM_DECL imVideoCaptureDeviceDesc(int device); + +/** Returns the extendend device description. May return NULL. + * + * \verbatim im.VideoCaptureDeviceExDesc(device: number) -> desc: string [in Lua 5] \endverbatim + * \ingroup capture */ +const char* IM_DECL imVideoCaptureDeviceExDesc(int device); + +/** Returns the device path configuration. This is a unique string. + * + * \verbatim im.VideoCaptureDevicePath(device: number) -> desc: string [in Lua 5] \endverbatim + * \ingroup capture */ +const char* IM_DECL imVideoCaptureDevicePath(int device); + +/** Returns the vendor information. May return NULL. + * + * \verbatim im.VideoCaptureDeviceVendorInfo(device: number) -> desc: string [in Lua 5] \endverbatim + * \ingroup capture */ +const char* IM_DECL imVideoCaptureDeviceVendorInfo(int device); + +/** Reload the device list. The devices can be dynamically removed or added to the system. + * Returns the number of available devices. + * + * \verbatim im.imVideoCaptureReloadDevices() -> count: number [in Lua 5] \endverbatim + * \ingroup capture */ +int IM_DECL imVideoCaptureReloadDevices(void); + +/** Creates a new imVideoCapture object. \n + * Returns NULL if there is no capture device available. \n + * In Windows returns NULL if DirectX version is older than 8. \n + * In Lua the IM videocapture metatable name is "imVideoCapture". + * When converted to a string will return "imVideoCapture(%p)" where %p is replaced by the userdata address. + * If the videocapture is already destroyed by im.VideoCaptureDestroy, then it will return also the suffix "-destroyed". + * + * \verbatim im.VideoCaptureCreate() -> vc: imVideoCapture [in Lua 5] \endverbatim + * \ingroup capture */ +imVideoCapture* IM_DECL imVideoCaptureCreate(void); + +/** Destroys a imVideoCapture object. \n + * In Lua if this function is not called, the videocapture is destroyed by the garbage collector. + * + * \verbatim im.VideoCaptureDestroy(vc: imVideoCapture) [in Lua 5] \endverbatim + * \verbatim vc:Destroy() [in Lua 5] \endverbatim + * \ingroup capture */ +void IM_DECL imVideoCaptureDestroy(imVideoCapture* vc); + +/** Connects to a capture device. + * More than one imVideoCapture object can be created + * but they must be connected to different devices. \n + * If the object is conected it will disconnect first. \n + * Use -1 to return the current connected device, + * in this case returns -1 if not connected. \n + * Returns zero if failed. + * + * \verbatim vc:Connect([device: number]) -> ret: number [in Lua 5] \endverbatim + * \ingroup capture */ +int IM_DECL imVideoCaptureConnect(imVideoCapture* vc, int device); + +/** Disconnect from a capture device. + * + * \verbatim vc:Disconnect() [in Lua 5] \endverbatim + * \ingroup capture */ +void IM_DECL imVideoCaptureDisconnect(imVideoCapture* vc); + +/** Returns the number of available configuration dialogs. + * + * \verbatim vc:DialogCount() -> count: number [in Lua 5] \endverbatim + * \ingroup capture */ +int IM_DECL imVideoCaptureDialogCount(imVideoCapture* vc); + +/** Displays a configuration modal dialog of the connected device. \n + * In Windows, the capturing will be stopped in some cases. \n + * In Windows parent is a HWND of a parent window, it can be NULL. \n + * dialog can be from 0 to \ref imVideoCaptureDialogCount. \n + * Returns zero if failed. + * + * \verbatim vc:ShowDialog(dialog: number, parent: userdata) -> error: boolean [in Lua 5] \endverbatim + * \ingroup capture */ +int IM_DECL imVideoCaptureShowDialog(imVideoCapture* vc, int dialog, void* parent); + +/** Allows to control the input and output of devices that have multiple input and outputs. + * The cross index controls in which stage the input/output will be set. Usually use 1, but some capture boards + * has a second stage. In Direct X it controls the crossbars. + * + * \verbatim vc:SetInOut(input, output, cross: number) -> error: boolean [in Lua 5] \endverbatim + * \ingroup capture */ +int IM_DECL imVideoCaptureSetInOut(imVideoCapture* vc, int input, int output, int cross); + +/** Returns the description of a configuration dialog. + * dialog can be from 0 to \ref imVideoCaptureDialogCount. \n + * + * \verbatim vc:DialogDesc(dialog: number) -> desc: string [in Lua 5] \endverbatim + * \ingroup capture */ +const char* IM_DECL imVideoCaptureDialogDesc(imVideoCapture* vc, int dialog); + +/** Returns the number of available video formats. \n + * Returns zero if failed. + * + * \verbatim vc:FormatCount() -> count: number [in Lua 5] \endverbatim + * \ingroup capture */ +int IM_DECL imVideoCaptureFormatCount(imVideoCapture* vc); + +/** Returns information about the video format. \n + * format can be from 0 to \ref imVideoCaptureFormatCount. \n + * desc should be of size 10. \n + * The image size is usually the maximum size for that format. + * Other sizes can be available using \ref imVideoCaptureSetImageSize. \n + * Returns zero if failed. + * + * \verbatim vc:GetFormat(format: number) -> error: boolean, width: number, height: number, desc: string [in Lua 5] \endverbatim + * \ingroup capture */ +int IM_DECL imVideoCaptureGetFormat(imVideoCapture* vc, int format, int *width, int *height, char* desc); + +/** Changes the video format of the connected device. \n + * Should NOT work for DV devices. Use \ref imVideoCaptureSetImageSize only. \n + * Use -1 to return the current format, in this case returns -1 if failed. \n + * When the format is changed in the dialog, for some formats + * the returned format is the preferred format, not the current format. \n + * This will not affect color_mode of the capture image. \n + * Returns zero if failed. + * + * \verbatim vc:SetFormat([format: number]) -> error: boolean | format: number [in Lua 5] \endverbatim + * \ingroup capture */ +int IM_DECL imVideoCaptureSetFormat(imVideoCapture* vc, int format); + +/** Returns the current image size of the connected device. \n + * width and height returns 0 if not connected. + * + * \verbatim vc:GetImageSize() -> width: number, height: number [in Lua 5] \endverbatim + * \ingroup capture */ +void IM_DECL imVideoCaptureGetImageSize(imVideoCapture* vc, int *width, int *height); + +/** Changes the image size of the connected device. \n + * Similar to \ref imVideoCaptureSetFormat, but changes only the size. \n + * Valid sizes can be obtained with \ref imVideoCaptureGetFormat. \n + * Returns zero if failed. + * + * \verbatim vc:SetImageSize(width: number, height: number) -> error: boolean [in Lua 5] \endverbatim + * \ingroup capture */ +int IM_DECL imVideoCaptureSetImageSize(imVideoCapture* vc, int width, int height); + +/** Returns a new captured frame. Use -1 for infinite timeout. \n + * Color space can be IM_RGB or IM_GRAY, and mode can be packed (IM_PACKED) or not. \n + * Data type is always IM_BYTE. \n + * It can not have an alpha channel and orientation is always bottom up. \n + * Returns zero if failed or timeout expired, the buffer is not changed. + * + * \verbatim vc:Frame(image: imImage, timeout: number) -> error: boolean [in Lua 5] \endverbatim + * \ingroup capture */ +int IM_DECL imVideoCaptureFrame(imVideoCapture* vc, unsigned char* data, int color_mode, int timeout); + +/** Start capturing, returns the new captured frame and stop capturing. \n + * This is more usefull if you are switching between devices. \n + * Data format is the same as imVideoCaptureFrame. \n + * Returns zero if failed. + * + * \verbatim vc:OneFrame(image: imImage) -> error: boolean [in Lua 5] \endverbatim + * \ingroup capture */ +int IM_DECL imVideoCaptureOneFrame(imVideoCapture* vc, unsigned char* data, int color_mode); + +/** Start capturing. \n + * Use -1 to return the current state. \n + * Returns zero if failed. + * + * \verbatim vc:Live([live: number]) -> error: boolean | live: number [in Lua 5] \endverbatim + * \ingroup capture */ +int IM_DECL imVideoCaptureLive(imVideoCapture* vc, int live); + +/** Resets a camera or video attribute to the default value or + * to the automatic setting. \n + * Not all attributes support automatic modes. \n + * Returns zero if failed. + * + * \verbatim vc:ResetAttribute(attrib: string, fauto: boolean) -> error: boolean [in Lua 5] \endverbatim + * \ingroup capture */ +int IM_DECL imVideoCaptureResetAttribute(imVideoCapture* vc, const char* attrib, int fauto); + +/** Returns a camera or video attribute in percentage of the valid range value. \n + * Returns zero if failed or attribute not supported. + * + * \verbatim vc:GetAttribute(attrib: string) -> error: boolean, percent: number [in Lua 5] \endverbatim + * \ingroup capture */ +int IM_DECL imVideoCaptureGetAttribute(imVideoCapture* vc, const char* attrib, float *percent); + +/** Changes a camera or video attribute in percentage of the valid range value. \n + * Returns zero if failed or attribute not supported. + * + * \verbatim vc:SetAttribute(attrib: string, percent: number) -> error: boolean [in Lua 5] \endverbatim + * \ingroup capture */ +int IM_DECL imVideoCaptureSetAttribute(imVideoCapture* vc, const char* attrib, float percent); + +/** Returns a list of the description of the valid attributes for the device class. \n + * But each device may still not support some of the returned attributes. \n + * Use the return value of \ref imVideoCaptureGetAttribute to check if the attribute is supported. + * + * \verbatim vc:GetAttributeList() -> attrib_list: table of strings [in Lua 5] \endverbatim + * \ingroup capture */ +const char** IM_DECL imVideoCaptureGetAttributeList(imVideoCapture* vc, int *num_attrib); + + +/** \defgroup winattrib Windows Attributes Names + * Not all attributes are supported by each device. + * Use the return value of \ref imVideoCaptureGetAttribute to check if the attribute is supported. +\verbatim + VideoBrightness - Specifies the brightness, also called the black level. + VideoContrast - Specifies the contrast, expressed as gain factor. + VideoHue - Specifies the hue angle. + VideoSaturation - Specifies the saturation. + VideoSharpness - Specifies the sharpness. + VideoGamma - Specifies the gamma. + VideoColorEnable - Specifies the color enable setting. (0/100) + VideoWhiteBalance - Specifies the white balance, as a color temperature in degrees Kelvin. + VideoBacklightCompensation - Specifies the backlight compensation setting. (0/100) + VideoGain - Specifies the gain adjustment. + CameraPanAngle - Specifies the camera's pan angle. To 100 rotate right, To 0 rotate left (view from above). + CameraTiltAngle - Specifies the camera's tilt angle. To 100 rotate up, To 0 rotate down. + CameraRollAngle - Specifies the camera's roll angle. To 100 rotate right, To 0 rotate left. + CameraLensZoom - Specifies the camera's zoom setting. + CameraExposure - Specifies the exposure setting. + CameraIris - Specifies the camera's iris setting. + CameraFocus - Specifies the camera's focus setting, as the distance to the optimally focused target. + FlipHorizontal - Specifies the video will be flipped in the horizontal direction. + FlipVertical - Specifies the video will be flipped in the vertical direction. + AnalogFormat - Specifies the video format standard NTSC, PAL, etc. Valid values: + NTSC_M = 0 + NTSC_M_J = 1 + NTSC_433 = 2 + PAL_B = 3 + PAL_D = 4 + PAL_H = 5 + PAL_I = 6 + PAL_M = 7 + PAL_N = 8 + PAL_60 = 9 + SECAM_B = 10 + SECAM_D = 11 + SECAM_G = 12 + SECAM_H = 13 + SECAM_K = 14 + SECAM_K1 = 15 + SECAM_L = 16 + SECAM_L1 = 17 + PAL_N_COMBO = 18 +\endverbatim + * \ingroup capture */ + + +#if defined(__cplusplus) +} + +/** A C++ Wrapper for the imVideoCapture structure functions. + * \ingroup capture */ +class imCapture +{ +public: + imCapture() + { vc = imVideoCaptureCreate(); } + + ~imCapture() + { if (vc) imVideoCaptureDestroy(vc); } + + int Failed() + { if (!vc) return 0; else return 1; } + + int Connect(int device) + { return imVideoCaptureConnect(vc, device); } + + void Disconnect() + { imVideoCaptureDisconnect(vc); } + + int DialogCount() + { return imVideoCaptureDialogCount(vc); } + + int ShowDialog(int dialog, void* parent) + { return imVideoCaptureShowDialog(vc, dialog, parent); } + + const char* DialogDescription(int dialog) + { return imVideoCaptureDialogDesc(vc, dialog); } + + int FormatCount() + { return imVideoCaptureFormatCount(vc); } + + int GetFormat(int format, int *width, int *height, char* desc) + { return imVideoCaptureGetFormat(vc, format, width, height, desc); } + + int SetFormat(int format) + { return imVideoCaptureSetFormat(vc, format); } + + void GetImageSize(int *width, int *height) + { imVideoCaptureGetImageSize(vc, width, height); } + + int SetImageSize(int width, int height) + { return imVideoCaptureSetImageSize(vc, width, height); } + + int GetFrame(unsigned char* data, int color_mode, int timeout) + { return imVideoCaptureFrame(vc, data, color_mode, timeout); } + + int GetOneFrame(unsigned char* data, int color_mode) + { return imVideoCaptureOneFrame(vc, data, color_mode); } + + int Live(int live) + { return imVideoCaptureLive(vc, live); } + + int ResetAttribute(const char* attrib, int fauto) + { return imVideoCaptureResetAttribute(vc, attrib, fauto); } + + int GetAttribute(const char* attrib, float *percent) + { return imVideoCaptureGetAttribute(vc, attrib, percent); } + + int SetAttribute(const char* attrib, float percent) + { return imVideoCaptureSetAttribute(vc, attrib, percent); } + + const char** GetAttributeList(int *num_attrib) + { return imVideoCaptureGetAttributeList(vc, num_attrib); } + +protected: + imVideoCapture* vc; +}; + +#endif + +#endif diff --git a/im/include/im_color.h b/im/include/im_color.h new file mode 100755 index 0000000..b38b22c --- /dev/null +++ b/im/include/im_color.h @@ -0,0 +1,465 @@ +/** \file + * \brief Color Manipulation + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_COLOR_H +#define __IM_COLOR_H + +#include "im_math.h" + +/** \defgroup color Color Manipulation + * + * \par + * Functions to convert from one color space to another, + * and color gammut utilities. + * \par + * See \ref im_color.h + * + * \section s1 Some Color Science + * \par + * Y is luminance, a linear-light quantity. + * It is directly proportional to physical intensity + * weighted by the spectral sensitivity of human vision. + * \par + * L* is lightness, a nonlinear luminance + * that aproximates the perception of brightness. + * It is nearly perceptual uniform. + * It has a range of 0 to 100. + * \par + * Y' is luma, a nonlinear luminance that aproximates lightness. + * \par + * Brightness is a visual sensation according to which an area + * apears to exhibit more or less light. + * It is a subjective quantity and can not be measured. + * \par + * One unit of euclidian distante in CIE L*u*v* or CIE L*a*b* corresponds + * roughly to a just-noticeable difference (JND) of color. + * \par +\verbatim + ChromaUV = sqrt(u*u + v*v) + HueUV = atan2(v, u) + SaturationUV = ChromaUV / L (called psychometric saturation) + (the same can be calculated for Lab) +\endverbatim + * \par + * IEC 61966-2.1 Default RGB colour space - sRGB + * \li ITU-R Recommendation BT.709 (D65 white point). + * \li D65 White Point (X,Y,Z) = (0.9505 1.0000 1.0890) + * \par + * Documentation extracted from Charles Poynton - Digital Video and HDTV - Morgan Kaufmann - 2003. + * + * \section Links + * \li www.color.org - ICC + * \li www.srgb.com - sRGB + * \li www.poynton.com - Charles Poynton + * \li www.littlecms.com - A free Color Management System (use this if you need precise color conversions) + * + * \section cci Color Component Intervals + * \par + * All the color components are stored in the 0-max interval, even the signed ones. \n + * Here are the pre-defined intervals for each data type. These values are used for standard color conversion. + * You should normalize data before converting betwwen color spaces. + * \par +\verbatim + byte [0,255] or [-128,+127] (1 byte) + ushort [0,65535] or [-32768,+32767] (2 bytes) + int [0,16777215] or [-8388608,+8388607] (3 bytes) + float [0,1] or [-0.5,+0.5] (4 bytes) +\endverbatim + * \ingroup util */ + +/** Returns the zero value for color conversion porpouses. \n + * This is a value to be compensated when the data_type is unsigned and component is signed. \n + * \ingroup color */ +inline float imColorZero(int data_type) +{ + float zero[] = {128.0f, 32768.0f, 8388608.0f, 0.5f}; + return zero[data_type]; +} + +/** Returns the maximum value for color conversion porpouses. \n + * \ingroup color */ +inline int imColorMax(int data_type) +{ + int max[] = {255, 65535, 16777215, 1}; + return max[data_type]; +} + +/** Quantize r=0-1 values into q=0-max. + * max is the maximum value. + * max and the returned value are usually integers, + * but the dummy quantizer uses real values. + * See also \ref math. + * \ingroup color */ +template +inline T imColorQuantize(const float& value, const T& max) +{ + if (max == 1) return (T)value; // to allow a dummy quantizer + if (value >= 1) return max; + if (value <= 0) return 0; + /* return (T)imRound(value*(max + 1) - 0.5f); not necessary since all values are positive */ + return (T)(value*(max + 1)); +} + +/** Reconstruct 0-max values into 0-1. \n + * max is the maximum value. + * max and the given value are usually integers, + * but the dummy reconstructor uses real values. + * See also \ref math. + * \ingroup color */ +template +inline float imColorReconstruct(const T& value, const T& max) +{ + if (max == 1) return (float)value; // to allow a dummy reconstructor + if (value <= 0) return 0; + if (value >= max) return 1; + return (((float)value + 0.5f)/((float)max + 1.0f)); +} + +/** Converts Y'CbCr to R'G'B' (all nonlinear). \n + * ITU-R Recommendation 601-1 with no headroom/footroom. +\verbatim + 0 <= Y <= 1 ; -0.5 <= CbCr <= 0.5 ; 0 <= RGB <= 1 + + R'= Y' + 0.000 *Cb + 1.402 *Cr + G'= Y' - 0.344 *Cb - 0.714 *Cr + B'= Y' + 1.772 *Cb + 0.000 *Cr +\endverbatim + * \ingroup color */ +template +inline void imColorYCbCr2RGB(const T Y, const T Cb, const T Cr, + T& R, T& G, T& B, + const T& zero, const T& max) +{ + float r = float(Y + 1.402f * (Cr - zero)); + float g = float(Y - 0.344f * (Cb - zero) - 0.714f * (Cr - zero)); + float b = float(Y + 1.772f * (Cb - zero)); + + // now we should enforce 0<= rgb <= max + + R = (T)IM_CROPMAX(r, max); + G = (T)IM_CROPMAX(g, max); + B = (T)IM_CROPMAX(b, max); +} + +/** Converts R'G'B' to Y'CbCr (all nonlinear). \n + * ITU-R Recommendation 601-1 with no headroom/footroom. +\verbatim + 0 <= Y <= 1 ; -0.5 <= CbCr <= 0.5 ; 0 <= RGB <= 1 + + Y' = 0.299 *R' + 0.587 *G' + 0.114 *B' + Cb = -0.169 *R' - 0.331 *G' + 0.500 *B' + Cr = 0.500 *R' - 0.419 *G' - 0.081 *B' +\endverbatim + * \ingroup color */ +template +inline void imColorRGB2YCbCr(const T R, const T G, const T B, + T& Y, T& Cb, T& Cr, + const T& zero) +{ + Y = (T)( 0.299f *R + 0.587f *G + 0.114f *B); + Cb = (T)(-0.169f *R - 0.331f *G + 0.500f *B + (float)zero); + Cr = (T)( 0.500f *R - 0.419f *G - 0.081f *B + (float)zero); + + // there is no need for cropping here, YCrCr is already at the limits +} + +/** Converts C'M'Y'K' to R'G'B' (all nonlinear). \n + * This is a poor conversion that works for a simple visualization. +\verbatim + 0 <= CMYK <= 1 ; 0 <= RGB <= 1 + + R = (1 - K) * (1 - C) + G = (1 - K) * (1 - M) + B = (1 - K) * (1 - Y) +\endverbatim + * \ingroup color */ +template +inline void imColorCMYK2RGB(const T C, const T M, const T Y, const T K, + T& R, T& G, T& B, const T& max) +{ + T W = max - K; + R = (T)((W * (max - C)) / max); + G = (T)((W * (max - M)) / max); + B = (T)((W * (max - Y)) / max); + + // there is no need for cropping here, RGB is already at the limits +} + +/** Converts CIE XYZ to Rec 709 RGB (all linear). \n + * ITU-R Recommendation BT.709 (D65 white point). \n +\verbatim + 0 <= XYZ <= 1 ; 0 <= RGB <= 1 + + R = 3.2406 *X - 1.5372 *Y - 0.4986 *Z + G = -0.9689 *X + 1.8758 *Y + 0.0415 *Z + B = 0.0557 *X - 0.2040 *Y + 1.0570 *Z +\endverbatim + * \ingroup color */ +template +inline void imColorXYZ2RGB(const T X, const T Y, const T Z, + T& R, T& G, T& B, const T& max) +{ + float r = 3.2406f *X - 1.5372f *Y - 0.4986f *Z; + float g = -0.9689f *X + 1.8758f *Y + 0.0415f *Z; + float b = 0.0557f *X - 0.2040f *Y + 1.0570f *Z; + + // we need to crop because not all XYZ colors are visible + + R = (T)IM_CROPMAX(r, max); + G = (T)IM_CROPMAX(g, max); + B = (T)IM_CROPMAX(b, max); +} + +/** Converts Rec 709 RGB to CIE XYZ (all linear). \n + * ITU-R Recommendation BT.709 (D65 white point). \n +\verbatim + 0 <= XYZ <= 1 ; 0 <= RGB <= 1 + + X = 0.4124 *R + 0.3576 *G + 0.1805 *B + Y = 0.2126 *R + 0.7152 *G + 0.0722 *B + Z = 0.0193 *R + 0.1192 *G + 0.9505 *B +\endverbatim + * \ingroup color */ +template +inline void imColorRGB2XYZ(const T R, const T G, const T B, + T& X, T& Y, T& Z) +{ + X = (T)(0.4124f *R + 0.3576f *G + 0.1805f *B); + Y = (T)(0.2126f *R + 0.7152f *G + 0.0722f *B); + Z = (T)(0.0193f *R + 0.1192f *G + 0.9505f *B); + + // there is no need for cropping here, XYZ is already at the limits +} + +#define IM_FWLAB(_w) (_w > 0.008856f? \ + powf(_w, 1.0f/3.0f): \ + 7.787f * _w + 0.16f/1.16f) + +/** Converts CIE XYZ (linear) to CIE L*a*b* (nonlinear). \n + * The white point is D65. \n +\verbatim + 0 <= L <= 1 ; -0.5 <= ab <= +0.5 ; 0 <= XYZ <= 1 + + if (t > 0.008856) + f(t) = pow(t, 1/3) + else + f(t) = 7.787*t + 16/116 + + fX = f(X / Xn) fY = f(Y / Yn) fZ = f(Z / Zn) + + L = 1.16 * fY - 0.16 + a = 2.5 * (fX - fY) + b = (fY - fZ) + +\endverbatim + * \ingroup color */ +inline void imColorXYZ2Lab(const float X, const float Y, const float Z, + float& L, float& a, float& b) +{ + float fX = X / 0.9505f; // white point D65 + float fY = Y / 1.0f; + float fZ = Z / 1.0890f; + + fX = IM_FWLAB(fX); + fY = IM_FWLAB(fY); + fZ = IM_FWLAB(fZ); + + L = 1.16f * fY - 0.16f; + a = 2.5f * (fX - fY); + b = (fY - fZ); +} + +#define IM_GWLAB(_w) (_w > 0.20689f? \ + powf(_w, 3.0f): \ + 0.1284f * (_w - 0.16f/1.16f)) + +/** Converts CIE L*a*b* (nonlinear) to CIE XYZ (linear). \n + * The white point is D65. \n + * 0 <= L <= 1 ; -0.5 <= ab <= +0.5 ; 0 <= XYZ <= 1 + * \ingroup color */ +inline void imColorLab2XYZ(const float L, const float a, const float b, + float& X, float& Y, float& Z) + +{ + float fY = (L + 0.16f) / 1.16f; + float gY = IM_GWLAB(fY); + + float fgY = IM_FWLAB(gY); + float gX = fgY + a / 2.5f; + float gZ = fgY - b; + gX = IM_GWLAB(gX); + gZ = IM_GWLAB(gZ); + + X = gX * 0.9505f; // white point D65 + Y = gY * 1.0f; + Z = gZ * 1.0890f; +} + +/** Converts CIE XYZ (linear) to CIE L*u*v* (nonlinear). \n + * The white point is D65. \n +\verbatim + 0 <= L <= 1 ; -1 <= uv <= +1 ; 0 <= XYZ <= 1 + + Y = Y / 1.0 (for D65) + if (Y > 0.008856) + fY = pow(Y, 1/3) + else + fY = 7.787 * Y + 0.16/1.16 + L = 1.16 * fY - 0.16 + + U(x, y, z) = (4 * x)/(x + 15 * y + 3 * z) + V(x, y, z) = (9 * x)/(x + 15 * y + 3 * z) + un = U(Xn, Yn, Zn) = 0.1978 (for D65) + vn = V(Xn, Yn, Zn) = 0.4683 (for D65) + fu = U(X, Y, Z) + fv = V(X, Y, Z) + + u = 13 * L * (fu - un) + v = 13 * L * (fv - vn) +\endverbatim + * \ingroup color */ +inline void imColorXYZ2Luv(const float X, const float Y, const float Z, + float& L, float& u, float& v) +{ + float XYZ = (float)(X + 15 * Y + 3 * Z); + float fY = Y / 1.0f; + + if (XYZ != 0) + { + L = 1.16f * IM_FWLAB(fY) - 0.16f; + u = 6.5f * L * ((4 * X)/XYZ - 0.1978f); + v = 6.5f * L * ((9 * Y)/XYZ - 0.4683f); + } + else + { + L = u = v = 0; + } +} + +/** Converts CIE L*u*v* (nonlinear) to CIE XYZ (linear). \n + * The white point is D65. + * 0 <= L <= 1 ; -0.5 <= uv <= +0.5 ; 0 <= XYZ <= 1 \n + * \ingroup color */ +inline void imColorLuv2XYZ(const float L, const float u, const float v, + float& X, float& Y, float& Z) + +{ + float fY = (L + 0.16f) / 1.16f; + Y = IM_GWLAB(fY) * 1.0f; + + float ul = 0.1978f, vl = 0.4683f; + if (L != 0) + { + ul = u / (6.5f * L) + 0.1978f; + vl = v / (6.5f * L) + 0.4683f; + } + + X = ((9 * ul) / (4 * vl)) * Y; + Z = ((12 - 3 * ul - 20 * vl) / (4 * vl)) * Y; +} + +/** Converts nonlinear values to linear values. \n + * We use the sRGB transfer function. sRGB uses ITU-R 709 primaries and D65 white point. \n +\verbatim + 0 <= l <= 1 ; 0 <= v <= 1 + + if (v < 0.03928) + l = v / 12.92 + else + l = pow((v + 0.055) / 1.055, 2.4) +\endverbatim + * \ingroup color */ +inline float imColorTransfer2Linear(const float& nonlinear_value) +{ + if (nonlinear_value < 0.03928f) + return nonlinear_value / 12.92f; + else + return powf((nonlinear_value + 0.055f) / 1.055f, 2.4f); +} + +/** Converts linear values to nonlinear values. \n + * We use the sRGB transfer function. sRGB uses ITU-R 709 primaries and D65 white point. \n +\verbatim + 0 <= l <= 1 ; 0 <= v <= 1 + + if (l < 0.0031308) + v = 12.92 * l + else + v = 1.055 * pow(l, 1/2.4) - 0.055 +\endverbatim + * \ingroup color */ +inline float imColorTransfer2Nonlinear(const float& value) +{ + if (value < 0.0031308f) + return 12.92f * value; + else + return 1.055f * powf(value, 1.0f/2.4f) - 0.055f; +} + +/** Converts RGB (linear) to R'G'B' (nonlinear). + * \ingroup color */ +inline void imColorRGB2RGBNonlinear(const float RL, const float GL, const float BL, + float& R, float& G, float& B) +{ + R = imColorTransfer2Nonlinear(RL); + G = imColorTransfer2Nonlinear(GL); + B = imColorTransfer2Nonlinear(BL); +} + +/** Converts R'G'B' to Y' (all nonlinear). \n +\verbatim + Y' = 0.299 *R' + 0.587 *G' + 0.114 *B' +\endverbatim + * \ingroup color */ +template +inline T imColorRGB2Luma(const T R, const T G, const T B) +{ + return (T)((299 * R + 587 * G + 114 * B) / 1000); +} + +/** Converts Luminance (CIE Y) to Lightness (CIE L*) (all linear). \n + * The white point is D65. +\verbatim + 0 <= Y <= 1 ; 0 <= L* <= 1 + + Y = Y / 1.0 (for D65) + if (Y > 0.008856) + fY = pow(Y, 1/3) + else + fY = 7.787 * Y + 0.16/1.16 + L = 1.16 * fY - 0.16 +\endverbatim + * \ingroup color */ +inline float imColorLuminance2Lightness(const float& Y) +{ + return 1.16f * IM_FWLAB(Y) - 0.16f; +} + +/** Converts Lightness (CIE L*) to Luminance (CIE Y) (all linear). \n + * The white point is D65. +\verbatim + 0 <= Y <= 1 ; 0 <= L* <= 1 + + fY = (L + 0.16)/1.16 + if (fY > 0.20689) + Y = pow(fY, 3) + else + Y = 0.1284 * (fY - 0.16/1.16) + Y = Y * 1.0 (for D65) +\endverbatim + * \ingroup color */ +inline float imColorLightness2Luminance(const float& L) +{ + float fY = (L + 0.16f) / 1.16f; + return IM_GWLAB(fY); +} + +#undef IM_FWLAB +#undef IM_GWLAB +#undef IM_CROPL +#undef IM_CROPC + +#endif diff --git a/im/include/im_colorhsi.h b/im/include/im_colorhsi.h new file mode 100755 index 0000000..9749002 --- /dev/null +++ b/im/include/im_colorhsi.h @@ -0,0 +1,56 @@ +/** \file + * \brief HSI Color Manipulation + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_COLORHSI_H +#define __IM_COLORHSI_H + +#if defined(__cplusplus) +extern "C" { +#endif + + +/** \defgroup hsi HSI Color Coordinate System Conversions + * + * \par + * HSI is just the RGB color space written in a different coordinate system. + * \par + * "I" is defined along the cube diagonal. It ranges from 0 (black) to 1 (white). \n + * HS are the polar coordinates of a plane normal to "I". \n + * "S" is the normal distance from the diagonal of the RGB cube. It ranges from 0 to 1. \n + * "H" is the angle starting from the red vector, given in degrees. + * \par + * This is not a new color space, this is exactly the same gammut as RGB. \n + * \par + * See \ref im_colorhsi.h + * \ingroup color */ + + +/** Returns I where S is maximum given H (here in radians). + * \ingroup hsi */ +float imColorHSI_ImaxS(float h, double cosh, double sinh); + +/** Converts from RGB to HSI. + * \ingroup hsi */ +void imColorRGB2HSI(float r, float g, float b, float *h, float *s, float *i); + +/** Converts from RGB (byte) to HSI. + * \ingroup hsi */ +void imColorRGB2HSIbyte(unsigned char r, unsigned char g, unsigned char b, float *h, float *s, float *i); + +/** Converts from HSI to RGB. + * \ingroup hsi */ +void imColorHSI2RGB(float h, float s, float i, float *r, float *g, float *b); + +/** Converts from HSI to RGB (byte). + * \ingroup hsi */ +void imColorHSI2RGBbyte(float h, float s, float i, unsigned char *r, unsigned char *g, unsigned char *b); + + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/im/include/im_complex.h b/im/include/im_complex.h new file mode 100755 index 0000000..1328dd5 --- /dev/null +++ b/im/include/im_complex.h @@ -0,0 +1,180 @@ +/** \file + * \brief Complex Data Type. + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_COMPLEX_H +#define __IM_COMPLEX_H + +#include "im_math.h" + +/** \defgroup cpx Complex Numbers + * \par + * See \ref im_complex.h + * \ingroup util + */ + +/** \brief Complex Float Data Type + * + * \par + * Complex class using two floats, one for real part, one for the imaginary part. + * \par + * It is not a complete complex class, we just implement constructors inside the class. + * All the other operators and functions are external to the class. + * \ingroup cpx */ +class imcfloat +{ +public: + float real; ///< Real part. + float imag; ///< Imaginary part. + + /// Default Constructor (0,0). + imcfloat():real(0), imag(0) {} + + /// Constructor from (real, imag) + imcfloat(const float& r, const float& i):real(r),imag(i) {} + + /// Constructor from (real) + imcfloat(const float& r):real(r),imag(0) {} +}; + +/** \addtogroup cpx + * Complex numbers operators. + * @{ + */ + +inline int operator <= (const imcfloat& C1, const imcfloat& C2) +{ + return ((C1.real <= C2.real) && (C1.imag <= C2.imag)); +} + +inline int operator <= (const imcfloat& C, const float& F) +{ + return ((F <= C.real) && (0 <= C.imag)); +} + +inline int operator < (const imcfloat& C1, const imcfloat& C2) +{ + return ((C1.real < C2.real) && (C1.imag < C2.imag)); +} + +inline int operator < (const imcfloat& C, const float& F) +{ + return ((F < C.real) && (0 < C.imag)); +} + +inline int operator > (const imcfloat& C1, const imcfloat& C2) +{ + return ((C1.real > C2.real) && (C1.imag > C2.imag)); +} + +inline int operator > (const imcfloat& C, const float& F) +{ + return ((F > C.real) && (0 > C.imag)); +} + +inline imcfloat operator + (const imcfloat& C1, const imcfloat& C2) +{ + return imcfloat(C1.real + C2.real, C1.imag + C2.imag); +} + +inline imcfloat operator += (const imcfloat& C1, const imcfloat& C2) +{ + return imcfloat(C1.real + C2.real, C1.imag + C2.imag); +} + +inline imcfloat operator - (const imcfloat& C1, const imcfloat& C2) +{ + return imcfloat(C1.real - C2.real, C1.imag - C2.imag); +} + +inline imcfloat operator * (const imcfloat& C1, const imcfloat& C2) +{ + return imcfloat(C1.real * C2.real - C1.imag * C2.imag, + C1.imag * C2.real + C1.real * C2.imag); +} + +inline imcfloat operator / (const imcfloat& C1, const imcfloat& C2) +{ + float den = C2.real * C2.real - C2.imag * C2.imag; + return imcfloat((C1.real * C2.real + C1.imag * C2.imag) / den, + (C1.imag * C2.real - C1.real * C2.imag) / den); +} + +inline imcfloat operator / (const imcfloat& C, const float& R) +{ + return imcfloat(C.real / R, C.imag / R); +} + +inline imcfloat operator /= (const imcfloat& C, const float& R) +{ + return imcfloat(C.real / R, C.imag / R); +} + +inline imcfloat operator * (const imcfloat& C, const float& R) +{ + return imcfloat(C.real * R, C.imag * R); +} + +inline int operator == (const imcfloat& C1, const imcfloat& C2) +{ + return ((C1.real == C2.real) && (C1.imag == C2.imag)); +} + +inline float cpxreal(const imcfloat& C) +{ + return C.real; +} + +inline float cpximag(const imcfloat& C) +{ + return C.imag; +} + +inline float cpxmag(const imcfloat& C) +{ + return sqrtf(C.real*C.real + C.imag*C.imag); +} + +inline float cpxphase(const imcfloat& C) +{ + return atan2f(C.real, C.imag); +} + +inline imcfloat cpxconj(const imcfloat& C) +{ + return imcfloat(C.real, -C.imag); +} + +inline imcfloat log(const imcfloat& C) +{ + return imcfloat(logf(cpxmag(C)), atan2f(C.real, C.imag)); +} + +inline imcfloat exp(const imcfloat& C) +{ + float mag = expf(C.real); + return imcfloat(mag * cosf(C.imag), mag * sinf(C.imag)); +} + +inline imcfloat pow(const imcfloat& C1, const imcfloat& C2) +{ + return exp(C1 * log(C2)); +} + +inline imcfloat sqrt(const imcfloat& C) +{ + float mag = sqrtf(sqrtf(C.real*C.real + C.imag*C.imag)); + float phase = atan2f(C.real, C.imag) / 2; + return imcfloat(mag * cosf(phase), mag * sinf(phase)); +} + +inline imcfloat cpxpolar(const float& mag, const float& phase) +{ + return imcfloat(mag * cosf(phase), mag * sinf(phase)); +} + +/** @} */ + +#endif diff --git a/im/include/im_convert.h b/im/include/im_convert.h new file mode 100755 index 0000000..794eed9 --- /dev/null +++ b/im/include/im_convert.h @@ -0,0 +1,142 @@ +/** \file + * \brief Image Conversion + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_CONVERT_H +#define __IM_CONVERT_H + +#include "im_image.h" + +#if defined(__cplusplus) +extern "C" { +#endif + + +/** \defgroup convert Image Conversion + * \par + * Converts one type of image into another. Can convert between color modes + * and between data types. + * \par + * See \ref im_convert.h + * \ingroup imgclass */ + + +/** Complex to real conversions + * \ingroup convert */ +enum imComplex2Real +{ + IM_CPX_REAL, + IM_CPX_IMAG, + IM_CPX_MAG, + IM_CPX_PHASE +}; + +/** Predefined Gamma factors. Gamma can be any real number. + * When gamma<0 use logarithmic, when gamma>0 use exponential. + * gamma(x,g) = ((e^(g*x))-1)/(exp(g)-1) + * gamma(x,g) = (log((g*x)+1))/(log(g+1)) + * \ingroup convert */ +enum imGammaFactor +{ + IM_GAMMA_LINEAR = 0, + IM_GAMMA_LOGLITE = -10, + IM_GAMMA_LOGHEAVY = -1000, + IM_GAMMA_EXPLITE = 2, + IM_GAMMA_EXPHEAVY = 7 +}; + +/** Predefined Cast Modes + * \ingroup convert */ +enum imCastMode +{ + IM_CAST_MINMAX, /**< scan for min and max values */ + IM_CAST_FIXED, /**< use predefied 0-max values, see \ref color Color Manipulation. */ + IM_CAST_DIRECT /**< direct type cast the value. Only byte and ushort will be cropped. */ +}; + +/** Changes the image data type, using a complex2real conversion, + * a gamma factor, and an abssolute mode (modulus). \n + * When demoting the data type the function will scan for min/max values or use fixed values (cast_mode) + * to scale the result according to the destiny range. \n + * Except complex to real that will use only the complex2real conversion. \n + * Images must be of the same size and color mode. \n + * Returns IM_ERR_NONE, IM_ERR_DATA or IM_ERR_COUNTER, see also \ref imErrorCodes. + * See also \ref imComplex2Real, \ref imGammaFactor and \ref imCastMode. + * + * \verbatim im.ConvertDataType(src_image: imImage, dst_image: imImage, cpx2real: number, gamma: number, abssolute: boolean, cast_mode: number) -> error: number [in Lua 5] \endverbatim + * \verbatim im.ConvertDataTypeNew(image: imImage, data_type: number, cpx2real: number, gamma: number, abssolute: boolean, cast_mode: number) -> error: number, new_image: imImage [in Lua 5] \endverbatim + * \ingroup convert */ +int imConvertDataType(const imImage* src_image, imImage* dst_image, int cpx2real, float gamma, int abssolute, int cast_mode); + +/** Converts one color space to another. Images must be of the same size and data type. \n + * CMYK can be converted to RGB only, and it is a very simple conversion. \n + * All colors can be converted to Binary, the non zero gray values are converted to 1. \n + * RGB to Map uses the median cut implementation from the free IJG JPEG software, copyright Thomas G. Lane. \n + * Alpha channel is considered and Transparency* attributes are converted to alpha channel. \n + * All other color space conversions assume sRGB and CIE definitions. \n + * Returns IM_ERR_NONE, IM_ERR_DATA or IM_ERR_COUNTER, see also \ref imErrorCodes. + * + * \verbatim im.ConvertColorSpace(src_image: imImage, dst_image: imImage) -> error: number [in Lua 5] \endverbatim + * \verbatim im.ConvertColorSpaceNew(image: imImage, color_space: number, has_alpha: boolean) -> error: number, new_image: imImage [in Lua 5] \endverbatim + * \ingroup convert */ +int imConvertColorSpace(const imImage* src_image, imImage* dst_image); + +/** Converts the image to its bitmap equivalent, + * uses \ref imConvertColorSpace and \ref imConvertDataType. \n + * Returns IM_ERR_NONE, IM_ERR_DATA or IM_ERR_COUNTER, see also \ref imErrorCodes. + * See also \ref imComplex2Real, \ref imGammaFactor and \ref imCastMode. \n + * The function im.ConvertToBitmapNew uses the default convertion result from \ref imColorModeToBitmap if color_space is nil. + * + * \verbatim im.ConvertToBitmap(src_image: imImage, dst_image: imImage, cpx2real: number, gamma: number, abssolute: boolean, cast_mode: number) -> error: number [in Lua 5] \endverbatim + * \verbatim im.ConvertToBitmapNew(image: imImage, color_space: number, has_alpha: boolean, cpx2real: number, gamma: number, abssolute: boolean, cast_mode: number) -> error: number, new_image: imImage [in Lua 5] \endverbatim + * \ingroup convert */ +int imConvertToBitmap(const imImage* src_image, imImage* dst_image, int cpx2real, float gamma, int abssolute, int cast_mode); + +/** Returns an OpenGL compatible data buffer. Also returns the correspondant pixel format. \n + * The memory allocated is stored in the attribute "GLDATA" with BYTE type. And it will exists while the image exists. \n + * It can be cleared by setting the attribute to NULL. \n + * MAP images are converted to RGB, and BINARY images are converted to GRAY. + * Alpha channel is considered and Transparency* attributes are converted to alpha channel. + * So calculate depth from glformat, not from image depth. + * + * \verbatim image:GetOpenGLData() -> gldata: userdata, glformat: number [in Lua 5] \endverbatim + * \ingroup convert */ +void* imImageGetOpenGLData(const imImage* image, int *glformat); + + + +/** \defgroup cnvutil Raw Data Conversion Utilities + * \par + * Utilities for raw data buffers. + * \par + * See \ref im_convert.h + * \ingroup imagerep */ + + +/** Changes the packing of the data buffer. Both must have the same depth. + * \ingroup cnvutil */ +void imConvertPacking(const void* src_data, void* dst_data, int width, int height, int depth, int data_type, int src_is_packed); + +/** Changes in-place a MAP data into a RGB data. The data must have room for the RGB image. \n + * depth can be 3 or 4. count=width*height. \n + * \ingroup cnvutil */ +void imConvertMapToRGB(unsigned char* data, int count, int depth, int packed, long* palette, int palette_count); + + + +/* Converts a RGB bitmap into a map bitmap using the median cut algorithm. + * Used only "im_convertcolor.cpp" implemented in "im_rgb2map.cpp". + * Internal function kept here because of the compatibility module. + * Will not be at the documentation. */ +int imConvertRGB2Map(int width, int height, + unsigned char *red, unsigned char *green, unsigned char *blue, + unsigned char *map, long *palette, int *palette_count); + + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/im/include/im_counter.h b/im/include/im_counter.h new file mode 100755 index 0000000..82714f5 --- /dev/null +++ b/im/include/im_counter.h @@ -0,0 +1,69 @@ +/** \file + * \brief Processing Counter + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_COUNTER_H +#define __IM_COUNTER_H + +#if defined(__cplusplus) +extern "C" { +#endif + + +/** \defgroup counter Counter + * \par + * Used to notify the application that a step in the loading, saving or processing operation has been performed. + * \par + * See \ref im_counter.h + * \ingroup util */ + +/** Counter callback, informs the progress of the operation to the client. \n + * Text contains a constant string that is NULL during normal counting, a title in the begining of a sequence + * and a message in the begining of a count. + * Counter id identifies diferrent counters. \n + * Progress in a count reports a value from 0 to 1000. If -1 indicates the start of a sequence of operations, 1001 ends the sequence. \n + * If returns 0 the client should abort the operation. \n + * If the counter is aborted, the callback will be called one last time at 1001. + * \ingroup counter */ +typedef int (*imCounterCallback)(int counter, void* user_data, const char* text, int progress); + +/** Changes the counter callback. Returns old callback. \n + * User data is changed only if not NULL. + * \ingroup counter */ +imCounterCallback imCounterSetCallback(void* user_data, imCounterCallback counter_func); + +/** Begins a new count, or a partial-count in a sequence. \n + * Calls the callback with "-1" and text=title, if it is at the top level. \n + * This is to be used by the operations. Returns a counter Id. + * \ingroup counter */ +int imCounterBegin(const char* title); + +/** Ends a count, or a partial-count in a sequence. \n + * Calls the callback with "1001", text=null, and releases the counter if it is at top level count. \n + * \ingroup counter */ +void imCounterEnd(int counter); + +/** Increments a count. Must set the total first. \n + * Calls the callback, text=message if it is the first increment for the count. \n + * Returns 0 if the callback aborted, 1 if returns normally. + * \ingroup counter */ +int imCounterInc(int counter); + +/** Set a specific count. Must set the total first. \n + * Calls the callback, text=message if it is the first increment for the count. \n + * Returns 0 if the callback aborted, 1 if returns normally. + * \ingroup counter */ +int imCounterIncTo(int counter, int count); + +/** Sets the total increments of a count. + * \ingroup counter */ +void imCounterTotal(int counter, int total, const char* message); + + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/im/include/im_dib.h b/im/include/im_dib.h new file mode 100755 index 0000000..49077b8 --- /dev/null +++ b/im/include/im_dib.h @@ -0,0 +1,195 @@ +/** \file + * \brief Windows DIB (Device Independent Bitmap) + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_DIB_H +#define __IM_DIB_H + +#if defined(__cplusplus) +extern "C" { +#endif + + +/** \defgroup dib Windows DIB + * + * \par + * Windows DIBs in memory are handled just like a BMP file without the file header. \n + * These functions will work only in Windows. They are usefull for interchanging data + * with the clipboard, with capture drivers, with the AVI and WMF file formats and others. + * \par + * Supported DIB aspects: + * \li bpp must be 1, 4, 8, 16, 24, or 32. + * \li BITMAPV4HEADER or BITMAPV5HEADER are handled but ignored. \n + * \li BITMAPCOREHEADER is not handled . + * \li BI_JPEG and BI_PNG compressions are not handled. + * \li biHeight can be negative, compression can be RLE only if created + * from imDibCreateReference, imDibPasteClipboard, imDibLoadFile. + * \li can not encode/decode Images to/from RLE compressed Dibs. + * \li if working with RLE Dibs bits_size is greatter than used. + * \li the resolution of a new Dib is taken from the screen. + * \li SetDIBitsToDevice(start_scan is 0, scan_lines is dib->bmih->biHeight). + * \li StretchDIBits(use always DIB_RGB_COLORS). + * \li CreateDIBPatternBrushPt(packed_dib is dib->dib). + * \par + * Must include before using these functions. \n + * Check for structures and definitions. + * \par + * See \ref im_dib.h + * \ingroup util */ + + +/** \brief Windows DIB Structure + * + * \par + * Handles a DIB in memory. \n + * The DIB is stored in only one buffer. + * The secondary members are pointers to the main buffer. + * \ingroup dib */ +typedef struct _imDib +{ + HGLOBAL handle; /**< The windows memory handle */ + BYTE* dib; /**< The DIB as it is defined in memory */ + int size; /**< Full size in memory */ + + BITMAPINFO* bmi; /**< Bitmap Info = Bitmap Info Header + Palette */ + BITMAPINFOHEADER* bmih; /**< Bitmap Info Header */ + RGBQUAD* bmic; /**< Bitmap Info Colors = Palette */ + BYTE* bits; /**< Bitmap Bits */ + + int palette_count; /**< number of colors in the palette */ + int bits_size; /**< size in bytes of the Bitmap Bits */ + int line_size; /**< size in bytes of one line, includes padding */ + int pad_size; /**< number of bytes remaining in the line, lines are in a word boundary */ + + int is_reference; /**< only a reference, do not free pointer */ +} imDib; + +/** Creates a new DIB. \n + * use bpp=-16/-32 to allocate space for BITFLIEDS. + * \ingroup dib */ +imDib* imDibCreate(int width, int height, int bpp); + +/** Duplicates the DIB contents in a new DIB. + * \ingroup dib */ +imDib* imDibCreateCopy(const imDib* dib); + +/** Creates a DIB using an already allocated memory. \n + * "bmi" must be a pointer to BITMAPINFOHEADER. \n + * "bits" can be NULL if it is inside "bmi" after the palette. + * \ingroup dib */ +imDib* imDibCreateReference(BYTE* bmi, BYTE* bits); + +/** Creates a DIB section for drawing porposes. \n + * Returns the image handle also created. + * \ingroup dib */ +imDib* imDibCreateSection(HDC hDC, HBITMAP *image, int width, int height, int bpp); + +/** Destroy the DIB + * \ingroup dib */ +void imDibDestroy(imDib* dib); + +/** DIB GetPixel function definition. \n + * the DWORD is a raw copy of the bits, use (unsigned char*)&pixel + * \ingroup dib */ +typedef unsigned int (*imDibLineGetPixel)(unsigned char* line, int col); + +/** Returns a function to read pixels from a DIB line. + * \ingroup dib */ +imDibLineGetPixel imDibLineGetPixelFunc(int bpp); + +/** DIB SetPixel function definition + * \ingroup dib */ +typedef void (*imDibLineSetPixel)(unsigned char* line, int col, unsigned int pixel); + +/** Returns a function to write pixels into a DIB line. + * \ingroup dib */ +imDibLineSetPixel imDibLineSetPixelFunc(int bpp); + +/** Creates a DIB from a image handle and a palette handle. + * \ingroup dib */ +imDib* imDibFromHBitmap(const HBITMAP image, const HPALETTE hPalette); + +/** Creates a image handle from a DIB. + * \ingroup dib */ +HBITMAP imDibToHBitmap(const imDib* dib); + +/** Returns a Logical palette from the DIB palette. \n + * DIB bpp must be <=8. + * \ingroup dib */ +HPALETTE imDibLogicalPalette(const imDib* dib); + +/** Captures the screen into a DIB. + * \ingroup dib */ +imDib* imDibCaptureScreen(int x, int y, int width, int height); + +/** Transfer the DIB to the clipboard. \n + * "dib" pointer can not be used after, or use imDibCopyClipboard(imDibCreateCopy(dib)). + * Warning: Clipboard functions in C++ can fail with Visual C++ /EHsc (Enable C++ Exceptions) +* \ingroup dib */ +void imDibCopyClipboard(imDib* dib); + +/** Creates a reference for the DIB in the clipboard if any. Returns NULL otherwise. + * Warning: Clipboard functions in C++ can fail with Visual C++ /EHsc (Enable C++ Exceptions) + * \ingroup dib */ +imDib* imDibPasteClipboard(void); + +/** Checks if there is a dib at the clipboard. + * \ingroup dib */ +int imDibIsClipboardAvailable(void); + +/** Saves the DIB into a file ".bmp". + * \ingroup dib */ +int imDibSaveFile(const imDib* dib, const char* filename); + +/** Creates a DIB from a file ".bmp". + * \ingroup dib */ +imDib* imDibLoadFile(const char* filename); + +/** Converts a DIB into an RGBA image. alpha is optional. bpp must be >8. \n + * alpha is used only when bpp=32. + * \ingroup dib */ +void imDibDecodeToRGBA(const imDib* dib, unsigned char* red, unsigned char* green, unsigned char* blue, unsigned char* alpha); + +/** Converts a DIB into an indexed image. bpp must be <=8. colors must have room for at least 256 colors. + * colors is rgb packed (RGBRGBRGB...) + * \ingroup dib */ +void imDibDecodeToMap(const imDib* dib, unsigned char* map, long* palette); + +/** Converts an RGBA image into a DIB. alpha is optional. bpp must be >8. \n + * alpha is used only when bpp=32. + * \ingroup dib */ +void imDibEncodeFromRGBA(imDib* dib, const unsigned char* red, const unsigned char* green, const unsigned char* blue, const unsigned char* alpha); + +/** Converts an indexed image into a DIB. bpp must be <=8. \n + * colors is rgb packed (RGBRGBRGB...) + * \ingroup dib */ +void imDibEncodeFromMap(imDib* dib, const unsigned char* map, const long* palette, int palette_count); + +/** Converts a IM_RGB packed image, with or without alpha, into a DIB. + * \ingroup dib */ +void imDibEncodeFromBitmap(imDib* dib, const unsigned char* data); + +/** Converts a DIB into IM_RGB packed image, with or without alpha. + * \ingroup dib */ +void imDibDecodeToBitmap(const imDib* dib, unsigned char* data); + +#ifdef __IM_IMAGE_H +/* You must include "im_image.h" before this header to enable these declarations. */ + +/** Creates a imImage from the dib data. + * \ingroup dib */ +imImage* imDibToImage(const imDib* dib); + +/** Creates a Dib from the image. It must be a bitmap image. + * \ingroup dib */ +imDib* imDibFromImage(const imImage* image); + +#endif + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/im/include/im_file.h b/im/include/im_file.h new file mode 100755 index 0000000..58022eb --- /dev/null +++ b/im/include/im_file.h @@ -0,0 +1,115 @@ +/** \file + * \brief File Access + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_FILE_H +#define __IM_FILE_H + +#include "im.h" + +#if defined(__cplusplus) +extern "C" { +#endif + + +/** \defgroup filesdk File Format SDK + * \par + * All the file formats are based on theses structures. Use them to create new file formats. \n + * The LineBuffer functions will help transfer image from format buffer to application buffer and vice-versa. + * \par + * See \ref im_file.h + * \ingroup file */ + + +/** \brief Image File Format Base Class (SDK Use Only) + * + * \par + * Base container to hold format independent state variables. + * \ingroup filesdk */ +struct _imFile +{ + int is_new; + void* attrib_table; /**< in fact is a imAttribTable, but we hide this here */ + + void* line_buffer; /**< used for line convertion, contains all components if packed, or only one if not */ + int line_buffer_size; + int line_buffer_extra; /**< extra bytes to be allocated */ + int line_buffer_alloc; /**< total allocated so far */ + int counter; + + int convert_bpp; /**< number of bpp to unpack/pack to/from 1 byte. + When reading converts n packed bits to 1 byte (unpack). If n>1 will also expand to 0-255. + When writing converts 1 byte to 1 bit (pack). + If negative will only expand to 0-255 (no unpack or pack). */ + int switch_type; /**< flag to switch the original data type: char-byte, short-ushort, uint-int, double-float */ + + long palette[256]; + int palette_count; + + int user_color_mode, + user_data_type, + file_color_mode, /* these two must be filled by te driver always. */ + file_data_type; + + /* these must be filled by the driver when reading, + and given by the user when writing. */ + + char compression[10]; + int image_count, + image_index, + width, + height; +}; + + +/* Internal Use only */ + +/* Initializes the imFile structure. + * Used by the special format RAW. */ +void imFileClear(imFile* ifile); + +/* Initializes the line buffer. + * Used by "im_file.cpp" only. */ +void imFileLineBufferInit(imFile* ifile); + +/* Check if the conversion is valid. + * Used by "im_file.cpp" only. */ +int imFileCheckConversion(imFile* ifile); + + +/* File Format SDK */ + +/** Number of lines to be accessed. + * \ingroup filesdk */ +int imFileLineBufferCount(imFile* ifile); + +/** Increments the row and plane counters. + * \ingroup filesdk */ +void imFileLineBufferInc(imFile* ifile, int *row, int *plane); + +/** Converts from FILE color mode to USER color mode. + * \ingroup filesdk */ +void imFileLineBufferRead(imFile* ifile, void* data, int line, int plane); + +/** Converts from USER color mode to FILE color mode. + * \ingroup filesdk */ +void imFileLineBufferWrite(imFile* ifile, const void* data, int line, int plane); + +/** Utility to calculate the line size in byte with a specified alignment. \n + * "align" can be 1, 2 or 4. + * \ingroup filesdk */ +int imFileLineSizeAligned(int width, int bpp, int align); + +/** Set the attributes FileFormat, FileCompression and FileImageCount. \n + * Used in imFileOpen and imFileOpenAs, and after the attribute list cleared with RemoveAll. + * \ingroup filesdk */ +void imFileSetBaseAttributes(imFile* ifile); + + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/im/include/im_format.h b/im/include/im_format.h new file mode 100755 index 0000000..6ee0473 --- /dev/null +++ b/im/include/im_format.h @@ -0,0 +1,97 @@ +/** \file + * \brief File Format Access + * + * See Copyright Notice in im_lib.h + */ + +#include "im_file.h" +#include "im_attrib.h" + +#ifndef __IM_FORMAT_H +#define __IM_FORMAT_H + + +class imFormat; + +/** \brief Image File Format Virtual Class (SDK Use Only) + * + * \par + * Virtual Base class for file formats. All file formats inherit from this class. + * \ingroup filesdk */ +class imFileFormatBase: public _imFile +{ +public: + const imFormat* iformat; + + imFileFormatBase(const imFormat* _iformat): iformat(_iformat) {} + virtual ~imFileFormatBase() {} + + imAttribTable* AttribTable() {return (imAttribTable*)this->attrib_table;} + + /* Pure Virtual Methods. Every driver must implement all the following methods. */ + + virtual int Open(const char* file_name) = 0; // Must initialize compression and image_count + virtual int New(const char* file_name) = 0; + virtual void Close() = 0; + virtual void* Handle(int index) = 0; + virtual int ReadImageInfo(int index) = 0; // Should update compression + virtual int ReadImageData(void* data) = 0; + virtual int WriteImageInfo() = 0; // Should update compression + virtual int WriteImageData(void* data) = 0; // Must update image_count +}; + +/** \brief Image File Format Descriptor (SDK Use Only) + * + * \par + * All file formats must define these informations. They are stored by \ref imFormatRegister. + * \ingroup filesdk */ +class imFormat +{ +public: + const char* format; + const char* desc; + const char* ext; + const char** comp; + int comp_count, + can_sequence; + + virtual imFileFormatBase* Create() const = 0; + virtual int CanWrite(const char* compression, int color_mode, int data_type) const = 0; + + imFormat(const char* _format, const char* _desc, const char* _ext, + const char** _comp, int _comp_count, int _can_sequence) + :format(_format), desc(_desc), ext(_ext), comp(_comp), + comp_count(_comp_count), can_sequence(_can_sequence) + {} + virtual ~imFormat() {} +}; + +extern "C" +{ + +/* Internal Use only */ + +/* Opens a file with the respective format driver + * Uses the file extension to speed up the search for the format driver. + * Used by "im_file.cpp" only. */ +imFileFormatBase* imFileFormatBaseOpen(const char* file_name, int *error); + +/* Opens a file with the given format + * Used by "im_file.cpp" only. */ +imFileFormatBase* imFileFormatBaseOpenAs(const char* file_name, const char* format, int *error); + +/* Creates a file using the given format driver. + * Used by "im_file.cpp" only. */ +imFileFormatBase* imFileFormatBaseNew(const char* file_name, const char* format, int *error); + + +/* File Format SDK */ + +/** Register a format driver. + * \ingroup filesdk */ +void imFormatRegister(imFormat* iformat); + + +} + +#endif diff --git a/im/include/im_format_all.h b/im/include/im_format_all.h new file mode 100755 index 0000000..8ebe938 --- /dev/null +++ b/im/include/im_format_all.h @@ -0,0 +1,360 @@ +/** \file + * \brief All the Internal File Formats. + * They are all automatically registered by the library. + * The signatures are in C, but the functions are C++. + * Header for internal use only. + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_FORMAT_ALL_H +#define __IM_FORMAT_ALL_H + +#if defined(__cplusplus) +extern "C" { +#endif + +/** \defgroup gif GIF - Graphics Interchange Format + * \section Description + * + * \par + * Copyright (c) 1987,1988,1989,1990 CompuServe Incorporated. \n + * GIF is a Service Mark property of CompuServe Incorporated. \n + * Graphics Interchange Format Programming Reference, 1990. \n + * LZW Copyright Unisys. + * \par + * Patial Internal Implementation. \n + * Decoding and encoding code were extracted from GIFLib 1.0. \n + * Copyright (c) 1989 Gershon Elber. + * + * \section Features + * +\verbatim + Data Types: Byte + Color Spaces: MAP only, (Gray and Binary saved as MAP) + Compressions: + LZW - Lempel-Ziv & Welch [default] + Can have more than one image. + No alpha channel. + Internally the lines are arranged from top down to bottom. + + Attributes: + ScreenHeight, ScreenWidth IM_USHORT (1) screen size [default to the first image size] + Interlaced IM_INT (1 | 0) default 0 + Description (string) + TransparencyIndex IM_BYTE (1) + XScreen, YScreen IM_USHORT (1) screen position + UserInput IM_BYTE (1) [1, 0] + Disposal (string) [UNDEF, LEAVE, RBACK, RPREV] + Delay IM_USHORT (1) [time to wait betweed frames in 1/100 of a second] + Iterations IM_USHORT (1) (NETSCAPE2.0 Application Extension) [The number of times to repeat the animation. 0 means to repeat forever. ] + + Comments: + Attributes after the last image are ignored. + Reads GIF87 and GIF89, but writes GIF89 always. + Ignored attributes: Background Color Index, Pixel Aspect Ratio, + Plain Text Extensions, Application Extensions... +\endverbatim + * \ingroup format */ +void imFormatRegisterGIF(void); + +/** \defgroup bmp BMP - Windows Device Independent Bitmap + * \section Description + * + * \par + * Windows Copyright Microsoft Corporation. + * \par + * Internal Implementation. + * + * \section Features + * +\verbatim + Data Types: Byte + Color Spaces: RGB, MAP and Binary (Gray saved as MAP) + Compressions: + NONE - no compression [default] + RLE - Run Lenght Encoding (only for MAP and Gray) + Only one image. + Can have an alpha channel (only for RGB) + Internally the components are always packed. + Lines arranged from top down to bottom or bottom up to top. But are saved always as bottom up. + + Attributes: + ResolutionUnit (string) ["DPC", "DPI"] + XResolution, YResolution IM_FLOAT (1) + + Comments: + Reads OS2 1.x and Windows 3, but writes Windows 3 always. + Version 4 and 5 BMPs are not supported. +\endverbatim + * \ingroup format */ +void imFormatRegisterBMP(void); + +/** \defgroup ras RAS - Sun Raster File + * \section Description + * + * \par + * Copyright Sun Corporation. + * \par + * Internal Implementation. + * + * \section Features + * +\verbatim + Data Types: Byte + Color Spaces: Gray, RGB, MAP and Binary + Compressions: + NONE - no compression [default] + RLE - Run Lenght Encoding + Only one image. + Can have an alpha channel (only for IM_RGB) + Internally the components are always packed. + Internally the lines are arranged from top down to bottom. + + Attributes: + none +\endverbatim + * \ingroup format */ +void imFormatRegisterRAS(void); + +/** \defgroup led LED - IUP image in LED + * \section Description + * + * \par + * Copyright Tecgraf/PUC-Rio and PETROBRAS/CENPES. + * \par + * Internal Implementation. + * + * \section Features + * +\verbatim + Data Types: Byte + Color Spaces: MAP only (Gray and Binary saved as MAP) + Compressions: + NONE - no compression [default] + Only one image. + No alpha channel. + Internally the lines are arranged from top down to bottom. + + Attributes: + none + + Comments: + LED file must start with "LEDImage = IMAGE[". +\endverbatim + * \ingroup format */ +void imFormatRegisterLED(void); + +/** \defgroup sgi SGI - Silicon Graphics Image File Format + * \section Description + * + * \par + * SGI is a trademark of Silicon Graphics, Inc. + * \par + * Internal Implementation. + * + * \section Features + * +\verbatim + Data Types: Byte and UShort + Color Spaces: Gray and RGB (Binary saved as Gray, MAP with fixed palette when reading only) + Compressions: + NONE - no compression [default] + RLE - Run Lenght Encoding + Only one image. + Can have an alpha channel (only for IM_RGB) + Internally the components are always packed. + Internally the lines are arranged from bottom up to top. + + Attributes: + Description (string) +\endverbatim + * \ingroup format */ +void imFormatRegisterSGI(void); + +/** \defgroup pcx PCX - ZSoft Picture + * \section Description + * + * \par + * Copyright ZSoft Corporation. \n + * ZSoft (1988) PCX Technical Reference Manual. + * \par + * Internal Implementation. + * + * \section Features + * +\verbatim + Data Types: Byte + Color Spaces: RGB, MAP and Binary (Gray saved as MAP) + Compressions: + NONE - no compression + RLE - Run Lenght Encoding [default - since uncompressed PCX is not well supported] + Only one image. + No alpha channel. + Internally the components are always packed. + Internally the lines are arranged from top down to bottom. + + Attributes: + ResolutionUnit (string) ["DPC", "DPI"] + XResolution, YResolution IM_FLOAT (1) + XScreen, YScreen IM_USHORT (1) screen position + + Comments: + Reads Versions 0-5, but writes Version 5 always. +\endverbatim + * \ingroup format */ +void imFormatRegisterPCX(void); + +/** \defgroup tga TGA - Truevision Graphics Adapter File + * \section Description + * + * \par + * Truevision TGA File Format Specification Version 2.0 \n + * Technical Manual Version 2.2 January, 1991 \n + * Copyright 1989, 1990, 1991 Truevision, Inc. + * \par + * Internal Implementation. + * + * \section Features + * +\verbatim + Supports 8 bits per component only. Data type is always Byte. + Color Spaces: Gray, RGB and MAP (Binary saved as Gray) + Compressions: + NONE - no compression [default] + RLE - Run Lenght Encoding + Only one image. + No alpha channel. + Internally the components are always packed. + Internally the lines are arranged from bottom up to top or from top down to bottom. + + Attributes: + XScreen, YScreen IM_USHORT (1) screen position + Title, Author, Description, JobName, Software (string) + SoftwareVersion (read only) (string) + DateTimeModified (string) [when writing uses the current system time] + Gamma IM_FLOAT (1) +\endverbatim + * \ingroup format */ +void imFormatRegisterTGA(void); + +/** \defgroup pnm PNM - Netpbm Portable Image Map + * \section Description + * + * \par + * PNM formats Copyright Jef Poskanzer + * \par + * Internal Implementation. + * + * \section Features + * +\verbatim + Data Types: Byte and UShort + Color Spaces: Gray, RGB and Binary + Compressions: + NONE - no compression [default] + ASCII (textual data) + Can have more than one image, but sequencial access only. + No alpha channel. + Internally the components are always packed. + Internally the lines are arranged from top down to bottom. + + Attributes: + Description (string) + + Comments: + In fact ASCII is an expansion, not a compression, because the file will be larger than binary data. +\endverbatim + * \ingroup format */ +void imFormatRegisterPNM(void); + +/** \defgroup ico ICO - Windows Icon + * \section Description + * + * \par + * Windows Copyright Microsoft Corporation. + * \par + * Internal Implementation. + * + * \section Features + * +\verbatim + Data Types: Byte + Color Spaces: RGB, MAP and Binary (Gray saved as MAP) + Compressions: + NONE - no compression [default] + Can have more than one image. But writing is limited to 5 images, + and all images must have different sizes and bpp. + Can have an alpha channel (only for RGB) + Internally the components are always packed. + Internally the lines are arranged from bottom up to top. + + Attributes: + TransparencyIndex IM_BYTE (1) + + Comments: + If the user specifies an alpha channel, the AND mask is loaded as alpha if + the file color mode does not contain the IM_ALPHA flag. + For MAP imagens, if the user does not specifies an alpha channel + the TransparencyIndex is used to initialize the AND mask when writing, + and if the user does specifies an alpha channel + the most repeated index with transparency will be the transparent index. + Although any size and common bpp can be used is recomended to use the typical configurations: + 16x16, 32x32, 48x48, 64x64 or 96x96 + 2 colors, 16 colors, 256 colors, 24bpp or 32bpp +\endverbatim + * \ingroup format */ +void imFormatRegisterICO(void); + +/** \defgroup krn KRN - IM Kernel File Format + * \section Description + * + * \par + * Textual format to provied a simple way to create kernel convolution images. + * \par + * Internal Implementation. + * + * \section Features + * +\verbatim + Data Types: Byte, Int + Color Spaces: Gray + Compressions: + NONE - no compression [default] + Only one image. + No alpha channel. + Internally the lines are arranged from top down to bottom. + + Attributes: + Description (string) + + Comments: + The format is very simple, inspired by PNM. + It was developed because PNM does not have support for INT and FLOAT. + Remeber that usually convolution operations use kernel size an odd number. + + Format Model: + IMKERNEL + Description up to 512 characters + width height + type (0 - IM_INT, 1 - IM_FLOAT) + data... + + Example: + IMKERNEL + Gradian + 3 3 + 0 + 0 -1 0 + 0 1 0 + 0 0 0 +\endverbatim + * \ingroup format */ +void imFormatRegisterKRN(void); + + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/im/include/im_format_avi.h b/im/include/im_format_avi.h new file mode 100755 index 0000000..535aa37 --- /dev/null +++ b/im/include/im_format_avi.h @@ -0,0 +1,88 @@ +/** \file + * \brief Register the AVI Format + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_FORMAT_AVI_H +#define __IM_FORMAT_AVI_H + +#if defined(__cplusplus) +extern "C" { +#endif + +/** \defgroup avi AVI - Windows Audio-Video Interleaved RIFF + * \section Description + * + * \par + * Windows Copyright Microsoft Corporation. + * \par + * Access to the AVI format uses Windows AVIFile library. Available in Windows Only. \n + * When writing a new file you must use an ".avi" extension, or the Windows API will fail. \n + * You must link the application with "im_avi.lib" + * and you must call the function \ref imFormatRegisterAVI once + * to register the format into the IM core library. + * In Lua call require"imlua_avi". \n + * Depends also on the VFW library (vfw32.lib). + * When using the "im_avi.dll" this extra library is not necessary. \n + * If using Cygwin or MingW must link with "-lvfw32". + * Old versions of Cygwin and MingW use the "-lvfw_ms32" and "-lvfw_avi32". + * \par + * See \ref im_format_avi.h + * + * \section Features + * +\verbatim + Data Types: Byte + Color Spaces: RGB, MAP and Binary (Gray saved as MAP) + Compressions (installed in Windows XP by default): + NONE - no compression [default] + RLE - Microsoft RLE (8bpp only) + CINEPACK - Cinepak Codec by Radius + MSVC - Microsoft Video 1 (old) + M261 - Microsoft H.261 Video Codec + M263 - Microsoft H.263 Video Codec + I420 - Intel 4:2:0 Video Codec (same as M263) + IV32 - Intel Indeo Video Codec 3.2 (old) + IV41 - Intel Indeo Video Codec 4.5 (old) + IV50 - Intel Indeo Video 5.1 + IYUV - Intel IYUV Codec + MPG4 - Microsoft MPEG-4 Video Codec V1 (not MPEG-4 compliant) (old) + MP42 - Microsoft MPEG-4 Video Codec V2 (not MPEG-4 compliant) + CUSTOM - (show compression dialog) + DIVX - DivX 5.0.4 Codec (DivX must be installed) + (others, must be the 4 charaters of the fourfcc code) + Can have more than one image. + Can have an alpha channel (only for RGB) + Internally the components are always packed. + Lines arranged from top down to bottom or bottom up to top. But are saved always as bottom up. + Handle(0) returns NULL. imBinFile is not supported. + Handle(1) returns PAVIFILE. + Handle(2) returns PAVISTREAM. + + Attributes: + FPS IM_FLOAT (1) (should set when writing, default 15) + AVIQuality IM_INT (1) [1-10000, default -1] (write only) [unsed if compression=CUSTOM] + KeyFrameRate IM_INT (1) (write only) [key frame frequency, if 0 not using key frames, default 15, unsed if compression=CUSTOM] + DataRate IM_INT (1) (write only) [kilobits/second, default 2400, unsed if compression=CUSTOM] + + Comments: + Reads only the first video stream. Other streams are ignored. + All the images have the same size, you must call imFileReadImageInfo/imFileWriteImageInfo + at least once. + For codecs comparsion and download go to: + http://graphics.lcs.mit.edu/~tbuehler/video/codecs/ + http://www.fourcc.org +\endverbatim + * \ingroup format */ + +/** Register the AVI Format. \n + * In Lua, when using require"imlua_avi" this function will be automatically called. + * \ingroup avi */ +void imFormatRegisterAVI(void); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/im/include/im_format_ecw.h b/im/include/im_format_ecw.h new file mode 100755 index 0000000..c9e91a3 --- /dev/null +++ b/im/include/im_format_ecw.h @@ -0,0 +1,93 @@ +/** \file + * \brief Register the ECW Format + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_FORMAT_ECW_H +#define __IM_FORMAT_ECW_H + +#if defined(__cplusplus) +extern "C" { +#endif + +/** \defgroup ecw ECW - ECW JPEG 2000 + * \section Description + * + * \par + * ECW JPEG 2000 Copyright 1998 Earth Resource Mapping Ltd. + * Two formats are supported with this module. The ECW (Enhanced Compression Wavelet) format and the ISO JPEG 2000 format. + * \par + * Access to the ECW format uses the ECW JPEG 2000 SDK version 3.3. + * Available in Windows, Linux and Solaris Only. But source code is also available. \n + * You must link the application with "im_ecw.lib" + * and you must call the function \ref imFormatRegisterECW once + * to register the format into the IM core library. \n + * Depends also on the ECW JPEG 2000 SDK libraries (NCSEcw.lib). + * \par + * When using other JPEG 2000 libraries the first registered library will be used to guess the file format. + * Use the extension *.ecw to shortcut to this implementation of the JPEG 2000 format. + * \par + * See \ref im_format_ecw.h + * \par + * \par + * http://www.ermapper.com/ecw/ \n + * The three types of licenses available for the ECW JPEG 2000 SDK are as follows: +\verbatim + - ECW JPEG 2000 SDK Free Use License Agreement - This license governs the free use of + the ECW JPEG 2000 SDK with Unlimited Decompression and Limited Compression (Less + than 500MB). + - ECW JPEG 2000 SDK Public Use License Agreement - This license governs the use of the + ECW SDK with Unlimited Decompression and Unlimited Compression for applications + licensed under a GNU General Public style license. + - ECW JPEG 2000 SDK Commercial Use License Agreement - This license governs the use + of the ECW JPEG 2000 SDK with Unlimited Decompression and Unlimited Compression + for commercial applications. +\endverbatim + * + * \section Features + * +\verbatim + Data Types: Byte, UShort, Float + Color Spaces: BINARY, GRAY, RGB, YCBCR + Compressions: + ECW - Enhanced Compression Wavelet + JPEG-2000 - ISO JPEG 2000 + Only one image. + Can have an alpha channel + Internally the components are always packed. + Lines arranged from top down to bottom. + Handle() returns NCSFileView* when reading, NCSEcwCompressClient* when writing. + + Attributes: + CompressionRatio IM_FLOAT (1) [example: Ratio=7 just like 7:1] + OriginX, OriginY IM_FLOAT (1) + Rotation IM_FLOAT (1) + CellIncrementX, CellIncrementY IM_FLOAT (1) + CellUnits (string) + Datum (string) + Projection (string) + ViewWidth, ViewHeight IM_INT (1) [view zoom] + ViewXmin, ViewYmin, ViewXmax, ViewYmax IM_INT (1) [view limits] + MultiBandCount IM_USHORT (1) [Number of bands in a multiband gray image.] + MultiBandSelect IM_USHORT (1) [Band number to read one band of a multiband gray image. Must be set before reading image info.] + + Comments: + Only read support is implemented. + To read a region of the image you must set the View* attributes before reading the image data. + After reading a partial image the width and height returned in ReadImageInfo is the view size. + The view limits define the region to be read. + The view size is the actual size of the image, so the result can be zoomed. +\endverbatim + * \ingroup format */ + +/** Register the ECW Format + * \ingroup ecw */ +void imFormatRegisterECW(void); + + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/im/include/im_format_jp2.h b/im/include/im_format_jp2.h new file mode 100755 index 0000000..5a8cd73 --- /dev/null +++ b/im/include/im_format_jp2.h @@ -0,0 +1,79 @@ +/** \file + * \brief Register the JP2 Format + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_FORMAT_JP2_H +#define __IM_FORMAT_JP2_H + +#if defined(__cplusplus) +extern "C" { +#endif + + +/** \defgroup jp2 JP2 - JPEG-2000 JP2 File Format + * \section Description + * + * \par + * ISO/IEC 15444 (2000, 2003)\n + * http://www.jpeg.org/ + * \par + * You must link the application with "im_jp2.lib" + * and you must call the function \ref imFormatRegisterJP2 once + * to register the format into the IM core library. + * In Lua call require"imlua_jp2". \n + * \par + * Access to the JPEG2000 file format uses libJasper version 1.900.1 \n + * http://www.ece.uvic.ca/~mdadams/jasper \n + * Copyright (c) 2001-2006 Michael David Adams. \n + * and GeoJasPer 1.4.0 \n + * Copyright (c) 2003-2007 Dmitry V. Fedorov. \n + * http://www.dimin.net/software/geojasper/ \n + * + * \par + * See \ref im_format_jp2.h + * + * \section Features + * +\verbatim + Data Types: Byte and UShort + Color Spaces: Binary, Gray, RGB, YCbCr, Lab and XYZ + Compressions: + JPEG-2000 - ISO JPEG 2000 [default] + Only one image. + Can have an alpha channel. + Internally the components are always unpacked. + Internally the lines are arranged from top down to bottom. + Handle(1) returns jas_image_t* + Handle(2) returns jas_stream_t* + + Attributes: + CompressionRatio IM_FLOAT (1) [write only, example: Ratio=7 just like 7:1] + GeoTIFFBox IM_BYTE (n) + XMLPacket IM_BYTE (n) + + Comments: + We read code stream syntax and JP2, but we write always as JP2. + Used definitions EXCLUDE_JPG_SUPPORT,EXCLUDE_MIF_SUPPORT, + EXCLUDE_PNM_SUPPORT,EXCLUDE_RAS_SUPPORT, + EXCLUDE_BMP_SUPPORT,EXCLUDE_PGX_SUPPORT + Changed jas_config.h to match our needs. + New file jas_binfile.c + Changed base/jas_stream.c to export jas_stream_create and jas_stream_initbuf. + Changed jp2/jp2_dec.c and jpc/jpc_cs.c to remove "uint" and "ulong" usage. + The counter is restarted many times, because it has many phases. +\endverbatim + * \ingroup format */ + +/** Register the JP2 Format. \n + * In Lua, when using require"imlua_jp2" this function will be automatically called. + * \ingroup jp2 */ +void imFormatRegisterJP2(void); + + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/im/include/im_format_raw.h b/im/include/im_format_raw.h new file mode 100755 index 0000000..4600271 --- /dev/null +++ b/im/include/im_format_raw.h @@ -0,0 +1,74 @@ +/** \file + * \brief Initialize the RAW Format Driver + * Header for internal use only. + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_FORMAT_RAW_H +#define __IM_FORMAT_RAW_H + +#if defined(__cplusplus) +extern "C" { +#endif + +/** \defgroup raw RAW - RAW File + * + * \par + * The file must be open/created with the functions \ref imFileOpenRaw and \ref imFileNewRaw. + * + * \section Description + * + * \par + * Internal Implementation. + * \par + * Supports RAW binary images. This is an unstructured and uncompressed binary data. + * It is NOT a Camera RAW file generated in many professional digital cameras. \n + * You must know image parameters a priori and must set the IM_INT attributes "Width", "Height", "ColorMode", "DataType" + * before the imFileReadImageInfo/imFileWriteImageInfo functions. + * \par + * The data must be in binary form, but can start in an arbitrary offset from the begining of the file, use attribute "StartOffset". + * The default is at 0 offset. + * \par + * Integer sign and double precision can be converted using attribute "SwitchType". \n + * The conversions will be BYTE<->CHAR, USHORT<->SHORT, INT<->UINT, FLOAT<->DOUBLE. + * \par + * Byte Order can be Little Endian (Intel=1) or Big Endian (Motorola=0), use the attribute "ByteOrder", the default is the current CPU. + * \par + * The lines can be aligned to a BYTE (1), WORD (2) or DWORD (4) boundaries, ue attribute "Padding" with the respective value. + * \par + * If the compression is ASCII the data is stored in textual format, instead of binary. + * In this case SwitchType and ByteOrder are ignored, and Padding should be 0. + * \par + * See \ref im_raw.h + * + * \section Features + * +\verbatim + Data Types: + Color Spaces: all, except MAP. + Compressions: + NONE - no compression [default] + ASCII (textual data) + Can have more than one image, depends on "StartOffset" attribute. + Can have an alpha channel. + Components can be packed or not. + Lines arranged from top down to bottom or bottom up to top. + + Attributes: + Width, Height, ColorMode, DataType IM_INT (1) + ImageCount[1], StartOffset[0], SwitchType[FALSE], ByteOrder[IM_LITTLEENDIAN], Padding[0] IM_INT (1) + + Comments: + In fact ASCII is an expansion, not a compression, because the file will be larger than binary data. +\endverbatim + * \ingroup format */ +imFormat* imFormatInitRAW(void); + +void imFormatFinishRAW(void); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/im/include/im_format_wmv.h b/im/include/im_format_wmv.h new file mode 100755 index 0000000..b60d4c4 --- /dev/null +++ b/im/include/im_format_wmv.h @@ -0,0 +1,101 @@ +/** \file + * \brief Register the WMF Format + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_FORMAT_WMV_H +#define __IM_FORMAT_WMV_H + +#if defined(__cplusplus) +extern "C" { +#endif + +/** \defgroup wmv WMV - Windows Media Video Format + * \section Description + * + * \par + * Advanced Systems Format (ASF) \n + * Windows Copyright Microsoft Corporation. + * \par + * Access to the WMV format uses Windows Media SDK. Available in Windows Only. \n + * You must link the application with "im_wmv.lib" + * and you must call the function \ref imFormatRegisterWMV once + * to register the format into the IM core library. + * In Lua call require"imlua_wmv". \n + * Depends also on the WMF SDK (wmvcore.lib). + * When using the "im_wmv.dll" this extra library is not necessary. + * \par + * The application users should have the WMV codec 9 installed: + * http://www.microsoft.com/windows/windowsmedia/format/codecdownload.aspx + * \par + * You must agree with the WMF SDK EULA to use the SDK. \n + * http://wmlicense.smdisp.net/v9sdk/ + * \par + * For more information: \n + * http://www.microsoft.com/windows/windowsmedia/9series/sdk.aspx \n + * http://msdn.microsoft.com/library/en-us/wmform/htm/introducingwindowsmediaformat.asp + * \par + * See \ref im_format_wmv.h + * + * \section Features + * +\verbatim + Data Types: Byte + Color Spaces: RGB and MAP (Gray and Binary saved as MAP) + Compressions (installed in Windows XP by default): + NONE - no compression + MPEG-4v3 - Windows Media MPEG-4 Video V3 + MPEG-4v1 - ISO MPEG-4 Video V1 + WMV7 - Windows Media Video V7 + WMV7Screen - Windows Media Screen V7 + WMV8 - Windows Media Video V8 + WMV9Screen - Windows Media Video 9 Screen + WMV9 - Windows Media Video 9 [default] + Unknown - Others + Can have more than one image. + Can have an alpha channel (only for RGB) ? + Internally the components are always packed. + Lines arranged from top down to bottom or bottom up to top. + Handle(0) return NULL. imBinFile is not supported. + Handle(1) returns IWMSyncReader* when reading, IWMWriter* when writing. + + Attributes: + FPS IM_FLOAT (1) (should set when writing, default 15) + WMFQuality IM_INT (1) [0-100, default 50] (write only) + MaxKeyFrameTime IM_INT (1) (write only) [maximum key frame interval in miliseconds, default 5 seconds] + DataRate IM_INT (1) (write only) [kilobits/second, default 2400] + VBR IM_INT (1) [0, 1] (write only) [0 - Constant Bit Rate (default), 1 - Variable Bit Rate (Quality-Based)] + (and several others from the file-level attributes) For ex: + Title, Author, Copyright, Description (string) + Duration IM_INT [100-nanosecond units] + Seekable, HasAudio, HasVideo, Is_Protected, Is_Trusted, IsVBR IM_INT (1) [0, 1] + NumberOfFrames IM_INT (1) + + Comments: + IMPORTANT - The "image_count" and the "FPS" attribute may not be available from the file, + we try to estimate from the duration and from the average time between frames, or using the default value. + We do not handle DRM protected files (Digital Rights Management). + Reads only the first video stream. Other streams are ignored. + All the images have the same size, you must call imFileReadImageInfo/imFileWriteImageInfo + at least once. + For optimal random reading, the file should be indexed previously. + If not indexed by frame, random positioning may not be precise. + Sequencial reading will always be precise. + When writing we use a custom profile and time indexing only. + We do not support multipass encoding. + Since the driver uses COM, CoInitialize(NULL) and CoUninitialize() are called every Open/Close. +\endverbatim + * \ingroup format */ + +/** Register the WMF Format. \n + * In Lua, when using require"imlua_wmv" this function will be automatically called. + * \ingroup wmv */ +void imFormatRegisterWMV(void); + + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/im/include/im_image.h b/im/include/im_image.h new file mode 100755 index 0000000..12dbad8 --- /dev/null +++ b/im/include/im_image.h @@ -0,0 +1,411 @@ +/** \file + * \brief Image Manipulation + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_IMAGE_H +#define __IM_IMAGE_H + +#if defined(__cplusplus) +extern "C" { +#endif + + +/** \defgroup imgclass imImage + * + * \par + * Base definitions and functions for image representation. \n + * Only the image processing operations depends on these definitions, + * Image Storage and Image Capture are completely independent. + * \par + * You can also initialize a structure with your own memory buffer, see \ref imImageInit. + * To release the structure without releasing the buffer, + * set "data[0]" to NULL before calling imImageDestroy. + * \par + * See \ref im_image.h + * \ingroup imagerep */ + + + +/** \brief imImage Structure Definition. + * + * \par + * An image representation than supports all the color spaces, + * but planes are always unpacked and the orientation is always bottom up. + * \ingroup imgclass */ +typedef struct _imImage +{ + /* main parameters */ + int width; /**< Number of columns. image:Width() -> width: number [in Lua 5]. */ + int height; /**< Number of lines. image:Height() -> height: number [in Lua 5]. */ + int color_space; /**< Color space descriptor. See also \ref imColorSpace. image:ColorSpace() -> color_space: number [in Lua 5]. */ + int data_type; /**< Data type descriptor. See also \ref imDataType. image:DataType() -> data_type: number [in Lua 5]. */ + int has_alpha; /**< Indicates that there is an extra channel with alpha. image:HasAlpha() -> has_alpha: number [in Lua 5]. \n + It will not affect the secondary parameters, i.e. the number of planes will be in fact depth+1. \n + It is always 0 unless imImageAddAlpha is called, this is done in image load functions. */ + + /* secondary parameters */ + int depth; /**< Number of planes (ColorSpaceDepth) */ + int line_size; /**< Number of bytes per line in one plane (width * DataTypeSize) */ + int plane_size; /**< Number of bytes per plane. (line_size * height) */ + int size; /**< Number of bytes occupied by the image (plane_size * depth) */ + int count; /**< Number of pixels (width * height) */ + + /* image data */ + void** data; /**< Image data organized as a 2D matrix with several planes. \n + But plane 0 is also a pointer to the full data. \n + The remaining planes are: data[i] = data[0] + i*plane_size \n + In Lua, data indexing is possible using: image[plane][row][column] */ + + /* image attributes */ + long *palette; /**< Color palette. image:GetPalette() -> palette: imPalette [in Lua 5]. \n + Used when depth=1. Otherwise is NULL. */ + int palette_count; /**< The palette is always 256 colors allocated, but can have less colors used. */ + + void* attrib_table; /**< in fact is an imAttribTable, but we hide this here */ +} imImage; + + +/** Creates a new image. + * See also \ref imDataType and \ref imColorSpace. Image data is cleared as \ref imImageClear. \n + * In Lua the IM image metatable name is "imImage". + * When converted to a string will return "imImage(%p) [width=%d,height=%d,color_space=%s,data_type=%s,depth=%d]" where %p is replaced by the userdata address, + * and other values are replaced by the respective attributes. + * If the image is already destroyed by im.ImageDestroy, then it will return also the suffix "-destroyed". + * + * \verbatim im.ImageCreate(width: number, height: number, color_space: number, data_type: number) -> image: imImage [in Lua 5] \endverbatim + * \ingroup imgclass */ +imImage* imImageCreate(int width, int height, int color_space, int data_type); + +/** Initializes the image structure but does not allocates image data. + * See also \ref imDataType and \ref imColorSpace. + * \ingroup imgclass */ +imImage* imImageInit(int width, int height, int color_space, int data_type, void* data_buffer, long* palette, int palette_count); + +/** Creates a new image based on an existing one. \n + * If the addicional parameters are -1, the given image parameters are used. \n + * The image atributes always are copied. HasAlpha is copied. + * See also \ref imDataType and \ref imColorSpace. + * + * \verbatim im.ImageCreateBased(image: imImage, [width: number], [height: number], [color_space: number], [data_type: number]) -> image: imImage [in Lua 5] \endverbatim + * The addicional parameters in Lua can be nil, + * and they can also be functions with the based image as a parameter to return the respective value. + * \ingroup imgclass */ +imImage* imImageCreateBased(const imImage* image, int width, int height, int color_space, int data_type); + +/** Destroys the image and frees the memory used. + * image data is destroyed only if its data[0] is not NULL. \n + * In Lua if this function is not called, the image is destroyed by the garbage collector. + * + * \verbatim im.ImageDestroy(image: imImage) [in Lua 5] \endverbatim + * \verbatim image:Destroy() [in Lua 5] \endverbatim + * \ingroup imgclass */ +void imImageDestroy(imImage* image); + +/** Adds an alpha channel plane. + * + * \verbatim image:AddAlpha() [in Lua 5] \endverbatim + * \ingroup imgclass */ +void imImageAddAlpha(imImage* image); + +/** Changes the buffer size. Reallocate internal buffers if the new size is larger than the original. + * + * \verbatim image:Reshape(width: number, height: number) [in Lua 5] \endverbatim + * \ingroup imgclass */ +void imImageReshape(imImage* image, int width, int height); + +/** Copy image data and attributes from one image to another. \n + * Images must have the same size and type. + * + * \verbatim image:Copy(dst_image: imImage) [in Lua 5] \endverbatim + * \ingroup imgclass */ +void imImageCopy(const imImage* src_image, imImage* dst_image); + +/** Copy image data only fom one image to another. \n + * Images must have the same size and type. + * + * \verbatim image:CopyData(dst_image: imImage) [in Lua 5] \endverbatim + * \ingroup imgclass */ +void imImageCopyData(const imImage* src_image, imImage* dst_image); + +/** Creates a copy of the image. + * + * \verbatim image:Duplicate() -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup imgclass */ +imImage* imImageDuplicate(const imImage* image); + +/** Creates a clone of the image. i.e. same attributes but ignore contents. + * + * \verbatim image:Clone() -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup imgclass */ +imImage* imImageClone(const imImage* image); + +/** Changes an extended attribute. \n + * The data will be internally duplicated. \n + * If data is NULL and count==0 the attribute is removed. \n + * If count is -1 and data_type is IM_BYTE then data is zero terminated. + * See also \ref imDataType. + * + * \verbatim image:SetAttribute(attrib: string, data_type: number, data: table of numbers or string) [in Lua 5] \endverbatim + * If data_type is IM_BYTE, as_string can be used as data. + * \ingroup imgclass */ +void imImageSetAttribute(const imImage* image, const char* attrib, int data_type, int count, const void* data); + +/** Returns an extended attribute. \n + * Returns NULL if not found. + * See also \ref imDataType. + * + * \verbatim image:GetAttribute(attrib: string, [as_string: boolean]) -> data: table of numbers or string, data_type: number [in Lua 5] \endverbatim + * If data_type is IM_BYTE, as_string can be used to return a string instead of a table. + * \ingroup imgclass */ +const void* imImageGetAttribute(const imImage* image, const char* attrib, int *data_type, int *count); + +/** Returns a list of the attribute names. \n + * "attrib" must contain room enough for "attrib_count" names. Use "attrib=NULL" to return only the count. + * + * \verbatim image:GetAttributeList() -> data: table of strings [in Lua 5] \endverbatim + * \ingroup imgclass */ +void imImageGetAttributeList(const imImage* image, char** attrib, int *attrib_count); + +/** Sets all image data to zero. But if color space is YCBCR, LAB or LUV, and data type is BYTE or USHORT, then + * data is initialized with 128 or 32768 accordingly. Alpha is initialized as transparent (0). + * + * \verbatim image:Clear() [in Lua 5] \endverbatim + * \ingroup imgclass */ +void imImageClear(imImage* image); + +/** Indicates that the image can be viewed in common graphic devices. + * Data type must be IM_BYTE. Color mode can be IM_RGB, IM_MAP, IM_GRAY or IM_BINARY. + * + * \verbatim image:IsBitmap() -> is_bitmap: boolean [in Lua 5] \endverbatim + * \ingroup imgclass */ +int imImageIsBitmap(const imImage* image); + +/** Changes the image palette. + * This will destroy the existing palette and replace it with the given palette pointer. + * Only the pointer is stored, so the palette should be a new palette and it can not be a static array. + * + * \verbatim image:SetPalette(palette: imPalette) [in Lua 5] \endverbatim + * \ingroup imgclass */ +void imImageSetPalette(imImage* image, long* palette, int palette_count); + +/** Copies the image attributes from src to dst. + * + * \verbatim image:CopyAttributes(dst_image: imImage) [in Lua 5] \endverbatim + * \ingroup imgclass */ +void imImageCopyAttributes(const imImage* src_image, imImage* dst_image); + +/** Returns 1 if the images match width and height. Returns 0 otherwise. + * + * \verbatim image:MatchSize(image2: imImage) -> match: boolean [in Lua 5] \endverbatim + * \ingroup imgclass */ +int imImageMatchSize(const imImage* image1, const imImage* image2); + +/** Returns 1 if the images match color mode and data type. Returns 0 otherwise. + * + * \verbatim image:MatchColor(image2: imImage) -> match: boolean [in Lua 5] \endverbatim + * \ingroup imgclass */ +int imImageMatchColor(const imImage* image1, const imImage* image2); + +/** Returns 1 if the images match width, height and data type. Returns 0 otherwise. + * + * \verbatim image:MatchDataType(image2: imImage) -> match: boolean [in Lua 5] \endverbatim + * \ingroup imgclass */ +int imImageMatchDataType(const imImage* image1, const imImage* image2); + +/** Returns 1 if the images match width, height and color space. Returns 0 otherwise. + * + * \verbatim image:MatchColorSpace(image2: imImage) -> match: boolean [in Lua 5] \endverbatim + * \ingroup imgclass */ +int imImageMatchColorSpace(const imImage* image1, const imImage* image2); + +/** Returns 1 if the images match in width, height, data type and color space. Returns 0 otherwise. + * + * \verbatim image:Match(image2: imImage) -> match: boolean [in Lua 5] \endverbatim + * \ingroup imgclass */ +int imImageMatch(const imImage* image1, const imImage* image2); + +/** Changes the image color space from gray to binary by just changing color_space and the palette. + * + * \verbatim image:SetBinary() [in Lua 5] \endverbatim + * \ingroup imgclass */ +void imImageSetBinary(imImage* image); + +/** Changes a gray BYTE data (0,255) into a binary data (0,1), done in-place. Color space is not changed. + * + * \verbatim image:MakeBinary() [in Lua 5] \endverbatim + * \ingroup imgclass */ +void imImageMakeBinary(imImage *image); + +/** Changes a binary data (0,1) into a gray BYTE data (0,255), done in-place. Color space is not changed. + * + * \verbatim image:MakeGray() [in Lua 5] \endverbatim + * \ingroup imgclass */ +void imImageMakeGray(imImage *image); + + + +/** \defgroup imgfile imImage Storage + * + * \par + * Functions to simplify the process of reading and writting imImage structures. + * Will also load and save the alpha planes when possible. + * \par + * See \ref im_image.h + * \ingroup file */ + + +/** Loads an image from an already open file. Returns NULL if failed. \n + * This will call \ref imFileReadImageInfo and \ref imFileReadImageData. \n + * index specifies the image number between 0 and image_count-1. \n + * The returned image will be of the same color_space and data_type of the image in the file. \n + * Attributes from the file will be stored at the image. + * See also \ref imErrorCodes. + * + * \verbatim ifile:LoadImage([index: number]) -> image: imImage, error: number [in Lua 5] \endverbatim + * Default index is 0. + * \ingroup imgfile */ +imImage* imFileLoadImage(imFile* ifile, int index, int *error); + +/** Loads an image from an already open file. Returns NULL if failed. \n + * This function assumes that the image in the file has the same parameters as the given image. \n + * This will call \ref imFileReadImageInfo and \ref imFileReadImageData. \n + * index specifies the image number between 0 and image_count-1. \n + * The returned image will be of the same color_space and data_type of the image in the file. \n + * Attributes from the file will be stored at the image. + * See also \ref imErrorCodes. + * + * \verbatim ifile:LoadImageFrame(index: number, image: imImage) -> error: number [in Lua 5] \endverbatim + * Default index is 0. + * \ingroup imgfile */ +void imFileLoadImageFrame(imFile* ifile, int index, imImage* image, int *error); + +/** Loads an image from an already open file, but forces the image to be a bitmap.\n + * The returned imagem will be always a Bitmap image, with color_space RGB, MAP, GRAY or BINARY, and data_type IM_BYTE. \n + * index specifies the image number between 0 and image_count-1. \n + * Returns NULL if failed. + * Attributes from the file will be stored at the image. + * See also \ref imErrorCodes. + * + * \verbatim ifile:LoadBitmap([index: number]) -> image: imImage, error: number [in Lua 5] \endverbatim + * Default index is 0. + * \ingroup imgfile */ +imImage* imFileLoadBitmap(imFile* ifile, int index, int *error); + +/** Loads an image region from an already open file. Returns NULL if failed. \n + * This will call \ref imFileReadImageInfo and \ref imFileReadImageData. \n + * index specifies the image number between 0 and image_count-1. \n + * The returned image will be of the same color_space and data_type of the image in the file, + * or will be a Bitmap image. \n + * Attributes from the file will be stored at the image. + * See also \ref imErrorCodes. \n + * For now, it works only for the ECW file format. + * + * \verbatim ifile:LoadRegion(index, bitmap, xmin, xmax, ymin, ymax, width, height: number) -> image: imImage, error: number [in Lua 5] \endverbatim + * Default index is 0. + * \ingroup imgfile */ +imImage* imFileLoadImageRegion(imFile* ifile, int index, int bitmap, int *error, + int xmin, int xmax, int ymin, int ymax, int width, int height); + +/** Loads an image from an already open file, but forces the image to be a bitmap.\n + * This function assumes that the image in the file has the same parameters as the given image. \n + * The imagem must be a Bitmap image, with color_space RGB, MAP, GRAY or BINARY, and data_type IM_BYTE. \n + * index specifies the image number between 0 and image_count-1. \n + * Returns NULL if failed. + * Attributes from the file will be stored at the image. + * See also \ref imErrorCodes. + * + * \verbatim ifile:LoadBitmapFrame(index: number, image: imImage) -> error: number [in Lua 5] \endverbatim + * Default index is 0. + * \ingroup imgfile */ +void imFileLoadBitmapFrame(imFile* ifile, int index, imImage* image, int *error); + +/** Saves the image to an already open file. \n + * This will call \ref imFileWriteImageInfo and \ref imFileWriteImageData. \n + * Attributes from the image will be stored at the file. + * Returns error code. + * + * \verbatim ifile:SaveImage(image: imImage) -> error: number [in Lua 5] \endverbatim + * \ingroup imgfile */ +int imFileSaveImage(imFile* ifile, const imImage* image); + +/** Loads an image from file. Open, loads and closes the file. \n + * index specifies the image number between 0 and image_count-1. \n + * Returns NULL if failed. + * Attributes from the file will be stored at the image. + * See also \ref imErrorCodes. + * + * \verbatim im.FileImageLoad(file_name: string, [index: number]) -> image: imImage, error: number [in Lua 5] \endverbatim + * Default index is 0. + * \ingroup imgfile */ +imImage* imFileImageLoad(const char* file_name, int index, int *error); + +/** Loads an image from file, but forces the image to be a bitmap. Open, loads and closes the file. \n + * index specifies the image number between 0 and image_count-1. \n + * Returns NULL if failed. + * Attributes from the file will be stored at the image. + * See also \ref imErrorCodes. + * + * \verbatim im.FileImageLoadBitmap(file_name: string, [index: number]) -> image: imImage, error: number [in Lua 5] \endverbatim + * Default index is 0. + * \ingroup imgfile */ +imImage* imFileImageLoadBitmap(const char* file_name, int index, int *error); + +/** Loads an image region from file. Open, loads and closes the file. \n + * index specifies the image number between 0 and image_count-1. \n + * Returns NULL if failed. + * Attributes from the file will be stored at the image. + * See also \ref imErrorCodes. \n + * For now, it works only for the ECW file format. + * + * \verbatim im.FileImageLoadRegion(file_name: string, index, bitmap, xmin, xmax, ymin, ymax, width, height: number, ) -> image: imImage, error: number [in Lua 5] \endverbatim + * Default index is 0. + * \ingroup imgfile */ +imImage* imFileImageLoadRegion(const char* file_name, int index, int bitmap, int *error, + int xmin, int xmax, int ymin, int ymax, int width, int height); + +/** Saves the image to file. Open, saves and closes the file. \n + * Returns error code. \n + * Attributes from the image will be stored at the file. + * + * \verbatim im.FileImageSave(file_name: string, format: string, image: imImage) -> error: number [in Lua 5] \endverbatim + * \verbatim image:Save(file_name: string, format: string) -> error: number [in Lua 5] \endverbatim + * \ingroup imgfile */ +int imFileImageSave(const char* file_name, const char* format, const imImage* image); + + + +/** Utility macro to draw the image in a CD library canvas. + * Works only for data_type IM_BYTE, and color spaces: IM_RGB, IM_MAP, IMGRAY and IM_BINARY. + * \ingroup imgclass */ +#define imcdCanvasPutImage(_canvas, _image, _x, _y, _w, _h, _xmin, _xmax, _ymin, _ymax) \ + { \ + if (_image->color_space == IM_RGB) \ + { \ + if (_image->has_alpha) \ + cdCanvasPutImageRectRGBA(_canvas, _image->width, _image->height, \ + (unsigned char*)_image->data[0], \ + (unsigned char*)_image->data[1], \ + (unsigned char*)_image->data[2], \ + (unsigned char*)_image->data[3], \ + _x, _y, _w, _h, _xmin, _xmax, _ymin, _ymax); \ + else \ + cdCanvasPutImageRectRGB(_canvas, _image->width, _image->height, \ + (unsigned char*)_image->data[0], \ + (unsigned char*)_image->data[1], \ + (unsigned char*)_image->data[2], \ + _x, _y, _w, _h, _xmin, _xmax, _ymin, _ymax); \ + } \ + else \ + cdCanvasPutImageRectMap(_canvas, _image->width, _image->height, \ + (unsigned char*)_image->data[0], _image->palette, \ + _x, _y, _w, _h, _xmin, _xmax, _ymin, _ymax); \ + } + + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/im/include/im_kernel.h b/im/include/im_kernel.h new file mode 100755 index 0000000..db066d8 --- /dev/null +++ b/im/include/im_kernel.h @@ -0,0 +1,315 @@ +/** \file + * \brief Kernel Generators + * Creates several known kernels + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_KERNEL_H +#define __IM_KERNEL_H + +#if defined(__cplusplus) +extern "C" { +#endif + + +/** \defgroup kernel Kernel Generators + * \par + * Creates several known kernels + * \par + * See \ref im_kernel.h + * \ingroup convolve */ + + +/** Creates a kernel with the following values: + * +\verbatim + 1 2 1 + 0 0 0 + -1 -2 -1 +\endverbatim + * + * \verbatim im.KernelSobel() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelSobel(void); + +/** Creates a kernel with the following values: + * +\verbatim + 1 1 1 + 0 0 0 + -1 -1 -1 +\endverbatim + * + * \verbatim im.KernelPrewitt() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelPrewitt(void); + +/** Creates a kernel with the following values: + * +\verbatim + 5 5 5 + -3 0 -3 + -3 -3 -3 +\endverbatim + * + * \verbatim im.KernelKirsh() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelKirsh(void); + +/** Creates a kernel with the following values: + * +\verbatim + 0 -1 0 + -1 4 -1 + 0 -1 0 +\endverbatim + * + * \verbatim im.KernelLaplacian4() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelLaplacian4(void); + +/** Creates a kernel with the following values: + * +\verbatim + -1 -1 -1 + -1 8 -1 + -1 -1 -1 +\endverbatim + * + * \verbatim im.KernelLaplacian8() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelLaplacian8(void); + +/** Creates a kernel with the following values: + * +\verbatim + 0 -1 -1 -1 0 + -1 0 1 0 -1 + -1 1 8 1 -1 + -1 0 1 0 -1 + 0 -1 -1 -1 0 +\endverbatim + * + * \verbatim im.KernelLaplacian5x5() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelLaplacian5x5(void); + +/** Creates a kernel with the following values: + * +\verbatim + -1 -1 -1 -1 -1 -1 -1 + -1 -1 -1 -1 -1 -1 -1 + -1 -1 -1 -1 -1 -1 -1 + -1 -1 -1 48 -1 -1 -1 + -1 -1 -1 -1 -1 -1 -1 + -1 -1 -1 -1 -1 -1 -1 + -1 -1 -1 -1 -1 -1 -1 +\endverbatim + * + * \verbatim im.KernelLaplacian7x7() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelLaplacian7x7(void); + +/** Creates a kernel with the following values: + * +\verbatim + 0 -1 0 + 0 1 0 + 0 0 0 +\endverbatim + * + * \verbatim im.KernelGradian3x3() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelGradian3x3(void); + +/** Creates a kernel with the following values: + * +\verbatim + 0 -1 -1 0 1 1 0 + -1 -2 -2 0 2 2 1 + -1 -2 -3 0 3 2 1 + -1 -2 -3 0 3 2 1 + -1 -2 -3 0 3 2 1 + -1 -2 -2 0 2 2 1 + 0 -1 -1 0 1 1 0 +\endverbatim + * + * \verbatim im.KernelGradian7x7() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelGradian7x7(void); + +/** Creates a kernel with the following values: + * +\verbatim + -1 0 0 + 0 0 0 + 0 0 1 +\endverbatim + * + * \verbatim im.KernelSculpt() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelSculpt(void); + +/** Creates a kernel with the following values: + * +\verbatim + 1 1 1 + 1 1 1 + 1 1 1 +\endverbatim + * + * \verbatim im.KernelMean3x3() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelMean3x3(void); + +/** Creates a kernel with the following values: + * +\verbatim + 1 1 1 1 1 + 1 1 1 1 1 + 1 1 1 1 1 + 1 1 1 1 1 + 1 1 1 1 1 +\endverbatim + * + * \verbatim im.KernelMean5x5() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelMean5x5(void); + +/** Creates a kernel with the following values: + * +\verbatim + 0 1 1 1 0 + 1 1 1 1 1 + 1 1 1 1 1 + 1 1 1 1 1 + 0 1 1 1 0 +\endverbatim + * + * \verbatim im.KernelMean5x5() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelCircularMean5x5(void); + +/** Creates a kernel with the following values: + * +\verbatim + 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 +\endverbatim + * + * \verbatim im.KernelMean7x7() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelMean7x7(void); + +/** Creates a kernel with the following values: + * +\verbatim + 0 0 1 1 1 0 0 + 0 1 1 1 1 1 0 + 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 + 0 1 1 1 1 1 0 + 0 0 1 1 1 0 0 +\endverbatim + * + * \verbatim im.KernelCircularMean7x7() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelCircularMean7x7(void); + +/** Creates a kernel with the following values: + * +\verbatim + 1 2 1 + 2 4 2 + 1 2 1 +\endverbatim + * + * \verbatim im.KernelGaussian3x3() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelGaussian3x3(void); + +/** Creates a kernel with the following values: + * +\verbatim + 1 4 6 4 1 + 4 16 24 16 4 + 6 24 36 24 6 + 4 16 24 16 4 + 1 4 6 4 1 +\endverbatim + * + * \verbatim im.KernelGaussian5x5() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelGaussian5x5(void); + +/** Creates a kernel with the following values: + * +\verbatim + 1 2 3 2 1 + 2 4 6 4 2 + 3 6 9 6 3 + 2 4 6 4 2 + 1 2 3 2 1 +\endverbatim + * + * \verbatim im.KernelBarlett5x5() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelBarlett5x5(void); + +/** Creates a kernel with the following values: + * +\verbatim + 0 -1 -1 -1 0 + -1 -1 3 -1 -1 + -1 3 4 3 -1 + -1 -1 3 -1 -1 + 0 -1 -1 -1 0 +\endverbatim + * + * \verbatim im.KernelTopHat5x5() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelTopHat5x5(void); + +/** Creates a kernel with the following values: + * +\verbatim + 0 0 -1 -1 -1 0 0 + 0 -1 -1 -1 -1 -1 0 + -1 -1 3 3 3 -1 -1 + -1 -1 3 4 3 -1 -1 + -1 -1 3 3 3 -1 -1 + 0 -1 -1 -1 -1 -1 0 + 0 0 -1 -1 -1 0 0 +\endverbatim + * + * \verbatim im.KernelTopHat7x7() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelTopHat7x7(void); + +/** Creates a kernel with the following values: + * +\verbatim + 0 -1 -2 -1 0 + -1 -4 0 -4 -1 + -2 0 40 0 -2 + -1 -4 0 -4 -1 + 0 -1 -2 -1 0 +\endverbatim + * + * \verbatim im.KernelEnhance() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelEnhance(void); + +#if defined(__cplusplus) +} +#endif + +#endif + diff --git a/im/include/im_lib.h b/im/include/im_lib.h new file mode 100755 index 0000000..b72b646 --- /dev/null +++ b/im/include/im_lib.h @@ -0,0 +1,191 @@ +/** \file + * \brief Library Management and Main Documentation + * + * See Copyright Notice in this file. + */ + +#ifndef __IM_LIB_H +#define __IM_LIB_H + +#if defined(__cplusplus) +extern "C" { +#endif + + +/** \defgroup lib Library Management + * \ingroup util + * \par + * Usefull definitions for about dialogs and + * for comparing the compiled version with the linked version of the library. + * \par + * \verbatim im._AUTHOR [in Lua 5] \endverbatim + * \verbatim im._COPYRIGHT [in Lua 5] \endverbatim + * \verbatim im._VERSION [in Lua 5] \endverbatim + * \verbatim im._VERSION_DATE [in Lua 5] \endverbatim + * \verbatim im._VERSION_NUMBER [in Lua 5] \endverbatim + * \verbatim im._DESCRIPTION [in Lua 5] \endverbatim + * \verbatim im._NAME [in Lua 5] \endverbatim + * \par + * See \ref im_lib.h + * @{ + */ +#define IM_AUTHOR "Antonio Scuri" +#define IM_COPYRIGHT "Copyright (C) 1994-2009 Tecgraf, PUC-Rio." +#define IM_VERSION "3.5" /* bug fixes are reported only by imVersion functions */ +#define IM_VERSION_NUMBER 305000 +#define IM_VERSION_DATE "2009/10/02" +#define IM_DESCRIPTION "Image Representation, Storage, Capture and Processing" +#define IM_NAME "IM - An Imaging Toolkit" +/** @} */ + + +/** Returns the library current version. Returns the definition IM_VERSION plus the bug fix number. + * + * \verbatim im.Version() -> version: string [in Lua 5] \endverbatim + * \ingroup lib */ +const char* imVersion(void); + +/** Returns the library current version release date. Returns the definition IM_VERSION_DATE. + * + * \verbatim im.VersionDate() -> date: string [in Lua 5] \endverbatim + * \ingroup lib */ +const char* imVersionDate(void); + +/** Returns the library current version number. Returns the definition IM_VERSION_NUMBER plus the bug fix number. \n + * Can be compared in run time with IM_VERSION_NUMBER to compare compiled and linked versions of the library. + * + * \verbatim im.VersionNumber() -> version: number [in Lua 5] \endverbatim + * \ingroup lib */ +int imVersionNumber(void); + + +#if defined(__cplusplus) +} +#endif + + +/*! \mainpage IM + *
+ *

Image Representation, Storage, Capture and Processing

+ * Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil \n + * http://www.tecgraf.puc-rio.br/im \n + * mailto:im@tecgraf.puc-rio.br + *
+ * + * \section over Overview + * \par + * IM is a toolkit for Digital Imaging. + * \par + * It provides support for image capture, several image file formats and many image processing operations. + * \par + * Image representation includes scientific data types (like IEEE floating point data) + * and attributes (or metadata like GeoTIFF and Exif tags). + * Animation, video and volumes are supported as image sequences, + * but there is no digital audio support. + * \par + * The main goal of the library is to provide a simple API and abstraction + * of images for scientific applications. + * \par + * The toolkit API is written in C. + * The core library source code is implemented in C++ and it is very portable, + * it can be compiled in Windows and UNIX with no modifications. + * New image processing operations can be implemented in C or in C++. + * \par + * IM is free software, can be used for public and commercial applications. + * \par + * This work was developed at Tecgraf/PUC-Rio + * by means of the partnership with PETROBRAS/CENPES. + * + * \section author Author + * \par + * Basic Software Group @ Tecgraf/PUC-Rio + * - Antonio Scuri scuri@tecgraf.puc-rio.br + * + * \section copyright Copyright Notice +\verbatim + +**************************************************************************** +Copyright (C) 1994-2009 Tecgraf, PUC-Rio. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +**************************************************************************** +\endverbatim + */ + + +/** \defgroup imagerep Image Representation + * \par + * See \ref im.h + */ + + +/** \defgroup file Image Storage + * \par + * See \ref im.h + */ + + +/** \defgroup format File Formats + * \par + * See \ref im.h + * + * Internal Predefined File Formats: + * \li "BMP" - Windows Device Independent Bitmap + * \li "PCX" - ZSoft Picture + * \li "GIF" - Graphics Interchange Format + * \li "TIFF" - Tagged Image File Format + * \li "RAS" - Sun Raster File + * \li "SGI" - Silicon Graphics Image File Format + * \li "JPEG" - JPEG File Interchange Format + * \li "LED" - IUP image in LED + * \li "TGA" - Truevision Targa + * \li "RAW" - RAW File + * \li "PNM" - Netpbm Portable Image Map + * \li "ICO" - Windows Icon + * \li "PNG" - Portable Network Graphic Format + * + * Other Supported File Formats: + * \li "JP2" - JPEG-2000 JP2 File Format + * \li "AVI" - Windows Audio-Video Interleaved RIFF + * \li "WMV" - Windows Media Video Format + * + * Some Known Compressions: + * \li "NONE" - No Compression. + * \li "RLE" - Run Lenght Encoding. + * \li "LZW" - Lempel, Ziff and Welsh. + * \li "JPEG" - Join Photographics Experts Group. + * \li "DEFLATE" - LZ77 variation (ZIP) + * + * \ingroup file */ + + +/* Library Names Convention + * + * Global Functions and Types - "im[Object][Action]" using first capitals (imFileOpen) + * Local Functions and Types - "i[Object][Action]" using first capitals (iTIFFGetCompIndex) + * Local Static Variables - same as local functions and types (iFormatCount) + * Local Static Tables - same as local functions and types with "Table" suffix (iTIFFCompTable) + * Variables and Members - no prefix, all lower case (width) + * Defines and Enumerations - all capitals (IM_ERR_NONE) + * + */ + + +#endif diff --git a/im/include/im_math.h b/im/include/im_math.h new file mode 100755 index 0000000..8e9b3dd --- /dev/null +++ b/im/include/im_math.h @@ -0,0 +1,368 @@ +/** \file + * \brief Math Utilities + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_MATH_H +#define __IM_MATH_H + +#include +#include "im_util.h" + +#ifdef IM_DEFMATHFLOAT +inline float acosf(float _X) {return ((float)acos((double)_X)); } +inline float asinf(float _X) {return ((float)asin((double)_X)); } +inline float atanf(float _X) {return ((float)atan((double)_X)); } +inline float atan2f(float _X, float _Y) {return ((float)atan2((double)_X, (double)_Y)); } +inline float ceilf(float _X) {return ((float)ceil((double)_X)); } +inline float cosf(float _X) {return ((float)cos((double)_X)); } +inline float coshf(float _X) {return ((float)cosh((double)_X)); } +inline float expf(float _X) {return ((float)exp((double)_X)); } +inline float fabsf(float _X) {return ((float)fabs((double)_X)); } +inline float floorf(float _X) {return ((float)floor((double)_X)); } +inline float fmodf(float _X, float _Y) {return ((float)fmod((double)_X, (double)_Y)); } +inline float logf(float _X) {return ((float)log((double)_X)); } +inline float log10f(float _X) {return ((float)log10((double)_X)); } +inline float powf(float _X, float _Y) {return ((float)pow((double)_X, (double)_Y)); } +inline float sinf(float _X) {return ((float)sin((double)_X)); } +inline float sinhf(float _X) {return ((float)sinh((double)_X)); } +inline float sqrtf(float _X) {return ((float)sqrt((double)_X)); } +inline float tanf(float _X) {return ((float)tan((double)_X)); } +inline float tanhf(float _X) {return ((float)tanh((double)_X)); } +#endif + +/** \defgroup math Math Utilities + * \par + * When converting between continuous and discrete use: \n + * Continuous = Discrete + 0.5 [Reconstruction/Interpolation] \n + * Discrete = Round(Continuous - 0.5) [Sampling/Quantization] \n + * \par + * Notice that must check 0-max limits when converting from Continuous to Discrete. + * \par + * When converting between discrete and discrete use: \n + * integer src_size, dst_len, src_i, dst_i \n + * real factor = (real)(dst_size)/(real)(src_size) \n + * dst_i = Round(factor*(src_i + 0.5) - 0.5) + * \par + * See \ref im_math.h + * \ingroup util */ + + +/** Round a real to the nearest integer. + * \ingroup math */ +inline int imRound(float x) +{ + return (int)(x < 0? x-0.5f: x+0.5f); +} +inline int imRound(double x) +{ + return (int)(x < 0? x-0.5: x+0.5); +} + +/** Converts between two discrete grids. + * factor is "dst_size/src_size". + * \ingroup math */ +inline int imResample(int x, float factor) +{ + float xr = factor*(x + 0.5f) - 0.5f; + return (int)(xr < 0? xr-0.5f: xr+0.5f); /* Round */ +} + +/** Does Zero Order Decimation (Mean). + * \ingroup math */ +template +inline T imZeroOrderDecimation(int width, int height, T *map, float xl, float yl, float box_width, float box_height, TU Dummy) +{ + int x0,x1,y0,y1; + (void)Dummy; + + x0 = (int)floor(xl - box_width/2.0 - 0.5) + 1; + y0 = (int)floor(yl - box_height/2.0 - 0.5) + 1; + x1 = (int)floor(xl + box_width/2.0 - 0.5); + y1 = (int)floor(yl + box_height/2.0 - 0.5); + + if (x0 == x1) x1++; + if (y0 == y1) y1++; + + x0 = x0<0? 0: x0>width-1? width-1: x0; + y0 = y0<0? 0: y0>height-1? height-1: y0; + x1 = x1<0? 0: x1>width-1? width-1: x1; + y1 = y1<0? 0: y1>height-1? height-1: y1; + + TU Value; + int Count = 0; + + Value = 0; + + for (int y = y0; y <= y1; y++) + { + for (int x = x0; x <= x1; x++) + { + Value += map[y*width+x]; + Count++; + } + } + + if (Count == 0) + { + Value = 0; + return (T)Value; + } + + return (T)(Value/(float)Count); +} + +/** Does Bilinear Decimation. + * \ingroup math */ +template +inline T imBilinearDecimation(int width, int height, T *map, float xl, float yl, float box_width, float box_height, TU Dummy) +{ + int x0,x1,y0,y1; + (void)Dummy; + + x0 = (int)floor(xl - box_width/2.0 - 0.5) + 1; + y0 = (int)floor(yl - box_height/2.0 - 0.5) + 1; + x1 = (int)floor(xl + box_width/2.0 - 0.5); + y1 = (int)floor(yl + box_height/2.0 - 0.5); + + if (x0 == x1) x1++; + if (y0 == y1) y1++; + + x0 = x0<0? 0: x0>width-1? width-1: x0; + y0 = y0<0? 0: y0>height-1? height-1: y0; + x1 = x1<0? 0: x1>width-1? width-1: x1; + y1 = y1<0? 0: y1>height-1? height-1: y1; + + TU Value, LineValue; + float LineNorm, Norm, dxr, dyr; + + Value = 0; + Norm = 0; + + for (int y = y0; y <= y1; y++) + { + dyr = yl - (y+0.5f); + if (dyr < 0) dyr *= -1; + + LineValue = 0; + LineNorm = 0; + + for (int x = x0; x <= x1; x++) + { + dxr = xl - (x+0.5f); + if (dxr < 0) dxr *= -1; + + LineValue += map[y*width+x] * dxr; + LineNorm += dxr; + } + + Value += LineValue * dyr; + Norm += dyr * LineNorm; + } + + if (Norm == 0) + { + Value = 0; + return (T)Value; + } + + return (T)(Value/Norm); +} + +/** Does Zero Order Interpolation (Nearest Neighborhood). + * \ingroup math */ +template +inline T imZeroOrderInterpolation(int width, int height, T *map, float xl, float yl) +{ + int x0 = imRound(xl-0.5f); + int y0 = imRound(yl-0.5f); + x0 = x0<0? 0: x0>width-1? width-1: x0; + y0 = y0<0? 0: y0>height-1? height-1: y0; + return map[y0*width + x0]; +} + +/** Does Bilinear Interpolation. + * \ingroup math */ +template +inline T imBilinearInterpolation(int width, int height, T *map, float xl, float yl) +{ + int x0, y0, x1, y1; + float t, u; + + if (xl < 0.5) + { + x1 = x0 = 0; + t = 0; + } + else if (xl > width-0.5) + { + x1 = x0 = width-1; + t = 0; + } + else + { + x0 = (int)(xl-0.5f); + x1 = x0+1; + t = xl - (x0+0.5f); + } + + if (yl < 0.5) + { + y1 = y0 = 0; + u = 0; + } + else if (yl > height-0.5) + { + y1 = y0 = height-1; + u = 0; + } + else + { + y0 = (int)(yl-0.5f); + y1 = y0+1; + u = yl - (y0+0.5f); + } + + T fll = map[y0*width + x0]; + T fhl = map[y0*width + x1]; + T flh = map[y1*width + x0]; + T fhh = map[y1*width + x1]; + + return (T)((fhh - flh - fhl + fll) * u * t + + (fhl - fll) * t + + (flh - fll) * u + + fll); +} + +/** Does Bicubic Interpolation. + * \ingroup math */ +template +inline T imBicubicInterpolation(int width, int height, T *map, float xl, float yl, TU Dummy) +{ + int X[4], Y[4]; + float t, u; + (void)Dummy; + + if (xl > width-0.5) + { + X[3] = X[2] = X[1] = width-1; + X[0] = X[1]-1; + t = 0; + } + else + { + X[1] = (int)(xl-0.5f); + if (X[1] < 0) X[1] = 0; + + X[0] = X[1]-1; + X[2] = X[1]+1; + X[3] = X[1]+2; + + if (X[0] < 0) X[0] = 0; + if (X[3] > width-1) X[3] = width-1; + + t = xl - (X[1]+0.5f); + } + + if (yl > height-0.5) + { + Y[3] = Y[2] = Y[1] = height-1; + Y[0] = Y[1]-1; + u = 0; + } + else + { + Y[1] = (int)(yl-0.5f); + if (Y[1] < 0) Y[1] = 0; + + Y[0] = Y[1]-1; + Y[2] = Y[1]+1; + Y[3] = Y[1]+2; + + if (Y[0] < 0) Y[0] = 0; + if (Y[3] > height-1) Y[3] = height-1; + + u = yl - (Y[1]+0.5f); + } + + float CX[4], CY[4]; + + // Optimize calculations + { + float c, c2, c3; + +#define C0 (-c3 + 2.0f*c2 - c) +#define C1 ( c3 - 2.0f*c2 + 1.0f) +#define C2 (-c3 + c2 + c) +#define C3 ( c3 - c2) + + c = t; + c2 = c*c; c3 = c2*c; + CX[0] = C0; CX[1] = C1; CX[2] = C2; CX[3] = C3; + + c = u; + c2 = c*c; c3 = c2*c; + CY[0] = C0; CY[1] = C1; CY[2] = C2; CY[3] = C3; + +#undef C0 +#undef C1 +#undef C2 +#undef C3 + } + + TU LineValue, Value; + float LineNorm, Norm; + + Value = 0; + Norm = 0; + + for (int y = 0; y < 4; y++) + { + LineValue = 0; + LineNorm = 0; + + for (int x = 0; x < 4; x++) + { + LineValue += map[Y[y]*width+X[x]] * CX[x]; + LineNorm += CX[x]; + } + + Value += LineValue * CY[y]; + Norm += CY[y] * LineNorm; + } + + if (Norm == 0) + { + Value = 0; + return (T)Value; + } + + Value = (Value/Norm); + + int size = sizeof(T); + if (size == 1) + return (T)(Value<=(TU)0? (TU)0: Value<=(TU)255? Value: (TU)255); + else + return (T)(Value); +} + +/** Calculates minimum and maximum values. + * \ingroup math */ +template +inline void imMinMax(const T *map, int count, T& min, T& max) +{ + min = *map++; + max = min; + for (int i = 1; i < count; i++) + { + T value = *map++; + + if (value > max) + max = value; + else if (value < min) + min = value; + } +} + +#endif diff --git a/im/include/im_math_op.h b/im/include/im_math_op.h new file mode 100755 index 0000000..2a4794f --- /dev/null +++ b/im/include/im_math_op.h @@ -0,0 +1,214 @@ +/** \file + * \brief Math Operations + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_MATH_OP_H +#define __IM_MATH_OP_H + +#include "im_complex.h" + + +/// Crop value to Byte limit +template +inline T crop_byte(const T& v) +{ + return v < 0? 0: v > 255? 255: v; +} + +/// Generic Addition with 2 template types +template +inline T1 add_op(const T1& v1, const T2& v2) +{ + return v2 + v1; +} + +/// Generic Subtraction with 2 template types +template +inline T1 sub_op(const T1& v1, const T2& v2) +{ + return v2 - v1; +} + +/// Generic Multiplication with 2 template types +template +inline T1 mul_op(const T1& v1, const T2& v2) +{ + return v2 * v1; +} + +/// Generic Division with 2 template types +template +inline T1 div_op(const T1& v1, const T2& v2) +{ + return v1 / v2; +} + +/// Generic Invert +template +inline T inv_op(const T& v) +{ + return 1/v; +} + +/// Generic Difference with 2 template types +template +inline T1 diff_op(const T1& v1, const T2& v2) +{ + if (v1 < v2) + return v2 - v1; + return v1 - v2; +} + +/// Generic Minimum with 2 template types +template +inline T1 min_op(const T1& v1, const T2& v2) +{ + if (v1 < v2) + return v1; + return v2; +} + +/// Generic Maximum with 2 template types +template +inline T1 max_op(const T1& v1, const T2& v2) +{ + if (v1 < v2) + return v2; + return v1; +} + +inline imbyte pow_op(const imbyte& v1, const imbyte& v2) +{ + return (imbyte)pow((float)v1, v2); +} + +inline imushort pow_op(const imushort& v1, const imushort& v2) +{ + return (imushort)pow((float)v1, v2); +} + +inline int pow_op(const int& v1, const int& v2) +{ + return (int)pow((float)v1, v2); +} + +/// Generic Power with 2 template types +template +inline T1 pow_op(const T1& v1, const T2& v2) +{ + return (T1)pow(v1, v2); +} + +/// Generic Abssolute +template +inline T abs_op(const T& v) +{ + if (v < 0) + return -1*v; + return v; +} + +/// Generic Less +template +inline T less_op(const T& v) +{ + return -1*v; +} + +/// Generic Square +template +inline T sqr_op(const T& v) +{ + return v*v; +} + +inline int sqrt(const int& C) +{ + return (int)sqrt(float(C)); +} + +/// Generic Square Root +template +inline T sqrt_op(const T& v) +{ + return (T)sqrt(v); +} + +inline int exp(const int& v) +{ + return (int)exp((float)v); +} + +/// Generic Exponential +template +inline T exp_op(const T& v) +{ + return (T)exp(v); +} + +inline int log(const int& v) +{ + return (int)log((float)v); +} + +/// Generic Logarithm +template +inline T log_op(const T& v) +{ + return (T)log(v); +} + +// Dummy sin +inline imcfloat sin(const imcfloat& v) +{ + return (v); +} + +inline int sin(const int& v) +{ + return (int)sin((float)v); +} + +/// Generic Sine +template +inline T sin_op(const T& v) +{ + return (T)sin(v); +} + +inline int cos(const int& v) +{ + return (int)cos((float)v); +} + +// Dummy cos +inline imcfloat cos(const imcfloat& v) +{ + return (v); +} + +/// Generic Cosine +template +inline T cos_op(const T& v) +{ + return (T)cos(v); +} + +/// Sets a bit in an array +inline void imDataBitSet(imbyte* data, int index, int bit) +{ + if (bit) + data[index / 8] |= (0x01 << (7 - (index % 8))); + else + data[index / 8] &= ~(0x01 << (7 - (index % 8))); +} + +/// Gets a bit from an array +inline int imDataBitGet(imbyte* data, int index) +{ + return (data[index / 8] >> (7 - (index % 8))) & 0x01; +} + +#endif diff --git a/im/include/im_palette.h b/im/include/im_palette.h new file mode 100755 index 0000000..c7ed88c --- /dev/null +++ b/im/include/im_palette.h @@ -0,0 +1,172 @@ +/** \file + * \brief Palette Generators + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_PALETTE_H +#define __IM_PALETTE_H + +#if defined(__cplusplus) +extern "C" { +#endif + + +/** \defgroup palette Palette Generators + * \par + * Creates several standard palettes. The palette is just an array of encoded color values. + * See also \ref colorutl. + * \par + * In Lua, to create a palette you can call im.PaletteCreate. + * \verbatim im.PaletteCreate([count: number]) -> pal: imPalette [in Lua 5] \endverbatim + * Default count is 256. + * IMLua and CDLua palettes are 100% compatible. The IM palette metatable name is "imPalette". \n + * When converted to a string will return "imPalete(%p)" where %p is replaced by the userdata address. + * If the palette is already destroyed by im.PaletteDestroy, then it will return also the suffix "-destroyed". + * \par + * In Lua, to destroy a palette you can call im.PaletteDestroy. + * If this function is not called, the palette is destroyed by the garbage collector. + * \verbatim im.PaletteDestroy(pal: imPalette) [in Lua 5] \endverbatim + * \par + * In Lua, array access is enabled so you can do:. + * \verbatim color = pal[index] \endverbatim + * \verbatim pal[index] = color \endverbatim + * \verbatim count = #pal \endverbatim + * \par + * See \ref im_palette.h + * \ingroup util */ + + +/** Searches for the nearest color on the table and returns the color index if successful. + * It looks in all palette entries and finds the minimum euclidian square distance. + * If the color matches the given color it returns immediately. + * See also \ref colorutl. + * + * \verbatim im.PaletteFindNearest(pal: imPalette, color: lightuserdata) -> index: number [in Lua 5] \endverbatim + * \ingroup palette */ +int imPaletteFindNearest(const long *palette, int palette_count, long color); + +/** Searches for the color on the table and returns the color index if successful. + * If the tolerance is 0 search for the exact match in the palette else search for the + * first color that fits in the tolerance range. + * See also \ref colorutl. + * + * \verbatim im.PaletteFindColor(pal: imPalette, color: lightuserdata, tol: number) -> index: number [in Lua 5] \endverbatim + * \ingroup palette */ +int imPaletteFindColor(const long *palette, int palette_count, long color, unsigned char tol); + +/** Creates a palette of gray scale values. + * The colors are arranged from black to white. + * + * \verbatim im.PaletteGray() -> pal: imPalette [in Lua 5] \endverbatim + * \ingroup palette */ +long* imPaletteGray(void); + +/** Creates a palette of a gradient of red colors. + * The colors are arranged from black to pure red. + * + * \verbatim im.PaletteRed() -> pal: imPalette [in Lua 5] \endverbatim + * \ingroup palette */ +long* imPaletteRed(void); + +/** Creates a palette of a gradient of green colors. + * The colors are arranged from black to pure green. + * + * \verbatim im.PaletteGreen() -> pal: imPalette [in Lua 5] \endverbatim + * \ingroup palette */ +long* imPaletteGreen(void); + +/** Creates a palette of a gradient of blue colors. + * The colors are arranged from black to pure blue. + * + * \verbatim im.PaletteBlue() -> pal: imPalette [in Lua 5] \endverbatim + * \ingroup palette */ +long* imPaletteBlue(void); + +/** Creates a palette of a gradient of yellow colors. + * The colors are arranged from black to pure yellow. + * + * \verbatim im.PaletteYellow() -> pal: imPalette [in Lua 5] \endverbatim + * \ingroup palette */ +long* imPaletteYellow(void); + +/** Creates a palette of a gradient of magenta colors. + * The colors are arranged from black to pure magenta. + * + * \verbatim im.PaletteMagenta() -> pal: imPalette [in Lua 5] \endverbatim + * \ingroup palette */ +long* imPaletteMagenta(void); + +/** Creates a palette of a gradient of cian colors. + * The colors are arranged from black to pure cian. + * + * \verbatim im.PaletteCian() -> pal: imPalette [in Lua 5] \endverbatim + * \ingroup palette */ +long* imPaletteCian(void); + +/** Creates a palette of rainbow colors. + * The colors are arranged in the light wave length spectrum order (starting from purple). + * + * \verbatim im.PaletteRainbow() -> pal: imPalette [in Lua 5] \endverbatim + * \ingroup palette */ +long* imPaletteRainbow(void); + +/** Creates a palette of hues with maximum saturation. + * + * \verbatim im.PaletteHues() -> pal: imPalette [in Lua 5] \endverbatim + * \ingroup palette */ +long* imPaletteHues(void); + +/** Creates a palette of a gradient of blue colors. + * The colors are arranged from pure blue to white. + * + * \verbatim im.PaletteBlueIce() -> pal: imPalette [in Lua 5] \endverbatim + * \ingroup palette */ +long* imPaletteBlueIce(void); + +/** Creates a palette of a gradient from black to white passing trough red and orange. + * + * \verbatim im.PaletteHotIron() -> pal: imPalette [in Lua 5] \endverbatim + * \ingroup palette */ +long* imPaletteHotIron(void); + +/** Creates a palette of a gradient from black to white passing trough red and yellow. + * + * \verbatim im.PaletteBlackBody() -> pal: imPalette [in Lua 5] \endverbatim + * \ingroup palette */ +long* imPaletteBlackBody(void); + +/** Creates a palette with high contrast colors. + * + * \verbatim im.PaletteHighContrast() -> pal: imPalette [in Lua 5] \endverbatim + * \ingroup palette */ +long* imPaletteHighContrast(void); + +/** Creates a palette of an uniform range of colors from black to white. + * This is a 2^(2.6) bits per pixel palette. + * + * \verbatim im.PaletteUniform() -> pal: imPalette [in Lua 5] \endverbatim + * \ingroup palette */ +long* imPaletteUniform(void); + +/** Returns the index of the correspondent RGB color of an uniform palette. + * + * \verbatim im.PaletteUniformIndex(color: lightuserdata) -> index: number [in Lua 5] \endverbatim + * \ingroup palette */ +int imPaletteUniformIndex(long color); + +/** Returns the index of the correspondent RGB color of an uniform palette. + * Uses an 8x8 ordered dither to lookup the index in a halftone matrix. + * The spatial position used by the halftone method. + * + * \verbatim im.PaletteUniformIndexHalftoned(color: lightuserdata, x: number, y: number) -> index: number [in Lua 5] \endverbatim + * \ingroup palette */ +int imPaletteUniformIndexHalftoned(long color, int x, int y); + + +#if defined(__cplusplus) +} +#endif + +#endif + diff --git a/im/include/im_plus.h b/im/include/im_plus.h new file mode 100755 index 0000000..0aabd1f --- /dev/null +++ b/im/include/im_plus.h @@ -0,0 +1,73 @@ +/** \file + * \brief C++ Wrapper for File Access + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_PLUS_H +#define __IM_PLUS_H + + +/** \brief C++ Wrapper for the Image File Structure + * + * \par + * Usage is just like the C API. Open and New are replaced by equivalent constructors. \n + * Close is replaced by the destructor. Error checking is done by the Error() member. \n + * Open and New errors are cheked using the Failed() member. + * \ingroup file */ +class imImageFile +{ + imFile* ifile; + int error; + + imImageFile() {}; + +public: + + imImageFile(const char* file_name) + { this->ifile = imFileOpen(file_name, &this->error); } + + imImageFile(const char* file_name, const char* format) + { this->ifile = imFileNew(file_name, format, &this->error); } + + ~imImageFile() + { if (this->ifile) imFileClose(this->ifile); } + + int Failed() + { return this->ifile == 0; } + + int Error() + { return this->error; } + + void SetAttribute(const char* attrib, int data_type, int count, const void* data) + { imFileSetAttribute(this->ifile, attrib, data_type, count, data); } + + const void* GetAttribute(const char* attrib, int *data_type, int *count) + { return imFileGetAttribute(this->ifile, attrib, data_type, count); } + + void GetInfo(char* format, char* compression, int *image_count) + { imFileGetInfo(this->ifile, format, compression, image_count); } + + void ReadImageInfo(int index, int *width, int *height, int *color_mode, int *data_type) + { this->error = imFileReadImageInfo(this->ifile, index, width, height, color_mode, data_type); } + + void GetPalette(long* palette, int *palette_count) + { imFileGetPalette(this->ifile, palette, palette_count); } + + void ReadImageData(void* data, int convert2bitmap, int color_mode_flags) + { this->error = imFileReadImageData(this->ifile, data, convert2bitmap, color_mode_flags); } + + void SetInfo(const char* compression) + { imFileSetInfo(this->ifile, compression); } + + void SetPalette(long* palette, int palette_count) + { imFileSetPalette(this->ifile, palette, palette_count); } + + void WriteImageInfo(int width, int height, int color_mode, int data_type) + { this->error = imFileWriteImageInfo(this->ifile, width, height, color_mode, data_type); } + + void WriteImageData(void* data) + { this->error = imFileWriteImageData(this->ifile, data); } +}; + +#endif diff --git a/im/include/im_process.h b/im/include/im_process.h new file mode 100755 index 0000000..812dad1 --- /dev/null +++ b/im/include/im_process.h @@ -0,0 +1,36 @@ +/** \file + * \brief Image Processing + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_PROCESS_H +#define __IM_PROCESS_H + +#include "im_process_pon.h" +#include "im_process_loc.h" +#include "im_process_glo.h" +#include "im_process_ana.h" + +#if defined(__cplusplus) +extern "C" { +#endif + + +/** \defgroup process Image Processing + * \par + * Several image processing functions based on the \ref imImage structure. + * \par + * You must link the application with "im_process.lib/.a/.so". + * In Lua call require"imlua_process". \n + * Some complex operations use the \ref counter.\n + * There is no check on the input/output image properties, + * check each function documentation before using it. + */ + + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/im/include/im_process_ana.h b/im/include/im_process_ana.h new file mode 100755 index 0000000..e7a897a --- /dev/null +++ b/im/include/im_process_ana.h @@ -0,0 +1,222 @@ +/** \file + * \brief Image Statistics and Analysis + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_PROC_ANA_H +#define __IM_PROC_ANA_H + +#include "im_image.h" + +#if defined(__cplusplus) +extern "C" { +#endif + + + +/** \defgroup stats Image Statistics Calculations + * \par + * Operations to calculate some statistics over images. + * \par + * See \ref im_process_ana.h + * \ingroup process */ + +/** Calculates the RMS error between two images (Root Mean Square Error). + * + * \verbatim im.CalcRMSError(image1: imImage, image2: imImage) -> rms: number [in Lua 5] \endverbatim + * \ingroup stats */ +float imCalcRMSError(const imImage* image1, const imImage* image2); + +/** Calculates the SNR of an image and its noise (Signal Noise Ratio). + * + * \verbatim im.CalcSNR(src_image: imImage, noise_image: imImage) -> snr: number [in Lua 5] \endverbatim + * \ingroup stats */ +float imCalcSNR(const imImage* src_image, const imImage* noise_image); + +/** Count the number of different colors in an image. \n + * Image must be IM_BYTE, but all color spaces except IM_CMYK. + * + * \verbatim im.CalcCountColors(image: imImage) -> count: number [in Lua 5] \endverbatim + * \ingroup stats */ +unsigned long imCalcCountColors(const imImage* image); + +/** Calculates the histogram of a IM_BYTE data. \n + * Histogram is always 256 positions long. \n + * When cumulative is different from zero it calculates the cumulative histogram. + * + * \verbatim im.CalcHistogram(image: imImage, plane: number, cumulative: boolean) -> histo: table of numbers [in Lua 5] \endverbatim + * Where plane is the depth plane to calculate the histogram. \n + * The returned table is zero indexed. image can be IM_USHORT or IM_BYTE. + * \ingroup stats */ +void imCalcHistogram(const unsigned char* data, int count, unsigned long* histo, int cumulative); + +/** Calculates the histogram of a IM_USHORT data. \n + * Histogram is always 65535 positions long. \n + * When cumulative is different from zero it calculates the cumulative histogram. \n + * Use \ref imCalcHistogram in Lua. + * \ingroup stats */ +void imCalcUShortHistogram(const unsigned short* data, int count, unsigned long* histo, int cumulative); + +/** Calculates the gray histogram of an image. \n + * Image must be IM_BYTE/(IM_RGB, IM_GRAY, IM_BINARY or IM_MAP). \n + * If the image is IM_RGB then the histogram of the luma component is calculated. \n + * Histogram is always 256 positions long. \n + * When cumulative is different from zero it calculates the cumulative histogram. + * + * \verbatim im.CalcGrayHistogram(image: imImage, cumulative: boolean) -> histo: table of numbers [in Lua 5] \endverbatim + * \ingroup stats */ +void imCalcGrayHistogram(const imImage* image, unsigned long* histo, int cumulative); + +/** Numerical Statistics Structure + * \ingroup stats */ +typedef struct _imStats +{ + float max; /**< Maximum value */ + float min; /**< Minimum value */ + unsigned long positive; /**< Number of Positive Values */ + unsigned long negative; /**< Number of Negative Values */ + unsigned long zeros; /**< Number of Zeros */ + float mean; /**< Mean */ + float stddev; /**< Standard Deviation */ +} imStats; + +/** Calculates the statistics about the image data. \n + * There is one stats for each depth plane. For ex: stats[0]=red stats, stats[0]=green stats, ... \n + * Supports all data types except IM_CFLOAT. \n + * + * \verbatim im.CalcImageStatistics(image: imImage) -> stats: table [in Lua 5] \endverbatim + * Table contains the following fields: max, min, positive, negative, zeros, mean, stddev. + * The same as the \ref imStats structure. + * \ingroup stats */ +void imCalcImageStatistics(const imImage* image, imStats* stats); + +/** Calculates the statistics about the image histogram data.\n + * There is one stats for each depth plane. For ex: stats[0]=red stats, stats[0]=green stats, ... \n + * Only IM_BYTE images are supported. + * + * \verbatim im.CalcHistogramStatistics(image: imImage) -> stats: table [in Lua 5] \endverbatim + * \ingroup stats */ +void imCalcHistogramStatistics(const imImage* image, imStats* stats); + +/** Calculates some extra statistics about the image histogram data.\n + * There is one stats for each depth plane. \n + * Only IM_BYTE images are supported. \n + * mode will be -1 if more than one max is found. + * + * \verbatim im.CalcHistoImageStatistics(image: imImage) -> median: number, mode: number [in Lua 5] \endverbatim + * \ingroup stats */ +void imCalcHistoImageStatistics(const imImage* image, int* median, int* mode); + + + +/** \defgroup analyze Image Analysis + * \par + * See \ref im_process_ana.h + * \ingroup process */ + +/** Find white regions in binary image. \n + * Result is IM_GRAY/IM_USHORT type. Regions can be 4 connected or 8 connected. \n + * Returns the number of regions found. Background is marked as 0. \n + * Regions touching the border are considered only if touch_border=1. + * + * \verbatim im.AnalyzeFindRegions(src_image: imImage, dst_image: imImage, connect: number, touch_border: boolean) -> count: number [in Lua 5] \endverbatim + * \verbatim im.AnalyzeFindRegionsNew(image: imImage, connect: number, touch_border: boolean) -> count: number, new_image: imImage [in Lua 5] \endverbatim + * \ingroup analyze */ +int imAnalyzeFindRegions(const imImage* src_image, imImage* dst_image, int connect, int touch_border); + +/** Measure the actual area of all regions. Holes are not included. \n + * This is the number of pixels of each region. \n + * Source image is IM_GRAY/IM_USHORT type (the result of \ref imAnalyzeFindRegions). \n + * area has size the number of regions. + * + * \verbatim im.AnalyzeMeasureArea(image: imImage, [region_count: number]) -> area: table of numbers [in Lua 5] \endverbatim + * The returned table is zero indexed. + * \ingroup analyze */ +void imAnalyzeMeasureArea(const imImage* image, int* area, int region_count); + +/** Measure the polygonal area limited by the perimeter line of all regions. Holes are not included. \n + * Notice that some regions may have polygonal area zero. \n + * Source image is IM_GRAY/IM_USHORT type (the result of \ref imAnalyzeFindRegions). \n + * perimarea has size the number of regions. + * + * \verbatim im.AnalyzeMeasurePerimArea(image: imImage, [region_count: number]) -> perimarea: table of numbers [in Lua 5] \endverbatim + * The returned table is zero indexed. + * \ingroup analyze */ +void imAnalyzeMeasurePerimArea(const imImage* image, float* perimarea); + +/** Calculate the centroid position of all regions. Holes are not included. \n + * Source image is IM_GRAY/IM_USHORT type (the result of \ref imAnalyzeFindRegions). \n + * area, cx and cy have size the number of regions. If area is NULL will be internally calculated. + * + * \verbatim im.AnalyzeMeasureCentroid(image: imImage, [area: table of numbers], [region_count: number]) -> cx: table of numbers, cy: table of numbers [in Lua 5] \endverbatim + * The returned tables are zero indexed. + * \ingroup analyze */ +void imAnalyzeMeasureCentroid(const imImage* image, const int* area, int region_count, float* cx, float* cy); + +/** Calculate the principal major axis slope of all regions. \n + * Source image is IM_GRAY/IM_USHORT type (the result of \ref imAnalyzeFindRegions). \n + * data has size the number of regions. If area or centroid are NULL will be internally calculated. \n + * Principal (major and minor) axes are defined to be those axes that pass through the + * centroid, about which the moment of inertia of the region is, respectively maximal or minimal. + * + * \verbatim im.AnalyzeMeasurePrincipalAxis(image: imImage, [area: table of numbers], [cx: table of numbers], [cy: table of numbers], [region_count: number]) + -> major_slope: table of numbers, major_length: table of numbers, minor_slope: table of numbers, minor_length: table of numbers [in Lua 5] \endverbatim + * The returned tables are zero indexed. + * \ingroup analyze */ +void imAnalyzeMeasurePrincipalAxis(const imImage* image, const int* area, const float* cx, const float* cy, + const int region_count, float* major_slope, float* major_length, + float* minor_slope, float* minor_length); + +/** Measure the number and area of holes of all regions. \n + * Source image is IM_USHORT type (the result of \ref imAnalyzeFindRegions). \n + * area and perim has size the number of regions, if some is NULL it will be not calculated. + * + * \verbatim im.AnalyzeMeasureHoles(image: imImage, connect: number, [region_count: number]) -> holes_count: number, area: table of numbers, perim: table of numbers [in Lua 5] \endverbatim + * The returned tables are zero indexed. + * \ingroup analyze */ +void imAnalyzeMeasureHoles(const imImage* image, int connect, int *holes_count, int* area, float* perim); + +/** Measure the total perimeter of all regions (external and internal). \n + * Source image is IM_GRAY/IM_USHORT type (the result of imAnalyzeFindRegions). \n + * It uses a half-pixel inter distance for 8 neighboors in a perimeter of a 4 connected region. \n + * This function can also be used to measure line lenght. \n + * perim has size the number of regions. + * + * \verbatim im.AnalyzeMeasurePerimeter(image: imImage) -> perim: table of numbers [in Lua 5] \endverbatim + * \ingroup analyze */ +void imAnalyzeMeasurePerimeter(const imImage* image, float* perim, int region_count); + +/** Isolates the perimeter line of gray integer images. Background is defined as being black (0). \n + * It just checks if at least one of the 4 connected neighboors is non zero. Image borders are extended with zeros. + * + * \verbatim im.ProcessPerimeterLine(src_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessPerimeterLineNew(image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup analyze */ +void imProcessPerimeterLine(const imImage* src_image, imImage* dst_image); + +/** Eliminates regions that have area size outside or inside the given interval. \n + * Source and destiny are a binary images. Regions can be 4 connected or 8 connected. \n + * Can be done in-place. end_size can be zero to indicate no upper limit or an area with width*height size. \n + * When searching inside the region the limits are inclusive (<= size >=), when searching outside the limits are exclusive (> size <). + * + * \verbatim im.ProcessRemoveByArea(src_image: imImage, dst_image: imImage, connect: number, start_size: number, end_size: number, inside: boolean) [in Lua 5] \endverbatim + * \verbatim im.ProcessRemoveByAreaNew(image: imImage, connect: number, start_size: number, end_size: number, inside: boolean) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup analyze */ +void imProcessRemoveByArea(const imImage* src_image, imImage* dst_image, int connect, int start_size, int end_size, int inside); + +/** Fill holes inside white regions. \n + * Source and destiny are a binary images. Regions can be 4 connected or 8 connected. \n + * Can be done in-place. + * + * \verbatim im.ProcessFillHoles(src_image: imImage, dst_image: imImage, connect: number) [in Lua 5] \endverbatim + * \verbatim im.ProcessFillHolesNew(image: imImage, connect: number) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup analyze */ +void imProcessFillHoles(const imImage* src_image, imImage* dst_image, int connect); + + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/im/include/im_process_glo.h b/im/include/im_process_glo.h new file mode 100755 index 0000000..d50c4c1 --- /dev/null +++ b/im/include/im_process_glo.h @@ -0,0 +1,170 @@ +/** \file + * \brief Image Processing - Global Operations + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_PROCESS_GLO_H +#define __IM_PROCESS_GLO_H + +#include "im_image.h" + +#if defined(__cplusplus) +extern "C" { +#endif + + + +/** \defgroup transform Other Domain Transform Operations + * \par + * Hough, Distance. + * + * See \ref im_process_glo.h + * \ingroup process */ + +/** Hough Lines Transform. \n + * It will detect white lines in a black background. So the source image must be a IM_BINARY image + * with the white lines of interest enhanced. The better the threshold with the white lines the better + * the line detection. \n + * The destiny image must have IM_GRAY, IM_INT, hg_width=180, hg_height=2*rmax+1, + * where rmax is the image diagonal/2 (rmax = srqrt(width*width + height*height)). \n + * The hough transform defines "cos(theta) * X + sin(theta) * Y = rho" and the parameters are in the interval: \n + * theta = "0 .. 179", rho = "-hg_height/2 .. hg_height/2" .\n + * Where rho is the perpendicular distance from the center of the image and theta the angle with the normal. + * So do not confuse theta with the line angle, they are perpendicular. \n + * Returns zero if the counter aborted. \n + * Inspired from ideas in XITE, Copyright 1991, Blab, UiO \n + * http://www.ifi.uio.no/~blab/Software/Xite/ + * + * \verbatim im.ProcessHoughLines(src_image: imImage, dst_image: imImage) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessHoughLinesNew(image: imImage) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup transform */ +int imProcessHoughLines(const imImage* src_image, imImage* dst_image); + +/** Draw detected hough lines. \n + * The source image must be IM_GRAY and IM_BYTE. The destiny image can be a clone of the source image or + * it can be the source image for in place processing. \n + * If the hough transform is not NULL, then the hough points are filtered to include only lines + * that are significally different from each other. \n + * The hough image is the hough transform image, but it is optional and can be NULL. + * If not NULL then it will be used to filter lines that are very similar. \n + * The hough points image is a hough transform image that was thresholded to a IM_BINARY image, + * usually using a Local Max threshold operation (see \ref imProcessLocalMaxThreshold). Again the better the threshold the better the results. \n + * The destiny image will be set to IM_MAP, and the detected lines will be drawn using a red color. \n + * Returns the number of detected lines. + * + * \verbatim im.ProcessHoughLinesDraw(src_image: imImage, hough: imImage, hough_points: imImage, dst_image: imImage) -> lines: number [in Lua 5] \endverbatim + * \verbatim im.ProcessHoughLinesDrawNew(image: imImage, hough: imImage, hough_points: imImage) -> lines: number, new_image: imImage [in Lua 5] \endverbatim + * \ingroup transform */ +int imProcessHoughLinesDraw(const imImage* src_image, const imImage* hough, const imImage* hough_points, imImage* dst_image); + +/** Calculates the Cross Correlation in the frequency domain. \n + * CrossCorr(a,b) = IFFT(Conj(FFT(a))*FFT(b)) \n + * Images must be of the same size and only destiny image must be of type complex. + * + * \verbatim im.ProcessCrossCorrelation(src_image1: imImage, src_image2: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessCrossCorrelationNew(image1: imImage, image2: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup transform */ +void imProcessCrossCorrelation(const imImage* src_image1, const imImage* src_image2, imImage* dst_image); + +/** Calculates the Auto Correlation in the frequency domain. \n + * Uses the cross correlation. + * Images must be of the same size and only destiny image must be of type complex. + * + * \verbatim im.ProcessAutoCorrelation(src_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessAutoCorrelationNew(image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup transform */ +void imProcessAutoCorrelation(const imImage* src_image, imImage* dst_image); + +/** Calculates the Distance Transform of a binary image + * using an aproximation of the euclidian distance.\n + * Each white pixel in the binary image is + * assigned a value equal to its distance from the nearest + * black pixel. \n + * Uses a two-pass algorithm incrementally calculating the distance. \n + * Source image must be IM_BINARY, destiny must be IM_FLOAT. + * + * \verbatim im.ProcessDistanceTransform(src_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessDistanceTransformNew(image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup transform */ +void imProcessDistanceTransform(const imImage* src_image, imImage* dst_image); + +/** Marks all the regional maximum of the distance transform. \n + * source is IMGRAY/IM_FLOAT destiny in IM_BINARY. \n + * We consider maximum all connected pixel values that have smaller pixel values around it. + * + * \verbatim im.ProcessRegionalMaximum(src_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessRegionalMaximumNew(image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup transform */ +void imProcessRegionalMaximum(const imImage* src_image, imImage* dst_image); + + + +/** \defgroup fourier Fourier Transform Operations + * \par + * All Fourier transforms use FFTW library. \n + * The pre-compiled binaries for FFTW version 2.1.5 includes all the necessary files. + * The pre-compiled binaries for FFTW version 3.x depends on an external library, not provided. + * To build the code that uses FFTW version 3 you must define USE_FFTW3. + * \par + * FFTW Copyright Matteo Frigo, Steven G. Johnson and the MIT. \n + * http://www.fftw.org \n + * See "fftw.h" + * \par + * Must link with "im_fftw" library. \n + * \par + * IMPORTANT: The FFTW lib has a GPL license. The license of the "im_fftw" library is automatically the GPL. + * So you cannot use it for commercial applications without contacting the authors. + * \par + * See \ref im_process_glo.h + * \ingroup process */ + +/** Forward FFT. \n + * The result has its lowest frequency at the center of the image. \n + * This is an unnormalized fft. \n + * Images must be of the same size. Destiny image must be of type complex. + * + * \verbatim im.ProcessFFT(src_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessFFTNew(image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup fourier */ +void imProcessFFT(const imImage* src_image, imImage* dst_image); + +/** Inverse FFT. \n + * The image has its lowest frequency restored to the origin before the transform. \n + * The result is normalized by (width*height). \n + * Images must be of the same size and both must be of type complex. + * + * \verbatim im.ProcessIFFT(src_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessIFFTNew(image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup fourier */ +void imProcessIFFT(const imImage* src_image, imImage* dst_image); + +/** Raw in-place FFT (forward or inverse). \n + * The lowest frequency can be centered after forward, or + * can be restored to the origin before inverse. \n + * The result can be normalized after the transform by sqrt(w*h) [1] or by (w*h) [2], + * or left unnormalized [0]. \n + * Images must be of the same size and both must be of type complex. + * + * \verbatim im.ProcessFFTraw(image: imImage, inverse: number, center: number, normalize: number) [in Lua 5] \endverbatim + * \ingroup fourier */ +void imProcessFFTraw(imImage* image, int inverse, int center, int normalize); + +/** Auxiliary function for the raw FFT. \n + * This is the function used internally to change the lowest frequency position in the image. \n + * If the image size has even dimensions the flag "center2origin" is useless. But if it is odd, + * you must specify if its from center to origin (usually used before inverse) or + * from origin to center (usually used after forward). \n + * Notice that this function is used for images in the the frequency domain. \n + * Image type must be complex. + * + * \verbatim im.ProcessSwapQuadrants(image: imImage, center2origin: number) [in Lua 5] \endverbatim + * \ingroup fourier */ +void imProcessSwapQuadrants(imImage* image, int center2origin); + + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/im/include/im_process_loc.h b/im/include/im_process_loc.h new file mode 100755 index 0000000..44e8281 --- /dev/null +++ b/im/include/im_process_loc.h @@ -0,0 +1,606 @@ +/** \file + * \brief Image Processing - Local Operations + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_PROCESS_LOC_H +#define __IM_PROCESS_LOC_H + +#include "im_image.h" + +#if defined(__cplusplus) +extern "C" { +#endif + + + +/** \defgroup resize Image Resize + * \par + * Operations to change the image size. + * \par + * See \ref im_process_loc.h + * \ingroup process */ + +/** Only reduze the image size using the given decimation order. \n + * Supported decimation orders: + * \li 0 - zero order (mean) + * \li 1 - first order (bilinear decimation) + * Images must be of the same type. If image type is IM_MAP or IM_BINARY, must use order=0. \n + * Returns zero if the counter aborted. + * + * \verbatim im.ProcessReduce(src_image: imImage, dst_image: imImage, order: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessReduceNew(image: imImage, order: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup resize */ +int imProcessReduce(const imImage* src_image, imImage* dst_image, int order); + +/** Change the image size using the given interpolation order. \n + * Supported interpolation orders: + * \li 0 - zero order (near neighborhood) + * \li 1 - first order (bilinear interpolation) + * \li 3 - third order (bicubic interpolation) + * Images must be of the same type. If image type is IM_MAP or IM_BINARY, must use order=0. \n + * Returns zero if the counter aborted. + * + * \verbatim im.ProcessResize(src_image: imImage, dst_image: imImage, order: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessResizeNew(image: imImage, order: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup resize */ +int imProcessResize(const imImage* src_image, imImage* dst_image, int order); + +/** Reduze the image area by 4 (w/2,h/2). \n + * Images must be of the same type. Destiny image size must be source image width/2, height/2. + * Can not operate on IM_MAP nor IM_BINARY images. + * + * \verbatim im.ProcessReduceBy4(src_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessReduceBy4New(image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup resize */ +void imProcessReduceBy4(const imImage* src_image, imImage* dst_image); + +/** Extract a rectangular region from an image. \n + * Images must be of the same type. Destiny image size must be smaller than source image width-xmin, height-ymin. \n + * ymin and xmin must be >0 and new_image: imImage [in Lua 5] \endverbatim + * \ingroup resize */ +void imProcessCrop(const imImage* src_image, imImage* dst_image, int xmin, int ymin); + +/** Insert a rectangular region in an image. \n + * Images must be of the same type. Region image size can be larger than source image. \n + * ymin and xmin must be >0 and new_image: imImage [in Lua 5] \endverbatim + * \ingroup resize */ +void imProcessInsert(const imImage* src_image, const imImage* region_image, imImage* dst_image, int xmin, int ymin); + +/** Increase the image size by adding pixels with zero value. \n + * Images must be of the same type. Destiny image size must be greatter than source image width+xmin, height+ymin. + * + * \verbatim im.ProcessAddMargins(src_image: imImage, dst_image: imImage, xmin: number, ymin: number) [in Lua 5] \endverbatim + * \verbatim im.ProcessAddMarginsNew(image: imImage, xmin: number, xmax: number, ymin: number, ymax: number) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup resize */ +void imProcessAddMargins(const imImage* src_image, imImage* dst_image, int xmin, int ymin); + + + +/** \defgroup geom Geometric Operations + * \par + * Operations to change the shape of the image. + * \par + * See \ref im_process_loc.h + * \ingroup process */ + +/** Calculates the size of the new image after rotation. + * + * \verbatim im.ProcessCalcRotateSize(width: number, height: number, cos0: number, sin0: number) [in Lua 5] \endverbatim + * \ingroup geom */ +void imProcessCalcRotateSize(int width, int height, int *new_width, int *new_height, double cos0, double sin0); + +/** Rotates the image using the given interpolation order (see \ref imProcessResize). \n + * Images must be of the same type. The destiny size can be calculated using \ref imProcessCalcRotateSize to fit the new image size, + * or can be any size, including the original size. The rotation is relative to the center of the image. \n + * Returns zero if the counter aborted. + * + * \verbatim im.ProcessRotate(src_image: imImage, dst_image: imImage, cos0: number, sin0: number, order: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessRotateNew(image: imImage, cos0: number, sin0: number, order: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup geom */ +int imProcessRotate(const imImage* src_image, imImage* dst_image, double cos0, double sin0, int order); + +/** Rotates the image using the given interpolation order (see \ref imProcessResize). \n + * Images must be of the same type. Destiny can have any size, including the original size. \n + * The rotation is relative to the reference point. But the result can be shifted to the origin. \n + * Returns zero if the counter aborted. + * + * \verbatim im.ProcessRotateRef(src_image: imImage, dst_image: imImage, cos0: number, sin0: number, x: number, y: number, to_origin: boolean, order: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessRotateRefNew(image: imImage, cos0: number, sin0: number, x: number, y: number, to_origin: boolean, order: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup geom */ +int imProcessRotateRef(const imImage* src_image, imImage* dst_image, double cos0, double sin0, int x, int y, int to_origin, int order); + +/** Rotates the image in 90 degrees counterclockwise or clockwise. Swap columns by lines. \n + * Images must be of the same type. Destiny width and height must be source height and width. \n + * Direction can be clockwise (1) or counter clockwise (-1). + * + * \verbatim im.ProcessRotate90(src_image: imImage, dst_image: imImage, dir_clockwise: boolean) [in Lua 5] \endverbatim + * \verbatim im.ProcessRotate90New(image: imImage, dir_clockwise: boolean) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup geom */ +void imProcessRotate90(const imImage* src_image, imImage* dst_image, int dir_clockwise); + +/** Rotates the image in 180 degrees. Swap columns and swap lines. \n + * Images must be of the same type and size. + * + * \verbatim im.ProcessRotate180(src_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessRotate180New(image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup geom */ +void imProcessRotate180(const imImage* src_image, imImage* dst_image); + +/** Mirror the image in a horizontal flip. Swap columns. \n + * Images must be of the same type and size. + * Can be done in-place. + * + * \verbatim im.ProcessMirror(src_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessMirrorNew(image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup geom */ +void imProcessMirror(const imImage* src_image, imImage* dst_image); + +/** Apply a vertical flip. Swap lines. \n + * Images must be of the same type and size. + * Can be done in-place. + * + * \verbatim im.ProcessFlip(src_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessFlipNew(image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup geom */ +void imProcessFlip(const imImage* src_image, imImage* dst_image); + +/** Apply a radial distortion using the given interpolation order (see imProcessResize). \n + * Images must be of the same type and size. Returns zero if the counter aborted. + * + * \verbatim im.ProcessRadial(src_image: imImage, dst_image: imImage, k1: number, order: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessRadialNew(image: imImage, k1: number, order: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup geom */ +int imProcessRadial(const imImage* src_image, imImage* dst_image, float k1, int order); + +/** Apply a swirl distortion using the given interpolation order (see imProcessResize). \n + * Images must be of the same type and size. Returns zero if the counter aborted. + * + * \verbatim im.ProcessSwirl(src_image: imImage, dst_image: imImage, k: number, order: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessSwirlNew(image: imImage, k: number, order: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup geom */ +int imProcessSwirl(const imImage* src_image, imImage* dst_image, float k1, int order); + +/** Split the image in two images, one containing the odd lines and other containing the even lines. \n + * Images must be of the same type. Height of the output images must be half the height of the input image. + * If the height of the input image is odd then the first image must have height equals to half+1. + * + * \verbatim im.ProcessInterlaceSplit(src_image: imImage, dst_image1: imImage, dst_image2: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessInterlaceSplitNew(image: imImage) -> new_image1: imImage, new_image2: imImage [in Lua 5] \endverbatim + * \ingroup geom */ +void imProcessInterlaceSplit(const imImage* src_image, imImage* dst_image1, imImage* dst_image2); + + + +/** \defgroup morphgray Morphology Operations for Gray Images + * \par + * See \ref im_process_loc.h + * \ingroup process */ + +/** Base gray morphology convolution. \n + * Supports all data types except IM_CFLOAT. Can be applied on color images. \n + * Kernel is always IM_INT. Use kernel size odd for better results. \n + * Use -1 for don't care positions in kernel. Kernel values are added to image values, then \n + * you can use the maximum or the minimum within the kernel area. \n + * No border extensions are used. + * All the gray morphology operations use this function. \n + * If the kernel image attribute "Description" exists it is used by the counter. + * + * \verbatim im.ProcessGrayMorphConvolve(src_image: imImage, dst_image: imImage, kernel: imImage, ismax: boolean) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessGrayMorphConvolveNew(image: imImage, kernel: imImage, ismax: boolean) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup morphgray */ +int imProcessGrayMorphConvolve(const imImage* src_image, imImage* dst_image, const imImage* kernel, int ismax); + +/** Gray morphology convolution with a kernel full of "0"s and use minimum value. + * + * \verbatim im.ProcessGrayMorphErode(src_image: imImage, dst_image: imImage, kernel_size: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessGrayMorphErodeNew(image: imImage, kernel_size: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup morphgray */ +int imProcessGrayMorphErode(const imImage* src_image, imImage* dst_image, int kernel_size); + +/** Gray morphology convolution with a kernel full of "0"s and use maximum value. + * + * \verbatim im.ProcessGrayMorphDilate(src_image: imImage, dst_image: imImage, kernel_size: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessGrayMorphDilateNew(image: imImage, kernel_size: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup morphgray */ +int imProcessGrayMorphDilate(const imImage* src_image, imImage* dst_image, int kernel_size); + +/** Erode+Dilate. + * + * \verbatim im.ProcessGrayMorphOpen(src_image: imImage, dst_image: imImage, kernel_size: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessGrayMorphOpenNew(image: imImage, kernel_size: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup morphgray */ +int imProcessGrayMorphOpen(const imImage* src_image, imImage* dst_image, int kernel_size); + +/** Dilate+Erode. + * + * \verbatim im.ProcessGrayMorphClose(src_image: imImage, dst_image: imImage, kernel_size: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessGrayMorphCloseNew(image: imImage, kernel_size: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup morphgray */ +int imProcessGrayMorphClose(const imImage* src_image, imImage* dst_image, int kernel_size); + +/** Open+Difference. + * + * \verbatim im.ProcessGrayMorphTopHat(src_image: imImage, dst_image: imImage, kernel_size: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessGrayMorphTopHatNew(image: imImage, kernel_size: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup morphgray */ +int imProcessGrayMorphTopHat(const imImage* src_image, imImage* dst_image, int kernel_size); + +/** Close+Difference. + * + * \verbatim im.ProcessGrayMorphWell(src_image: imImage, dst_image: imImage, kernel_size: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessGrayMorphWellNew(image: imImage, kernel_size: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup morphgray */ +int imProcessGrayMorphWell(const imImage* src_image, imImage* dst_image, int kernel_size); + +/** Difference(Erode, Dilate). + * + * \verbatim im.ProcessGrayMorphGradient(src_image: imImage, dst_image: imImage, kernel_size: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessGrayMorphGradientNew(image: imImage, kernel_size: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup morphgray */ +int imProcessGrayMorphGradient(const imImage* src_image, imImage* dst_image, int kernel_size); + + + +/** \defgroup morphbin Morphology Operations for Binary Images + * \par + * See \ref im_process_loc.h + * \ingroup process */ + +/** Base binary morphology convolution. \n + * Images are all IM_BINARY. Kernel is IM_INT, but values can be only 1, 0 or -1. Use kernel size odd for better results. \n + * Hit white means hit=1 and miss=0, or else hit=0 and miss=1. \n + * Use -1 for don't care positions in kernel. Kernel values are simply compared with image values. \n + * The operation can be repeated by a number of iterations. + * The border is zero extended. \n + * Almost all the binary morphology operations use this function.\n + * If the kernel image attribute "Description" exists it is used by the counter. + * + * \verbatim im.ProcessBinMorphConvolve(src_image: imImage, dst_image: imImage, kernel: imImage, hit_white: boolean, iter: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessBinMorphConvolveNew(image: imImage, kernel: imImage, hit_white: boolean, iter: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup morphbin */ +int imProcessBinMorphConvolve(const imImage* src_image, imImage* dst_image, const imImage* kernel, int hit_white, int iter); + +/** Binary morphology convolution with a kernel full of "1"s and hit white. + * + * \verbatim im.ProcessBinMorphErode(src_image: imImage, dst_image: imImage, kernel_size: number, iter: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessBinMorphErodeNew(image: imImage, kernel_size: number, iter: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup morphbin */ +int imProcessBinMorphErode(const imImage* src_image, imImage* dst_image, int kernel_size, int iter); + +/** Binary morphology convolution with a kernel full of "0"s and hit black. + * + * \verbatim im.ProcessBinMorphDilate(src_image: imImage, dst_image: imImage, kernel_size: number, iter: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessBinMorphDilateNew(image: imImage, kernel_size: number, iter: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup morphbin */ +int imProcessBinMorphDilate(const imImage* src_image, imImage* dst_image, int kernel_size, int iter); + +/** Erode+Dilate. + * When iteration is more than one it means Erode+Erode+Erode+...+Dilate+Dilate+Dilate+... + * + * \verbatim im.ProcessBinMorphOpen(src_image: imImage, dst_image: imImage, kernel_size: number, iter: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessBinMorphOpenNew(image: imImage, kernel_size: number, iter: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup morphbin */ +int imProcessBinMorphOpen(const imImage* src_image, imImage* dst_image, int kernel_size, int iter); + +/** Dilate+Erode. + * + * \verbatim im.ProcessBinMorphClose(src_image: imImage, dst_image: imImage, kernel_size: number, iter: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessBinMorphCloseNew(image: imImage, kernel_size: number, iter: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup morphbin */ +int imProcessBinMorphClose(const imImage* src_image, imImage* dst_image, int kernel_size, int iter); + +/** Erode+Difference. \n + * The difference from the source image is applied only once. + * + * \verbatim im.ProcessBinMorphOutline(src_image: imImage, dst_image: imImage, kernel_size: number, iter: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessBinMorphOutlineNew(image: imImage, kernel_size: number, iter: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup morphbin */ +int imProcessBinMorphOutline(const imImage* src_image, imImage* dst_image, int kernel_size, int iter); + +/** Thins the supplied binary image using Rosenfeld's parallel thinning algorithm. \n + * Reference: \n + * "Efficient Binary Image Thinning using Neighborhood Maps" \n + * by Joseph M. Cychosz, 3ksnn64@ecn.purdue.edu \n + * in "Graphics Gems IV", Academic Press, 1994 + * + * \verbatim im.ProcessBinMorphThin(src_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessBinMorphThinNew(image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup morphbin */ +void imProcessBinMorphThin(const imImage* src_image, imImage* dst_image); + + + +/** \defgroup rank Rank Convolution Operations + * \par + * All the rank convolution use the same base function. Near the border the base function + * includes only the real image pixels in the rank. No border extensions are used. + * \par + * See \ref im_process_loc.h + * \ingroup process */ + +/** Rank convolution using the median value. \n + * Returns zero if the counter aborted. \n + * Supports all data types except IM_CFLOAT. Can be applied on color images. + * + * \verbatim im.ProcessMedianConvolve(src_image: imImage, dst_image: imImage, kernel_size: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessMedianConvolveNew(image: imImage, kernel_size: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup rank */ +int imProcessMedianConvolve(const imImage* src_image, imImage* dst_image, int kernel_size); + +/** Rank convolution using (maximum-minimum) value. \n + * Returns zero if the counter aborted. \n + * Supports all data types except IM_CFLOAT. Can be applied on color images. + * + * \verbatim im.ProcessRangeConvolve(src_image: imImage, dst_image: imImage, kernel_size: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessRangeConvolveNew(image: imImage, kernel_size: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup rank */ +int imProcessRangeConvolve(const imImage* src_image, imImage* dst_image, int kernel_size); + +/** Rank convolution using the closest maximum or minimum value. \n + * Returns zero if the counter aborted. \n + * Supports all data types except IM_CFLOAT. Can be applied on color images. + * + * \verbatim im.ProcessRankClosestConvolve(src_image: imImage, dst_image: imImage, kernel_size: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessRankClosestConvolveNew(image: imImage, kernel_size: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup rank */ +int imProcessRankClosestConvolve(const imImage* src_image, imImage* dst_image, int kernel_size); + +/** Rank convolution using the maximum value. \n + * Returns zero if the counter aborted. \n + * Supports all data types except IM_CFLOAT. Can be applied on color images. + * + * \verbatim im.ProcessRankMaxConvolve(src_image: imImage, dst_image: imImage, kernel_size: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessRankMaxConvolveNew(image: imImage, kernel_size: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup rank */ +int imProcessRankMaxConvolve(const imImage* src_image, imImage* dst_image, int kernel_size); + +/** Rank convolution using the minimum value. \n + * Returns zero if the counter aborted. \n + * Supports all data types except IM_CFLOAT. Can be applied on color images. + * + * \verbatim im.ProcessRankMinConvolve(src_image: imImage, dst_image: imImage, kernel_size: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessRankMinConvolveNew(image: imImage, kernel_size: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup rank */ +int imProcessRankMinConvolve(const imImage* src_image, imImage* dst_image, int kernel_size); + +/** Threshold using a rank convolution with a range contrast function. \n + * Supports all integer IM_GRAY images as source, and IM_BINARY as destiny. \n + * Local variable threshold by the method of Bernsen. \n + * Extracted from XITE, Copyright 1991, Blab, UiO \n + * http://www.ifi.uio.no/~blab/Software/Xite/ +\verbatim + Reference: + Bernsen, J: "Dynamic thresholding of grey-level images" + Proc. of the 8th ICPR, Paris, Oct 1986, 1251-1255. + Author: Oivind Due Trier +\endverbatim + * Returns zero if the counter aborted. + * + * \verbatim im.ProcessRangeContrastThreshold(src_image: imImage, dst_image: imImage, kernel_size: number, min_range: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessRangeContrastThresholdNew(image: imImage, kernel_size: number, min_range: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup threshold */ +int imProcessRangeContrastThreshold(const imImage* src_image, imImage* dst_image, int kernel_size, int min_range); + +/** Threshold using a rank convolution with a local max function. \n + * Returns zero if the counter aborted. \n + * Supports all integer IM_GRAY images as source, and IM_BINARY as destiny. + * + * \verbatim im.ProcessLocalMaxThreshold(src_image: imImage, dst_image: imImage, kernel_size: number, min_level: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessLocalMaxThresholdNew(image: imImage, kernel_size: number, min_level: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup threshold */ +int imProcessLocalMaxThreshold(const imImage* src_image, imImage* dst_image, int kernel_size, int min_level); + + + +/** \defgroup convolve Convolution Operations + * \par + * See \ref im_process_loc.h + * \ingroup process */ + +/** Base Convolution with a kernel. \n + * Kernel can be IM_INT or IM_FLOAT, but always IM_GRAY. Use kernel size odd for better results. \n + * Supports all data types. The border is mirrored. \n + * Returns zero if the counter aborted. Most of the convolutions use this function.\n + * If the kernel image attribute "Description" exists it is used by the counter. + * + * \verbatim im.ProcessConvolve(src_image: imImage, dst_image: imImage, kernel: imImage) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessConvolveNew(image: imImage, kernel: imImage) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup convolve */ +int imProcessConvolve(const imImage* src_image, imImage* dst_image, const imImage* kernel); + +/** Base convolution when the kernel is separable. Only the first line and the first column will be used. \n + * Returns zero if the counter aborted.\n + * If the kernel image attribute "Description" exists it is used by the counter. + * + * \verbatim im.ProcessConvolveSep(src_image: imImage, dst_image: imImage, kernel: imImage) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessConvolveSepNew(image: imImage, kernel: imImage) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup convolve */ +int imProcessConvolveSep(const imImage* src_image, imImage* dst_image, const imImage* kernel); + +/** Base Convolution with two kernels. The result is the magnitude of the result of each convolution. \n + * Kernel can be IM_INT or IM_FLOAT, but always IM_GRAY. Use kernel size odd for better results. \n + * Supports all data types. The border is mirrored. \n + * Returns zero if the counter aborted. Most of the convolutions use this function.\n + * If the kernel image attribute "Description" exists it is used by the counter. + * + * \verbatim im.ProcessConvolveDual(src_image: imImage, dst_image: imImage, kernel1, kernel2: imImage) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessConvolveDualNew(image: imImage, kernel1, kernel2: imImage) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup convolve */ +int imProcessConvolveDual(const imImage* src_image, imImage* dst_image, const imImage *kernel1, const imImage *kernel2); + +/** Repeats the convolution a number of times. \n + * Returns zero if the counter aborted.\n + * If the kernel image attribute "Description" exists it is used by the counter. + * + * \verbatim im.ProcessConvolveRep(src_image: imImage, dst_image: imImage, kernel: imImage, count: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessConvolveRepNew(image: imImage, kernel: imImage, count: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup convolve */ +int imProcessConvolveRep(const imImage* src_image, imImage* dst_image, const imImage* kernel, int count); + +/** Convolve with a kernel rotating it 8 times and getting the absolute maximum value. \n + * Kernel must be square. \n + * The rotation is implemented only for kernel sizes 3x3, 5x5 and 7x7. \n + * Supports all data types except IM_CFLOAT. + * Returns zero if the counter aborted.\n + * If the kernel image attribute "Description" exists it is used by the counter. + * + * \verbatim im.ProcessCompassConvolve(src_image: imImage, dst_image: imImage, kernel: imImage) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessCompassConvolveNew(image: imImage, kernel: imImage) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup convolve */ +int imProcessCompassConvolve(const imImage* src_image, imImage* dst_image, imImage* kernel); + +/** Utility function to rotate a kernel one time. + * + * \verbatim im.ProcessRotateKernel(kernel: imImage) [in Lua 5] \endverbatim + * \ingroup convolve */ +void imProcessRotateKernel(imImage* kernel); + +/** Difference(Gaussian1, Gaussian2). \n + * Supports all data types, + * but if source is IM_BYTE or IM_USHORT destiny image must be of type IM_INT. + * + * \verbatim im.ProcessDiffOfGaussianConvolve(src_image: imImage, dst_image: imImage, stddev1: number, stddev2: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessDiffOfGaussianConvolveNew(image: imImage, stddev1: number, stddev2: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup convolve */ +int imProcessDiffOfGaussianConvolve(const imImage* src_image, imImage* dst_image, float stddev1, float stddev2); + +/** Convolution with a laplacian of a gaussian kernel. \n + * Supports all data types, + * but if source is IM_BYTE or IM_USHORT destiny image must be of type IM_INT. + * + * \verbatim im.ProcessLapOfGaussianConvolve(src_image: imImage, dst_image: imImage, stddev: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessLapOfGaussianConvolveNew(image: imImage, stddev: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup convolve */ +int imProcessLapOfGaussianConvolve(const imImage* src_image, imImage* dst_image, float stddev); + +/** Convolution with a kernel full of "1"s inside a circle. \n + * Supports all data types. + * + * \verbatim im.ProcessMeanConvolve(src_image: imImage, dst_image: imImage, kernel_size: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessMeanConvolveNew(image: imImage, kernel_size: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup convolve */ +int imProcessMeanConvolve(const imImage* src_image, imImage* dst_image, int kernel_size); + +/** Convolution with a float gaussian kernel. \n + * If sdtdev is negative its magnitude will be used as the kernel size. \n + * Supports all data types. + * + * \verbatim im.ProcessGaussianConvolve(src_image: imImage, dst_image: imImage, stddev: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessGaussianConvolveNew(image: imImage, stddev: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup convolve */ +int imProcessGaussianConvolve(const imImage* src_image, imImage* dst_image, float stddev); + +/** Convolution with a barlett kernel. \n + * Supports all data types. + * + * \verbatim im.ProcessBarlettConvolve(src_image: imImage, dst_image: imImage, kernel_size: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessBarlettConvolveNew(image: imImage, kernel_size: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup convolve */ +int imProcessBarlettConvolve(const imImage* src_image, imImage* dst_image, int kernel_size); + +/** Magnitude of the sobel convolution. \n + * Supports all data types. + * + * \verbatim im.ProcessSobelConvolve(src_image: imImage, dst_image: imImage) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessSobelConvolveNew(image: imImage) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup convolve */ +int imProcessSobelConvolve(const imImage* src_image, imImage* dst_image); + +/** Magnitude of the prewitt convolution. \n + * Supports all data types. + * + * \verbatim im.ProcessPrewittConvolve(src_image: imImage, dst_image: imImage) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessPrewittConvolveNew(image: imImage) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup convolve */ +int imProcessPrewittConvolve(const imImage* src_image, imImage* dst_image); + +/** Spline edge dectection. \n + * Supports all data types. + * + * \verbatim im.ProcessSplineEdgeConvolve(src_image: imImage, dst_image: imImage) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessSplineEdgeConvolveNew(image: imImage) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup convolve */ +int imProcessSplineEdgeConvolve(const imImage* src_image, imImage* dst_image); + +/** Finds the zero crossings of IM_INT and IM_FLOAT images. Crossings are marked with non zero values + * indicating the intensity of the edge. It is usually used after a second derivative, laplace. \n + * Extracted from XITE, Copyright 1991, Blab, UiO \n + * http://www.ifi.uio.no/~blab/Software/Xite/ + * + * \verbatim im.ProcessZeroCrossing(src_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessZeroCrossingNew(image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup convolve */ +void imProcessZeroCrossing(const imImage* src_image, imImage* dst_image); + +/** First part of the Canny edge detector. Includes the gaussian filtering and the nonmax suppression. \n + * After using this you could apply a Hysteresis Threshold, see \ref imProcessHysteresisThreshold. \n + * Image must be IM_BYTE/IM_GRAY. \n + * Implementation from the book: + \verbatim + J. R. Parker + "Algoritms for Image Processing and Computer Vision" + WILEY + \endverbatim + * + * \verbatim im.ProcessCanny(src_image: imImage, dst_image: imImage, stddev: number) [in Lua 5] \endverbatim + * \verbatim im.ProcessCannyNew(image: imImage, stddev: number) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup convolve */ +void imProcessCanny(const imImage* src_image, imImage* dst_image, float stddev); + +/** Calculates the kernel size given the standard deviation. \n + * If sdtdev is negative its magnitude will be used as the kernel size. + * + * \verbatim im.GaussianStdDev2KernelSize(stddev: number) -> kernel_size: number [in Lua 5] \endverbatim + * \ingroup convolve */ +int imGaussianStdDev2KernelSize(float stddev); + +/** Calculates the standard deviation given the kernel size. + * + * \verbatim im.GaussianKernelSize2StdDev(kernel_size: number) -> stddev: number [in Lua 5] \endverbatim + * \ingroup convolve */ +float imGaussianKernelSize2StdDev(int kernel_size); + +/** Edge enhancement using Unsharp mask. stddev control the gaussian filter, + * amount controls how much the edges will enhance the image (0 new_image: imImage [in Lua 5] \endverbatim + * \ingroup convolve */ +int imProcessUnsharp(const imImage* src_image, imImage* dst_image, float stddev, float amount, float threshold); + +/** Edge enhancement using Laplacian8 mask. + * amount controls how much the edges will enhance the image (0 new_image: imImage [in Lua 5] \endverbatim + * \ingroup convolve */ +int imProcessSharp(const imImage* src_image, imImage* dst_image, float amount, float threshold); + +/** Edge enhancement using a given kernel. + * If kernel has all positive values, then the unsharp technique is used, else sharp is used. + * amount controls how much the edges will enhance the image (0 new_image: imImage [in Lua 5] \endverbatim + * \ingroup convolve */ +int imProcessSharpKernel(const imImage* src_image, const imImage* kernel, imImage* dst_image, float amount, float threshold); + + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/im/include/im_process_pon.h b/im/include/im_process_pon.h new file mode 100755 index 0000000..0611cc6 --- /dev/null +++ b/im/include/im_process_pon.h @@ -0,0 +1,720 @@ +/** \file + * \brief Image Processing - Pontual Operations + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_PROCESS_PON_H +#define __IM_PROCESS_PON_H + +#include "im_image.h" + +#if defined(__cplusplus) +extern "C" { +#endif + + + +/** \defgroup arithm Arithmetic Operations + * \par + * Simple math operations for images. + * \par + * See \ref im_process_pon.h + * \ingroup process */ + +/** Unary Arithmetic Operations. \n + * Inverse and log may lead to math exceptions. + * \ingroup arithm */ +enum imUnaryOp { + IM_UN_EQL, /**< equal = a */ + IM_UN_ABS, /**< abssolute = |a| */ + IM_UN_LESS, /**< less = -a */ + IM_UN_INV, /**< invert = 1/a (#) */ + IM_UN_SQR, /**< square = a*a */ + IM_UN_SQRT, /**< square root = a^(1/2) */ + IM_UN_LOG, /**< natural logarithm = ln(a) (#) */ + IM_UN_EXP, /**< exponential = exp(a) */ + IM_UN_SIN, /**< sine = sin(a) */ + IM_UN_COS, /**< cosine = cos(a) */ + IM_UN_CONJ, /**< complex conjugate = ar - ai*i */ + IM_UN_CPXNORM /**< complex normalization by magnitude = a / cpxmag(a) */ +}; + +/** Apply an arithmetic unary operation. \n + * Can be done in place, images must match size. \n + * Destiny image can be several types depending on source: \n + * \li byte -> byte, ushort, int, float + * \li ushort -> byte, ushort, int, float + * \li int -> byte, ushort, int, float + * \li float -> float + * \li complex -> complex + * If destiny is byte, then the result is cropped to 0-255. + * + * \verbatim im.ProcessUnArithmeticOp(src_image: imImage, dst_image: imImage, op: number) [in Lua 5] \endverbatim + * \verbatim im.ProcessUnArithmeticOpNew(image: imImage, op: number) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup arithm */ +void imProcessUnArithmeticOp(const imImage* src_image, imImage* dst_image, int op); + +/** Binary Arithmetic Operations. \n + * Divide may lead to math exceptions. + * \ingroup arithm */ +enum imBinaryOp { + IM_BIN_ADD, /**< add = a+b */ + IM_BIN_SUB, /**< subtract = a-b */ + IM_BIN_MUL, /**< multiply = a*b */ + IM_BIN_DIV, /**< divide = a/b (#) */ + IM_BIN_DIFF, /**< difference = |a-b| */ + IM_BIN_POW, /**< power = a^b */ + IM_BIN_MIN, /**< minimum = (a < b)? a: b */ + IM_BIN_MAX /**< maximum = (a > b)? a: b */ +}; + +/** Apply a binary arithmetic operation. \n + * Can be done in place, images must match size. \n + * Source images must match type, destiny image can be several types depending on source: \n + * \li byte -> byte, ushort, int, float + * \li ushort -> ushort, int, float + * \li int -> int, float + * \li float -> float + * \li complex -> complex + * One exception is that you can combine complex with float resulting complex. + * If destiny is byte, then the result is cropped to 0-255. + * + * \verbatim im.ProcessArithmeticOp(src_image1: imImage, src_image2: imImage, dst_image: imImage, op: number) [in Lua 5] \endverbatim + * \verbatim im.ProcessArithmeticOpNew(image1: imImage, image2: imImage, op: number) -> new_image: imImage [in Lua 5] \endverbatim + * The New function will create a new image of the same type of the source images. + * \ingroup arithm */ +void imProcessArithmeticOp(const imImage* src_image1, const imImage* src_image2, imImage* dst_image, int op); + +/** Apply a binary arithmetic operation with a constant value. \n + * Can be done in place, images must match size. \n + * Destiny image can be several types depending on source: \n + * \li byte -> byte, ushort, int, float + * \li ushort -> byte, ushort, int, float + * \li int -> byte, ushort, int, float + * \li float -> float + * \li complex -> complex + * The constant value is type casted to an apropriate type before the operation. + * If destiny is byte, then the result is cropped to 0-255. + * + * \verbatim im.ProcessArithmeticConstOp(src_image: imImage, src_const: number, dst_image: imImage, op: number) [in Lua 5] \endverbatim + * \verbatim im.ProcessArithmeticConstOpNew(image: imImage, src_const: number, op: number) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup arithm */ +void imProcessArithmeticConstOp(const imImage* src_image, float src_const, imImage* dst_image, int op); + +/** Blend two images using an alpha value = [a * alpha + b * (1 - alpha)]. \n + * Can be done in place, images must match size and type. \n + * alpha value must be in the interval [0.0 - 1.0]. + * + * \verbatim im.ProcessBlendConst(src_image1: imImage, src_image2: imImage, dst_image: imImage, alpha: number) [in Lua 5] \endverbatim + * \verbatim im.ProcessBlendConstNew(image1: imImage, image2: imImage, alpha: number) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup arithm */ +void imProcessBlendConst(const imImage* src_image1, const imImage* src_image2, imImage* dst_image, float alpha); + +/** Blend two images using an alpha channel = [a * alpha + b * (1 - alpha)]. \n + * Can be done in place, images must match size and type. \n + * alpha_image must have the same data type except for complex images that must be float, and color_space must be IM_GRAY. + * integer alpha values must be: +\verbatim +0 - 255 IM_BYTE +0 - 65535 IM_USHORT +0 - 2147483647 IM_INT +\endverbatim + * that will be normalized to 0 - 1. + * \verbatim im.ProcessBlend(src_image1: imImage, src_image2: imImage, alpha_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessBlendNew(image1: imImage, image2: imImage, alpha_image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup arithm */ +void imProcessBlend(const imImage* src_image1, const imImage* src_image2, const imImage* alpha_image, imImage* dst_image); + +/** Split a complex image into two images with real and imaginary parts \n + * or magnitude and phase parts (polar). \n + * Source image must be IM_CFLOAT, destiny images must be IM_FLOAT. + * + * \verbatim im.ProcessSplitComplex(src_image: imImage, dst_image1: imImage, dst_image2: imImage, polar: boolean) [in Lua 5] \endverbatim + * \verbatim im.ProcessSplitComplexNew(image: imImage, polar: boolean) -> dst_image1: imImage, dst_image2: imImage [in Lua 5] \endverbatim + * \ingroup arithm */ +void imProcessSplitComplex(const imImage* src_image, imImage* dst_image1, imImage* dst_image2, int polar); + +/** Merges two images as the real and imaginary parts of a complex image, \n + * or as magnitude and phase parts (polar = 1). \n + * Source images must be IM_FLOAT, destiny image must be IM_CFLOAT. + * + * \verbatim im.ProcessMergeComplex(src_image1: imImage, src_image2: imImage, dst_image: imImage, polar: boolean) [in Lua 5] \endverbatim + * \verbatim im.ProcessMergeComplexNew(image1: imImage, image2: imImage, polar: boolean) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup arithm */ +void imProcessMergeComplex(const imImage* src_image1, const imImage* src_image2, imImage* dst_image, int polar); + +/** Calculates the mean of multiple images. \n + * Images must match size and type. + * + * \verbatim im.ProcessMultipleMean(src_image_list: table of imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessMultipleMeanNew(src_image_list: table of imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup arithm */ +void imProcessMultipleMean(const imImage** src_image_list, int src_image_count, imImage* dst_image); + +/** Calculates the standard deviation of multiple images. \n + * Images must match size and type. Use \ref imProcessMultipleMean to calculate the mean_image. + * + * \verbatim im.ProcessMultipleStdDev(src_image_list: table of imImage, mean_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessMultipleStdDevNew(src_image_list: table of imImage, mean_image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup arithm */ +void imProcessMultipleStdDev(const imImage** src_image_list, int src_image_count, const imImage *mean_image, imImage* dst_image); + +/** Calculates the auto-covariance of an image with the mean of a set of images. \n + * Images must match size and type. Returns zero if the counter aborted. \n + * Destiny is IM_FLOAT. + * + * \verbatim im.ProcessAutoCovariance(src_image: imImage, mean_image: imImage, dst_image: imImage) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessAutoCovarianceNew(src_image: imImage, mean_image: imImage) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup arithm */ +int imProcessAutoCovariance(const imImage* src_image, const imImage* mean_image, imImage* dst_image); + +/** Multiplies the conjugate of one complex image with another complex image. \n + * Images must match size. Conj(img1) * img2 \n + * Can be done in-place. + * + * \verbatim im.ProcessMultiplyConj(src_image1: imImage, src_image2: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessMultiplyConjNew(src_image1: imImage, src_image2: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup arithm */ +void imProcessMultiplyConj(const imImage* src_image1, const imImage* src_image2, imImage* dst_image); + + + +/** \defgroup quantize Additional Image Quantization Operations + * \par + * Additionally operations to the \ref imConvertColorSpace function. + * \par + * See \ref im_process_pon.h + * \ingroup process */ + +/** Converts a RGB image to a MAP image using uniform quantization + * with an optional 8x8 ordered dither. The RGB image must have data type IM_BYTE. + * + * \verbatim im.ProcessQuantizeRGBUniform(src_image: imImage, dst_image: imImage, do_dither: boolean) [in Lua 5] \endverbatim + * \verbatim im.ProcessQuantizeRGBUniformNew(src_image: imImage, do_dither: boolean) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup quantize */ +void imProcessQuantizeRGBUniform(const imImage* src_image, imImage* dst_image, int do_dither); + +/** Quantizes a gray scale image in less that 256 grays using uniform quantization. \n + * Both images must be IM_BYTE/IM_GRAY. Can be done in place. + * + * \verbatim im.ProcessQuantizeGrayUniform(src_image: imImage, dst_image: imImage, grays: number) [in Lua 5] \endverbatim + * \verbatim im.ProcessQuantizeGrayUniformNew(src_image: imImage, grays: number) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup quantize */ +void imProcessQuantizeGrayUniform(const imImage* src_image, imImage* dst_image, int grays); + + + +/** \defgroup histo Histogram Based Operations + * \par + * See \ref im_process_pon.h + * \ingroup process */ + +/** Performs an histogram expansion based on a percentage of the number of pixels. \n + * Percentage defines an amount of pixels to include at the lowest level and at the highest level. + * If its is zero only empty counts of the histogram will be considered. \n + * Images must be IM_BYTE/(IM_RGB or IM_GRAY). Can be done in place. \n + * To expand the gammut without using the histogram, by just specifing the lowest and highest levels + * use the \ref IM_GAMUT_EXPAND tone gammut operation (\ref imProcessToneGamut). + * + * \verbatim im.ProcessExpandHistogram(src_image: imImage, dst_image: imImage, percent: number) [in Lua 5] \endverbatim + * \verbatim im.ProcessExpandHistogramNew(src_image: imImage, percent: number) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup histo */ +void imProcessExpandHistogram(const imImage* src_image, imImage* dst_image, float percent); + +/** Performs an histogram equalization. \n + * Images must be IM_BYTE/(IM_RGB or IM_GRAY). Can be done in place. + * + * \verbatim im.ProcessEqualizeHistogram(src_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessEqualizeHistogramNew(src_image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup histo */ +void imProcessEqualizeHistogram(const imImage* src_image, imImage* dst_image); + + + +/** \defgroup colorproc Color Processing Operations + * \par + * Operations to change the color components configuration. + * \par + * See \ref im_process_pon.h + * \ingroup process */ + +/** Split a RGB image into luma and chroma. \n + * Chroma is calculated as R-Y,G-Y,B-Y. Source image must be IM_RGB/IM_BYTE. \n + * luma image is IM_GRAY/IM_BYTE and chroma is IM_RGB/IM_BYTE. \n + * Source and destiny must have the same size. + * + * \verbatim im.ProcessSplitYChroma(src_image: imImage, y_image: imImage, chroma_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessSplitYChromaNew(src_image: imImage) -> y_image: imImage, chroma_image: imImage [in Lua 5] \endverbatim + * \ingroup colorproc */ +void imProcessSplitYChroma(const imImage* src_image, imImage* y_image, imImage* chroma_image); + +/** Split a RGB image into HSI planes. \n + * Source image must be IM_RGB/IM_BYTE,IM_FLOAT. Destiny images are all IM_GRAY/IM_FLOAT. \n + * Source images must normalized to 0-1 if type is IM_FLOAT (\ref imProcessToneGamut can be used). See \ref hsi for a definition of the color conversion.\n + * Source and destiny must have the same size. + * + * \verbatim im.ProcessSplitHSI(src_image: imImage, h_image: imImage, s_image: imImage, i_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessSplitHSINew(src_image: imImage) -> h_image: imImage, s_image: imImage, i_image: imImage [in Lua 5] \endverbatim + * \ingroup colorproc */ +void imProcessSplitHSI(const imImage* src_image, imImage* h_image, imImage* s_image, imImage* i_image); + +/** Merge HSI planes into a RGB image. \n + * Source images must be IM_GRAY/IM_FLOAT. Destiny image can be IM_RGB/IM_BYTE,IM_FLOAT. \n + * Source and destiny must have the same size. See \ref hsi for a definition of the color conversion. + * + * \verbatim im.ProcessMergeHSI(h_image: imImage, s_image: imImage, i_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessMergeHSINew(h_image: imImage, s_image: imImage, i_image: imImage) -> dst_image: imImage [in Lua 5] \endverbatim + * \ingroup colorproc */ +void imProcessMergeHSI(const imImage* h_image, const imImage* s_image, const imImage* i_image, imImage* dst_image); + +/** Split a multicomponent image into separate components.\n + * Destiny images must be IM_GRAY. Size and data types must be all the same.\n + * The number of destiny images must match the depth of the source image. + * + * \verbatim im.ProcessSplitComponents(src_image: imImage, dst_image_list: table of imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessSplitComponentsNew(src_image: imImage) -> dst_image_list: table of imImage [in Lua 5] \endverbatim + * \ingroup colorproc */ +void imProcessSplitComponents(const imImage* src_image, imImage** dst_image_list); + +/** Merges separate components into a multicomponent image.\n + * Source images must be IM_GRAY. Size and data types must be all the same.\n + * The number of source images must match the depth of the destiny image. + * + * \verbatim im.ProcessMergeComponents(src_image_list: table of imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessMergeComponentsNew(src_image_list: table of imImage) -> dst_image: imImage [in Lua 5] \endverbatim + * \ingroup colorproc */ +void imProcessMergeComponents(const imImage** src_image_list, imImage* dst_image); + +/** Normalize the color components by their sum. Example: c1 = c1/(c1+c2+c3). \n + * Destiny image must be IM_FLOAT. + * + * \verbatim im.ProcessNormalizeComponents(src_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessNormalizeComponentsNew(src_image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup colorproc */ +void imProcessNormalizeComponents(const imImage* src_image, imImage* dst_image); + +/** Replaces the source color by the destiny color. \n + * The color will be type casted to the image data type. \n + * The colors must have the same number of components of the images. \n + * Supports all color spaces and all data types except IM_CFLOAT. + * + * \verbatim im.ProcessReplaceColor(src_image: imImage, dst_image: imImage, src_color: table of numbers, dst_color: table of numbers) [in Lua 5] \endverbatim + * \verbatim im.ProcessReplaceColorNew(src_image: imImage, src_color: table of numbers, dst_color: table of numbers) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup colorproc */ +void imProcessReplaceColor(const imImage* src_image, imImage* dst_image, float* src_color, float* dst_color); + + + +/** \defgroup logic Logical Arithmetic Operations + * \par + * Logical binary math operations for images. + * \par + * See \ref im_process_pon.h + * \ingroup process */ + +/** Logical Operations. + * \ingroup logic */ +enum imLogicOp { + IM_BIT_AND, /**< and = a & b */ + IM_BIT_OR, /**< or = a | b */ + IM_BIT_XOR /**< xor = ~(a | b) */ +}; + +/** Apply a logical operation.\n + * Images must have data type IM_BYTE, IM_USHORT or IM_INT. Can be done in place. + * + * \verbatim im.ProcessBitwiseOp(src_image1: imImage, src_image2: imImage, dst_image: imImage, op: number) [in Lua 5] \endverbatim + * \verbatim im.ProcessBitwiseOpNew(src_image1: imImage, src_image2: imImage, op: number) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup logic */ +void imProcessBitwiseOp(const imImage* src_image1, const imImage* src_image2, imImage* dst_image, int op); + +/** Apply a logical NOT operation.\n + * Images must have data type IM_BYTE, IM_USHORT or IM_INT. Can be done in place. + * + * \verbatim im.ProcessBitwiseNot(src_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessBitwiseNotNew(src_image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup logic */ +void imProcessBitwiseNot(const imImage* src_image, imImage* dst_image); + +/** Apply a bit mask. \n + * The same as imProcessBitwiseOp but the second image is replaced by a fixed mask. \n + * Images must have data type IM_BYTE. It is valid only for AND, OR and XOR. Can be done in place. + * + * \verbatim im.ProcessBitMask(src_image: imImage, dst_image: imImage, mask: string, op: number) [in Lua 5] \endverbatim + * \verbatim im.ProcessBitMaskNew(src_image: imImage, mask: string, op: number) -> new_image: imImage [in Lua 5] \endverbatim + * In Lua, mask is a string with 0s and 1s, for example: "11001111". + * \ingroup logic */ +void imProcessBitMask(const imImage* src_image, imImage* dst_image, unsigned char mask, int op); + +/** Extract or Reset a bit plane. For ex: 000X0000 or XXX0XXXX (plane=3).\n + * Images must have data type IM_BYTE. Can be done in place. + * + * \verbatim im.ProcessBitPlane(src_image: imImage, dst_image: imImage, plane: number, do_reset: boolean) [in Lua 5] \endverbatim + * \verbatim im.ProcessBitPlaneNew(src_image: imImage, plane: number, do_reset: boolean) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup logic */ +void imProcessBitPlane(const imImage* src_image, imImage* dst_image, int plane, int do_reset); + + + +/** \defgroup render Synthetic Image Render + * \par + * Renders some 2D mathematical functions as images. All the functions operates in place + * and supports all data types except IM_CFLOAT. + * \par + * See \ref im_process_pon.h + * \ingroup process */ + +/** Render Funtion. + * \verbatim render_func(x: number, y: number, d: number, param: table of number) -> value: number [in Lua 5] \endverbatim + * \ingroup render */ +typedef float (*imRenderFunc)(int x, int y, int d, float* param); + +/** Render Conditional Funtion. + * \verbatim render_cond_func(x: number, y: number, d: number, param: table of number) -> value: number, cond: boolean [in Lua 5] \endverbatim + * \ingroup render */ +typedef float (*imRenderCondFunc)(int x, int y, int d, int *cond, float* param); + +/** Render a synthetic image using a render function. \n + * plus will make the render be added to the current image data, + * or else all data will be replaced. All the render functions use this or the conditional function. \n + * Returns zero if the counter aborted. + * + * \verbatim im.ProcessRenderOp(image: imImage, render_func: function, render_name: string, param: table of number, plus: boolean) -> counter: boolean [in Lua 5] \endverbatim + * \ingroup render */ +int imProcessRenderOp(imImage* image, imRenderFunc render_func, char* render_name, float* param, int plus); + +/** Render a synthetic image using a conditional render function. \n + * Data will be rendered only if the condional param is true. \n + * Returns zero if the counter aborted. + * + * \verbatim im.ProcessRenderCondOp(image: imImage, render_cond_func: function, render_name: string, param: table of number) -> counter: boolean [in Lua 5] \endverbatim + * \ingroup render */ +int imProcessRenderCondOp(imImage* image, imRenderCondFunc render_cond_func, char* render_name, float* param); + +/** Render speckle noise on existing data. Can be done in place. + * + * \verbatim im.ProcessRenderAddSpeckleNoise(src_image: imImage, dst_image: imImage, percent: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessRenderAddSpeckleNoiseNew(src_image: imImage, percent: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup render */ +int imProcessRenderAddSpeckleNoise(const imImage* src_image, imImage* dst_image, float percent); + +/** Render gaussian noise on existing data. Can be done in place. + * + * \verbatim im.ProcessRenderAddGaussianNoise(src_image: imImage, dst_image: imImage, mean: number, stddev: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessRenderAddGaussianNoiseNew(src_image: imImage, mean: number, stddev: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup render */ +int imProcessRenderAddGaussianNoise(const imImage* src_image, imImage* dst_image, float mean, float stddev); + +/** Render uniform noise on existing data. Can be done in place. + * + * \verbatim im.ProcessRenderAddUniformNoise(src_image: imImage, dst_image: imImage, mean: number, stddev: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessRenderAddUniformNoiseNew(src_image: imImage, mean: number, stddev: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup render */ +int imProcessRenderAddUniformNoise(const imImage* src_image, imImage* dst_image, float mean, float stddev); + +/** Render random noise. + * + * \verbatim im.ProcessRenderRandomNoise(image: imImage) -> counter: boolean [in Lua 5] \endverbatim + * \ingroup render */ +int imProcessRenderRandomNoise(imImage* image); + +/** Render a constant. The number of values must match the depth of the image. + * + * \verbatim im.ProcessRenderConstant(image: imImage, value: table of number) -> counter: boolean [in Lua 5] \endverbatim + * \ingroup render */ +int imProcessRenderConstant(imImage* image, float* value); + +/** Render a centered wheel. + * + * \verbatim im.ProcessRenderWheel(image: imImage, internal_radius: number, external_radius: number) -> counter: boolean [in Lua 5] \endverbatim + * \ingroup render */ +int imProcessRenderWheel(imImage* image, int internal_radius, int external_radius); + +/** Render a centered cone. + * + * \verbatim im.ProcessRenderCone(image: imImage, radius: number) -> counter: boolean [in Lua 5] \endverbatim + * \ingroup render */ +int imProcessRenderCone(imImage* image, int radius); + +/** Render a centered tent. + * + * \verbatim im.ProcessRenderTent(image: imImage, tent_width: number, tent_height: number) -> counter: boolean [in Lua 5] \endverbatim + * \ingroup render */ +int imProcessRenderTent(imImage* image, int tent_width, int tent_height); + +/** Render a ramp. Direction can be vertical (1) or horizontal (0). + * + * \verbatim im.ProcessRenderRamp(image: imImage, start: number, end: number, vert_dir: boolean) -> counter: boolean [in Lua 5] \endverbatim + * \ingroup render */ +int imProcessRenderRamp(imImage* image, int start, int end, int vert_dir); + +/** Render a centered box. + * + * \verbatim im.ProcessRenderBox(image: imImage, box_width: number, box_height: number) -> counter: boolean [in Lua 5] \endverbatim + * \ingroup render */ +int imProcessRenderBox(imImage* image, int box_width, int box_height); + +/** Render a centered sinc. + * + * \verbatim im.ProcessRenderSinc(image: imImage, x_period: number, y_period: number) -> counter: boolean [in Lua 5] \endverbatim + * \ingroup render */ +int imProcessRenderSinc(imImage* image, float x_period, float y_period); + +/** Render a centered gaussian. + * + * \verbatim im.ProcessRenderGaussian(image: imImage, stddev: number) -> counter: boolean [in Lua 5] \endverbatim + * \ingroup render */ +int imProcessRenderGaussian(imImage* image, float stddev); + +/** Render the laplacian of a centered gaussian. + * + * \verbatim im.ProcessRenderLapOfGaussian(image: imImage, stddev: number) -> counter: boolean [in Lua 5] \endverbatim + * \ingroup render */ +int imProcessRenderLapOfGaussian(imImage* image, float stddev); + +/** Render a centered cosine. + * + * \verbatim im.ProcessRenderCosine(image: imImage, x_period: number, y_period: number) -> counter: boolean [in Lua 5] \endverbatim + * \ingroup render */ +int imProcessRenderCosine(imImage* image, float x_period, float y_period); + +/** Render a centered grid. + * + * \verbatim im.ProcessRenderGrid(image: imImage, x_space: number, y_space: number) -> counter: boolean [in Lua 5] \endverbatim + * \ingroup render */ +int imProcessRenderGrid(imImage* image, int x_space, int y_space); + +/** Render a centered chessboard. + * + * \verbatim im.ProcessRenderChessboard(image: imImage, x_space: number, y_space: number) -> counter: boolean [in Lua 5] \endverbatim + * \ingroup render */ +int imProcessRenderChessboard(imImage* image, int x_space, int y_space); + + + +/** \defgroup tonegamut Tone Gamut Operations + * \par + * Operations that try to preserve the min-max interval in the output (the dynamic range). + * \par + * See \ref im_process_pon.h + * \ingroup process */ + + +/** Tone Gamut Operations. + * \ingroup tonegamut */ +enum imToneGamut { + IM_GAMUT_NORMALIZE, /**< normalize = (a-min) / (max-min) (destiny image must be IM_FLOAT) */ + IM_GAMUT_POW, /**< pow = ((a-min) / (max-min))^gamma * (max-min) + min \n + param[0]=gamma */ + IM_GAMUT_LOG, /**< log = log(K * (a-min) / (max-min) + 1))*(max-min)/log(K+1) + min \n + param[0]=K (K>0) */ + IM_GAMUT_EXP, /**< exp = (exp(K * (a-min) / (max-min)) - 1))*(max-min)/(exp(K)-1) + min \n + param[0]=K */ + IM_GAMUT_INVERT, /**< invert = max - (a-min) */ + IM_GAMUT_ZEROSTART, /**< zerostart = a - min */ + IM_GAMUT_SOLARIZE, /**< solarize = a < level ? a: (level * (max-min) - a * (level-min)) / (max-level) \n + param[0]=level percentage (0-100) relative to min-max \n + photography solarization effect. */ + IM_GAMUT_SLICE, /**< slice = start < a || a > end ? min: binarize? max: a \n + param[0]=start, param[1]=end, param[2]=binarize */ + IM_GAMUT_EXPAND, /**< expand = a < start ? min: a > end ? max : (a-start)*(max-min)/(end-start) + min \n + param[0]=start, param[1]=end */ + IM_GAMUT_CROP, /**< crop = a < start ? start: a > end ? end : a \n + param[0]=start, param[1]=end */ + IM_GAMUT_BRIGHTCONT /**< brightcont = a < min ? min: a > max ? max: a * tan(c_a) + b_s + (max-min)*(1 - tan(c_a))/2 \n + param[0]=bright_shift (-100%..+100%), param[1]=contrast_factor (-100%..+100%) \n + change brightness and contrast simultaneously. */ +}; + +/** Apply a gamut operation with arguments. \n + * Supports all data types except IM_CFLOAT. \n + * The linear operation do a special convertion when min > 0 and max < 1, it forces min=0 and max=1. \n + * IM_BYTE images have min=0 and max=255 always. \n + * Can be done in place. When there is no extra params, can use NULL. + * + * \verbatim im.ProcessToneGamut(src_image: imImage, dst_image: imImage, op: number, param: table of number) [in Lua 5] \endverbatim + * \verbatim im.ProcessToneGamutNew(src_image: imImage, op: number, param: table of number) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup tonegamut */ +void imProcessToneGamut(const imImage* src_image, imImage* dst_image, int op, float* param); + +/** Converts from (0-1) to (0-255), crop out of bounds values. \n + * Source image must be IM_FLOAT, and destiny image must be IM_BYTE. + * + * \verbatim im.ProcessUnNormalize(src_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessUnNormalizeNew(src_image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup tonegamut */ +void imProcessUnNormalize(const imImage* src_image, imImage* dst_image); + +/** Directly converts IM_USHORT, IM_INT and IM_FLOAT into IM_BYTE images. \n + * This can also be done using \ref imConvertDataType with IM_CAST_DIRECT. + * + * \verbatim im.ProcessDirectConv(src_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessDirectConvNew(src_image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup tonegamut */ +void imProcessDirectConv(const imImage* src_image, imImage* dst_image); + +/** A negative effect. Uses \ref imProcessToneGamut with IM_GAMUT_INVERT for non MAP images. \n + * Supports all color spaces and all data types except IM_CFLOAT. \n + * Can be done in place. + * + * \verbatim im.ProcessNegative(src_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessNegativeNew(src_image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup tonegamut */ +void imProcessNegative(const imImage* src_image, imImage* dst_image); + + + +/** \defgroup threshold Threshold Operations + * \par + * Operations that converts a usually IM_GRAY/IM_BYTE image into a IM_BINARY image using several threshold techniques. + * \par + * See \ref im_process_pon.h + * \ingroup process */ + +/** Apply a manual threshold. \n + * threshold = a <= level ? 0: value \n + * Normal value is 1 but another common value is 255. Can be done in place for IM_BYTE source. \n + * Supports all integer IM_GRAY images as source, and IM_BINARY as destiny. + * + * \verbatim im.ProcessThreshold(src_image: imImage, dst_image: imImage, level: number, value: number) [in Lua 5] \endverbatim + * \verbatim im.ProcessThresholdNew(src_image: imImage, level: number, value: number) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup threshold */ +void imProcessThreshold(const imImage* src_image, imImage* dst_image, int level, int value); + +/** Apply a threshold by the difference of two images. \n + * threshold = a1 <= a2 ? 0: 1 \n + * Can be done in place. + * + * \verbatim im.ProcessThresholdByDiff(src_image1: imImage, src_image2: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessThresholdByDiffNew(src_image1: imImage, src_image2: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup threshold */ +void imProcessThresholdByDiff(const imImage* src_image1, const imImage* src_image2, imImage* dst_image); + +/** Apply a threshold by the Hysteresis method. \n + * Hysteresis thersholding of edge pixels. Starting at pixels with a + * value greater than the HIGH threshold, trace a connected sequence + * of pixels that have a value greater than the LOW threhsold. \n + * Supports only IM_BYTE images. + * Note: could not find the original source code author name. + * + * \verbatim im.ProcessHysteresisThreshold(src_image: imImage, dst_image: imImage, low_thres: number, high_thres: number) [in Lua 5] \endverbatim + * \verbatim im.ProcessHysteresisThresholdNew(src_image: imImage, low_thres: number, high_thres: number) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup threshold */ +void imProcessHysteresisThreshold(const imImage* src_image, imImage* dst_image, int low_thres, int high_thres); + +/** Estimates hysteresis low and high threshold levels. \n + * Supports only IM_BYTE images. + * Usefull for \ref imProcessHysteresisThreshold. + * + * \verbatim im.ProcessHysteresisThresEstimate(image: imImage) -> low_level: number, high_level: number [in Lua 5] \endverbatim + * \ingroup threshold */ +void imProcessHysteresisThresEstimate(const imImage* image, int *low_level, int *high_level); + +/** Calculates the threshold level for manual threshold using an uniform error approach. \n + * Supports only IM_BYTE images. + * Extracted from XITE, Copyright 1991, Blab, UiO \n + * http://www.ifi.uio.no/~blab/Software/Xite/ +\verbatim + Reference: + S. M. Dunn & D. Harwood & L. S. Davis: + "Local Estimation of the Uniform Error Threshold" + IEEE Trans. on PAMI, Vol PAMI-6, No 6, Nov 1984. + Comments: It only works well on images whith large objects. + Author: Olav Borgli, BLAB, ifi, UiO + Image processing lab, Department of Informatics, University of Oslo +\endverbatim + * Returns the used level. + * + * \verbatim im.ProcessUniformErrThreshold(src_image: imImage, dst_image: imImage) -> level: number [in Lua 5] \endverbatim + * \verbatim im.ProcessUniformErrThresholdNew(src_image: imImage) -> level: number, new_image: imImage [in Lua 5] \endverbatim + * \ingroup threshold */ +int imProcessUniformErrThreshold(const imImage* src_image, imImage* dst_image); + +/** Apply a dithering on each image channel by using a difusion error method. \n + * It can be applied on any IM_BYTE images. It will "threshold" each channel indivudually, so + * source and destiny must be of the same depth. + * + * \verbatim im.ProcessDifusionErrThreshold(src_image: imImage, dst_image: imImage, level: number) [in Lua 5] \endverbatim + * \verbatim im.ProcessDifusionErrThresholdNew(src_image: imImage, level: number) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup threshold */ +void imProcessDifusionErrThreshold(const imImage* src_image, imImage* dst_image, int level); + +/** Calculates the threshold level for manual threshold using a percentage of pixels + * that should stay bellow the threshold. \n + * Supports only IM_BYTE images. + * Returns the used level. + * + * \verbatim im.ProcessPercentThreshold(src_image: imImage, dst_image: imImage, percent: number) -> level: number [in Lua 5] \endverbatim + * \verbatim im.ProcessPercentThresholdNew(src_image: imImage, percent: number) -> level: number, new_image: imImage [in Lua 5] \endverbatim + * \ingroup threshold */ +int imProcessPercentThreshold(const imImage* src_image, imImage* dst_image, float percent); + +/** Calculates the threshold level for manual threshold using the Otsu approach. \n + * Returns the used level. \n + * Supports only IM_BYTE images. + * Original implementation by Flavio Szenberg. + * + * \verbatim im.ProcessOtsuThreshold(src_image: imImage, dst_image: imImage) -> level: number [in Lua 5] \endverbatim + * \verbatim im.ProcessOtsuThresholdNew(src_image: imImage) -> level: number, new_image: imImage [in Lua 5] \endverbatim + * \ingroup threshold */ +int imProcessOtsuThreshold(const imImage* src_image, imImage* dst_image); + +/** Calculates the threshold level for manual threshold using (max-min)/2. \n + * Returns the used level. \n + * Supports all integer IM_GRAY images as source, and IM_BINARY as destiny. + * + * \verbatim im.ProcessMinMaxThreshold(src_image: imImage, dst_image: imImage) -> level: number [in Lua 5] \endverbatim + * \verbatim im.ProcessMinMaxThresholdNew(src_image: imImage) -> level: number, new_image: imImage [in Lua 5] \endverbatim + * \ingroup threshold */ +int imProcessMinMaxThreshold(const imImage* src_image, imImage* dst_image); + +/** Estimates Local Max threshold level for IM_BYTE images. + * + * \verbatim im.ProcessLocalMaxThresEstimate(image: imImage) -> level: number [in Lua 5] \endverbatim + * \ingroup threshold */ +void imProcessLocalMaxThresEstimate(const imImage* image, int *level); + +/** Apply a manual threshold using an interval. \n + * threshold = start_level <= a <= end_level ? 1: 0 \n + * Normal value is 1 but another common value is 255. Can be done in place for IM_BYTE source. \n + * Supports all integer IM_GRAY images as source, and IM_BINARY as destiny. + * + * \verbatim im.ProcessSliceThreshold(src_image: imImage, dst_image: imImage, start_level: number, end_level: number) [in Lua 5] \endverbatim + * \verbatim im.ProcessSliceThresholdNew(src_image: imImage, start_level: number, end_level: number) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup threshold */ +void imProcessSliceThreshold(const imImage* src_image, imImage* dst_image, int start_level, int end_level); + + +/** \defgroup effects Special Effects + * \par + * Operations to change image appearance. + * \par + * See \ref im_process_pon.h + * \ingroup process */ + + +/** Generates a zoom in effect averaging colors inside a square region. \n + * Operates only on IM_BYTE images. + * + * \verbatim im.ProcessPixelate(src_image: imImage, dst_image: imImage, box_size: number) [in Lua 5] \endverbatim + * \verbatim im.ProcessPixelateNew(src_image: imImage, box_size: number) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup effects */ +void imProcessPixelate(const imImage* src_image, imImage* dst_image, int box_size); + +/** A simple Posterize effect. It reduces the number of colors in the image eliminating + * less significant bit planes. Can have 1 to 7 levels. See \ref imProcessBitMask. \n + * Images must have data type IM_BYTE. + * + * \verbatim im.ProcessPosterize(src_image: imImage, dst_image: imImage, level: number) [in Lua 5] \endverbatim + * \verbatim im.ProcessPosterizeNew(src_image: imImage, level: number) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup effects */ +void imProcessPosterize(const imImage* src_image, imImage* dst_image, int level); + + + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/im/include/im_raw.h b/im/include/im_raw.h new file mode 100755 index 0000000..073ad7d --- /dev/null +++ b/im/include/im_raw.h @@ -0,0 +1,34 @@ +/** \file + * \brief RAW File Format + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_RAW_H +#define __IM_RAW_H + +#if defined(__cplusplus) +extern "C" { +#endif + + +/** Opens a RAW image file. + * See also \ref imErrorCodes. + * + * \verbatim im.FileOpenRaw(file_name: string) -> ifile: imFile, error: number [in Lua 5] \endverbatim + * \ingroup raw */ +imFile* imFileOpenRaw(const char* file_name, int *error); + +/** Creates a RAW image file. + * See also \ref imErrorCodes. + * + * \verbatim im.FileNewRaw(file_name: string) -> ifile: imFile, error: number [in Lua 5] \endverbatim + * \ingroup raw */ +imFile* imFileNewRaw(const char* file_name, int *error); + + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/im/include/im_util.h b/im/include/im_util.h new file mode 100755 index 0000000..7858b39 --- /dev/null +++ b/im/include/im_util.h @@ -0,0 +1,277 @@ +/** \file + * \brief Utilities + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_UTIL_H +#define __IM_UTIL_H + +#if defined(__cplusplus) +extern "C" { +#endif + + +/** \defgroup util Utilities + * \par + * See \ref im_util.h + * @{ + */ + +#define IM_MIN(_a, _b) (_a < _b? _a: _b) +#define IM_MAX(_a, _b) (_a > _b? _a: _b) + +/** @} */ + + +/** \defgroup str String Utilities + * \par + * See \ref im_util.h + * \ingroup util */ + +/** Check if the two strings are equal. + * \ingroup str */ +int imStrEqual(const char* str1, const char* str2); + +/** Calculate the size of the string but limited to max_len. + * \ingroup str */ +int imStrNLen(const char* str, int max_len); + +/** Check if the data is a string. + * \ingroup str */ +int imStrCheck(const void* data, int count); + + + +/** \defgroup imageutil Raw Data Utilities + * \par + * See \ref im_util.h + * \ingroup imagerep */ + +/** Returns the size of the data buffer. + * + * \verbatim im.ImageDataSize(width: number, height: number, color_mode: number, data_type: number) -> datasize: number [in Lua 5] \endverbatim + * \ingroup imageutil */ +int imImageDataSize(int width, int height, int color_mode, int data_type); + +/** Returns the size of one line of the data buffer. \n + * This depends if the components are packed. If packed includes all components, if not includes only one. + * + * \verbatim im.ImageLineSize(width: number, color_mode: number, data_type: number) -> linesize: number [in Lua 5] \endverbatim + * \ingroup imageutil */ +int imImageLineSize(int width, int color_mode, int data_type); + +/** Returns the number of elements of one line of the data buffer. \n + * This depends if the components are packed. If packed includes all components, if not includes only one. + * + * \verbatim im.ImageLineCount(width: number, color_mode: number) -> linecount: number [in Lua 5] \endverbatim + * \ingroup imageutil */ +int imImageLineCount(int width, int color_mode); + +/** Check if the combination color_mode+data_type is valid. + * + * \verbatim im.ImageCheckFormat(color_mode: number, data_type: number) -> check: boolean [in Lua 5] \endverbatim + * \ingroup imageutil */ +int imImageCheckFormat(int color_mode, int data_type); + + + +/** \defgroup colorutl Color Utilities + * \par + * See \ref im_util.h + * \ingroup util */ + +/** Encode RGB components in a long for palete usage. \n + * "long" definition is compatible with the CD library definition. + * + * \verbatim im.ColorEncode(red: number, green: number, blue: number) -> color: lightuserdata [in Lua 5] \endverbatim + * \ingroup colorutl */ +long imColorEncode(unsigned char red, unsigned char green, unsigned char blue); + +/** Decode RGB components from a long for palete usage. \n + * "long" definition is compatible with the CD library definition. + * + * \verbatim im.ColorDecode(color: lightuserdata) -> red: number, green: number, blue: number [in Lua 5] \endverbatim + * \ingroup colorutl */ +void imColorDecode(unsigned char *red, unsigned char *green, unsigned char *blue, long color); + + + +/** \defgroup colormodeutl Color Mode Utilities + * \par + * See \ref im_util.h + * \ingroup imagerep */ + +/** Returns the color mode name. + * + * \verbatim im.ColorModeSpaceName(color_mode: number) -> name: string [in Lua 5] \endverbatim + * \ingroup colormodeutl */ +const char* imColorModeSpaceName(int color_mode); + +/** Returns the number of components of the color space including alpha. + * + * \verbatim im.ColorModeDepth(color_mode: number) -> depth: number [in Lua 5] \endverbatim + * \ingroup colormodeutl */ +int imColorModeDepth(int color_mode); + +/** Returns the color space of the color mode. + * + * \verbatim im.ColorModeSpace(color_mode: number) -> color_space: number [in Lua 5] \endverbatim + * \ingroup colormodeutl */ +#define imColorModeSpace(_cm) (_cm & 0xFF) + +/** Check if the two color modes match. Only the color space is compared. + * + * \verbatim im.ColorModeMatch(color_mode1: number, color_mode2: number) -> match: boolean [in Lua 5] \endverbatim + * \ingroup colormodeutl */ +#define imColorModeMatch(_cm1, _cm2) (imColorModeSpace(_cm1) == imColorModeSpace(_cm2)) + +/** Check if the color mode has an alpha channel. + * + * \verbatim im.ColorModeHasAlpha(color_mode: number) -> has_alpha: boolean [in Lua 5] \endverbatim + * \ingroup colormodeutl */ +#define imColorModeHasAlpha(_cm) (_cm & IM_ALPHA) + +/** Check if the color mode components are packed in one plane. + * + * \verbatim im.ColorModeIsPacked(color_mode: number) -> is_packed: boolean [in Lua 5] \endverbatim + * \ingroup colormodeutl */ +#define imColorModeIsPacked(_cm) (_cm & IM_PACKED) + +/** Check if the color mode orients the image from top down to bottom. + * + * \verbatim im.ColorModeIsTopDown(color_mode: number) -> is_top_down: boolean [in Lua 5] \endverbatim + * \ingroup colormodeutl */ +#define imColorModeIsTopDown(_cm) (_cm & IM_TOPDOWN) + +/** Returns the color space of the equivalent display bitmap image. \n + * Original packing and alpha are ignored. Returns IM_RGB, IM_GRAY, IM_MAP or IM_BINARY. + * + * \verbatim im.ColorModeToBitmap(color_mode: number) -> color_space: number [in Lua 5] \endverbatim + * \ingroup colormodeutl */ +int imColorModeToBitmap(int color_mode); + +/** Check if the color mode and data_type defines a display bitmap image. + * + * \verbatim im.ColorModeIsBitmap(color_mode: number, data_type: number) -> is_bitmap: boolean [in Lua 5] \endverbatim + * \ingroup colormodeutl */ +int imColorModeIsBitmap(int color_mode, int data_type); + + + +/** \defgroup datatypeutl Data Type Utilities + * \par + * See \ref im_util.h + * \ingroup util + * @{ + */ + +typedef unsigned char imbyte; +typedef unsigned short imushort; + +#define IM_BYTECROP(_v) (_v < 0? 0: _v > 255? 255: _v) +#define IM_CROPMAX(_v, _max) (_v < 0? 0: _v > _max? _max: _v) + +/** @} */ + +/** Returns the size in bytes of a specified numeric data type. + * + * \verbatim im.DataTypeSize(data_type: number) -> size: number [in Lua 5] \endverbatim + * \ingroup datatypeutl */ +int imDataTypeSize(int data_type); + +/** Returns the numeric data type name given its identifier. + * + * \verbatim im.DataTypeName(data_type: number) -> name: string [in Lua 5] \endverbatim + * \ingroup datatypeutl */ +const char* imDataTypeName(int data_type); + +/** Returns the maximum value of an integer data type. For floating point returns 0. + * + * \verbatim im.DataTypeIntMax(data_type: number) -> int_max: number [in Lua 5] \endverbatim + * \ingroup datatypeutl */ +unsigned long imDataTypeIntMax(int data_type); + +/** Returns the minimum value of an integer data type. For floating point returns 0. + * + * \verbatim im.DataTypeIntMin(data_type: number) -> int_min: number [in Lua 5] \endverbatim + * \ingroup datatypeutl */ +long imDataTypeIntMin(int data_type); + + + +/** \defgroup bin Binary Data Utilities + * \par + * See \ref im_util.h + * \ingroup util */ + +/** CPU Byte Orders. + * \ingroup bin */ +enum imByteOrder +{ + IM_LITTLEENDIAN, /**< Little Endian - The most significant byte is on the right end of a word. Used by Intel processors. */ + IM_BIGENDIAN /**< Big Endian - The most significant byte is on the left end of a word. Used by Motorola processors, also is the network standard byte order. */ +}; + +/** Returns the current CPU byte order. + * \ingroup bin */ +int imBinCPUByteOrder(void); + +/** Changes the byte order of an array of 2, 4 or 8 byte values. + * \ingroup bin */ +void imBinSwapBytes(void *data, int count, int size); + +/** Changes the byte order of an array of 2 byte values. + * \ingroup bin */ +void imBinSwapBytes2(void *data, int count); + +/** Inverts the byte order of the 4 byte values + * \ingroup bin */ +void imBinSwapBytes4(void *data, int count); + +/** Inverts the byte order of the 8 byte values + * \ingroup bin */ +void imBinSwapBytes8(void *data, int count); + + + +/** \defgroup compress Data Compression Utilities + * \par + * Deflate compression support uses zlib version 1.2.3. \n + * http://www.zlib.org/ \n + * Copyright (C) 1995-2004 Jean-loup Gailly and Mark Adler + * \par + * LZF compression support uses libLZF version 3.5. \n + * http://software.schmorp.de/pkg/liblzf \n + * Copyright (C) 2000-2009 Marc Alexander Lehmann + * See \ref im_util.h + * \ingroup util */ + +/** Compresses the data using the ZLIB Deflate compression. \n + * The destination buffer must be at least 0.1% larger than source_size plus 12 bytes. \n + * It compresses raw byte data. zip_quality can be 1 to 9. \n + * Returns the size of the compressed buffer or zero if failed. + * \ingroup compress */ +int imCompressDataZ(const void* src_data, int src_size, void* dst_data, int dst_size, int zip_quality); + +/** Uncompresses the data compressed with the ZLIB Deflate compression. \n + * Returns zero if failed. + * \ingroup compress */ +int imCompressDataUnZ(const void* src_data, int src_size, void* dst_data, int dst_size); + +/** Compresses the data using the libLZF compression. \n + * Returns the size of the compressed buffer or zero if failed. + * \ingroup compress */ +int imCompressDataLZF(const void* src_data, int src_size, void* dst_data, int dst_size, int zip_quality); + +/** Uncompresses the data compressed with the libLZF compression. + * Returns zero if failed. + * \ingroup compress */ +int imCompressDataUnLZF(const void* src_data, int src_size, void* dst_data, int dst_size); + + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/im/include/imlua.h b/im/include/imlua.h new file mode 100755 index 0000000..5714dff --- /dev/null +++ b/im/include/imlua.h @@ -0,0 +1,83 @@ +/** \file + * \brief IM Lua 5 Binding + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IMLUA_H +#define __IMLUA_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup imlua IM Lua 5 Binding + * \par + * Binding for the Lua 5 scripting language. \n + * Lua 5.1 Copyright (C) 1994-2005 Lua.org, PUC-Rio \n + * R. Ierusalimschy, L. H. de Figueiredo & W. Celes \n + * http://www.lua.org + * \par + * The name of the functions were changed because of the namespace "im" and because of the object orientation. \n + * As a general rule use: +\verbatim + imXxx -> im.Xxx + IM_XXX -> im.XXX + imFileXXX(ifile,... -> ifile:XXX(... + imImageXXX(image,... -> image:XXX(... +\endverbatim + * All the objects are garbage collected by the Lua garbage collector. + * \par + * See \ref imlua.h + * \ingroup util */ + +#ifdef LUA_NOOBJECT /* Lua 3 */ +void imlua_open(void); +#endif + +#ifdef LUA_TNONE /* Lua 5 */ + +/** Initializes the Lua binding of the main IM library. \n + * Returns 1 (leaves the "im" table on the top of the stack). + * You must link the application with the "imlua51" library. + * \ingroup imlua */ +int imlua_open(lua_State *L); +int luaopen_imlua(lua_State *L); + +/** Pushes an image as a metatable on the stack. + * \ingroup imlua */ +void imlua_pushimage(lua_State *L, imImage* image); + +/** Gets an image as a metatable from the stack, checks for correct type. + * \ingroup imlua */ +imImage* imlua_checkimage(lua_State *L, int param); + +/** Initializes the Lua binding of the capture library. \n + * Returns 1 (leaves the "im" table on the top of the stack). + * You must link the application with the "imlua_capture51" library. + * \ingroup imlua */ +int imlua_open_capture(lua_State *L); +int luaopen_imlua_capture(lua_State *L); + +/** Initializes the Lua binding of the process library. \n + * Returns 1 (leaves the "im" table on the top of the stack). + * You must link the application with the "imlua_process51" library. + * \ingroup imlua */ +int imlua_open_process(lua_State *L); +int luaopen_imlua_process(lua_State *L); + +/** Initializes the Lua binding of the fourier transform library. \n + * Returns 1 (leaves the "im" table on the top of the stack). + * You must link the application with the "imlua_fftw51" library. + * \ingroup imlua */ +int imlua_open_fftw(lua_State *L); +int luaopen_imlua_fftw(lua_State *L); + + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/im/include/old_im.h b/im/include/old_im.h new file mode 100755 index 0000000..f000221 --- /dev/null +++ b/im/include/old_im.h @@ -0,0 +1,59 @@ +/** \file + * \brief Old API + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_OLD_H +#define __IM_OLD_H + +#if defined(__cplusplus) +extern "C" { +#endif + +enum {IM_BMP, IM_PCX, IM_GIF, IM_TIF, IM_RAS, IM_SGI, IM_JPG, IM_LED, IM_TGA}; +enum {IM_NONE = 0x0000, IM_DEFAULT = 0x0100, IM_COMPRESSED = 0x0200}; + +#define IM_ERR_READ IM_ERR_ACCESS +#define IM_ERR_WRITE IM_ERR_ACCESS +#define IM_ERR_TYPE IM_ERR_DATA +#define IM_ERR_COMP IM_ERR_COMPRESS + +long imEncodeColor(unsigned char red, unsigned char green, unsigned char blue); +void imDecodeColor(unsigned char* red, unsigned char* green, unsigned char* blue, long palette); +int imFileFormat(char *filename, int* format); +int imImageInfo(char *filename, int *width, int *height, int *type, int *palette_count); +int imLoadRGB(char *filename, unsigned char *red, unsigned char *green, unsigned char *blue); +int imSaveRGB(int width, int height, int format, unsigned char *red, unsigned char *green, unsigned char *blue, char *filename); +int imLoadMap(char *filename, unsigned char *map, long *palette); +int imSaveMap(int width, int height, int format, unsigned char *map, int palette_count, long *palette, char *filename); +void imRGB2Map(int width, int height, unsigned char *red, unsigned char *green, unsigned char *blue, unsigned char *map, int palette_count, long *palette); +void imMap2RGB(int width, int height, unsigned char *map, int palette_count, long *colors, unsigned char *red, unsigned char *green, unsigned char *blue); +void imRGB2Gray(int width, int height, unsigned char *red, unsigned char *green, unsigned char *blue, unsigned char *map, long *grays); +void imMap2Gray(int width, int height, unsigned char *map, int palette_count, long *colors, unsigned char *grey_map, long *grays); +void imResize(int src_width, int src_height, unsigned char *src_map, int dst_width, int dst_height, unsigned char *dst_map); +void imStretch(int src_width, int src_height, unsigned char *src_map, int dst_width, int dst_height, unsigned char *dst_map); +typedef int (*imCallback)(char *filename); +int imRegisterCallback(imCallback cb, int cb_id, int format); + +#define IM_INTERRUPTED -1 +#define IM_ALL -1 +#define IM_COUNTER_CB 0 +typedef int (*imFileCounterCallback)(char *filename, int percent, int io); + +#define IM_RESOLUTION_CB 1 +typedef int (*imResolutionCallback)(char *filename, double* xres, double* yres, int* res_unit); + +enum {IM_RES_NONE, IM_RES_DPI, IM_RES_DPC}; + +#define IM_GIF_TRANSPARENT_COLOR_CB 0 +typedef int (*imGifTranspIndex)(char *filename, unsigned char *transp_index); + +#define IM_TIF_IMAGE_DESCRIPTION_CB 0 +typedef int (*imTiffImageDesc)(char *filename, char* img_desc); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/im/mak.vc8/im.sln b/im/mak.vc8/im.sln new file mode 100755 index 0000000..3860357 --- /dev/null +++ b/im/mak.vc8/im.sln @@ -0,0 +1,177 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "im", "im.vcproj", "{5A761929-07C3-48BD-8E4A-B37EC5C72C42}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "im_avi", "im_avi.vcproj", "{CB863607-6B6C-0000-0000-000000000000}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "im_capture", "im_capture.vcproj", "{CB868607-6B6C-4CDF-9B6D-27AA925AE473}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "im_jp2", "im_jp2.vcproj", "{CB96E607-6B6C-0000-0000-000000000000}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "im_process", "im_process.vcproj", "{CB80E607-6B6C-4ADF-9B6D-27AA925AE493}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "im_wmv", "im_wmv.vcproj", "{CB86E507-6B6C-4FDF-9B6D-27AA925AE463}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "im_fftw", "im_fftw.vcproj", "{CB80E607-6B6C-345F-9B6D-27AA9123E493}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "imlua3", "imlua3.vcproj", "{43564684-75A9-41FE-847B-BF8514C14571}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "imlua5", "imlua5.vcproj", "{CB863607-6B6C-0000-0000-000000001234}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "imlua_capture5", "imlua_capture5.vcproj", "{CB863607-6B6C-0000-0000-678900001234}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "imlua_fftw5", "imlua_fftw5.vcproj", "{CB863607-6B6C-0000-1234-000000001234}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "imlua_process5", "imlua_process5.vcproj", "{CB863607-6B6C-0000-7689-000000001234}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "im_ecw", "im_ecw.vcproj", "{CB86E507-6B6C-4FDF-9B6D-27AA123AE463}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Lua3", "Lua3", "{0AB99E2F-D746-4ABC-BF14-33F6936CF927}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Test", "Test", "{F36FF650-2081-42D4-82C2-645324897900}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Lua5", "Lua5", "{45695057-0514-4294-AE1D-15D4017F0389}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Formats", "Formats", "{E23E03B7-7DFC-4A8F-B996-F0D052E8EBDD}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "im_info", "im_info.vcproj", "{909637FA-8229-45A9-9F42-53D8ED5F91C5}" + ProjectSection(ProjectDependencies) = postProject + {CB863607-6B6C-0000-0000-000000000000} = {CB863607-6B6C-0000-0000-000000000000} + {CB86E507-6B6C-4FDF-9B6D-27AA925AE463} = {CB86E507-6B6C-4FDF-9B6D-27AA925AE463} + {CB96E607-6B6C-0000-0000-000000000000} = {CB96E607-6B6C-0000-0000-000000000000} + {5A761929-07C3-48BD-8E4A-B37EC5C72C42} = {5A761929-07C3-48BD-8E4A-B37EC5C72C42} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "im_copy", "im_copy.vcproj", "{328002C9-0726-4BB5-AD09-1BA1DC96F912}" + ProjectSection(ProjectDependencies) = postProject + {CB863607-6B6C-0000-0000-000000000000} = {CB863607-6B6C-0000-0000-000000000000} + {CB86E507-6B6C-4FDF-9B6D-27AA925AE463} = {CB86E507-6B6C-4FDF-9B6D-27AA925AE463} + {CB96E607-6B6C-0000-0000-000000000000} = {CB96E607-6B6C-0000-0000-000000000000} + {5A761929-07C3-48BD-8E4A-B37EC5C72C42} = {5A761929-07C3-48BD-8E4A-B37EC5C72C42} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "im_view", "im_view.vcproj", "{99675DC2-A7EE-4BC8-B7E7-CD437D4FAC3B}" + ProjectSection(ProjectDependencies) = postProject + {CB863607-6B6C-0000-0000-000000000000} = {CB863607-6B6C-0000-0000-000000000000} + {CB96E607-6B6C-0000-0000-000000000000} = {CB96E607-6B6C-0000-0000-000000000000} + {5A761929-07C3-48BD-8E4A-B37EC5C72C42} = {5A761929-07C3-48BD-8E4A-B37EC5C72C42} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5A761929-07C3-48BD-8E4A-B37EC5C72C42}.Debug|Win32.ActiveCfg = Debug|Win32 + {5A761929-07C3-48BD-8E4A-B37EC5C72C42}.Debug|Win32.Build.0 = Debug|Win32 + {5A761929-07C3-48BD-8E4A-B37EC5C72C42}.Debug|x64.ActiveCfg = Debug|x64 + {5A761929-07C3-48BD-8E4A-B37EC5C72C42}.Release|Win32.ActiveCfg = Debug|Win32 + {5A761929-07C3-48BD-8E4A-B37EC5C72C42}.Release|x64.ActiveCfg = Debug|x64 + {CB863607-6B6C-0000-0000-000000000000}.Debug|Win32.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-0000-000000000000}.Debug|Win32.Build.0 = Debug|Win32 + {CB863607-6B6C-0000-0000-000000000000}.Debug|x64.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-0000-000000000000}.Release|Win32.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-0000-000000000000}.Release|Win32.Build.0 = Debug|Win32 + {CB863607-6B6C-0000-0000-000000000000}.Release|x64.ActiveCfg = Debug|Win32 + {CB868607-6B6C-4CDF-9B6D-27AA925AE473}.Debug|Win32.ActiveCfg = Debug|Win32 + {CB868607-6B6C-4CDF-9B6D-27AA925AE473}.Debug|Win32.Build.0 = Debug|Win32 + {CB868607-6B6C-4CDF-9B6D-27AA925AE473}.Debug|x64.ActiveCfg = Debug|Win32 + {CB868607-6B6C-4CDF-9B6D-27AA925AE473}.Release|Win32.ActiveCfg = Debug|Win32 + {CB868607-6B6C-4CDF-9B6D-27AA925AE473}.Release|x64.ActiveCfg = Debug|Win32 + {CB96E607-6B6C-0000-0000-000000000000}.Debug|Win32.ActiveCfg = Debug|Win32 + {CB96E607-6B6C-0000-0000-000000000000}.Debug|Win32.Build.0 = Debug|Win32 + {CB96E607-6B6C-0000-0000-000000000000}.Debug|x64.ActiveCfg = Debug|Win32 + {CB96E607-6B6C-0000-0000-000000000000}.Release|Win32.ActiveCfg = Debug|Win32 + {CB96E607-6B6C-0000-0000-000000000000}.Release|x64.ActiveCfg = Debug|Win32 + {CB80E607-6B6C-4ADF-9B6D-27AA925AE493}.Debug|Win32.ActiveCfg = Debug|Win32 + {CB80E607-6B6C-4ADF-9B6D-27AA925AE493}.Debug|Win32.Build.0 = Debug|Win32 + {CB80E607-6B6C-4ADF-9B6D-27AA925AE493}.Debug|x64.ActiveCfg = Debug|Win32 + {CB80E607-6B6C-4ADF-9B6D-27AA925AE493}.Release|Win32.ActiveCfg = Debug|Win32 + {CB80E607-6B6C-4ADF-9B6D-27AA925AE493}.Release|x64.ActiveCfg = Debug|Win32 + {CB86E507-6B6C-4FDF-9B6D-27AA925AE463}.Debug|Win32.ActiveCfg = Debug|Win32 + {CB86E507-6B6C-4FDF-9B6D-27AA925AE463}.Debug|Win32.Build.0 = Debug|Win32 + {CB86E507-6B6C-4FDF-9B6D-27AA925AE463}.Debug|x64.ActiveCfg = Debug|Win32 + {CB86E507-6B6C-4FDF-9B6D-27AA925AE463}.Release|Win32.ActiveCfg = Debug|Win32 + {CB86E507-6B6C-4FDF-9B6D-27AA925AE463}.Release|x64.ActiveCfg = Debug|Win32 + {CB80E607-6B6C-345F-9B6D-27AA9123E493}.Debug|Win32.ActiveCfg = Debug|Win32 + {CB80E607-6B6C-345F-9B6D-27AA9123E493}.Debug|Win32.Build.0 = Debug|Win32 + {CB80E607-6B6C-345F-9B6D-27AA9123E493}.Debug|x64.ActiveCfg = Debug|Win32 + {CB80E607-6B6C-345F-9B6D-27AA9123E493}.Release|Win32.ActiveCfg = Debug|Win32 + {CB80E607-6B6C-345F-9B6D-27AA9123E493}.Release|x64.ActiveCfg = Debug|Win32 + {43564684-75A9-41FE-847B-BF8514C14571}.Debug|Win32.ActiveCfg = Debug|Win32 + {43564684-75A9-41FE-847B-BF8514C14571}.Debug|Win32.Build.0 = Debug|Win32 + {43564684-75A9-41FE-847B-BF8514C14571}.Debug|x64.ActiveCfg = Debug|Win32 + {43564684-75A9-41FE-847B-BF8514C14571}.Release|Win32.ActiveCfg = Debug|Win32 + {43564684-75A9-41FE-847B-BF8514C14571}.Release|x64.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-0000-000000001234}.Debug|Win32.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-0000-000000001234}.Debug|Win32.Build.0 = Debug|Win32 + {CB863607-6B6C-0000-0000-000000001234}.Debug|x64.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-0000-000000001234}.Release|Win32.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-0000-000000001234}.Release|Win32.Build.0 = Debug|Win32 + {CB863607-6B6C-0000-0000-000000001234}.Release|x64.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-0000-678900001234}.Debug|Win32.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-0000-678900001234}.Debug|Win32.Build.0 = Debug|Win32 + {CB863607-6B6C-0000-0000-678900001234}.Debug|x64.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-0000-678900001234}.Release|Win32.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-0000-678900001234}.Release|Win32.Build.0 = Debug|Win32 + {CB863607-6B6C-0000-0000-678900001234}.Release|x64.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-1234-000000001234}.Debug|Win32.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-1234-000000001234}.Debug|Win32.Build.0 = Debug|Win32 + {CB863607-6B6C-0000-1234-000000001234}.Debug|x64.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-1234-000000001234}.Release|Win32.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-1234-000000001234}.Release|Win32.Build.0 = Debug|Win32 + {CB863607-6B6C-0000-1234-000000001234}.Release|x64.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-7689-000000001234}.Debug|Win32.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-7689-000000001234}.Debug|Win32.Build.0 = Debug|Win32 + {CB863607-6B6C-0000-7689-000000001234}.Debug|x64.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-7689-000000001234}.Release|Win32.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-7689-000000001234}.Release|Win32.Build.0 = Debug|Win32 + {CB863607-6B6C-0000-7689-000000001234}.Release|x64.ActiveCfg = Debug|Win32 + {CB86E507-6B6C-4FDF-9B6D-27AA123AE463}.Debug|Win32.ActiveCfg = Debug|Win32 + {CB86E507-6B6C-4FDF-9B6D-27AA123AE463}.Debug|Win32.Build.0 = Debug|Win32 + {CB86E507-6B6C-4FDF-9B6D-27AA123AE463}.Debug|x64.ActiveCfg = Debug|Win32 + {CB86E507-6B6C-4FDF-9B6D-27AA123AE463}.Release|Win32.ActiveCfg = Debug|Win32 + {CB86E507-6B6C-4FDF-9B6D-27AA123AE463}.Release|Win32.Build.0 = Debug|Win32 + {CB86E507-6B6C-4FDF-9B6D-27AA123AE463}.Release|x64.ActiveCfg = Debug|Win32 + {909637FA-8229-45A9-9F42-53D8ED5F91C5}.Debug|Win32.ActiveCfg = Debug|Win32 + {909637FA-8229-45A9-9F42-53D8ED5F91C5}.Debug|Win32.Build.0 = Debug|Win32 + {909637FA-8229-45A9-9F42-53D8ED5F91C5}.Debug|x64.ActiveCfg = Debug|Win32 + {909637FA-8229-45A9-9F42-53D8ED5F91C5}.Release|Win32.ActiveCfg = Debug|Win32 + {909637FA-8229-45A9-9F42-53D8ED5F91C5}.Release|Win32.Build.0 = Debug|Win32 + {909637FA-8229-45A9-9F42-53D8ED5F91C5}.Release|x64.ActiveCfg = Debug|Win32 + {328002C9-0726-4BB5-AD09-1BA1DC96F912}.Debug|Win32.ActiveCfg = Debug|Win32 + {328002C9-0726-4BB5-AD09-1BA1DC96F912}.Debug|Win32.Build.0 = Debug|Win32 + {328002C9-0726-4BB5-AD09-1BA1DC96F912}.Debug|x64.ActiveCfg = Debug|Win32 + {328002C9-0726-4BB5-AD09-1BA1DC96F912}.Release|Win32.ActiveCfg = Debug|Win32 + {328002C9-0726-4BB5-AD09-1BA1DC96F912}.Release|Win32.Build.0 = Debug|Win32 + {328002C9-0726-4BB5-AD09-1BA1DC96F912}.Release|x64.ActiveCfg = Debug|Win32 + {99675DC2-A7EE-4BC8-B7E7-CD437D4FAC3B}.Debug|Win32.ActiveCfg = Debug|Win32 + {99675DC2-A7EE-4BC8-B7E7-CD437D4FAC3B}.Debug|Win32.Build.0 = Debug|Win32 + {99675DC2-A7EE-4BC8-B7E7-CD437D4FAC3B}.Debug|x64.ActiveCfg = Debug|Win32 + {99675DC2-A7EE-4BC8-B7E7-CD437D4FAC3B}.Release|Win32.ActiveCfg = Debug|Win32 + {99675DC2-A7EE-4BC8-B7E7-CD437D4FAC3B}.Release|Win32.Build.0 = Debug|Win32 + {99675DC2-A7EE-4BC8-B7E7-CD437D4FAC3B}.Release|x64.ActiveCfg = Debug|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {43564684-75A9-41FE-847B-BF8514C14571} = {0AB99E2F-D746-4ABC-BF14-33F6936CF927} + {909637FA-8229-45A9-9F42-53D8ED5F91C5} = {F36FF650-2081-42D4-82C2-645324897900} + {328002C9-0726-4BB5-AD09-1BA1DC96F912} = {F36FF650-2081-42D4-82C2-645324897900} + {99675DC2-A7EE-4BC8-B7E7-CD437D4FAC3B} = {F36FF650-2081-42D4-82C2-645324897900} + {CB863607-6B6C-0000-7689-000000001234} = {45695057-0514-4294-AE1D-15D4017F0389} + {CB863607-6B6C-0000-1234-000000001234} = {45695057-0514-4294-AE1D-15D4017F0389} + {CB863607-6B6C-0000-0000-678900001234} = {45695057-0514-4294-AE1D-15D4017F0389} + {CB863607-6B6C-0000-0000-000000001234} = {45695057-0514-4294-AE1D-15D4017F0389} + {CB863607-6B6C-0000-0000-000000000000} = {E23E03B7-7DFC-4A8F-B996-F0D052E8EBDD} + {CB86E507-6B6C-4FDF-9B6D-27AA123AE463} = {E23E03B7-7DFC-4A8F-B996-F0D052E8EBDD} + {CB96E607-6B6C-0000-0000-000000000000} = {E23E03B7-7DFC-4A8F-B996-F0D052E8EBDD} + {CB86E507-6B6C-4FDF-9B6D-27AA925AE463} = {E23E03B7-7DFC-4A8F-B996-F0D052E8EBDD} + EndGlobalSection + GlobalSection(DevPartner Solution Properties) = postSolution + EndGlobalSection +EndGlobal diff --git a/im/mak.vc8/im.vcproj b/im/mak.vc8/im.vcproj new file mode 100755 index 0000000..afce120 --- /dev/null +++ b/im/mak.vc8/im.vcproj @@ -0,0 +1,1224 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/im/mak.vc8/im_avi.vcproj b/im/mak.vc8/im_avi.vcproj new file mode 100755 index 0000000..40238d5 --- /dev/null +++ b/im/mak.vc8/im_avi.vcproj @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/im/mak.vc8/im_capture.vcproj b/im/mak.vc8/im_capture.vcproj new file mode 100755 index 0000000..bbfcb42 --- /dev/null +++ b/im/mak.vc8/im_capture.vcproj @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/im/mak.vc8/im_copy.vcproj b/im/mak.vc8/im_copy.vcproj new file mode 100755 index 0000000..9beee7b --- /dev/null +++ b/im/mak.vc8/im_copy.vcproj @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/im/mak.vc8/im_ecw.vcproj b/im/mak.vc8/im_ecw.vcproj new file mode 100755 index 0000000..e980260 --- /dev/null +++ b/im/mak.vc8/im_ecw.vcproj @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/im/mak.vc8/im_fftw.vcproj b/im/mak.vc8/im_fftw.vcproj new file mode 100755 index 0000000..49ddd6a --- /dev/null +++ b/im/mak.vc8/im_fftw.vcproj @@ -0,0 +1,425 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/im/mak.vc8/im_info.vcproj b/im/mak.vc8/im_info.vcproj new file mode 100755 index 0000000..700b113 --- /dev/null +++ b/im/mak.vc8/im_info.vcproj @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/im/mak.vc8/im_jp2.vcproj b/im/mak.vc8/im_jp2.vcproj new file mode 100755 index 0000000..b139e55 --- /dev/null +++ b/im/mak.vc8/im_jp2.vcproj @@ -0,0 +1,444 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/im/mak.vc8/im_process.vcproj b/im/mak.vc8/im_process.vcproj new file mode 100755 index 0000000..bf3773d --- /dev/null +++ b/im/mak.vc8/im_process.vcproj @@ -0,0 +1,224 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/im/mak.vc8/im_view.vcproj b/im/mak.vc8/im_view.vcproj new file mode 100755 index 0000000..e7d8c56 --- /dev/null +++ b/im/mak.vc8/im_view.vcproj @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/im/mak.vc8/im_wmv.vcproj b/im/mak.vc8/im_wmv.vcproj new file mode 100755 index 0000000..79d9234 --- /dev/null +++ b/im/mak.vc8/im_wmv.vcproj @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/im/mak.vc8/imlua3.vcproj b/im/mak.vc8/imlua3.vcproj new file mode 100755 index 0000000..1ad10a9 --- /dev/null +++ b/im/mak.vc8/imlua3.vcproj @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/im/mak.vc8/imlua5.vcproj b/im/mak.vc8/imlua5.vcproj new file mode 100755 index 0000000..8ddd74a --- /dev/null +++ b/im/mak.vc8/imlua5.vcproj @@ -0,0 +1,164 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/im/mak.vc8/imlua_capture5.vcproj b/im/mak.vc8/imlua_capture5.vcproj new file mode 100755 index 0000000..9ee907b --- /dev/null +++ b/im/mak.vc8/imlua_capture5.vcproj @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/im/mak.vc8/imlua_fftw5.vcproj b/im/mak.vc8/imlua_fftw5.vcproj new file mode 100755 index 0000000..0219dcc --- /dev/null +++ b/im/mak.vc8/imlua_fftw5.vcproj @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/im/mak.vc8/imlua_process5.vcproj b/im/mak.vc8/imlua_process5.vcproj new file mode 100755 index 0000000..f490e45 --- /dev/null +++ b/im/mak.vc8/imlua_process5.vcproj @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/im/mak.vc9/im.sln b/im/mak.vc9/im.sln new file mode 100755 index 0000000..2a2d791 --- /dev/null +++ b/im/mak.vc9/im.sln @@ -0,0 +1,177 @@ +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "im", "im.vcproj", "{5A761929-07C3-48BD-8E4A-B37EC5C72C42}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "im_avi", "im_avi.vcproj", "{CB863607-6B6C-0000-0000-000000000000}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "im_capture", "im_capture.vcproj", "{CB868607-6B6C-4CDF-9B6D-27AA925AE473}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "im_jp2", "im_jp2.vcproj", "{CB96E607-6B6C-0000-0000-000000000000}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "im_process", "im_process.vcproj", "{CB80E607-6B6C-4ADF-9B6D-27AA925AE493}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "im_wmv", "im_wmv.vcproj", "{CB86E507-6B6C-4FDF-9B6D-27AA925AE463}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "im_fftw", "im_fftw.vcproj", "{CB80E607-6B6C-345F-9B6D-27AA9123E493}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "imlua3", "imlua3.vcproj", "{43564684-75A9-41FE-847B-BF8514C14571}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "imlua5", "imlua5.vcproj", "{CB863607-6B6C-0000-0000-000000001234}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "imlua_capture5", "imlua_capture5.vcproj", "{CB863607-6B6C-0000-0000-678900001234}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "imlua_fftw5", "imlua_fftw5.vcproj", "{CB863607-6B6C-0000-1234-000000001234}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "imlua_process5", "imlua_process5.vcproj", "{CB863607-6B6C-0000-7689-000000001234}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "im_ecw", "im_ecw.vcproj", "{CB86E507-6B6C-4FDF-9B6D-27AA123AE463}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Lua3", "Lua3", "{0AB99E2F-D746-4ABC-BF14-33F6936CF927}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Test", "Test", "{F36FF650-2081-42D4-82C2-645324897900}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Lua5", "Lua5", "{45695057-0514-4294-AE1D-15D4017F0389}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Formats", "Formats", "{E23E03B7-7DFC-4A8F-B996-F0D052E8EBDD}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "im_info", "im_info.vcproj", "{909637FA-8229-45A9-9F42-53D8ED5F91C5}" + ProjectSection(ProjectDependencies) = postProject + {CB863607-6B6C-0000-0000-000000000000} = {CB863607-6B6C-0000-0000-000000000000} + {CB86E507-6B6C-4FDF-9B6D-27AA925AE463} = {CB86E507-6B6C-4FDF-9B6D-27AA925AE463} + {CB96E607-6B6C-0000-0000-000000000000} = {CB96E607-6B6C-0000-0000-000000000000} + {5A761929-07C3-48BD-8E4A-B37EC5C72C42} = {5A761929-07C3-48BD-8E4A-B37EC5C72C42} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "im_copy", "im_copy.vcproj", "{328002C9-0726-4BB5-AD09-1BA1DC96F912}" + ProjectSection(ProjectDependencies) = postProject + {CB863607-6B6C-0000-0000-000000000000} = {CB863607-6B6C-0000-0000-000000000000} + {CB86E507-6B6C-4FDF-9B6D-27AA925AE463} = {CB86E507-6B6C-4FDF-9B6D-27AA925AE463} + {CB96E607-6B6C-0000-0000-000000000000} = {CB96E607-6B6C-0000-0000-000000000000} + {5A761929-07C3-48BD-8E4A-B37EC5C72C42} = {5A761929-07C3-48BD-8E4A-B37EC5C72C42} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "im_view", "im_view.vcproj", "{99675DC2-A7EE-4BC8-B7E7-CD437D4FAC3B}" + ProjectSection(ProjectDependencies) = postProject + {CB863607-6B6C-0000-0000-000000000000} = {CB863607-6B6C-0000-0000-000000000000} + {CB96E607-6B6C-0000-0000-000000000000} = {CB96E607-6B6C-0000-0000-000000000000} + {5A761929-07C3-48BD-8E4A-B37EC5C72C42} = {5A761929-07C3-48BD-8E4A-B37EC5C72C42} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5A761929-07C3-48BD-8E4A-B37EC5C72C42}.Debug|Win32.ActiveCfg = Debug|Win32 + {5A761929-07C3-48BD-8E4A-B37EC5C72C42}.Debug|Win32.Build.0 = Debug|Win32 + {5A761929-07C3-48BD-8E4A-B37EC5C72C42}.Debug|x64.ActiveCfg = Debug|x64 + {5A761929-07C3-48BD-8E4A-B37EC5C72C42}.Release|Win32.ActiveCfg = Debug|Win32 + {5A761929-07C3-48BD-8E4A-B37EC5C72C42}.Release|x64.ActiveCfg = Debug|x64 + {CB863607-6B6C-0000-0000-000000000000}.Debug|Win32.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-0000-000000000000}.Debug|Win32.Build.0 = Debug|Win32 + {CB863607-6B6C-0000-0000-000000000000}.Debug|x64.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-0000-000000000000}.Release|Win32.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-0000-000000000000}.Release|Win32.Build.0 = Debug|Win32 + {CB863607-6B6C-0000-0000-000000000000}.Release|x64.ActiveCfg = Debug|Win32 + {CB868607-6B6C-4CDF-9B6D-27AA925AE473}.Debug|Win32.ActiveCfg = Debug|Win32 + {CB868607-6B6C-4CDF-9B6D-27AA925AE473}.Debug|Win32.Build.0 = Debug|Win32 + {CB868607-6B6C-4CDF-9B6D-27AA925AE473}.Debug|x64.ActiveCfg = Debug|Win32 + {CB868607-6B6C-4CDF-9B6D-27AA925AE473}.Release|Win32.ActiveCfg = Debug|Win32 + {CB868607-6B6C-4CDF-9B6D-27AA925AE473}.Release|x64.ActiveCfg = Debug|Win32 + {CB96E607-6B6C-0000-0000-000000000000}.Debug|Win32.ActiveCfg = Debug|Win32 + {CB96E607-6B6C-0000-0000-000000000000}.Debug|Win32.Build.0 = Debug|Win32 + {CB96E607-6B6C-0000-0000-000000000000}.Debug|x64.ActiveCfg = Debug|Win32 + {CB96E607-6B6C-0000-0000-000000000000}.Release|Win32.ActiveCfg = Debug|Win32 + {CB96E607-6B6C-0000-0000-000000000000}.Release|x64.ActiveCfg = Debug|Win32 + {CB80E607-6B6C-4ADF-9B6D-27AA925AE493}.Debug|Win32.ActiveCfg = Debug|Win32 + {CB80E607-6B6C-4ADF-9B6D-27AA925AE493}.Debug|Win32.Build.0 = Debug|Win32 + {CB80E607-6B6C-4ADF-9B6D-27AA925AE493}.Debug|x64.ActiveCfg = Debug|Win32 + {CB80E607-6B6C-4ADF-9B6D-27AA925AE493}.Release|Win32.ActiveCfg = Debug|Win32 + {CB80E607-6B6C-4ADF-9B6D-27AA925AE493}.Release|x64.ActiveCfg = Debug|Win32 + {CB86E507-6B6C-4FDF-9B6D-27AA925AE463}.Debug|Win32.ActiveCfg = Debug|Win32 + {CB86E507-6B6C-4FDF-9B6D-27AA925AE463}.Debug|Win32.Build.0 = Debug|Win32 + {CB86E507-6B6C-4FDF-9B6D-27AA925AE463}.Debug|x64.ActiveCfg = Debug|Win32 + {CB86E507-6B6C-4FDF-9B6D-27AA925AE463}.Release|Win32.ActiveCfg = Debug|Win32 + {CB86E507-6B6C-4FDF-9B6D-27AA925AE463}.Release|x64.ActiveCfg = Debug|Win32 + {CB80E607-6B6C-345F-9B6D-27AA9123E493}.Debug|Win32.ActiveCfg = Debug|Win32 + {CB80E607-6B6C-345F-9B6D-27AA9123E493}.Debug|Win32.Build.0 = Debug|Win32 + {CB80E607-6B6C-345F-9B6D-27AA9123E493}.Debug|x64.ActiveCfg = Debug|Win32 + {CB80E607-6B6C-345F-9B6D-27AA9123E493}.Release|Win32.ActiveCfg = Debug|Win32 + {CB80E607-6B6C-345F-9B6D-27AA9123E493}.Release|x64.ActiveCfg = Debug|Win32 + {43564684-75A9-41FE-847B-BF8514C14571}.Debug|Win32.ActiveCfg = Debug|Win32 + {43564684-75A9-41FE-847B-BF8514C14571}.Debug|Win32.Build.0 = Debug|Win32 + {43564684-75A9-41FE-847B-BF8514C14571}.Debug|x64.ActiveCfg = Debug|Win32 + {43564684-75A9-41FE-847B-BF8514C14571}.Release|Win32.ActiveCfg = Debug|Win32 + {43564684-75A9-41FE-847B-BF8514C14571}.Release|x64.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-0000-000000001234}.Debug|Win32.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-0000-000000001234}.Debug|Win32.Build.0 = Debug|Win32 + {CB863607-6B6C-0000-0000-000000001234}.Debug|x64.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-0000-000000001234}.Release|Win32.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-0000-000000001234}.Release|Win32.Build.0 = Debug|Win32 + {CB863607-6B6C-0000-0000-000000001234}.Release|x64.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-0000-678900001234}.Debug|Win32.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-0000-678900001234}.Debug|Win32.Build.0 = Debug|Win32 + {CB863607-6B6C-0000-0000-678900001234}.Debug|x64.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-0000-678900001234}.Release|Win32.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-0000-678900001234}.Release|Win32.Build.0 = Debug|Win32 + {CB863607-6B6C-0000-0000-678900001234}.Release|x64.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-1234-000000001234}.Debug|Win32.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-1234-000000001234}.Debug|Win32.Build.0 = Debug|Win32 + {CB863607-6B6C-0000-1234-000000001234}.Debug|x64.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-1234-000000001234}.Release|Win32.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-1234-000000001234}.Release|Win32.Build.0 = Debug|Win32 + {CB863607-6B6C-0000-1234-000000001234}.Release|x64.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-7689-000000001234}.Debug|Win32.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-7689-000000001234}.Debug|Win32.Build.0 = Debug|Win32 + {CB863607-6B6C-0000-7689-000000001234}.Debug|x64.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-7689-000000001234}.Release|Win32.ActiveCfg = Debug|Win32 + {CB863607-6B6C-0000-7689-000000001234}.Release|Win32.Build.0 = Debug|Win32 + {CB863607-6B6C-0000-7689-000000001234}.Release|x64.ActiveCfg = Debug|Win32 + {CB86E507-6B6C-4FDF-9B6D-27AA123AE463}.Debug|Win32.ActiveCfg = Debug|Win32 + {CB86E507-6B6C-4FDF-9B6D-27AA123AE463}.Debug|Win32.Build.0 = Debug|Win32 + {CB86E507-6B6C-4FDF-9B6D-27AA123AE463}.Debug|x64.ActiveCfg = Debug|Win32 + {CB86E507-6B6C-4FDF-9B6D-27AA123AE463}.Release|Win32.ActiveCfg = Debug|Win32 + {CB86E507-6B6C-4FDF-9B6D-27AA123AE463}.Release|Win32.Build.0 = Debug|Win32 + {CB86E507-6B6C-4FDF-9B6D-27AA123AE463}.Release|x64.ActiveCfg = Debug|Win32 + {909637FA-8229-45A9-9F42-53D8ED5F91C5}.Debug|Win32.ActiveCfg = Debug|Win32 + {909637FA-8229-45A9-9F42-53D8ED5F91C5}.Debug|Win32.Build.0 = Debug|Win32 + {909637FA-8229-45A9-9F42-53D8ED5F91C5}.Debug|x64.ActiveCfg = Debug|Win32 + {909637FA-8229-45A9-9F42-53D8ED5F91C5}.Release|Win32.ActiveCfg = Debug|Win32 + {909637FA-8229-45A9-9F42-53D8ED5F91C5}.Release|Win32.Build.0 = Debug|Win32 + {909637FA-8229-45A9-9F42-53D8ED5F91C5}.Release|x64.ActiveCfg = Debug|Win32 + {328002C9-0726-4BB5-AD09-1BA1DC96F912}.Debug|Win32.ActiveCfg = Debug|Win32 + {328002C9-0726-4BB5-AD09-1BA1DC96F912}.Debug|Win32.Build.0 = Debug|Win32 + {328002C9-0726-4BB5-AD09-1BA1DC96F912}.Debug|x64.ActiveCfg = Debug|Win32 + {328002C9-0726-4BB5-AD09-1BA1DC96F912}.Release|Win32.ActiveCfg = Debug|Win32 + {328002C9-0726-4BB5-AD09-1BA1DC96F912}.Release|Win32.Build.0 = Debug|Win32 + {328002C9-0726-4BB5-AD09-1BA1DC96F912}.Release|x64.ActiveCfg = Debug|Win32 + {99675DC2-A7EE-4BC8-B7E7-CD437D4FAC3B}.Debug|Win32.ActiveCfg = Debug|Win32 + {99675DC2-A7EE-4BC8-B7E7-CD437D4FAC3B}.Debug|Win32.Build.0 = Debug|Win32 + {99675DC2-A7EE-4BC8-B7E7-CD437D4FAC3B}.Debug|x64.ActiveCfg = Debug|Win32 + {99675DC2-A7EE-4BC8-B7E7-CD437D4FAC3B}.Release|Win32.ActiveCfg = Debug|Win32 + {99675DC2-A7EE-4BC8-B7E7-CD437D4FAC3B}.Release|Win32.Build.0 = Debug|Win32 + {99675DC2-A7EE-4BC8-B7E7-CD437D4FAC3B}.Release|x64.ActiveCfg = Debug|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {CB96E607-6B6C-0000-0000-000000000000} = {E23E03B7-7DFC-4A8F-B996-F0D052E8EBDD} + {CB86E507-6B6C-4FDF-9B6D-27AA925AE463} = {E23E03B7-7DFC-4A8F-B996-F0D052E8EBDD} + {CB86E507-6B6C-4FDF-9B6D-27AA123AE463} = {E23E03B7-7DFC-4A8F-B996-F0D052E8EBDD} + {CB863607-6B6C-0000-0000-000000000000} = {E23E03B7-7DFC-4A8F-B996-F0D052E8EBDD} + {43564684-75A9-41FE-847B-BF8514C14571} = {0AB99E2F-D746-4ABC-BF14-33F6936CF927} + {CB863607-6B6C-0000-0000-678900001234} = {45695057-0514-4294-AE1D-15D4017F0389} + {CB863607-6B6C-0000-1234-000000001234} = {45695057-0514-4294-AE1D-15D4017F0389} + {CB863607-6B6C-0000-7689-000000001234} = {45695057-0514-4294-AE1D-15D4017F0389} + {CB863607-6B6C-0000-0000-000000001234} = {45695057-0514-4294-AE1D-15D4017F0389} + {909637FA-8229-45A9-9F42-53D8ED5F91C5} = {F36FF650-2081-42D4-82C2-645324897900} + {328002C9-0726-4BB5-AD09-1BA1DC96F912} = {F36FF650-2081-42D4-82C2-645324897900} + {99675DC2-A7EE-4BC8-B7E7-CD437D4FAC3B} = {F36FF650-2081-42D4-82C2-645324897900} + EndGlobalSection + GlobalSection(DevPartner Solution Properties) = postSolution + EndGlobalSection +EndGlobal diff --git a/im/mak.vc9/im.vcproj b/im/mak.vc9/im.vcproj new file mode 100755 index 0000000..964847a --- /dev/null +++ b/im/mak.vc9/im.vcproj @@ -0,0 +1,1224 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/im/mak.vc9/im_avi.vcproj b/im/mak.vc9/im_avi.vcproj new file mode 100755 index 0000000..9222223 --- /dev/null +++ b/im/mak.vc9/im_avi.vcproj @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/im/mak.vc9/im_capture.vcproj b/im/mak.vc9/im_capture.vcproj new file mode 100755 index 0000000..bb61644 --- /dev/null +++ b/im/mak.vc9/im_capture.vcproj @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/im/mak.vc9/im_copy.vcproj b/im/mak.vc9/im_copy.vcproj new file mode 100755 index 0000000..d9bc064 --- /dev/null +++ b/im/mak.vc9/im_copy.vcproj @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/im/mak.vc9/im_ecw.vcproj b/im/mak.vc9/im_ecw.vcproj new file mode 100755 index 0000000..4528dfc --- /dev/null +++ b/im/mak.vc9/im_ecw.vcproj @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/im/mak.vc9/im_fftw.vcproj b/im/mak.vc9/im_fftw.vcproj new file mode 100755 index 0000000..702d5ff --- /dev/null +++ b/im/mak.vc9/im_fftw.vcproj @@ -0,0 +1,425 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/im/mak.vc9/im_info.vcproj b/im/mak.vc9/im_info.vcproj new file mode 100755 index 0000000..7cdd700 --- /dev/null +++ b/im/mak.vc9/im_info.vcproj @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/im/mak.vc9/im_jp2.vcproj b/im/mak.vc9/im_jp2.vcproj new file mode 100755 index 0000000..ec88634 --- /dev/null +++ b/im/mak.vc9/im_jp2.vcproj @@ -0,0 +1,444 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/im/mak.vc9/im_process.vcproj b/im/mak.vc9/im_process.vcproj new file mode 100755 index 0000000..7365b39 --- /dev/null +++ b/im/mak.vc9/im_process.vcproj @@ -0,0 +1,224 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/im/mak.vc9/im_view.vcproj b/im/mak.vc9/im_view.vcproj new file mode 100755 index 0000000..e7642c7 --- /dev/null +++ b/im/mak.vc9/im_view.vcproj @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/im/mak.vc9/im_wmv.vcproj b/im/mak.vc9/im_wmv.vcproj new file mode 100755 index 0000000..f767689 --- /dev/null +++ b/im/mak.vc9/im_wmv.vcproj @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/im/mak.vc9/imlua3.vcproj b/im/mak.vc9/imlua3.vcproj new file mode 100755 index 0000000..30955af --- /dev/null +++ b/im/mak.vc9/imlua3.vcproj @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/im/mak.vc9/imlua5.vcproj b/im/mak.vc9/imlua5.vcproj new file mode 100755 index 0000000..20ab587 --- /dev/null +++ b/im/mak.vc9/imlua5.vcproj @@ -0,0 +1,164 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/im/mak.vc9/imlua_capture5.vcproj b/im/mak.vc9/imlua_capture5.vcproj new file mode 100755 index 0000000..4d3064f --- /dev/null +++ b/im/mak.vc9/imlua_capture5.vcproj @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/im/mak.vc9/imlua_fftw5.vcproj b/im/mak.vc9/imlua_fftw5.vcproj new file mode 100755 index 0000000..bd0ae2a --- /dev/null +++ b/im/mak.vc9/imlua_fftw5.vcproj @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/im/mak.vc9/imlua_process5.vcproj b/im/mak.vc9/imlua_process5.vcproj new file mode 100755 index 0000000..e80ba7d --- /dev/null +++ b/im/mak.vc9/imlua_process5.vcproj @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/im/src/COPYRIGHT b/im/src/COPYRIGHT new file mode 100755 index 0000000..ca0b899 --- /dev/null +++ b/im/src/COPYRIGHT @@ -0,0 +1,32 @@ +IM License +----------- + +IM is licensed under the terms of the MIT license reproduced below. +This means that IM is free software and can be used for both academic +and commercial purposes at absolutely no cost. + +=============================================================================== + +Copyright (C) 1994-2009 Tecgraf, PUC-Rio. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +=============================================================================== + +(end of COPYRIGHT) diff --git a/im/src/Makefile b/im/src/Makefile new file mode 100755 index 0000000..3fe5908 --- /dev/null +++ b/im/src/Makefile @@ -0,0 +1,15 @@ + +.PHONY: do_all im im_jp2 im_process imlua3 imlua5 imlua_jp2 imlua_process5 +#do_all: im im_jp2 im_process im_fftw imlua3 imlua5 imlua_jp2 imlua_process5 imlua_fftw5 +do_all: im im_process imlua5 imlua_jp2 imlua_process5 + +im: + $(MAKE) --no-print-directory -f tecmake_compact.mak +im_process: + @$(MAKE) --no-print-directory -f tecmake_compact.mak MF=im_process +imlua3: + @$(MAKE) --no-print-directory -f tecmake_compact.mak MF=imlua3 +imlua5: + @$(MAKE) --no-print-directory -f tecmake_compact.mak MF=imlua5 +imlua_process5: + @$(MAKE) --no-print-directory -f tecmake_compact.mak MF=imlua_process5 diff --git a/im/src/README b/im/src/README new file mode 100755 index 0000000..3dbcbd5 --- /dev/null +++ b/im/src/README @@ -0,0 +1,11 @@ +README for IM + + IM is a toolkit for Digital Imaging. IM is based on 4 concepts: Image Representation, Storage, Processing and Capture. The main goal of the library is to provide a simple API and abstraction of images for scientific applications. + The most popular file formats are supported: TIFF, BMP, PNG, JPEG, GIF and AVI. Image representation includes scientific data types. About a hundred Image Processing operations are available. + + Build instructions and usage are available in the IM documentation. + + For complete information, visit IM's web site at http://www.tecgraf.puc-rio.br/im + or access its documentation in the HTML folder. + +(end of README) diff --git a/im/src/config.mak b/im/src/config.mak new file mode 100755 index 0000000..a938100 --- /dev/null +++ b/im/src/config.mak @@ -0,0 +1,89 @@ +PROJNAME = im +LIBNAME = im +OPT = YES + +INCLUDES = . ../include + +# WORDS_BIGENDIAN used by libTIFF +ifeq ($(TEC_SYSARCH), ppc) + DEFINES = WORDS_BIGENDIAN +endif +ifeq ($(TEC_SYSARCH), mips) + DEFINES = WORDS_BIGENDIAN +endif +ifeq ($(TEC_SYSARCH), sparc) + DEFINES = WORDS_BIGENDIAN +endif + +SRC = \ + old_imcolor.c old_imresize.c im_converttype.cpp \ + im_attrib.cpp im_format.cpp im_format_tga.cpp im_filebuffer.cpp \ + im_bin.cpp im_format_all.cpp im_format_raw.cpp \ + im_binfile.cpp im_format_sgi.cpp im_datatype.cpp im_format_pcx.cpp \ + im_colorhsi.cpp im_format_bmp.cpp im_image.cpp im_rgb2map.cpp \ + im_colormode.cpp im_format_gif.cpp im_lib.cpp im_format_pnm.cpp \ + im_colorutil.cpp im_format_ico.cpp im_palette.cpp \ + im_convertbitmap.cpp im_format_led.cpp im_counter.cpp im_str.cpp \ + im_convertcolor.cpp im_fileraw.cpp im_format_krn.cpp \ + im_file.cpp im_format_ras.cpp old_im.cpp \ + $(SRCJPEG) $(SRCTIFF) $(SRCPNG) $(SRCZLIB) $(SRCLZF) + + +ifneq ($(findstring Win, $(TEC_SYSNAME)), ) + SRC += im_sysfile_win32.cpp im_dib.cpp im_dibxbitmap.cpp + + ifneq ($(findstring dll, $(TEC_UNAME)), ) + SRC += im.rc + endif + + ifeq ($(findstring _64, $(TEC_UNAME)), ) + # optimize PNG lib for VC + ifneq ($(findstring vc, $(TEC_UNAME)), ) + SRC += libpng/pngvcrd.c + DEFINES += PNG_USE_PNGVCRD + endif + ifneq ($(findstring dll, $(TEC_UNAME)), ) + SRC += libpng/pngvcrd.c + DEFINES += PNG_USE_PNGVCRD + endif + endif + + # force the definition of math functions using float + # Watcom does not define them + ifneq ($(findstring ow, $(TEC_UNAME)), ) + DEFINES += IM_DEFMATHFLOAT + endif + + ifneq ($(findstring bc, $(TEC_UNAME)), ) + DEFINES += IM_DEFMATHFLOAT + else + USE_EXIF = Yes + endif +else + SRC += im_sysfile_unix.cpp +endif + +ifdef USE_EXIF + SRC += $(SRCEXIF) + DEFINES += USE_EXIF +endif + +ifneq ($(findstring Linux, $(TEC_UNAME)), ) + # optimize PNG lib for Linux in x86 + ifeq "$(TEC_SYSARCH)" "x86" + SRC += libpng/pnggccrd.c + DEFINES += PNG_USE_PNGGCCRD + endif +endif + +ifneq ($(findstring AIX, $(TEC_UNAME)), ) + DEFINES += IM_DEFMATHFLOAT +endif + +ifneq ($(findstring SunOS, $(TEC_UNAME)), ) + DEFINES += IM_DEFMATHFLOAT +endif + +ifneq ($(findstring HP-UX, $(TEC_UNAME)), ) + DEFINES += IM_DEFMATHFLOAT +endif diff --git a/im/src/im.def b/im/src/im.def new file mode 100755 index 0000000..41aa175 --- /dev/null +++ b/im/src/im.def @@ -0,0 +1,200 @@ +EXPORTS + imFileGetAttribute + imFileNew + imFileOpen + imFileFormat + imFileReadImageData + imFileReadImageInfo + imFileWriteImageData + imFileWriteImageInfo + imFileClose + imFileGetInfo + imFileGetPalette + imFileSetAttribute + imFileGetAttributeList + imFileSetBaseAttributes + imFileSetInfo + imFileSetPalette + imFileOpenAs + imFileHandle + imFileLineBufferCount + imFileLineSizeAligned + imFileLineBufferInc + imFileLineBufferRead + imFileLineBufferWrite + imFileImageLoad + imFileImageLoadBitmap + imFileImageSave + imFileLoadImageFrame + imFileLoadBitmapFrame + imFileSaveImage + imFileLoadBitmap + imFileLoadImage + imVersion + imVersionDate + imVersionNumber + imPaletteFindColor + imPaletteFindNearest + imPaletteUniformIndex + imPaletteUniformIndexHalftoned + imPaletteBlackBody + imPaletteBlue + imPaletteBlueIce + imPaletteCian + imPaletteGray + imPaletteGreen + imPaletteHotIron + imPaletteHues + imPaletteMagenta + imPaletteRainbow + imPaletteRed + imPaletteUniform + imPaletteYellow + imPaletteHighContrast + imFormatRegister + imFormatRegisterInternal + imFormatRemoveAll + imFormatCanWriteImage + imFormatCompressions + imFormatInfo + imFormatList + imColorModeSpaceName + imDataTypeName + imBinCPUByteOrder + imColorModeDepth + imColorModeIsBitmap + imColorModeToBitmap + imDataTypeSize + imStrCheck + imStrEqual + imStrNLen + imColorEncode + imDataTypeIntMin + imDataTypeIntMax + imBinSwapBytes2 + imBinSwapBytes4 + imBinSwapBytes8 + imColorDecode + imCounterSetCallback + imCounterBegin + imCounterInc + imCounterIncTo + imCounterEnd + imCounterTotal + imAttribTableCreate + imAttribTableDestroy + imAttribTableCount + imAttribTableRemoveAll + imAttribTableGet + imAttribTableSet + imAttribTableUnSet + imAttribTableCopyFrom + imAttribTableForEach + imImageGetAttribute + imImageClone + imImageCreate + imImageDuplicate + imImageInit + imImageCheckFormat + imImageDataSize + imImageLineCount + imImageLineSize + imImageIsBitmap + imImageGetOpenGLData + imImageMatch + imImageMatchColor + imImageMatchColorSpace + imImageMatchDataType + imImageMatchSize + imImageClear + imImageCopyAttributes + imImageDestroy + imImageGetAttributeList + imImageReshape + imImageSetAttribute + imImageSetBinary + imImageMakeBinary + imImageMakeGray + imImageSetPalette + imImageCopy + imImageCopyData + imImageCreateBased + imImageAddAlpha + imDibToHBitmap + imDibLogicalPalette + imDibCaptureScreen + imDibCreate + imDibCreateCopy + imDibCreateReference + imDibCreateSection + imDibFromHBitmap + imDibFromImage + imDibLoadFile + imDibPasteClipboard + imDibLineGetPixelFunc + imDibLineSetPixelFunc + imDibToImage + imDibIsClipboardAvailable + imDibSaveFile + imDibCopyClipboard + imDibDecodeToBitmap + imDibDecodeToMap + imDibDecodeToRGBA + imDibDestroy + imDibEncodeFromBitmap + imDibEncodeFromMap + imDibEncodeFromRGBA + imConvertColorSpace + imConvertDataType + imConvertToBitmap + imConvertPacking + imConvertMapToRGB + imConvertRGB2Map + imFileNewRaw + imFileOpenRaw + imBinFileNew + imBinFileOpen + imBinFileByteOrder + imBinFileEndOfFile + imBinFileError + imBinFileRegisterModule + imBinFileSetCurrentModule + imBinFilePrintf + imBinFileReadInteger + imBinFileReadFloat + imBinFileRead + imBinFileSize + imBinFileTell + imBinFileWrite + imBinFileClose + imBinFileSeekFrom + imBinFileSeekOffset + imBinFileSeekTo + imColorHSI_ImaxS + imColorHSI2RGB + imColorHSI2RGBbyte + imColorRGB2HSI + imColorRGB2HSIbyte + imEncodeColor + imDecodeColor + imImageInfo + imLoadRGB + imSaveRGB + imLoadMap + imSaveMap + imRGB2Map + imMap2RGB + imRGB2Gray + imMap2Gray + imResize + imStretch + imRegisterCallback + imCompressDataZ + imCompressDataUnZ + imAttribArrayCreate + imAttribArrayGet + imAttribArraySet + imAttribArrayCopyFrom + imBinMemoryRelease + imFileImageLoadRegion + imFileLoadImageRegion diff --git a/im/src/im.dep b/im/src/im.dep new file mode 100644 index 0000000..9f83359 --- /dev/null +++ b/im/src/im.dep @@ -0,0 +1,121 @@ +$(OBJDIR)/old_imcolor.o: old_imcolor.c ../include/old_im.h ../include/im.h \ + ../include/old_im.h ../include/im_util.h ../include/im_image.h \ + ../include/im_convert.h ../include/im_image.h +$(OBJDIR)/old_imresize.o: old_imresize.c ../include/old_im.h +$(OBJDIR)/im_converttype.o: im_converttype.cpp ../include/im.h ../include/old_im.h \ + ../include/im_util.h ../include/im_complex.h ../include/im_math.h \ + ../include/im_util.h ../include/im_image.h ../include/im_convert.h \ + ../include/im_image.h ../include/im_color.h ../include/im_counter.h +$(OBJDIR)/im_attrib.o: im_attrib.cpp ../include/im_attrib.h \ + ../include/im_attrib_flat.h ../include/im_util.h +$(OBJDIR)/im_format.o: im_format.cpp ../include/im.h ../include/old_im.h \ + ../include/im_format.h ../include/im_file.h ../include/im.h \ + ../include/im_attrib.h ../include/im_attrib_flat.h ../include/im_util.h +$(OBJDIR)/im_format_tga.o: im_format_tga.cpp ../include/im_format.h \ + ../include/im_file.h ../include/im.h ../include/old_im.h \ + ../include/im_attrib.h ../include/im_attrib_flat.h ../include/im_util.h \ + ../include/im_format_all.h ../include/im_counter.h ../include/im_math.h \ + ../include/im_util.h ../include/im_binfile.h +$(OBJDIR)/im_filebuffer.o: im_filebuffer.cpp ../include/im.h ../include/old_im.h \ + ../include/im_format.h ../include/im_file.h ../include/im.h \ + ../include/im_attrib.h ../include/im_attrib_flat.h ../include/im_util.h \ + ../include/im_complex.h ../include/im_math.h ../include/im_util.h \ + ../include/im_color.h +$(OBJDIR)/im_bin.o: im_bin.cpp ../include/im_util.h +$(OBJDIR)/im_format_all.o: im_format_all.cpp ../include/im.h ../include/old_im.h \ + ../include/im_format.h ../include/im_file.h ../include/im.h \ + ../include/im_attrib.h ../include/im_attrib_flat.h \ + ../include/im_format_all.h +$(OBJDIR)/im_format_raw.o: im_format_raw.cpp ../include/im_format.h \ + ../include/im_file.h ../include/im.h ../include/old_im.h \ + ../include/im_attrib.h ../include/im_attrib_flat.h ../include/im_util.h \ + ../include/im_format_raw.h ../include/im_counter.h \ + ../include/im_binfile.h ../include/im_util.h +$(OBJDIR)/im_binfile.o: im_binfile.cpp ../include/im_util.h ../include/im_binfile.h \ + ../include/im_util.h +$(OBJDIR)/im_format_sgi.o: im_format_sgi.cpp ../include/im_format.h \ + ../include/im_file.h ../include/im.h ../include/old_im.h \ + ../include/im_attrib.h ../include/im_attrib_flat.h ../include/im_util.h \ + ../include/im_format_all.h ../include/im_counter.h \ + ../include/im_binfile.h ../include/im_util.h +$(OBJDIR)/im_datatype.o: im_datatype.cpp ../include/im.h ../include/old_im.h \ + ../include/im_util.h +$(OBJDIR)/im_format_pcx.o: im_format_pcx.cpp ../include/im_format.h \ + ../include/im_file.h ../include/im.h ../include/old_im.h \ + ../include/im_attrib.h ../include/im_attrib_flat.h \ + ../include/im_format_all.h ../include/im_util.h ../include/im_counter.h \ + ../include/im_binfile.h ../include/im_util.h +$(OBJDIR)/im_colorhsi.o: im_colorhsi.cpp ../include/im_colorhsi.h \ + ../include/im_color.h ../include/im_math.h ../include/im_util.h +$(OBJDIR)/im_format_bmp.o: im_format_bmp.cpp ../include/im_format.h \ + ../include/im_file.h ../include/im.h ../include/old_im.h \ + ../include/im_attrib.h ../include/im_attrib_flat.h \ + ../include/im_format_all.h ../include/im_util.h ../include/im_counter.h \ + ../include/im_binfile.h ../include/im_util.h +$(OBJDIR)/im_image.o: im_image.cpp ../include/im.h ../include/old_im.h \ + ../include/im_image.h ../include/im_util.h ../include/im_attrib.h \ + ../include/im_attrib_flat.h ../include/im_file.h ../include/im.h +$(OBJDIR)/im_rgb2map.o: im_rgb2map.cpp ../include/im.h ../include/old_im.h \ + ../include/im_util.h ../include/im_convert.h ../include/im_image.h \ + ../include/im_counter.h +$(OBJDIR)/im_colormode.o: im_colormode.cpp ../include/im.h ../include/old_im.h \ + ../include/im_util.h +$(OBJDIR)/im_format_gif.o: im_format_gif.cpp ../include/im_format.h \ + ../include/im_file.h ../include/im.h ../include/old_im.h \ + ../include/im_attrib.h ../include/im_attrib_flat.h \ + ../include/im_format_all.h ../include/im_util.h ../include/im_counter.h \ + ../include/im_binfile.h ../include/im_util.h +$(OBJDIR)/im_lib.o: im_lib.cpp ../include/im_lib.h +$(OBJDIR)/im_format_pnm.o: im_format_pnm.cpp ../include/im_format.h \ + ../include/im_file.h ../include/im.h ../include/old_im.h \ + ../include/im_attrib.h ../include/im_attrib_flat.h \ + ../include/im_format_all.h ../include/im_util.h ../include/im_counter.h \ + ../include/im_binfile.h ../include/im_util.h +$(OBJDIR)/im_colorutil.o: im_colorutil.cpp ../include/im.h ../include/old_im.h \ + ../include/im_util.h +$(OBJDIR)/im_format_ico.o: im_format_ico.cpp ../include/im_format.h \ + ../include/im_file.h ../include/im.h ../include/old_im.h \ + ../include/im_attrib.h ../include/im_attrib_flat.h \ + ../include/im_format_all.h ../include/im_util.h ../include/im_counter.h \ + ../include/im_binfile.h ../include/im_util.h +$(OBJDIR)/im_palette.o: im_palette.cpp ../include/im.h ../include/old_im.h \ + ../include/im_util.h ../include/im_palette.h ../include/im_colorhsi.h +$(OBJDIR)/im_convertbitmap.o: im_convertbitmap.cpp ../include/im.h \ + ../include/old_im.h ../include/im_util.h ../include/im_complex.h \ + ../include/im_math.h ../include/im_util.h ../include/im_image.h \ + ../include/im_convert.h ../include/im_image.h ../include/im_counter.h +$(OBJDIR)/im_format_led.o: im_format_led.cpp ../include/im_format.h \ + ../include/im_file.h ../include/im.h ../include/old_im.h \ + ../include/im_attrib.h ../include/im_attrib_flat.h \ + ../include/im_format_all.h ../include/im_util.h ../include/im_counter.h \ + ../include/im_binfile.h ../include/im_util.h +$(OBJDIR)/im_counter.o: im_counter.cpp ../include/im_counter.h +$(OBJDIR)/im_str.o: im_str.cpp ../include/im_util.h +$(OBJDIR)/im_convertcolor.o: im_convertcolor.cpp ../include/im.h \ + ../include/old_im.h ../include/im_util.h ../include/im_complex.h \ + ../include/im_math.h ../include/im_util.h ../include/im_image.h \ + ../include/im_convert.h ../include/im_image.h ../include/im_color.h \ + ../include/im_counter.h +$(OBJDIR)/im_fileraw.o: im_fileraw.cpp ../include/im.h ../include/old_im.h \ + ../include/im_image.h ../include/im_util.h ../include/im_counter.h \ + ../include/im_raw.h ../include/im_format.h ../include/im_file.h \ + ../include/im.h ../include/im_attrib.h ../include/im_attrib_flat.h \ + ../include/im_format_raw.h +$(OBJDIR)/im_format_krn.o: im_format_krn.cpp ../include/im_format.h \ + ../include/im_file.h ../include/im.h ../include/old_im.h \ + ../include/im_attrib.h ../include/im_attrib_flat.h \ + ../include/im_format_all.h ../include/im_util.h ../include/im_counter.h \ + ../include/im_binfile.h ../include/im_util.h +$(OBJDIR)/im_file.o: im_file.cpp ../include/im.h ../include/old_im.h \ + ../include/im_format.h ../include/im_file.h ../include/im.h \ + ../include/im_attrib.h ../include/im_attrib_flat.h ../include/im_util.h \ + ../include/im_attrib.h ../include/im_counter.h ../include/im_plus.h +$(OBJDIR)/im_format_ras.o: im_format_ras.cpp ../include/im_format.h \ + ../include/im_file.h ../include/im.h ../include/old_im.h \ + ../include/im_attrib.h ../include/im_attrib_flat.h \ + ../include/im_format_all.h ../include/im_util.h ../include/im_counter.h \ + ../include/im_binfile.h ../include/im_util.h +$(OBJDIR)/old_im.o: old_im.cpp ../include/old_im.h ../include/im.h \ + ../include/old_im.h ../include/im_util.h ../include/im_counter.h +$(OBJDIR)/im_sysfile_unix.o: im_sysfile_unix.cpp ../include/im_util.h \ + ../include/im_binfile.h ../include/im_util.h diff --git a/im/src/im.rc b/im/src/im.rc new file mode 100755 index 0000000..990266a --- /dev/null +++ b/im/src/im.rc @@ -0,0 +1,19 @@ +1 VERSIONINFO + FILEVERSION 3,4,2,0 + PRODUCTVERSION 3,4,2,0 +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Comments", "www.tecgraf.puc-rio.br/im\0" + VALUE "CompanyName", "Tecgraf/PUC-Rio\0" + VALUE "FileDescription", "IM - Image Representation, Storage, Capture and Processing\0" + VALUE "FileVersion", "3.4.2\0" + VALUE "LegalCopyright", "Copyright © 1994-2009 Tecgraf, PUC-Rio.\0" + VALUE "OriginalFilename", "im.dll\0" + VALUE "ProductName", "IM for Windows\0" + VALUE "ProductVersion", "3.4.2\0" + END + END +END diff --git a/im/src/im_attrib.cpp b/im/src/im_attrib.cpp new file mode 100755 index 0000000..10d4599 --- /dev/null +++ b/im/src/im_attrib.cpp @@ -0,0 +1,319 @@ +/** \file + * \brief Attributes Table + * + * See Copyright Notice in im_lib.h + * $Id: im_attrib.cpp,v 1.3 2009/08/22 04:31:04 scuri Exp $ + */ + +#include +#include +#include +#include + +#include "im_attrib.h" +#include "im_util.h" + +#define IM_DEFAULTSIZE 101 +#define IM_MULTIPLIER 31 + +// Unique Hash index for a name +static int iHashIndex(const char *name, int hash_size) +{ + unsigned short hash = 0; + const unsigned char *p_name = (const unsigned char*)name; + + for(; *p_name; p_name++) + hash = hash*IM_MULTIPLIER + *p_name; + + return hash % hash_size; +} + + +/*******************************************************************/ + + +class imAttribNode +{ +public: + int data_type; + int count; + void* data; + char* name; + + imAttribNode* next; + + imAttribNode(const char* name, int _data_type, int _count, const void* _data, imAttribNode* next); + ~imAttribNode(); +}; + +static char* utlStrDup(const char* str) +{ + int size; + char* new_str; + + assert(str); + + size = strlen(str) + 1; + new_str = (char*)malloc(size); + memcpy(new_str, str, size); + + return new_str; +} + +imAttribNode::imAttribNode(const char* name, int _data_type, int _count, const void* _data, imAttribNode* _next) +{ + if (_data_type == 0 && _count == -1) /* BYTE meaning a string */ + _count = strlen((char*)_data)+1; + + this->name = utlStrDup(name); + this->data_type = _data_type; + this->count = _count; + this->next = _next; + + int size = _count * imDataTypeSize(_data_type); + this->data = malloc(size); + if (_data) memcpy(this->data, _data, size); + else memset(this->data, 0, size); +} + +imAttribNode::~imAttribNode() +{ + free(this->name); + free(this->data); +} + + +/*******************************************************************/ + +struct imAttribTablePrivate +{ + int count, + hash_size; + imAttribNode* *hash_table; +}; + +imAttribTablePrivate* imAttribTableCreate(int hash_size) +{ + imAttribTablePrivate* ptable = (imAttribTablePrivate*)malloc(sizeof(imAttribTablePrivate)); + ptable->count = 0; + ptable->hash_size = (hash_size == 0)? IM_DEFAULTSIZE: hash_size; + ptable->hash_table = (imAttribNode**)malloc(ptable->hash_size*sizeof(imAttribNode*)); + memset(ptable->hash_table, 0, ptable->hash_size*sizeof(imAttribNode*)); + return ptable; +} + +imAttribTablePrivate* imAttribArrayCreate(int count) +{ + imAttribTablePrivate* ptable = (imAttribTablePrivate*)malloc(sizeof(imAttribTablePrivate)); + ptable->hash_size = ptable->count = count; + ptable->hash_table = (imAttribNode**)malloc(ptable->count*sizeof(imAttribNode*)); + memset(ptable->hash_table, 0, ptable->hash_size*sizeof(imAttribNode*)); + return ptable; +} + +void imAttribTableDestroy(imAttribTablePrivate* ptable) +{ + imAttribTableRemoveAll(ptable); + free(ptable->hash_table); + free(ptable); +} + +int imAttribTableCount(imAttribTablePrivate* ptable) +{ + return ptable->count; +} + +void imAttribTableRemoveAll(imAttribTablePrivate* ptable) +{ + if (ptable->count == 0) return; + + int n = 0; + for(int i = 0; i < ptable->hash_size; i++) + { + imAttribNode* cur_node = ptable->hash_table[i]; + while (cur_node) + { + imAttribNode* next_node = cur_node->next; + delete cur_node; + cur_node = next_node; + n++; + } + + ptable->hash_table[i] = NULL; + + if (n == ptable->count) + break; + } + + ptable->count = 0; +} + +void imAttribTableSet(imAttribTablePrivate* ptable, const char* name, int data_type, int count, const void* data) +{ + assert(name); + + int index = iHashIndex(name, ptable->hash_size); + imAttribNode* first_node = ptable->hash_table[index]; + + // The name already exists ? + imAttribNode* cur_node = first_node; + imAttribNode* prev_node = NULL; + while (cur_node) + { + if (imStrEqual(cur_node->name, name)) + { + // Found, replace current node. + imAttribNode* new_node = new imAttribNode(name, data_type, count, data, cur_node->next); + + // Is first node ? + if (cur_node == first_node) + ptable->hash_table[index] = new_node; + else + prev_node->next = new_node; + + delete cur_node; + return; + } + + prev_node = cur_node; + cur_node = cur_node->next; + } + + // Not found, the new item goes first. + cur_node = new imAttribNode(name, data_type, count, data, first_node); + ptable->hash_table[index] = cur_node; + ptable->count++; +} + +void imAttribTableUnSet(imAttribTablePrivate* ptable, const char *name) +{ + assert(name); + + if (ptable->count == 0) return; + + int index = iHashIndex(name, ptable->hash_size); + + imAttribNode* cur_node = ptable->hash_table[index]; + imAttribNode* prev_node = cur_node; + while (cur_node) + { + if (imStrEqual(cur_node->name, name)) + { + // Is first node ? + if (cur_node == prev_node) + ptable->hash_table[index] = cur_node->next; + else + prev_node->next = cur_node->next; + + delete cur_node; + ptable->count--; + return; + } + + prev_node = cur_node; + cur_node = cur_node->next; + } +} + +const void* imAttribTableGet(const imAttribTablePrivate* ptable, const char *name, int *data_type, int *count) +{ + assert(name); + + if (ptable->count == 0) return NULL; + + int index = iHashIndex(name, ptable->hash_size); + + imAttribNode* cur_node = ptable->hash_table[index]; + while (cur_node) + { + if (imStrEqual(cur_node->name, name)) + { + if (data_type) *data_type = cur_node->data_type; + if (count) *count = cur_node->count; + return cur_node->data; + } + + cur_node = cur_node->next; + } + + return NULL; +} + +void imAttribArraySet(imAttribTablePrivate* ptable, int index, const char* name, int data_type, int count, const void* data) +{ + assert(name); + assert(index < ptable->count); + + if (index >= ptable->count) return; + + imAttribNode* node = ptable->hash_table[index]; + if (node) delete node; + + ptable->hash_table[index] = new imAttribNode(name, data_type, count, data, NULL); +} + +const void* imAttribArrayGet(const imAttribTablePrivate* ptable, int index, char *name, int *data_type, int *count) +{ + if (ptable->count == 0) return NULL; + + imAttribNode* node = ptable->hash_table[index]; + if (node) + { + if (name) strcpy(name, node->name); + if (data_type) *data_type = node->data_type; + if (count) *count = node->count; + return node->data; + } + + return NULL; +} + +void imAttribTableForEach(const imAttribTablePrivate* ptable, void* user_data, imAttribTableCallback attrib_func) +{ + assert(attrib_func); + + if (ptable->count == 0) return; + + int index = 0; + for(int i = 0; i < ptable->hash_size; i++) + { + imAttribNode* cur_node = ptable->hash_table[i]; + while (cur_node) + { + if (!attrib_func(user_data, index, cur_node->name, cur_node->data_type, cur_node->count, cur_node->data)) + return; + + index++; + cur_node = cur_node->next; + } + + if (index == ptable->count) + return; + } +} + +static int iCopyFunc(void* user_data, int index, const char* name, int data_type, int count, const void* data) +{ + (void)index; + imAttribTablePrivate* ptable = (imAttribTablePrivate*)user_data; + imAttribTableSet(ptable, name, data_type, count, data); + return 1; +} + +void imAttribTableCopyFrom(imAttribTablePrivate* ptable_dst, const imAttribTablePrivate* ptable_src) +{ + imAttribTableForEach(ptable_src, (void*)ptable_dst, iCopyFunc); +} + +static int iCopyArrayFunc(void* user_data, int index, const char* name, int data_type, int count, const void* data) +{ + (void)index; + imAttribTablePrivate* ptable = (imAttribTablePrivate*)user_data; + imAttribArraySet(ptable, index, name, data_type, count, data); + return 1; +} + +void imAttribArrayCopyFrom(imAttribTablePrivate* ptable_dst, const imAttribTablePrivate* ptable_src) +{ + imAttribTableForEach(ptable_src, (void*)ptable_dst, iCopyArrayFunc); +} diff --git a/im/src/im_bin.cpp b/im/src/im_bin.cpp new file mode 100755 index 0000000..de279b5 --- /dev/null +++ b/im/src/im_bin.cpp @@ -0,0 +1,111 @@ +/** \file + * \brief Binary Data Utilities + * + * See Copyright Notice in im_lib.h + * $Id: im_bin.cpp,v 1.1 2008/10/17 06:10:16 scuri Exp $ + */ + +#include + +#include "im_util.h" + + +int imBinCPUByteOrder(void) +{ + static int CPUByteOrder = -1; + + if (CPUByteOrder == -1) + { + unsigned short w = 0x0001; + unsigned char* b = (unsigned char*)&w; + CPUByteOrder = (b[0] == 0x01)? IM_LITTLEENDIAN: IM_BIGENDIAN; + } + + return CPUByteOrder; +} + +void imBinSwapBytes(void *data, int count, int size) +{ + switch(size) + { + case 2: + imBinSwapBytes2(data, count); + break; + case 4: + imBinSwapBytes4(data, count); + break; + case 8: + imBinSwapBytes8(data, count); + break; + } +} + +void imBinSwapBytes2(void *data, int count) +{ + assert(data); + + unsigned char lTemp; + unsigned char *values = (unsigned char *)data; + + while (count-- != 0) + { + lTemp = values[1]; + values[1] = values[0]; + values[0] = lTemp; + + values += 2; + } +} + +void imBinSwapBytes4(void *data, int count) +{ + assert(data); + + unsigned char lTemp; + unsigned char *values = (unsigned char *)data; + + while (count-- != 0) + { + lTemp = values[3]; + values[3] = values[0]; + values[0] = lTemp; + + lTemp = values[2]; + values[2] = values[1]; + values[1] = lTemp; + + values += 4; + } +} + +void imBinSwapBytes8(void *data, int count) +{ + assert(data); + + unsigned char lTemp; + unsigned char *values = (unsigned char *)data; + + assert(values); + + while (count-- != 0) + { + lTemp = values[7]; + values[7] = values[0]; + values[0] = lTemp; + + lTemp = values[6]; + values[6] = values[1]; + values[1] = lTemp; + + lTemp = values[5]; + values[5] = values[2]; + values[2] = lTemp; + + lTemp = values[4]; + values[4] = values[3]; + values[3] = lTemp; + + values += 8; + } +} + diff --git a/im/src/im_binfile.cpp b/im/src/im_binfile.cpp new file mode 100755 index 0000000..7171032 --- /dev/null +++ b/im/src/im_binfile.cpp @@ -0,0 +1,710 @@ +/** \file + * \brief Binary File Access + * + * See Copyright Notice in im_lib.h + * $Id: im_binfile.cpp,v 1.2 2009/10/01 14:15:47 scuri Exp $ + */ + + +#include +#include +#include +#include +#include + +#include "im_util.h" +#include "im_binfile.h" + + +/************************************************** + imBinMemoryFile +***************************************************/ + +class imBinMemoryFile: public imBinFileBase +{ +protected: + unsigned long CurrentSize, BufferSize; + unsigned char* Buffer, *CurPos; + int Error; + float Reallocate; + imBinMemoryFileName* file_name; + + unsigned long ReadBuf(void* pValues, unsigned long pSize); + unsigned long WriteBuf(void* pValues, unsigned long pSize); + +public: + void Open(const char* pFileName); + void New(const char* pFileName); + void Close() {} // Does nothing, the memory belongs to the user + + unsigned long FileSize(); + int HasError() const; + void SeekTo(unsigned long pOffset); + void SeekOffset(long pOffset); + void SeekFrom(long pOffset); + unsigned long Tell() const; + int EndOfFile() const; +}; + +static imBinFileBase* iBinMemoryFileNewFunc() +{ + return new imBinMemoryFile(); +} + +void imBinMemoryRelease(unsigned char *buffer) +{ + free(buffer); +} + +void imBinMemoryFile::Open(const char* pFileName) +{ + this->file_name = (imBinMemoryFileName*)pFileName; + + InitByteOrder(imBinCPUByteOrder()); + this->IsNew = 0; + + assert(this->file_name->size); + + this->Buffer = this->file_name->buffer; + this->BufferSize = this->file_name->size; + this->Reallocate = this->file_name->reallocate; + this->CurrentSize = this->BufferSize; + this->CurPos = this->Buffer; + this->Error = 0; +} + +void imBinMemoryFile::New(const char* pFileName) +{ + this->file_name = (imBinMemoryFileName*)pFileName; + + InitByteOrder(imBinCPUByteOrder()); + this->IsNew = 1; + + assert(this->file_name->size); + + this->Buffer = this->file_name->buffer; + this->BufferSize = this->file_name->size; + this->Reallocate = this->file_name->reallocate; + this->CurrentSize = 0; + + if (!this->Buffer) + { + this->Buffer = (unsigned char*)malloc(this->BufferSize); + this->file_name->buffer = this->Buffer; + } + + this->CurPos = this->Buffer; + this->Error = 0; +} + +unsigned long imBinMemoryFile::ReadBuf(void* pValues, unsigned long pSize) +{ + assert(this->Buffer); + + unsigned long lOffset = this->CurPos - this->Buffer; + + this->Error = 0; + if (lOffset + pSize > this->CurrentSize) + { + this->Error = 1; + pSize = this->CurrentSize - lOffset; + } + + if (pSize) + { + memcpy(pValues, this->CurPos, pSize); + this->CurPos += pSize; + } + + return pSize; +} + +unsigned long imBinMemoryFile::WriteBuf(void* pValues, unsigned long pSize) +{ + assert(this->Buffer); + + unsigned long lOffset = this->CurPos - this->Buffer; + + this->Error = 0; + if (lOffset + pSize > this->BufferSize) + { + if (this->Reallocate != 0.0) + { + unsigned long nSize = this->BufferSize; + while (lOffset + pSize > nSize) + nSize += (unsigned long)(this->Reallocate*(float)this->BufferSize); + + this->Buffer = (unsigned char*)realloc(this->Buffer, nSize); + + if (this->Buffer) + { + this->BufferSize = nSize; + this->file_name->buffer = this->Buffer; + this->file_name->size = this->BufferSize; + } + else + { + this->Buffer = this->file_name->buffer; + this->Error = 1; + pSize = this->BufferSize - lOffset; + } + + this->CurPos = this->Buffer + lOffset; + } + else + { + this->Error = 1; + pSize = this->BufferSize - lOffset; + } + } + + memcpy(this->CurPos, pValues, pSize); + + if (lOffset + pSize > this->CurrentSize) + this->CurrentSize = lOffset + pSize; + + this->CurPos += pSize; + + return pSize; +} + +unsigned long imBinMemoryFile::FileSize() +{ + assert(this->Buffer); + return this->CurrentSize; +} + +int imBinMemoryFile::HasError() const +{ + if (!this->Buffer) return 1; + return this->Error; +} + +void imBinMemoryFile::SeekTo(unsigned long pOffset) +{ + assert(this->Buffer); + + this->Error = 0; + if (pOffset > this->BufferSize) + { + this->Error = 1; + return; + } + + this->CurPos = this->Buffer + pOffset; + + /* update size if we seek after EOF */ + if (pOffset > this->CurrentSize) + this->CurrentSize = pOffset; +} + +void imBinMemoryFile::SeekFrom(long pOffset) +{ + assert(this->Buffer); + + /* remember that offset is usually a negative value in this case */ + + this->Error = 0; + if (this->CurrentSize + pOffset > this->BufferSize || + (long)this->CurrentSize + pOffset < 0) + { + this->Error = 1; + return; + } + + this->CurPos = this->Buffer + this->CurrentSize + pOffset; + + /* update size if we seek after EOF */ + if (pOffset > 0) + this->CurrentSize = this->CurrentSize + pOffset; +} + +void imBinMemoryFile::SeekOffset(long pOffset) +{ + assert(this->Buffer); + long lOffset = this->CurPos - this->Buffer; + + this->Error = 0; + if (lOffset + pOffset < 0 || lOffset + pOffset > (long)this->BufferSize) + { + this->Error = 1; + return; + } + + this->CurPos += pOffset; + + /* update size if we seek after EOF */ + if (lOffset + pOffset > (long)this->CurrentSize) + this->CurrentSize = lOffset + pOffset; +} + +unsigned long imBinMemoryFile::Tell() const +{ + assert(this->Buffer); + unsigned long lOffset = this->CurPos - this->Buffer; + return lOffset; +} + +int imBinMemoryFile::EndOfFile() const +{ + assert(this->Buffer); + unsigned long lOffset = this->CurPos - this->Buffer; + return lOffset == this->CurrentSize? 1: 0; +} + +/************************************************** + imBinSubFile +**************************************************/ + +static imBinFileBase* iBinFileBaseHandle(const char* pFileName); + +class imBinSubFile: public imBinFileBase +{ +protected: + imBinFileBase* FileHandle; + unsigned long StartOffset; + + unsigned long ReadBuf(void* pValues, unsigned long pSize); + unsigned long WriteBuf(void* pValues, unsigned long pSize); + +public: + void Open(const char* pFileName); + void New(const char* pFileName); + void Close() {} // Does nothing, the file should be close by the parent file. + + unsigned long FileSize(); + int HasError() const; + void SeekTo(unsigned long pOffset); + void SeekOffset(long pOffset); + void SeekFrom(long pOffset); + unsigned long Tell() const; + int EndOfFile() const; +}; + +static imBinFileBase* iBinSubFileNewFunc() +{ + return new imBinSubFile(); +} + +void imBinSubFile::Open(const char* pFileName) +{ + this->FileHandle = iBinFileBaseHandle(pFileName); + this->FileByteOrder = this->FileByteOrder; + this->IsNew = 0; + + StartOffset = this->FileHandle->Tell(); +} + +void imBinSubFile::New(const char* pFileName) +{ + this->FileHandle = iBinFileBaseHandle(pFileName); + this->FileByteOrder = this->FileByteOrder; + this->IsNew = 1; + + StartOffset = this->FileHandle->Tell(); +} + +unsigned long imBinSubFile::FileSize() +{ + assert(this->FileHandle); + return this->FileHandle->FileSize(); +} + +unsigned long imBinSubFile::ReadBuf(void* pValues, unsigned long pSize) +{ + assert(this->FileHandle); + return this->FileHandle->ReadBuf(pValues, pSize); +} + +unsigned long imBinSubFile::WriteBuf(void* pValues, unsigned long pSize) +{ + assert(this->FileHandle); + return this->FileHandle->WriteBuf(pValues, pSize); +} + +int imBinSubFile::HasError() const +{ + assert(this->FileHandle); + return this->FileHandle->HasError(); +} + +void imBinSubFile::SeekTo(unsigned long pOffset) +{ + assert(this->FileHandle); + this->FileHandle->SeekTo(StartOffset + pOffset); +} + +void imBinSubFile::SeekOffset(long pOffset) +{ + assert(this->FileHandle); + this->FileHandle->SeekOffset(pOffset); +} + +void imBinSubFile::SeekFrom(long pOffset) +{ + assert(this->FileHandle); + this->FileHandle->SeekFrom(pOffset); +} + +unsigned long imBinSubFile::Tell() const +{ + assert(this->FileHandle); + return this->FileHandle->Tell() - StartOffset; +} + +int imBinSubFile::EndOfFile() const +{ + assert(this->FileHandle); + return this->FileHandle->EndOfFile(); +} + +/************************************************** + imBinStreamFile +**************************************************/ + +class imBinStreamFile: public imBinFileBase +{ +protected: + FILE* FileHandle; + + unsigned long ReadBuf(void* pValues, unsigned long pSize); + unsigned long WriteBuf(void* pValues, unsigned long pSize); + +public: + void Open(const char* pFileName); + void New(const char* pFileName); + void Close(); + + unsigned long FileSize(); + int HasError() const; + void SeekTo(unsigned long pOffset); + void SeekOffset(long pOffset); + void SeekFrom(long pOffset); + unsigned long Tell() const; + int EndOfFile() const; +}; + +static imBinFileBase* iBinStreamFileNewFunc() +{ + return new imBinStreamFile(); +} + +void imBinStreamFile::Open(const char* pFileName) +{ + this->FileHandle = fopen(pFileName, "rb"); + InitByteOrder(imBinCPUByteOrder()); + this->IsNew = 0; +} + +void imBinStreamFile::New(const char* pFileName) +{ + this->FileHandle = fopen(pFileName, "wb"); + InitByteOrder(imBinCPUByteOrder()); + this->IsNew = 1; +} + +void imBinStreamFile::Close() +{ + if (this->FileHandle) fclose(this->FileHandle); +} + +unsigned long imBinStreamFile::FileSize() +{ + assert(this->FileHandle); + unsigned long lCurrentPosition = ftell(this->FileHandle); + fseek(this->FileHandle, 0L, SEEK_END); + unsigned long lSize = ftell(this->FileHandle); + fseek(this->FileHandle, lCurrentPosition, SEEK_SET); + return lSize; +} + +unsigned long imBinStreamFile::ReadBuf(void* pValues, unsigned long pSize) +{ + assert(this->FileHandle); + return fread(pValues, 1, pSize, this->FileHandle); +} + +unsigned long imBinStreamFile::WriteBuf(void* pValues, unsigned long pSize) +{ + assert(this->FileHandle); + return fwrite(pValues, 1, pSize, this->FileHandle); +} + +int imBinStreamFile::HasError() const +{ + if (!this->FileHandle) return 1; + return ferror(this->FileHandle) == 0? 0: 1; +} + +void imBinStreamFile::SeekTo(unsigned long pOffset) +{ + assert(this->FileHandle); + fseek(this->FileHandle, pOffset, SEEK_SET); +} + +void imBinStreamFile::SeekOffset(long pOffset) +{ + assert(this->FileHandle); + fseek(this->FileHandle, pOffset, SEEK_CUR); +} + +void imBinStreamFile::SeekFrom(long pOffset) +{ + assert(this->FileHandle); + fseek(this->FileHandle, pOffset, SEEK_END); +} + +unsigned long imBinStreamFile::Tell() const +{ + assert(this->FileHandle); + return ftell(this->FileHandle); +} + +int imBinStreamFile::EndOfFile() const +{ + assert(this->FileHandle); + return feof(this->FileHandle) == 0? 0: 1; +} + +/************************************************** + NewFuncModules +**************************************************/ + +/* implemented in "im_sysfile*.cpp" */ +imBinFileBase* iBinSystemFileNewFunc(); +imBinFileBase* iBinSystemFileHandleNewFunc(); + +#define MAX_MODULES 10 + +static imBinFileNewFunc iBinFileModule[MAX_MODULES] = +{ + iBinSystemFileNewFunc, + iBinStreamFileNewFunc, + iBinMemoryFileNewFunc, + iBinSubFileNewFunc, + iBinSystemFileHandleNewFunc +}; +static int iBinFileModuleCount = 5; +static int iBinFileModuleCurrent = 0; // default module is the first + +int imBinFileSetCurrentModule(int pModule) +{ + int old_module = iBinFileModuleCurrent; + + if (pModule >= iBinFileModuleCount) + return -1; + + iBinFileModuleCurrent = pModule; + + return old_module; +} + +int imBinFileRegisterModule(imBinFileNewFunc pNewFunc) +{ + if (iBinFileModuleCount == MAX_MODULES) return -1; + int id = iBinFileModuleCount; + iBinFileModule[id] = pNewFunc; + iBinFileModuleCount++; + return id; +} + +/************************************************** + imBinFile +**************************************************/ + +struct _imBinFile +{ + imBinFileBase* binfile; +}; + +imBinFile* imBinFileOpen(const char* pFileName) +{ + assert(pFileName); + + assert(iBinFileModuleCurrent < iBinFileModuleCount); + assert(iBinFileModuleCurrent < MAX_MODULES); + + imBinFileNewFunc NewFunc = iBinFileModule[iBinFileModuleCurrent]; + imBinFileBase* binfile = NewFunc(); + + binfile->Open(pFileName); + if (binfile->HasError()) + { + delete binfile; + return NULL; + } + + imBinFile* bfile = new imBinFile; + bfile->binfile = binfile; + + return bfile; +} + +imBinFile* imBinFileNew(const char* pFileName) +{ + assert(pFileName); + + imBinFileNewFunc NewFunc = iBinFileModule[iBinFileModuleCurrent]; + imBinFileBase* binfile = NewFunc(); + + binfile->New(pFileName); + if (binfile->HasError()) + { + delete binfile; + return NULL; + } + + imBinFile* bfile = new imBinFile; + bfile->binfile = binfile; + + return bfile; +} + +void imBinFileClose(imBinFile* bfile) +{ + assert(bfile); + bfile->binfile->Close(); + delete bfile->binfile; + delete bfile; +} + +int imBinFileByteOrder(imBinFile* bfile, int pByteOrder) +{ + assert(bfile); + return bfile->binfile->InitByteOrder(pByteOrder); +} + +int imBinFileError(imBinFile* bfile) +{ + assert(bfile); + return bfile->binfile->HasError(); +} + +unsigned long imBinFileSize(imBinFile* bfile) +{ + assert(bfile); + return bfile->binfile->FileSize(); +} + +unsigned long imBinFileRead(imBinFile* bfile, void* pValues, unsigned long pCount, int pSizeOf) +{ + assert(bfile); + return bfile->binfile->Read(pValues, pCount, pSizeOf); +} + +unsigned long imBinFileWrite(imBinFile* bfile, void* pValues, unsigned long pCount, int pSizeOf) +{ + assert(bfile); + return bfile->binfile->Write(pValues, pCount, pSizeOf); +} + +void imBinFileSeekTo(imBinFile* bfile, unsigned long pOffset) +{ + assert(bfile); + bfile->binfile->SeekTo(pOffset); +} + +void imBinFileSeekOffset(imBinFile* bfile, long pOffset) +{ + assert(bfile); + bfile->binfile->SeekOffset(pOffset); +} + +void imBinFileSeekFrom(imBinFile* bfile, long pOffset) +{ + assert(bfile); + bfile->binfile->SeekFrom(pOffset); +} + +unsigned long imBinFileTell(imBinFile* bfile) +{ + assert(bfile); + return bfile->binfile->Tell(); +} + +int imBinFileEndOfFile(imBinFile* bfile) +{ + assert(bfile); + return bfile->binfile->EndOfFile(); +} + +unsigned long imBinFilePrintf(imBinFile* bfile, char *format, ...) +{ + va_list arglist; + va_start(arglist, format); + char buffer[4096]; + int size = vsprintf(buffer, format, arglist); + return imBinFileWrite(bfile, buffer, size, 1); +} + +int imBinFileReadInteger(imBinFile* handle, int *value) +{ + int i = 0, found = 0; + char buffer[11], c; + + while (!found) + { + imBinFileRead(handle, &c, 1, 1); + + /* if it's an integer, increments the number of characters read */ + if ((c >= '0' && c <= '9') || (c == '-')) + { + buffer[i] = c; + i++; + } + else + { + /* if it's not, and we read some characters, convert them to an integer */ + if (i > 0) + { + buffer[i] = 0; + *value = atoi(buffer); + found = 1; + } + } + + if (imBinFileError(handle) || i > 10) + return 0; + } + + return 1; +} + +int imBinFileReadFloat(imBinFile* handle, float *value) +{ + int i = 0, found = 0; + char buffer[17], c; + + while (!found) + { + imBinFileRead(handle, &c, 1, 1); + + /* if it's a floating point number, increments the number of characters read */ + if ((c >= '0' && c <= '9') || c == '-' || c == '+' || c == '.' || c == 'e' || c == 'E') + { + buffer[i] = c; + i++; + } + else + { + /* if it's not, and we read some characters convert them to an integer */ + if (i > 0) + { + buffer[i] = 0; + *value = (float)atof(buffer); + found = 1; + } + } + + if (imBinFileError(handle) || i > 16) + return 0; + } + + return 1; +} + +static imBinFileBase* iBinFileBaseHandle(const char* pFileName) +{ + imBinFile* bfile = (imBinFile*)pFileName; + return (imBinFileBase*)bfile->binfile; +} diff --git a/im/src/im_capture.def b/im/src/im_capture.def new file mode 100755 index 0000000..6b44ac3 --- /dev/null +++ b/im/src/im_capture.def @@ -0,0 +1,27 @@ +EXPORTS + imVideoCaptureDeviceCount + imVideoCaptureDeviceDesc + imVideoCaptureReloadDevices + imVideoCaptureCreate + imVideoCaptureDestroy + imVideoCaptureConnect + imVideoCaptureDisconnect + imVideoCaptureShowDialog + imVideoCaptureDialogCount + imVideoCaptureDialogDesc + imVideoCaptureGetImageSize + imVideoCaptureSetImageSize + imVideoCaptureFrame + imVideoCaptureOneFrame + imVideoCaptureLive + imVideoCaptureResetAttribute + imVideoCaptureGetAttribute + imVideoCaptureSetAttribute + imVideoCaptureGetAttributeList + imVideoCaptureFormatCount + imVideoCaptureGetFormat + imVideoCaptureSetFormat + imVideoCaptureSetInOut + imVideoCaptureDeviceExDesc + imVideoCaptureDevicePath + imVideoCaptureDeviceVendorInfo diff --git a/im/src/im_capture.mak b/im/src/im_capture.mak new file mode 100755 index 0000000..8f10bc7 --- /dev/null +++ b/im/src/im_capture.mak @@ -0,0 +1,73 @@ +PROJNAME = im +LIBNAME = im_capture +OPT = YES + +INCLUDES = ../include + +# New Direct X does not includes Direct Show +# Direct Show is included in latest Platform SDK, but depends on Direct X... +DXSDK = d:/lng/dxsdk +WINSDK = d:/lng/winsdk + +ifeq ($(TEC_UNAME), vc6) + #Use old Direct X with Direct Show + #But do NOT use the VC6 strmiids.lib + PLATSDK = d:/lng/vc7/PlatformSDK +endif + +ifeq ($(TEC_UNAME), dll) + #Use old Direct X with Direct Show + PLATSDK = d:/lng/vc7/PlatformSDK + LDIR = ../lib/$(TEC_UNAME) +endif + +ifeq ($(TEC_UNAME), vc8) + INCLUDES += $(WINSDK)/include + LDIR = $(WINSDK)/lib +endif + +ifeq ($(TEC_UNAME), dll8) + INCLUDES += $(WINSDK)/include + LDIR = $(WINSDK)/lib +endif + +ifeq ($(TEC_UNAME), vc8_64) + INCLUDES += $(WINSDK)/include + LDIR = $(WINSDK)/lib/amd64 +endif + +ifeq ($(TEC_UNAME), dll8_64) + INCLUDES += $(WINSDK)/include + LDIR = $(WINSDK)/lib/amd64 +endif + +ifneq ($(findstring Win, $(TEC_SYSNAME)), ) + INCLUDES += $(DXSDK)/include + SRC = im_capture_dx.cpp +endif + +#ifneq ($(findstring Linux, $(TEC_UNAME)), ) +# SRC = im_capture_v4l.cpp +#endif + +LIBS = strmiids + +mingw3-dll: + @echo Importing MingW stub library + @cd ../lib/dll + @dlltool -d im_capture.def -D im_capture.dll -l ../lib/mingw3/libim_capture.a + @cd ../src + +mingw4-dll: + @echo Importing MingW stub library + @cd ../lib/dll + @dlltool -d im_capture.def -D im_capture.dll -l ../lib/mingw4/libim_capture.a + @cd ../src + +bc56-dll: + @echo Importing Bcc stub library + @d:/lng/cbuilderx/bin/implib -a ../lib/bc56/im_capture.lib ../lib/dll/im_capture.dll + +#owc1-dll: +# @wlib -b -c -n -q -fo -io ../lib/owc1/im_capture.lib @im_capture.wlib +# TEST @wlib -b -c -n -q -fo -io ../lib/owc1/im_capture.lib +../lib/dll/im_capture.dll diff --git a/im/src/im_capture.wlib b/im/src/im_capture.wlib new file mode 100644 index 0000000..7dca75e --- /dev/null +++ b/im/src/im_capture.wlib @@ -0,0 +1,22 @@ +++imVideoCaptureDeviceCount.im_capture._imVideoCaptureDeviceCount +++imVideoCaptureDeviceDesc.im_capture._imVideoCaptureDeviceDesc +++imVideoCaptureReloadDevices.im_capture._imVideoCaptureReloadDevices +++imVideoCaptureCreate.im_capture._imVideoCaptureCreate +++imVideoCaptureDestroy.im_capture._imVideoCaptureDestroy +++imVideoCaptureConnect.im_capture._imVideoCaptureConnect +++imVideoCaptureDisconnect.im_capture._imVideoCaptureDisconnect +++imVideoCaptureShowDialog.im_capture._imVideoCaptureShowDialog +++imVideoCaptureDialogCount.im_capture._imVideoCaptureDialogCount +++imVideoCaptureDialogDesc.im_capture._imVideoCaptureDialogDesc +++imVideoCaptureGetImageSize.im_capture._imVideoCaptureGetImageSize +++imVideoCaptureSetImageSize.im_capture._imVideoCaptureSetImageSize +++imVideoCaptureFrame.im_capture._imVideoCaptureFrame +++imVideoCaptureOneFrame.im_capture._imVideoCaptureOneFrame +++imVideoCaptureLive.im_capture._imVideoCaptureLive +++imVideoCaptureResetAttribute.im_capture._imVideoCaptureResetAttribute +++imVideoCaptureGetAttribute.im_capture._imVideoCaptureGetAttribute +++imVideoCaptureSetAttribute.im_capture._imVideoCaptureSetAttribute +++imVideoCaptureGetAttributeList.im_capture._imVideoCaptureGetAttributeList +++imVideoCaptureFormatCount.im_capture._imVideoCaptureFormatCount +++imVideoCaptureGetFormat.im_capture._imVideoCaptureGetFormat +++imVideoCaptureSetFormat.im_capture._imVideoCaptureSetFormat diff --git a/im/src/im_capture_dx.cpp b/im/src/im_capture_dx.cpp new file mode 100755 index 0000000..cb4749b --- /dev/null +++ b/im/src/im_capture_dx.cpp @@ -0,0 +1,2255 @@ +/** \file + * \brief Video Capture Using Direct Show 9 + * + * See Copyright Notice in im.h + * $Id: im_capture_dx.cpp,v 1.1 2008/10/17 06:10:16 scuri Exp $ + */ + +/* + The Direct Show Graph is composed by 3 components: + capture source, sample grabber and null renderer. + + Filters are connected: + capture_filter(out)->(int)grabber_filter(out)->(in)null_filter + + But when the graph is rendered other transform filters + can be inserted to connect the capture and the grabber. + + We do not use MFC, ATL and the Direct Show Base Classes. + This module only needs the library "strmiids.lib". + If the extra error functions were used, you will need to link with "quartz.lib" or "dxerr9.lib". + + We use the buffer of the ISampleGrabber. But this can not be done in a user callback, + so we leave the grab loop for the application, it can also be done in the idle function. + + If you use the idle function for the grab loop, then WDM Source Dialog will interrupt the "live" mode. + Just because it is a modal dialog and it does not use the application message loop. + It can be solved if the grab loop is implemented using a timer. + + Since there is no gray format, bpp is always 24bpp. +*/ + +#define _WIN32_WINNT 0x0500 // Because of TryEnterCriticalSection + +#include +#include + +#include +#include +#include + +#include +#include + +#include "im_capture.h" + +#define VC_CAMERADELAY 200 // This vary from camera to camera, so we use a reasonable value and hope it will work for all. +#define VC_MAXVIDDEVICES 30 // Maximum number of devices to list + +//#define VC_REGISTER_FILTERGRAPH // Use this to allow GraphEdit to spy the graph +//#define VC_INCLUDE_VFW_DEVICES // Use this to allow old video for windows devices +//#define VC_PRINT_ERROR_MESSAGES // Use this to display a system custom error message + +#if defined(_DEBUG) | defined(DEBUG) +#define VC_REGISTER_FILTERGRAPH +#define VC_PRINT_ERROR_MESSAGES +#endif + + +/************************************************************************** + imTrackingGrabberCB +***************************************************************************/ + +// This is better than using the sample grabber internal buffer +// because we have a more precise control of the data flow. + +class imTrackingGrabberCB: public ISampleGrabberCB +{ +public: + imTrackingGrabberCB(); + ~imTrackingGrabberCB(); + + STDMETHODIMP SampleCB(double SampleTime, IMediaSample *pSample); + STDMETHODIMP BufferCB(double SampleTime, BYTE *pBuffer, long BufferLen) {return E_NOTIMPL;} + STDMETHODIMP_(ULONG) AddRef() {return 2;} + STDMETHODIMP_(ULONG) Release() {return 1;} + STDMETHODIMP QueryInterface(REFIID riid, void ** ppv); + + void SetImageSize(int width, int height); + int GetImage(unsigned char* data, int color_mode, int timeout); + +protected: + int m_Width, m_Height; + bool m_newImageFlag; + unsigned char *m_ImageData; + CRITICAL_SECTION m_sect; + HANDLE m_imageReady; +}; + +imTrackingGrabberCB::imTrackingGrabberCB() +{ + InitializeCriticalSection(&m_sect); + m_newImageFlag = 0; + m_ImageData = NULL; + m_imageReady = CreateEvent(NULL, FALSE, TRUE, NULL); +} + +imTrackingGrabberCB::~imTrackingGrabberCB() +{ + CloseHandle(m_imageReady); + EnterCriticalSection(&m_sect); + DeleteCriticalSection(&m_sect); + if (m_ImageData) delete m_ImageData; +} + +STDMETHODIMP imTrackingGrabberCB::QueryInterface(REFIID riid, void ** ppv) +{ + if( riid == IID_ISampleGrabberCB || riid == IID_IUnknown ) { + *ppv = (void *) static_cast (this); + return NOERROR; + } + return E_NOINTERFACE; +} + +void imTrackingGrabberCB::SetImageSize(int width, int height) +{ + EnterCriticalSection(&m_sect); + + // This can be done because the capture system always returns + // images that are a multiple of 4. + int new_size = width * height * 3; + + if (!m_ImageData) + { + m_ImageData = (BYTE*)calloc(new_size, 1); + m_Width = width; + m_Height = height; + } + + if (m_Width*m_Height < new_size) + m_ImageData = (BYTE*)realloc(m_ImageData, new_size); + + m_Width = width; + m_Height = height; + + LeaveCriticalSection(&m_sect); +} + +STDMETHODIMP imTrackingGrabberCB::SampleCB(double, IMediaSample *pSample) +{ + if (!m_ImageData) return S_OK; + + EnterCriticalSection(&m_sect); + + int size = pSample->GetSize(); + if (size > m_Width*m_Height*3) + { + LeaveCriticalSection(&m_sect); + return S_OK; + } + + BYTE *pData; + pSample->GetPointer(&pData); + CopyMemory(m_ImageData, pData, size); + m_newImageFlag = 1; + + LeaveCriticalSection(&m_sect); + + SetEvent(m_imageReady); + + return S_OK; +} + +int imTrackingGrabberCB::GetImage(unsigned char* data, int color_mode, int timeout) +{ + if (timeout != 0) + { + DWORD ret = WaitForSingleObject(m_imageReady, timeout); + if (ret != WAIT_OBJECT_0) + return 0; + } + + if (!TryEnterCriticalSection(&m_sect)) + return 0; + + if (m_newImageFlag == 1) + { + int count = m_Width*m_Height; + unsigned char* src_data = m_ImageData; + + if (imColorModeSpace(color_mode) == IM_RGB) + { + if (imColorModeIsPacked(color_mode)) + { + unsigned char* dst_data = data; + for (int i = 0; i < count; i++) + { + *(dst_data+2) = *src_data++; + *(dst_data+1) = *src_data++; + *dst_data = *src_data++; + dst_data += 3; + } + } + else + { + unsigned char* red = data; + unsigned char* green = data + count; + unsigned char* blue = data + 2*count; + for (int i = 0; i < count; i++) + { + *blue++ = *src_data++; + *green++ = *src_data++; + *red++ = *src_data++; + } + } + } + else + { + unsigned char* map = data; + for (int i = 0; i < count; i++) + { + *map++ = *src_data; + src_data += 3; + } + } + + m_newImageFlag = 0; + + LeaveCriticalSection(&m_sect); + return 1; + } + + LeaveCriticalSection(&m_sect); + return 0; +} + + +/************************************************************************** + Direct Show Only +***************************************************************************/ + + +struct vcDevice +{ + IBaseFilter *filter; + char vendorinfo[128]; + char desc[128]; + char ex_desc[256]; + char path[512]; +}; +static vcDevice vc_DeviceList[VC_MAXVIDDEVICES]; +static int vc_DeviceCount = 0; + +static void vc_AddDevice(IBaseFilter *filter, char* desc, char* ex_desc, char* path, char* vendorinfo) +{ + int i = vc_DeviceCount; + vcDevice* device = &vc_DeviceList[i]; + + memset(device, 0, sizeof(vcDevice)); + + device->filter = filter; + + if (!desc) desc = "device"; + sprintf(device->desc, "%d - %s", i, desc); + + if (ex_desc) strcpy(device->ex_desc, ex_desc); + if (path) strcpy(device->path, path); + if (vendorinfo) strcpy(device->vendorinfo, vendorinfo); + + vc_DeviceCount++; +} + + +#ifdef VC_PRINT_ERROR_MESSAGES +//#include + +static int vc_ShowError(HRESULT hr) +{ + if (FAILED(hr)) + { + TCHAR szErr[MAX_ERROR_TEXT_LEN]; + DWORD res = AMGetErrorText(hr, szErr, MAX_ERROR_TEXT_LEN); // Must link with quartz.lib + if (res == 0) wsprintf(szErr, "Unknown Error: 0x%2x", hr); + MessageBox(0, szErr, "imCapture Error!", MB_OK | MB_ICONERROR); +// MessageBox(NULL, DXGetErrorDescription9(hr), DXGetErrorString9(hr), MB_OK | MB_ICONERROR); + return 1; + } + + return 0; +} + +#define VC_HARDFAILED(_x) vc_ShowError(_x) +#else +#define VC_HARDFAILED FAILED +#endif + +static char* vc_Wide2Char(WCHAR* wstr) +{ + if (wstr) + { + int n = wcslen(wstr)+1; + char* str = (char*)malloc(n); + WideCharToMultiByte(CP_ACP, 0, wstr, -1, str, n, NULL, NULL); + return str; + } + + return NULL; +} + +#ifdef VC_INCLUDE_VFW_DEVICES +#define VC_CATEGORY_FLAG 0 +#else +#define VC_CATEGORY_FLAG CDEF_DEVMON_FILTER|CDEF_DEVMON_PNP_DEVICE +#endif + +static char* vc_GetDeviceProp(IPropertyBag *pPropBag, const WCHAR* PropName) +{ + VARIANT varProp; + VariantInit(&varProp); + HRESULT hr = pPropBag->Read(PropName, &varProp, 0); + if (SUCCEEDED(hr)) + { + char* str = vc_Wide2Char(varProp.bstrVal); + VariantClear(&varProp); + return str; + } + return NULL; +} + +static void vc_EnumerateDevices(void) +{ + // Selecting a Capture Device + ICreateDevEnum *pDevEnum = NULL; + IEnumMoniker *pEnum = NULL; + + CoInitialize(NULL); + + // Create the System Device Enumerator. + HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, + CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, + reinterpret_cast(&pDevEnum)); + if (FAILED(hr)) return; + + // Create an enumerator for the video capture category. + hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, VC_CATEGORY_FLAG); + if (FAILED(hr) || !pEnum) + { + pDevEnum->Release(); + return; + } + + IMoniker *pMoniker = NULL; + while (pEnum->Next(1, &pMoniker, NULL) == S_OK) + { + IBaseFilter *capture_filter = NULL; + hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&capture_filter); + if (FAILED(hr)) + { + pMoniker->Release(); + continue; // Skip this one, maybe the next one will work. + } + + IPropertyBag *pPropBag; + hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)(&pPropBag)); + if (FAILED(hr)) + { + capture_filter->Release(); + pMoniker->Release(); + continue; // Skip this one, maybe the next one will work. + } + + char* desc = vc_GetDeviceProp(pPropBag, L"FriendlyName"); + char* ex_desc = vc_GetDeviceProp(pPropBag, L"Description"); + char* path = vc_GetDeviceProp(pPropBag, L"DevicePath"); + + char* vendorinfo = NULL; + LPWSTR VendorInfo; + if (capture_filter->QueryVendorInfo(&VendorInfo) == S_OK) + { + vendorinfo = vc_Wide2Char(VendorInfo); + CoTaskMemFree(VendorInfo); + } + + vc_AddDevice(capture_filter, desc, ex_desc, path, vendorinfo); + + if (desc) free(desc); + if (ex_desc) free(ex_desc); + if (path) free(path); + if (vendorinfo) free(vendorinfo); + + pPropBag->Release(); + pMoniker->Release(); + } + + pEnum->Release(); + pDevEnum->Release(); +} + +static IPin* vc_GetPin(IBaseFilter* pFilter, PIN_DIRECTION dir) +{ + IEnumPins* pEnumPins = NULL; + IPin* pPin = NULL; + + pFilter->EnumPins(&pEnumPins); + if(!pEnumPins) + return NULL; + + for(;;) + { + ULONG cFetched = 0; + PIN_DIRECTION pinDir = PIN_DIRECTION(-1); + pPin = 0; + + if (FAILED(pEnumPins->Next(1, &pPin, &cFetched))) + { + pEnumPins->Release(); + return NULL; + } + + if(cFetched == 1 && pPin != 0) + { + pPin->QueryDirection(&pinDir); + if(pinDir == dir) break; + pPin->Release(); + } + } + + pEnumPins->Release(); + return pPin; +} + +static void vc_NukeDownstream(IGraphBuilder* filter_builder, IBaseFilter *filter) +{ + IPin *pPin=0, *pPinTo=0; + IEnumPins *pEnumPins = NULL; + PIN_INFO pininfo; + + HRESULT hr = filter->EnumPins(&pEnumPins); + if (FAILED(hr)) return; + + pEnumPins->Reset(); + + while(hr == NOERROR) + { + hr = pEnumPins->Next(1, &pPin, NULL); + if(hr == S_OK && pPin) + { + pPin->ConnectedTo(&pPinTo); + if(pPinTo) + { + hr = pPinTo->QueryPinInfo(&pininfo); + if(hr == NOERROR) + { + if(pininfo.dir == PINDIR_INPUT) + { + vc_NukeDownstream(filter_builder, pininfo.pFilter); + filter_builder->Disconnect(pPinTo); + filter_builder->Disconnect(pPin); + filter_builder->RemoveFilter(pininfo.pFilter); + } + + pininfo.pFilter->Release(); + } + + pPinTo->Release(); + } + + pPin->Release(); + } + } + + pEnumPins->Release(); +} + +static int vc_DisconnectFilters(IGraphBuilder* filter_builder, IBaseFilter* source, IBaseFilter* destiny) +{ + IPin *pOut = vc_GetPin(source, PINDIR_OUTPUT); + IPin *pIn = vc_GetPin(destiny, PINDIR_INPUT); + HRESULT hr = filter_builder->Disconnect(pOut); + hr = filter_builder->Disconnect(pIn); + pOut->Release(); + pIn->Release(); + if (VC_HARDFAILED(hr)) return 0; + return 1; +} + +static int vc_DisconnectFilterPin(IGraphBuilder* filter_builder, IBaseFilter* filter, PIN_DIRECTION dir) +{ + IPin *pIn = vc_GetPin(filter, dir); + IPin *pOut; + pIn->ConnectedTo(&pOut); + + HRESULT hr = filter_builder->Disconnect(pIn); + pIn->Release(); + if (VC_HARDFAILED(hr)) + { + if (pOut) pOut->Release(); + return 0; + } + + if (pOut) + { + hr = filter_builder->Disconnect(pOut); + pOut->Release(); + + if (VC_HARDFAILED(hr)) + return 0; + } + + return 1; +} + +static int vc_ConnectFilters(IGraphBuilder* filter_builder, IBaseFilter* source, IBaseFilter* destiny, int direct) +{ + HRESULT hr; + IPin *pOut = vc_GetPin(source, PINDIR_OUTPUT); + IPin *pIn = vc_GetPin(destiny, PINDIR_INPUT); + if (direct) + hr = filter_builder->ConnectDirect(pOut, pIn, NULL); + else + hr = filter_builder->Connect(pOut, pIn); + pOut->Release(); + pIn->Release(); + if (VC_HARDFAILED(hr)) return 0; + return 1; +} + +static DWORD vc_AddGraphToRot(IUnknown *pUnkGraph) +{ + IMoniker * pMoniker; + IRunningObjectTable *pROT; + WCHAR wsz[128]; + HRESULT hr; + + if (FAILED(GetRunningObjectTable(0, &pROT))) + return 0; + + wsprintfW(wsz, L"FilterGraph %08x pid %08x\0", (DWORD_PTR)pUnkGraph, GetCurrentProcessId()); + + hr = CreateItemMoniker(L"!", wsz, &pMoniker); + if (SUCCEEDED(hr)) + { + DWORD dwRegister; + hr = pROT->Register(ROTFLAGS_REGISTRATIONKEEPSALIVE, pUnkGraph, pMoniker, &dwRegister); + pROT->Release(); + + pMoniker->Release(); + + if (SUCCEEDED(hr)) + return dwRegister; + } + + pROT->Release(); + return 0; +} + +static void vc_RemoveGraphFromRot(DWORD pdwRegister) +{ + IRunningObjectTable *pROT; + + if (SUCCEEDED(GetRunningObjectTable(0, &pROT))) + { + pROT->Revoke(pdwRegister); + pROT->Release(); + } +} + +/************************************************************************** + imVideoCapture +***************************************************************************/ + +typedef int (*vcDialogFunc)(imVideoCapture* vc, HWND parent); + +struct _imVideoCapture +{ + int registered_graph, + live, + device; /* current connected device. -1 if not connected. */ + + char* dialog_desc[6]; + vcDialogFunc dialog_func[6]; + int dialog_count; /* number of available configuration dialogs for the current connection. */ + + IGraphBuilder* filter_builder; /* The Filter Graph Manager */ + ICaptureGraphBuilder2* capture_graph_builder; /* Helps the Filter Graph Manager */ + IBaseFilter* capture_filter; /* the capture device (can vary), it's a source filter. */ + IBaseFilter* grabber_filter; /* returns the capture data, it's a transform filter */ + IBaseFilter* null_filter; /* does nothing, act as a terminator, it's a rendering filter */ + ISampleGrabber* sample_grabber; /* Used to access the ISampleGrabber interface, since grabber_filter is a generic IBaseFilter interface based on ISampleGrabber. */ + IMediaControl* media_control; /* Used to Run and Stop the graph flow. */ + IBaseFilter* overlay_renderer; /* Used when there is a video port without a preview */ + IBaseFilter *overlay_mixer; + + IAMVideoProcAmp* video_prop; /* Used to set/get video properties */ + IAMCameraControl* camera_prop; /* Used to set/get camera properties */ + IAMVideoControl* videoctrl_prop; /* Used to set/get video properties */ + + imTrackingGrabberCB* sample_callback; /* Used to intercept the samples. */ + + int format_count; /* number of supported formats */ + int format_current; /* current format */ + int format_map[50]; /* table to map returned formats to direct X formats */ +}; + +int imVideoCaptureDeviceCount(void) +{ + return vc_DeviceCount; +} + +int imVideoCaptureReloadDevices(void) +{ + for (int i = 0; i < vc_DeviceCount; i++) + { + vc_DeviceList[i].filter->Release(); + } + + vc_DeviceCount = 0; + vc_EnumerateDevices(); + return vc_DeviceCount; +} + +static int vc_CheckDeviceList(int device) +{ + // List available Devices once + if (vc_DeviceCount == 0) + { + vc_EnumerateDevices(); + + if (vc_DeviceCount == 0) + return 0; + } + + if (device < 0 || device >= vc_DeviceCount) + return 0; + + return 1; +} + +const char* imVideoCaptureDeviceDesc(int device) +{ + if (!vc_CheckDeviceList(device)) + return NULL; + + return vc_DeviceList[device].desc; +} + +const char* imVideoCaptureDeviceExDesc(int device) +{ + if (!vc_CheckDeviceList(device)) + return NULL; + + return vc_DeviceList[device].ex_desc; +} + +const char* imVideoCaptureDevicePath(int device) +{ + if (!vc_CheckDeviceList(device)) + return NULL; + + return vc_DeviceList[device].path; +} + +const char* imVideoCaptureDeviceVendorInfo(int device) +{ + if (!vc_CheckDeviceList(device)) + return NULL; + + return vc_DeviceList[device].vendorinfo; +} + +#define vc_SafeRelease(_p) { if( (_p) != 0 ) { (_p)->Release(); (_p)= NULL; } } + +static void vc_CheckVideoPort(imVideoCapture* vc) +{ +/* + If the video capture card supports the video port pin without a video preview pin this will not work. + The DirectShow architecture requires that the video port pin be connected to the Overlay Mixer Filter. + If this pin is not connected, data cannot be captured in DirectShow. +*/ + HRESULT hr; + + IPin *pPreviewPin = NULL; + hr = vc->capture_graph_builder->FindPin( + vc->capture_filter, // Pointer to the capture filter. + PINDIR_OUTPUT, // Look for an output pin. + &PIN_CATEGORY_PREVIEW, // Look for a preview pin. + NULL, // Any media type. + FALSE, // Pin can be connected. + 0, // Retrieve the first matching pin. + &pPreviewPin // Receives a pointer to the pin. + ); + if (hr == S_OK) + { + pPreviewPin->Release(); + return; + } + + IPin *pVideoPortPin = NULL; + hr = vc->capture_graph_builder->FindPin( + vc->capture_filter, // Pointer to the capture filter. + PINDIR_OUTPUT, // Look for an output pin. + &PIN_CATEGORY_VIDEOPORT, // Look for a video port pin. + NULL, // Any media type. + FALSE, // Pin can be connected. + 0, // Retrieve the first matching pin. + &pVideoPortPin // Receives a pointer to the pin. + ); + if (FAILED(hr)) return; + + // Create the overlay mixer. + CoCreateInstance(CLSID_OverlayMixer, NULL, CLSCTX_INPROC, + IID_IBaseFilter, (void **)&vc->overlay_mixer); + + // Add it to the filter graph. + vc->filter_builder->AddFilter(vc->overlay_mixer, L"Overlay Mixer"); + + IPin *pOverlayPin = NULL; + vc->capture_graph_builder->FindPin(vc->overlay_mixer, PINDIR_INPUT, NULL, NULL, TRUE, 0, &pOverlayPin); + + vc->filter_builder->Connect(pVideoPortPin, pOverlayPin); + if (FAILED(hr)) return; + + vc_SafeRelease(pVideoPortPin); + vc_SafeRelease(pOverlayPin); + + CoCreateInstance(CLSID_VideoRenderer, NULL, CLSCTX_INPROC_SERVER, + IID_IBaseFilter, reinterpret_cast(&vc->overlay_renderer)); + vc->filter_builder->AddFilter(vc->overlay_renderer, L"Overlay Renderer"); + + vc_ConnectFilters(vc->filter_builder, vc->overlay_mixer, vc->overlay_renderer, 1); + + IVideoWindow* pVideoWindow = NULL; + vc->overlay_renderer->QueryInterface(IID_IVideoWindow,(void**)&pVideoWindow); + pVideoWindow->put_AutoShow(OAFALSE); + pVideoWindow->Release(); +} + +static void vc_ReleaseMixer(imVideoCapture* vc) +{ + IPin *pOverlayPin = vc_GetPin(vc->overlay_mixer, PINDIR_INPUT); + IPin *pVideoPortPin = NULL; + pOverlayPin->ConnectedTo(&pVideoPortPin); + vc->filter_builder->Disconnect(pOverlayPin); + vc->filter_builder->Disconnect(pVideoPortPin); + vc_SafeRelease(pVideoPortPin); + vc_SafeRelease(pOverlayPin); + + vc_DisconnectFilters(vc->filter_builder, vc->overlay_mixer, vc->overlay_renderer); + + vc->filter_builder->RemoveFilter(vc->overlay_renderer); + vc->filter_builder->RemoveFilter(vc->overlay_mixer); + vc_SafeRelease(vc->overlay_renderer); + vc_SafeRelease(vc->overlay_mixer); +} + +static int vc_InitCaptureGraphBuilder(imVideoCapture* vc) +{ + HRESULT hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, + IID_ICaptureGraphBuilder2, reinterpret_cast(&vc->capture_graph_builder)); + if (FAILED(hr)) return 0; + + hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, + IID_IGraphBuilder, reinterpret_cast(&vc->filter_builder)); + if (FAILED(hr)) return 0; + + hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, + IID_IBaseFilter, reinterpret_cast(&vc->grabber_filter)); + if (FAILED(hr)) return 0; + + hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER, + IID_IBaseFilter, reinterpret_cast(&vc->null_filter)); + if (FAILED(hr)) return 0; + + // Initialize the Capture Graph Builder. + vc->capture_graph_builder->SetFiltergraph(vc->filter_builder); + + hr = vc->filter_builder->QueryInterface(IID_IMediaControl,(void**)&vc->media_control); + hr = vc->grabber_filter->QueryInterface(IID_ISampleGrabber, (void **)&vc->sample_grabber); + + AM_MEDIA_TYPE mt; + ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE)); + mt.majortype = MEDIATYPE_Video; + mt.subtype = MEDIASUBTYPE_RGB24; // Force 24 bpp + vc->sample_grabber->SetMediaType(&mt); + vc->sample_grabber->SetOneShot(FALSE); + vc->sample_grabber->SetBufferSamples(FALSE); + + vc->sample_callback = new imTrackingGrabberCB(); + + hr = vc->filter_builder->AddFilter(vc->grabber_filter, L"imSampleGrabber"); + hr = vc->filter_builder->AddFilter(vc->null_filter, L"imNullRenderer"); + + // Remove clock to speed up things + IMediaFilter* pMediaFilter = NULL; + vc->filter_builder->QueryInterface(IID_IMediaFilter, (void**)&pMediaFilter); + pMediaFilter->SetSyncSource(NULL); + pMediaFilter->Release(); + +#ifdef VC_REGISTER_FILTERGRAPH + vc->registered_graph = vc_AddGraphToRot(vc->filter_builder); +#endif + + return 1; +} + +imVideoCapture* imVideoCaptureCreate(void) +{ + imVideoCapture* vc = (imVideoCapture*)malloc(sizeof(imVideoCapture)); + memset(vc, 0, sizeof(imVideoCapture)); + + // List available Devices once + if (vc_DeviceCount == 0) + { + vc_EnumerateDevices(); + + if (vc_DeviceCount == 0) + { + free(vc); + return NULL; + } + } + + if (!vc_InitCaptureGraphBuilder(vc)) + { + vc_SafeRelease(vc->grabber_filter); + vc_SafeRelease(vc->filter_builder); + vc_SafeRelease(vc->capture_graph_builder); + vc_SafeRelease(vc->null_filter); + free(vc); + return NULL; + } + + vc->device = -1; + + return vc; +} + +static void vc_CaptureRemove(imVideoCapture* vc) +{ + vc->filter_builder->RemoveFilter(vc->capture_filter); + + vc->capture_filter = NULL; /* do not release here */ + vc_SafeRelease(vc->video_prop); + vc_SafeRelease(vc->camera_prop); + vc_SafeRelease(vc->videoctrl_prop); + + vc->dialog_count = 0; + vc->live = 0; + vc->device = -1; +} + +void imVideoCaptureDestroy(imVideoCapture* vc) +{ + assert(vc); + +#ifdef VC_REGISTER_FILTERGRAPH + if (vc->registered_graph) vc_RemoveGraphFromRot(vc->registered_graph); +#endif + + imVideoCaptureDisconnect(vc); + + delete vc->sample_callback; + + vc_SafeRelease(vc->overlay_mixer); + vc_SafeRelease(vc->overlay_renderer); + vc_SafeRelease(vc->media_control); + vc_SafeRelease(vc->sample_grabber); + + vc->null_filter->Release(); + vc->grabber_filter->Release(); + vc->filter_builder->Release(); + vc->capture_graph_builder->Release(); + + free(vc); +} + +static void vc_StopLive(imVideoCapture* vc) +{ + if (vc->live) // If it is live, stop it + { + vc->media_control->Stop(); + Sleep(VC_CAMERADELAY); + } +} + +static int vc_StartLive(imVideoCapture* vc) +{ + if (vc->live) // If it should be started, start it + { + HRESULT hr = vc->media_control->Run(); + if (VC_HARDFAILED(hr)) + { + vc->live = 0; + return 0; + } + + Sleep(VC_CAMERADELAY); + } + + return 1; +} + +int imVideoCaptureOneFrame(imVideoCapture* vc, unsigned char* data, int color_mode) +{ + assert(vc); + assert(vc->device != -1); + + vc_StopLive(vc); + vc->live = 0; + + vc->sample_grabber->SetOneShot(TRUE); + + vc->live = 1; + if (!vc_StartLive(vc)) + { + vc->sample_grabber->SetOneShot(FALSE); + return 0; + } + + int ret = imVideoCaptureFrame(vc, data, color_mode, -1); + + vc_StopLive(vc); + vc->live = 0; + + vc->sample_grabber->SetOneShot(FALSE); + + return ret; +} + +int imVideoCaptureFrame(imVideoCapture* vc, unsigned char* data, int color_mode, int timeout) +{ + assert(vc); + assert(vc->device != -1); + assert(vc->live); + return vc->sample_callback->GetImage(data, color_mode, timeout); +} + +static int vc_CaptureDisconnect(imVideoCapture* vc) +{ + vc->sample_grabber->SetCallback(NULL, 0); + + if (vc->overlay_mixer) + vc_ReleaseMixer(vc); + + vc_DisconnectFilters(vc->filter_builder, vc->grabber_filter, vc->null_filter); + + // Disconnect the grabber to preserve it + if (!vc_DisconnectFilterPin(vc->filter_builder, vc->grabber_filter, PINDIR_INPUT)) + return 0; + + // Remove everything downstream the capture filter, except the null renderer + vc_NukeDownstream(vc->filter_builder, vc->capture_filter); + + return 1; +} + +void imVideoCaptureDisconnect(imVideoCapture* vc) +{ + assert(vc); + + if (vc->device == -1) + return; + + vc_StopLive(vc); + vc->live = 0; + + vc_CaptureDisconnect(vc); + vc_CaptureRemove(vc); +} + +static void vc_UpdateSize(imVideoCapture* vc) +{ + int width, height; + imVideoCaptureGetImageSize(vc, &width, &height); + vc->sample_callback->SetImageSize(width, height); +} + +static void vc_UpdateDialogs(imVideoCapture* vc); +static void vc_UpdateFormatList(imVideoCapture* vc); + +static int vc_CaptureConnect(imVideoCapture* vc) +{ + vc_CheckVideoPort(vc); + + if (!vc_ConnectFilters(vc->filter_builder, vc->capture_filter, vc->grabber_filter, 0)) + { + vc_CaptureRemove(vc); + return 0; + } + + vc_ConnectFilters(vc->filter_builder, vc->grabber_filter, vc->null_filter, 1); + + vc_UpdateDialogs(vc); + vc_UpdateFormatList(vc); + vc_UpdateSize(vc); + vc->sample_grabber->SetCallback(vc->sample_callback, 0); // associate the sample_grabber with the sample_callback + + return 1; +} + +int imVideoCaptureConnect(imVideoCapture* vc, int device) +{ + assert(vc); + + if (device == -1) + return vc->device; + + if (device == vc->device) + return 1; + + if (device < -1 || device > vc_DeviceCount) + return 0; + + if (vc->device != -1) + imVideoCaptureDisconnect(vc); + + vc->capture_filter = vc_DeviceList[device].filter; + if (!vc->capture_filter) + return 0; + + vc->filter_builder->AddFilter(vc->capture_filter, L"imCaptureSource"); + vc->device = device; + + if (!vc_CaptureConnect(vc)) + return 0; + + return 1; +} + +int imVideoCaptureLive(imVideoCapture* vc, int live) +{ + assert(vc); + + if (live == -1) + return vc->live; + + if (vc->device == -1) + return 0; + + if (live == vc->live) + return 1; + + if (live) + { + vc->live = 1; + if (!vc_StartLive(vc)) + return 0; + } + else + { + vc_StopLive(vc); + vc->live = 0; + } + + return 1; +} + + +/************************************************************************** + Format and Size +***************************************************************************/ + + +void imVideoCaptureGetImageSize(imVideoCapture* vc, int *width, int *height) +{ + assert(vc); + assert(vc->device != -1); + + AM_MEDIA_TYPE mt; + ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE)); + HRESULT hr = vc->sample_grabber->GetConnectedMediaType(&mt); + + if ( SUCCEEDED(hr) && + (mt.majortype == MEDIATYPE_Video) && + (mt.formattype == FORMAT_VideoInfo) && + (mt.cbFormat >= sizeof (VIDEOINFOHEADER)) && + (mt.pbFormat != NULL)) + { + VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)mt.pbFormat; + *width = pVih->bmiHeader.biWidth; + *height = abs(pVih->bmiHeader.biHeight); + CoTaskMemFree((PVOID)mt.pbFormat); + } + else + { + *width = 0; + *height = 0; + } +} + +static IIPDVDec* vc_GetDVDecoder(imVideoCapture* vc) +{ + IIPDVDec *pDV = NULL; + HRESULT hr = vc->capture_graph_builder->FindInterface(NULL, + &MEDIATYPE_Video, vc->capture_filter, IID_IIPDVDec, (void **)&pDV); + if(FAILED(hr)) + return NULL; + + return pDV; +} + +static IAMStreamConfig* vc_GetStreamConfig(imVideoCapture* vc) +{ + IAMStreamConfig *pSC = NULL; + if (FAILED(vc->capture_graph_builder->FindInterface(&PIN_CATEGORY_CAPTURE, + &MEDIATYPE_Video, vc->capture_filter, IID_IAMStreamConfig, (void **)&pSC))) + return NULL; + + return pSC; +} + +static void vc_DeleteMediaType(AM_MEDIA_TYPE *pmt) +{ + CoTaskMemFree((PVOID)pmt->pbFormat); + CoTaskMemFree(pmt); +} + +static int vc_SetStreamSize(imVideoCapture* vc, int width, int height) +{ + IAMStreamConfig *pSC = vc_GetStreamConfig(vc); + if (!pSC) return 0; + + AM_MEDIA_TYPE *pmt; + HRESULT hr = pSC->GetFormat(&pmt); + if (FAILED(hr)) return 0; + + VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)pmt->pbFormat; + BITMAPINFOHEADER* bih = &vih->bmiHeader; + + /* dibs are DWORD aligned */ + int data_size = height * ((width * bih->biBitCount + 31) / 32) * 4; /* 4 bytes boundary */ + + bih->biSize = sizeof(BITMAPINFOHEADER); + bih->biHeight = height; + bih->biWidth = width; + bih->biSizeImage = data_size; + + int fps = 30; // desired frame rate + vih->dwBitRate = fps * data_size; + vih->AvgTimePerFrame = 10000000 / fps; + + pmt->cbFormat = sizeof(VIDEOINFOHEADER); + pmt->lSampleSize = data_size; + + hr = pSC->SetFormat(pmt); + pSC->Release(); + + vc_DeleteMediaType(pmt); + + return SUCCEEDED(hr); +} + +static int vc_SetImageSize(imVideoCapture* vc, int width, int height) +{ + IIPDVDec* pDV = vc_GetDVDecoder(vc); + if (pDV) + { + int size = 0; + + switch(width) + { + case 720: + size = DVRESOLUTION_FULL; + break; + case 360: + size = DVRESOLUTION_HALF; + break; + case 180: + size = DVRESOLUTION_QUARTER; + break; + case 88: + size = DVRESOLUTION_DC; + break; + } + + if (!size) + return 0; + + int ret = SUCCEEDED(pDV->put_IPDisplay(size)); + if (ret) + vc->sample_callback->SetImageSize(width, height); + + return ret; + } + + int ret = vc_SetStreamSize(vc, width, height); + if (ret) + vc->sample_callback->SetImageSize(width, height); + + return ret; +} + +int imVideoCaptureSetImageSize(imVideoCapture* vc, int width, int height) +{ + assert(vc); + assert(vc->device != -1); + + vc_StopLive(vc); + + // must be disconnected to change size or format + vc_CaptureDisconnect(vc); + + int ret = vc_SetImageSize(vc, width, height); + + if (!vc_CaptureConnect(vc)) + ret = 0; + + vc_StartLive(vc); + + return ret; +} + +static void vc_UpdateFormatList(imVideoCapture* vc) +{ + vc->format_count = 0; + vc->format_current = -1; + + IAMStreamConfig *pSC = vc_GetStreamConfig(vc); + if (!pSC) return; + + int iCount = 0, iSize = 0; + if (FAILED(pSC->GetNumberOfCapabilities(&iCount, &iSize))) + { + pSC->Release(); + return; + } + + AM_MEDIA_TYPE *curr_pmt; + HRESULT hr = pSC->GetFormat(&curr_pmt); + if (FAILED(hr)) + { + pSC->Release(); + return; + } + + for (int iFormat = 0; iFormat < iCount; iFormat++) + { + VIDEO_STREAM_CONFIG_CAPS scc; + AM_MEDIA_TYPE *pmt; + if (SUCCEEDED(pSC->GetStreamCaps(iFormat, &pmt, (BYTE*)&scc))) + { + if (scc.guid == FORMAT_VideoInfo) + { + VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)curr_pmt->pbFormat; + BITMAPINFOHEADER* bih = &vih->bmiHeader; + int width = bih->biWidth; + int height = abs(bih->biHeight); + + if (curr_pmt->subtype == pmt->subtype && + width == scc.InputSize.cx && + height == scc.InputSize.cy) + { + vc->format_current = vc->format_count; + } + + vc->format_map[vc->format_count] = iFormat; + vc->format_count++; + } + + vc_DeleteMediaType(pmt); + } + } + + vc_DeleteMediaType(curr_pmt); + pSC->Release(); +} + +int imVideoCaptureFormatCount(imVideoCapture* vc) +{ + assert(vc); + assert(vc->device != -1); + + return vc->format_count; +} + +static void vc_GetFormatName(GUID subtype, char* desc) +{ +#define VC_NUM_FORMATS 7 + typedef struct _guid2name { + char* name; + const GUID* subtype; + } guid2name; + static guid2name map_table[VC_NUM_FORMATS] = { + {"RGB1",&MEDIASUBTYPE_RGB1}, + {"RGB4",&MEDIASUBTYPE_RGB4}, + {"RGB8",&MEDIASUBTYPE_RGB8}, + {"RGB565",&MEDIASUBTYPE_RGB565}, + {"RGB555",&MEDIASUBTYPE_RGB555}, + {"RGB24",&MEDIASUBTYPE_RGB24}, + {"RGB32",&MEDIASUBTYPE_RGB32} + }; + + for (int i = 0; i < VC_NUM_FORMATS; i++) + { + if (*(map_table[i].subtype) == subtype) + { + strcpy(desc, map_table[i].name); + return; + } + } + + desc[0] = (char)(subtype.Data1); + desc[1] = (char)(subtype.Data1 >> 8); + desc[2] = (char)(subtype.Data1 >> 16); + desc[3] = (char)(subtype.Data1 >> 32); + desc[4] = 0; +} + +int imVideoCaptureGetFormat(imVideoCapture* vc, int format, int *width, int *height, char* desc) +{ + assert(vc); + assert(vc->device != -1); + assert(vc->format_count); + + if (format >= vc->format_count) + return 0; + + IAMStreamConfig *pSC = vc_GetStreamConfig(vc); + if (!pSC) return 0; + + VIDEO_STREAM_CONFIG_CAPS scc; + AM_MEDIA_TYPE *pmt; + if (SUCCEEDED(pSC->GetStreamCaps(vc->format_map[format], &pmt, (BYTE*)&scc))) + { + *width = scc.InputSize.cx; + *height = scc.InputSize.cy; + vc_GetFormatName(pmt->subtype, desc); + + pSC->Release(); + vc_DeleteMediaType(pmt); + return 1; + } + + pSC->Release(); + return 0; +} + +static int vc_SetStreamFormat(imVideoCapture* vc, int format) +{ + IAMStreamConfig *pSC = vc_GetStreamConfig(vc); + if (!pSC) return 0; + + VIDEO_STREAM_CONFIG_CAPS scc; + AM_MEDIA_TYPE *pmt; + if (FAILED(pSC->GetStreamCaps(vc->format_map[format], &pmt, (BYTE*)&scc))) + { + pSC->Release(); + return 0; + } + + pSC->SetFormat(pmt); + pSC->Release(); + + vc->sample_callback->SetImageSize(scc.InputSize.cx, scc.InputSize.cy); + + vc_DeleteMediaType(pmt); + + return 1; +} + +int imVideoCaptureSetFormat(imVideoCapture* vc, int format) +{ + assert(vc); + assert(vc->device != -1); + + if (format == -1) + return vc->format_current; + + if (format >= vc->format_count) + return 0; + + vc_StopLive(vc); + + // must be disconnected to change size or format + vc_CaptureDisconnect(vc); + + int ok = vc_SetStreamFormat(vc, format); + + if (!vc_CaptureConnect(vc)) + ok = 0; + + if (ok) + vc->format_current = format; + + vc_StartLive(vc); + + return ok; +} + + +/************************************************************************** + Dialogs +***************************************************************************/ + + +static ISpecifyPropertyPages* vc_GetPropertyPages(IUnknown* obj) +{ + ISpecifyPropertyPages *pSpec = NULL; + + HRESULT hr = obj->QueryInterface(IID_ISpecifyPropertyPages, (void **)&pSpec); + if (FAILED(hr)) return NULL; + + CAUUID cauuid; + hr = pSpec->GetPages(&cauuid); + CoTaskMemFree(cauuid.pElems); + + if (FAILED(hr)) + { + pSpec->Release(); + return NULL; + } + + return pSpec; +} + +static int vc_ShowPropertyPages(HWND parent, IUnknown* obj, WCHAR* title) +{ + ISpecifyPropertyPages *pSpec = vc_GetPropertyPages(obj); + + CAUUID cauuid; + pSpec->GetPages(&cauuid); + + HRESULT hr = OleCreatePropertyFrame(parent, 30, 30, title, 1, + &obj, cauuid.cElems, (GUID *)cauuid.pElems, 0, 0, NULL); + + CoTaskMemFree(cauuid.pElems); + pSpec->Release(); + + if (FAILED(hr)) return 0; + return 1; +} + +static IAMVfwCaptureDialogs* vc_getVfwDialogs(imVideoCapture* vc) +{ + IAMVfwCaptureDialogs* pDlg = NULL; + HRESULT hr = vc->capture_graph_builder->FindInterface(&PIN_CATEGORY_CAPTURE, + &MEDIATYPE_Video, vc->capture_filter, IID_IAMVfwCaptureDialogs, (void **)&pDlg); + + if (FAILED(hr)) + return NULL; + + return pDlg; +} + +static int vc_ShowVfwDialog(imVideoCapture* vc, HWND parent, VfwCaptureDialogs dialog) +{ + assert(vc); + assert(vc->device != -1); + + IAMVfwCaptureDialogs *pDlg = vc_getVfwDialogs(vc); + if(!pDlg) return 0; + + HRESULT hr = pDlg->HasDialog(dialog); + if (FAILED(hr)) + { + pDlg->Release(); + return 0; + } + + int ret = 0; + vc_StopLive(vc); + + // must be disconnected to change size or format + vc_CaptureDisconnect(vc); + + hr = pDlg->ShowDialog(dialog, parent); + if (SUCCEEDED(hr)) + ret = 1; + + if (!vc_CaptureConnect(vc)) + ret = 0; + + vc_StartLive(vc); + + pDlg->Release(); + return ret; +} + +static int vc_ShowVfwFormatDialog(imVideoCapture* vc, HWND parent) +{ + return vc_ShowVfwDialog(vc, parent, VfwCaptureDialog_Format); +} + +static int vc_ShowVfwSourceDialog(imVideoCapture* vc, HWND parent) +{ + return vc_ShowVfwDialog(vc, parent, VfwCaptureDialog_Source); +} + +static int vc_ShowVfwDisplayDialog(imVideoCapture* vc, HWND parent) +{ + return vc_ShowVfwDialog(vc, parent, VfwCaptureDialog_Display); +} + +static int vc_ShowFormatDialog(imVideoCapture* vc, HWND parent) +{ + assert(vc); + assert(vc->device != -1); + + IAMStreamConfig *pSC = vc_GetStreamConfig(vc); + if (!pSC) return 0; + + vc_StopLive(vc); + + // must be disconnected to change size or format + vc_CaptureDisconnect(vc); + + int ok = vc_ShowPropertyPages(parent, (IUnknown*)pSC, L"Format"); + pSC->Release(); + + if (!vc_CaptureConnect(vc)) + ok = 0; + + vc_StartLive(vc); + + return ok; +} + +static int vc_ShowSourceDialog(imVideoCapture* vc, HWND parent) +{ + assert(vc); + assert(vc->device != -1); + + return vc_ShowPropertyPages(parent, (IUnknown*)vc->capture_filter, L"Source"); +} + +static IAMTVTuner* vc_GetTVTuner(imVideoCapture* vc) +{ + IAMTVTuner *pTVT = NULL; + + HRESULT hr = vc->capture_graph_builder->FindInterface(&PIN_CATEGORY_CAPTURE, + &MEDIATYPE_Video, vc->capture_filter, IID_IAMTVTuner, (void **)&pTVT); + if(FAILED(hr)) + return NULL; + + return pTVT; +} + +static int vc_ShowTVTunerDialog(imVideoCapture* vc, HWND parent) +{ + assert(vc); + assert(vc->device != -1); + + IAMTVTuner* pTVT = vc_GetTVTuner(vc); + if (!pTVT) + return 0; + + int ret = vc_ShowPropertyPages(parent, (IUnknown*)pTVT, L"TV Turner"); + pTVT->Release(); + return ret; +} + +static IAMCrossbar* vc_GetCrossBar(imVideoCapture* vc) +{ + IAMCrossbar *pX = NULL; + HRESULT hr = vc->capture_graph_builder->FindInterface(&PIN_CATEGORY_CAPTURE, + &MEDIATYPE_Video, vc->capture_filter, IID_IAMCrossbar, (void **)&pX); + if(FAILED(hr)) + return NULL; + + return pX; +} + +static int vc_ShowCrossbarDialog(imVideoCapture* vc, HWND parent) +{ + assert(vc); + assert(vc->device != -1); + + IAMCrossbar* pX = vc_GetCrossBar(vc); + if (!pX) + return 0; + + int ret = vc_ShowPropertyPages(parent, (IUnknown*)pX, L"Crossbar"); + pX->Release(); + return ret; +} + +static IAMCrossbar* vc_GetSecondCrossBar(imVideoCapture* vc, IAMCrossbar *pX) +{ + IAMCrossbar *pX2 = NULL; + IBaseFilter *pXF; + HRESULT hr = pX->QueryInterface(IID_IBaseFilter, (void **)&pXF); + if(hr != S_OK) return NULL; + + hr = vc->capture_graph_builder->FindInterface(&LOOK_UPSTREAM_ONLY, + NULL, pXF, IID_IAMCrossbar, (void **)&pX2); + pXF->Release(); + if(FAILED(hr)) return NULL; + + return pX2; +} + +static int vc_ShowSecondCrossbarDialog(imVideoCapture* vc, HWND parent) +{ + assert(vc); + assert(vc->device != -1); + + IAMCrossbar* pX = vc_GetCrossBar(vc); + if (!pX) + return 0; + + IAMCrossbar* pX2 = vc_GetSecondCrossBar(vc, pX); + if (!pX2) + { + pX->Release(); + return 0; + } + + int ret = vc_ShowPropertyPages(parent, (IUnknown*)pX2, L"Second Crossbar"); + pX->Release(); + pX2->Release(); + return ret; +} + +static int vc_ShowDVDecDialog(imVideoCapture* vc, HWND parent) +{ + assert(vc); + assert(vc->device != -1); + + IIPDVDec* pDV = vc_GetDVDecoder(vc); + if (!pDV) + return 0; + + vc_StopLive(vc); + + int ret = vc_ShowPropertyPages(parent, (IUnknown*)pDV, L"DV Decoder"); + pDV->Release(); + + vc_StartLive(vc); + + return ret; +} + +static void vc_UpdateDialogs(imVideoCapture* vc) +{ + vc->dialog_count = 0; + + IAMVfwCaptureDialogs *pDlg = vc_getVfwDialogs(vc); + if(pDlg) + { + if(pDlg->HasDialog(VfwCaptureDialog_Format) == S_OK) + { + vc->dialog_desc[vc->dialog_count] = "Format... (VFW)"; + vc->dialog_func[vc->dialog_count] = vc_ShowVfwFormatDialog; + vc->dialog_count++; + } + + if(pDlg->HasDialog(VfwCaptureDialog_Source) == S_OK) + { + vc->dialog_desc[vc->dialog_count] = "Source... (VFW)"; + vc->dialog_func[vc->dialog_count] = vc_ShowVfwSourceDialog; + vc->dialog_count++; + } + + if(pDlg->HasDialog(VfwCaptureDialog_Display) == S_OK) + { + vc->dialog_desc[vc->dialog_count] = "Display... (VFW)"; + vc->dialog_func[vc->dialog_count] = vc_ShowVfwDisplayDialog; + vc->dialog_count++; + } + + return; + } + + ISpecifyPropertyPages *pSpec; + IAMStreamConfig *pSC = vc_GetStreamConfig(vc); + if (pSC) + { + pSpec = vc_GetPropertyPages((IUnknown*)pSC); + if (pSpec) + { + vc->dialog_desc[vc->dialog_count] = "Format..."; + vc->dialog_func[vc->dialog_count] = vc_ShowFormatDialog; + vc->dialog_count++; + pSpec->Release(); + } + + pSC->Release(); + } + + pSpec = vc_GetPropertyPages((IUnknown*)vc->capture_filter); + if (pSpec) + { + vc->dialog_desc[vc->dialog_count] = "Source..."; + vc->dialog_func[vc->dialog_count] = vc_ShowSourceDialog; + vc->dialog_count++; + pSpec->Release(); + } + + IIPDVDec* pDV = vc_GetDVDecoder(vc); + if (pDV) + { + pSpec = vc_GetPropertyPages((IUnknown*)pDV); + if (pSpec) + { + vc->dialog_desc[vc->dialog_count] = "DV Decoder..."; + vc->dialog_func[vc->dialog_count] = vc_ShowDVDecDialog; + vc->dialog_count++; + pSpec->Release(); + } + + pDV->Release(); + } + + IAMCrossbar* pX = vc_GetCrossBar(vc); + if (pX) + { + pSpec = vc_GetPropertyPages((IUnknown*)pX); + if (pSpec) + { + vc->dialog_desc[vc->dialog_count] = "Crossbar..."; + vc->dialog_func[vc->dialog_count] = vc_ShowCrossbarDialog; + vc->dialog_count++; + pSpec->Release(); + } + + IAMCrossbar* pX2 = vc_GetSecondCrossBar(vc, pX); + if (pX2) + { + pSpec = vc_GetPropertyPages((IUnknown*)pX2); + if (pSpec) + { + vc->dialog_desc[vc->dialog_count] = "Second Crossbar..."; + vc->dialog_func[vc->dialog_count] = vc_ShowSecondCrossbarDialog; + vc->dialog_count++; + pSpec->Release(); + } + + pX2->Release(); + } + + pX->Release(); + } + + IAMTVTuner* pTVT = vc_GetTVTuner(vc); + if (pTVT) + { + pSpec = vc_GetPropertyPages((IUnknown*)pTVT); + if (pSpec) + { + vc->dialog_desc[vc->dialog_count] = "TV Tuner..."; + vc->dialog_func[vc->dialog_count] = vc_ShowTVTunerDialog; + vc->dialog_count++; + pSpec->Release(); + } + + pTVT->Release(); + } +} + +int imVideoCaptureDialogCount(imVideoCapture* vc) +{ + assert(vc); + assert(vc->device != -1); + + return vc->dialog_count; +} + +const char* imVideoCaptureDialogDesc(imVideoCapture* vc, int dialog) +{ + assert(vc); + assert(vc->device != -1); + + if (dialog >= vc->dialog_count) + return NULL; + + return vc->dialog_desc[dialog]; +} + +int imVideoCaptureShowDialog(imVideoCapture* vc, int dialog, void* parent) +{ + assert(vc); + assert(vc->device != -1); + + if (dialog >= vc->dialog_count) + return 0; + + return vc->dialog_func[dialog](vc, (HWND)parent); +} + +int imVideoCaptureSetInOut(imVideoCapture* vc, int input, int output, int cross) +{ + assert(vc); + assert(vc->device != -1); + + IAMCrossbar* pX = vc_GetCrossBar(vc); + if (pX) + { + HRESULT hr = S_FALSE; + + if (cross == 1) + hr = pX->Route(output, input); + else + { + IAMCrossbar* pX2 = vc_GetSecondCrossBar(vc, pX); + if (pX2) + { + hr = pX2->Route(output, input); + pX2->Release(); + } + } + + pX->Release(); + if (hr == S_OK) + return 1; + } + + return 0; +} + +/************************************************************************** + Attributes +***************************************************************************/ + + +static float vc_Value2Percent(long Min, long Max, long Val) +{ + return ((Val - Min)*100.0f)/((float)(Max - Min)); +} + +static long vc_Percent2Value(long Min, long Max, long Step, float Per) +{ + long Val = (long)((Per/100.)*(Max - Min) + Min); + if (Step == 1) + return Val; + + long num_step = (Val - Min + Step-1) / Step; + return num_step*Step + Min; +} + +static IAMVideoProcAmp* vc_InitVideoProcAmp(IBaseFilter* capture_filter, IAMVideoProcAmp* *video_prop) +{ + if (*video_prop) + return *video_prop; + + HRESULT hr = capture_filter->QueryInterface(IID_IAMVideoProcAmp, (void**)video_prop); + if (FAILED(hr)) + return NULL; + + return *video_prop; +} + +static int vc_SetVideoProcAmpProperty(IBaseFilter* capture_filter, IAMVideoProcAmp* *video_prop, long property, float percent) +{ + IAMVideoProcAmp *pProp = vc_InitVideoProcAmp(capture_filter, video_prop); + if (!pProp) return 0; + HRESULT hr; + VideoProcAmpProperty prop = (VideoProcAmpProperty)property; + long Min, Max, Step, Default, Flags; + hr = pProp->GetRange(prop, &Min, &Max, &Step, &Default, &Flags); + hr = pProp->Set(prop, vc_Percent2Value(Min, Max, Step, percent), VideoProcAmp_Flags_Manual); + if (FAILED(hr)) return 0; + return 1; +} + +static int vc_GetVideoProcAmpProperty(IBaseFilter* capture_filter, IAMVideoProcAmp* *video_prop, long property, float *percent) +{ + IAMVideoProcAmp *pProp = vc_InitVideoProcAmp(capture_filter, video_prop); + if (!pProp) return 0; + + HRESULT hr; + VideoProcAmpProperty prop = (VideoProcAmpProperty)property; + long Min, Max, Step, Default, Flags, Val; + hr = pProp->GetRange(prop, &Min, &Max, &Step, &Default, &Flags); + hr = pProp->Get(prop, &Val, &Flags); + + if (FAILED(hr)) return 0; + *percent = vc_Value2Percent(Min, Max, Val); + return 1; +} + +static int vc_ResetVideoProcAmpProperty(IBaseFilter* capture_filter, IAMVideoProcAmp* *video_prop, long property, int fauto) +{ + IAMVideoProcAmp *pProp = vc_InitVideoProcAmp(capture_filter, video_prop); + if (!pProp) return 0; + + HRESULT hr; + VideoProcAmpProperty prop = (VideoProcAmpProperty)property; + long Min, Max, Step, Default, Flags; + hr = pProp->GetRange(prop, &Min, &Max, &Step, &Default, &Flags); + + if (fauto && (Flags & VideoProcAmp_Flags_Auto)) + hr = pProp->Set(prop, Default, VideoProcAmp_Flags_Auto); + else + hr = pProp->Set(prop, Default, VideoProcAmp_Flags_Manual); + + if (FAILED(hr)) return 0; + return 1; +} + +static IAMCameraControl* vc_InitCameraControl(IBaseFilter* capture_filter, IAMCameraControl* *camera_prop) +{ + if (*camera_prop) + return *camera_prop; + + HRESULT hr = capture_filter->QueryInterface(IID_IAMCameraControl, (void**)camera_prop); + if (FAILED(hr)) + return NULL; + + return *camera_prop; +} + +static int vc_SetCameraControlProperty(IBaseFilter* capture_filter, IAMCameraControl* *camera_prop, long property, float percent) +{ + IAMCameraControl *pProp = vc_InitCameraControl(capture_filter, camera_prop); + if (!pProp) return 0; + + HRESULT hr; + CameraControlProperty prop = (CameraControlProperty)property; + long Min, Max, Step, Default, Flags; + hr = pProp->GetRange(prop, &Min, &Max, &Step, &Default, &Flags); + hr = pProp->Set(prop, vc_Percent2Value(Min, Max, Step, percent), CameraControl_Flags_Manual); + + if (FAILED(hr)) return 0; + return 1; +} + +static int vc_GetCameraControlProperty(IBaseFilter* capture_filter, IAMCameraControl* *camera_prop, long property, float *percent) +{ + IAMCameraControl *pProp = vc_InitCameraControl(capture_filter, camera_prop); + if (!pProp) return 0; + + HRESULT hr; + CameraControlProperty prop = (CameraControlProperty)property; + long Min, Max, Step, Default, Flags, Val; + hr = pProp->GetRange(prop, &Min, &Max, &Step, &Default, &Flags); + hr = pProp->Get(prop, &Val, &Flags); + + if (FAILED(hr)) return 0; + *percent = vc_Value2Percent(Min, Max, Val); + return 1; +} + +static int vc_ResetCameraControlProperty(IBaseFilter* capture_filter, IAMCameraControl* *camera_prop, long property, int fauto) +{ + IAMCameraControl *pProp = vc_InitCameraControl(capture_filter, camera_prop); + if (!pProp) return 0; + + HRESULT hr; + CameraControlProperty prop = (CameraControlProperty)property; + long Min, Max, Step, Default, Flags; + hr = pProp->GetRange(prop, &Min, &Max, &Step, &Default, &Flags); + + if (fauto && (Flags & CameraControl_Flags_Auto)) + hr = pProp->Set(prop, Default, CameraControl_Flags_Auto); + else + hr = pProp->Set(prop, Default, CameraControl_Flags_Manual); + + if (FAILED(hr)) return 0; + return 1; +} + +static IAMVideoControl* vc_InitVideoControl(IBaseFilter* capture_filter, IAMVideoControl* *video_prop) +{ + if (*video_prop) + return *video_prop; + + HRESULT hr = capture_filter->QueryInterface(IID_IAMVideoControl, (void**)video_prop); + if (FAILED(hr)) + return NULL; + + return *video_prop; +} + +static int vc_SetVideoControlProperty(IBaseFilter* capture_filter, IAMVideoControl* *video_prop, long property, float percent) +{ + IAMVideoControl *pProp = vc_InitVideoControl(capture_filter, video_prop); + if (!pProp) return 0; + + HRESULT hr; + IPin *pOutPin = vc_GetPin(capture_filter, PINDIR_OUTPUT); + long Mode; + hr = pProp->GetMode(pOutPin, &Mode); + if (percent) + Mode = Mode | property; + else + Mode = Mode & ~property; + hr = pProp->SetMode(pOutPin, Mode); + pOutPin->Release(); + + if (FAILED(hr)) return 0; + return 1; +} + +static int vc_GetVideoControlProperty(IBaseFilter* capture_filter, IAMVideoControl* *video_prop, long property, float *percent) +{ + IAMVideoControl *pProp = vc_InitVideoControl(capture_filter, video_prop); + if (!pProp) return 0; + + HRESULT hr; + long Mode; + IPin *pOutPin = vc_GetPin(capture_filter, PINDIR_OUTPUT); + hr = pProp->GetMode(pOutPin, &Mode); + pOutPin->Release(); + + if (FAILED(hr)) return 0; + if (Mode & property) + *percent = 100.; + else + *percent = 0.; + return 1; +} + +static int vc_ResetVideoControlProperty(IBaseFilter* capture_filter, IAMVideoControl* *video_prop, long property, int fauto) +{ + IAMVideoControl *pProp = vc_InitVideoControl(capture_filter, video_prop); + if (!pProp) return 0; + + HRESULT hr; + long Mode; + IPin *pOutPin = vc_GetPin(capture_filter, PINDIR_OUTPUT); + hr = pProp->GetMode(pOutPin, &Mode); + if (Mode & property) + Mode = Mode & ~property; + else + Mode = Mode | property; + hr = pProp->SetMode(pOutPin, Mode); + pOutPin->Release(); + + if (FAILED(hr)) return 0; + return 1; +} + +static long vc_AnalogFormat[19] = +{ + AnalogVideo_NTSC_M, + AnalogVideo_NTSC_M_J, + AnalogVideo_NTSC_433, + AnalogVideo_PAL_B, + AnalogVideo_PAL_D, + AnalogVideo_PAL_H, + AnalogVideo_PAL_I, + AnalogVideo_PAL_M, + AnalogVideo_PAL_N, + AnalogVideo_PAL_60, + AnalogVideo_SECAM_B, + AnalogVideo_SECAM_D, + AnalogVideo_SECAM_G, + AnalogVideo_SECAM_H, + AnalogVideo_SECAM_K, + AnalogVideo_SECAM_K1, + AnalogVideo_SECAM_L, + AnalogVideo_SECAM_L1, + AnalogVideo_PAL_N_COMBO +}; + +static int vc_SetAnalogFormat(IBaseFilter* capture_filter, float percent) +{ + IAMAnalogVideoDecoder* video_decoder = NULL; + HRESULT hr = capture_filter->QueryInterface(IID_IAMAnalogVideoDecoder, (void**)video_decoder); + if (FAILED(hr)) + return 0; + + hr = video_decoder->put_TVFormat(vc_AnalogFormat[(int)percent]); + video_decoder->Release(); + + if (FAILED(hr)) return 0; + return 1; +} + +static int vc_GetAnalogFormat(IBaseFilter* capture_filter, float *percent) +{ + IAMAnalogVideoDecoder* video_decoder = NULL; + HRESULT hr = capture_filter->QueryInterface(IID_IAMAnalogVideoDecoder, (void**)video_decoder); + if (FAILED(hr)) + return 0; + + long format; + hr = video_decoder->get_TVFormat(&format); + video_decoder->Release(); + + if (FAILED(hr)) return 0; + for (int i = 0; i < 19; i++) + { + if (vc_AnalogFormat[i] == format) + { + *percent = (float)i; + return 1; + } + } + return 0; +} + +#define VC_HASH_SIZE 101 +#define VC_HASH_MULTIPLIER 31 + +/** Unique Hash index for a key + * We use the hash function described in "The Pratice of Programming" of Kernighan & Pike. */ +static int vc_HashIndex(const char *key, int hash_size) +{ + unsigned short hash = 0; + const unsigned char *p_key = (const unsigned char*)key; + + for(; *p_key; p_key++) + hash = hash*VC_HASH_MULTIPLIER + *p_key; + + return hash % hash_size; +} + +#define VC_CAMERASHIFT 20 +#define VC_VIDEOSHIFT 40 +#define VC_ANALOGSHIFT 60 + +static long vc_Attrib2Property(const char* attrib) +{ + static long prop_table[VC_HASH_SIZE]; + static int first = 1; + if (first) + { + memset(prop_table, 0, VC_HASH_SIZE*sizeof(long)); + prop_table[vc_HashIndex("CameraPanAngle", VC_HASH_SIZE)] = (long)CameraControl_Pan + VC_CAMERASHIFT + 1; + prop_table[vc_HashIndex("CameraTiltAngle", VC_HASH_SIZE)] = (long)CameraControl_Tilt + VC_CAMERASHIFT + 1; + prop_table[vc_HashIndex("CameraRollAngle", VC_HASH_SIZE)] = (long)CameraControl_Roll + VC_CAMERASHIFT + 1; + prop_table[vc_HashIndex("CameraLensZoom", VC_HASH_SIZE)] = (long)CameraControl_Zoom + VC_CAMERASHIFT + 1; + prop_table[vc_HashIndex("CameraExposure", VC_HASH_SIZE)] = (long)CameraControl_Exposure + VC_CAMERASHIFT + 1; + prop_table[vc_HashIndex("CameraIris", VC_HASH_SIZE)] = (long)CameraControl_Iris + VC_CAMERASHIFT + 1; + prop_table[vc_HashIndex("CameraFocus", VC_HASH_SIZE)] = (long)CameraControl_Focus + VC_CAMERASHIFT + 1; + prop_table[vc_HashIndex("VideoBrightness", VC_HASH_SIZE)] = (long)VideoProcAmp_Brightness + 1; + prop_table[vc_HashIndex("VideoContrast", VC_HASH_SIZE)] = (long)VideoProcAmp_Contrast + 1; + prop_table[vc_HashIndex("VideoHue", VC_HASH_SIZE)] = (long)VideoProcAmp_Hue + 1; + prop_table[vc_HashIndex("VideoSaturation", VC_HASH_SIZE)] = (long)VideoProcAmp_Saturation + 1; + prop_table[vc_HashIndex("VideoSharpness", VC_HASH_SIZE)] = (long)VideoProcAmp_Sharpness + 1; + prop_table[vc_HashIndex("VideoGamma", VC_HASH_SIZE)] = (long)VideoProcAmp_Gamma + 1; + prop_table[vc_HashIndex("VideoColorEnable", VC_HASH_SIZE)] = (long)VideoProcAmp_ColorEnable + 1; + prop_table[vc_HashIndex("VideoWhiteBalance", VC_HASH_SIZE)] = (long)VideoProcAmp_WhiteBalance + 1; + prop_table[vc_HashIndex("VideoBacklightCompensation", VC_HASH_SIZE)] = (long)VideoProcAmp_BacklightCompensation + 1; + prop_table[vc_HashIndex("VideoGain", VC_HASH_SIZE)] = (long)VideoProcAmp_Gain + 1; + prop_table[vc_HashIndex("FlipHorizontal", VC_HASH_SIZE)] = (long)VideoControlFlag_FlipHorizontal + VC_VIDEOSHIFT + 1; + prop_table[vc_HashIndex("FlipVertical", VC_HASH_SIZE)] = (long)VideoControlFlag_FlipVertical + VC_VIDEOSHIFT + 1; + prop_table[vc_HashIndex("AnalogFormat", VC_HASH_SIZE)] = (long)0 + VC_ANALOGSHIFT + 1; + first = 0; + } + long prop = prop_table[vc_HashIndex(attrib, VC_HASH_SIZE)]; + if (!prop) + return 0; + return prop-1; +} + +int imVideoCaptureSetAttribute(imVideoCapture* vc, const char* attrib, float percent) +{ + assert(vc); + assert(vc->device != -1); + + long property = vc_Attrib2Property(attrib); + if (property == -1) return 0; + if (property < VC_CAMERASHIFT) + return vc_SetVideoProcAmpProperty(vc->capture_filter, &vc->video_prop, property, percent); + else if (property < VC_VIDEOSHIFT) + return vc_SetCameraControlProperty(vc->capture_filter, &vc->camera_prop, property-VC_CAMERASHIFT, percent); + else if (property < VC_ANALOGSHIFT) + return vc_SetVideoControlProperty(vc->capture_filter, &vc->videoctrl_prop, property-VC_VIDEOSHIFT, percent); + else + return vc_SetAnalogFormat(vc->capture_filter, percent); +} + +int imVideoCaptureGetAttribute(imVideoCapture* vc, const char* attrib, float *percent) +{ + assert(vc); + assert(vc->device != -1); + + long property = vc_Attrib2Property(attrib); + if (property == -1) return 0; + if (property < VC_CAMERASHIFT) + return vc_GetVideoProcAmpProperty(vc->capture_filter, &vc->video_prop, property, percent); + else if (property < VC_VIDEOSHIFT) + return vc_GetCameraControlProperty(vc->capture_filter, &vc->camera_prop, property-VC_CAMERASHIFT, percent); + else if (property < VC_ANALOGSHIFT) + return vc_GetVideoControlProperty(vc->capture_filter, &vc->videoctrl_prop, property-VC_VIDEOSHIFT, percent); + else + return vc_GetAnalogFormat(vc->capture_filter, percent); +} + +int imVideoCaptureResetAttribute(imVideoCapture* vc, const char* attrib, int fauto) +{ + assert(vc); + assert(vc->device != -1); + + long property = vc_Attrib2Property(attrib); + if (property == -1) return 0; + if (property < VC_CAMERASHIFT) + return vc_ResetVideoProcAmpProperty(vc->capture_filter, &vc->video_prop, property, fauto); + else if (property < VC_VIDEOSHIFT) + return vc_ResetCameraControlProperty(vc->capture_filter, &vc->camera_prop, property-VC_CAMERASHIFT, fauto); + else if (property < VC_ANALOGSHIFT) + return vc_ResetVideoControlProperty(vc->capture_filter, &vc->videoctrl_prop, property-VC_VIDEOSHIFT, fauto); + return 0; +} + +const char** imVideoCaptureGetAttributeList(imVideoCapture* vc, int *num_attrib) +{ +#define VC_VIDEOPROC_MAX 10 +#define VC_CAMERACONTROL_MAX 7 +#define VC_VIDEOCONTROL_MAX 2 +#define VC_VIDEODECODER_MAX 1 +#define VC_NUM_ATTRIB_MAX (VC_VIDEOPROC_MAX+VC_CAMERACONTROL_MAX+VC_VIDEOCONTROL_MAX+VC_VIDEODECODER_MAX) + static char* attrib_list[VC_NUM_ATTRIB_MAX]; + static char* all_attrib_list[VC_NUM_ATTRIB_MAX] = + { //Pre-calculated Hash Index: + "VideoBrightness", // (97) + "VideoContrast", // (80) + "VideoHue", // (98) + "VideoSaturation", // (4) + "VideoSharpness", // (56) + "VideoGamma", // (67) + "VideoColorEnable", // (91) + "VideoWhiteBalance", // (26) + "VideoBacklightCompensation", // (50) + "VideoGain", // (36) + "CameraPanAngle", // (64) + "CameraTiltAngle", // (54) + "CameraRollAngle", // (85) + "CameraLensZoom", // (57) + "CameraExposure", // (84) + "CameraIris", // (20) + "CameraFocus", // (62) + "FlipHorizontal", // (21) + "FlipVertical", // (28) + "AnalogFormat"}; // (89) + + int i; + *num_attrib = 0; + + IAMVideoProcAmp *video_prop; + HRESULT hr = vc->capture_filter->QueryInterface(IID_IAMVideoProcAmp, (void**)&video_prop); + if (SUCCEEDED(hr)) + { + for (i = 0; i < VC_VIDEOPROC_MAX; i++) + attrib_list[i] = all_attrib_list[i]; + *num_attrib = VC_VIDEOPROC_MAX; + video_prop->Release(); + } + + IAMCameraControl *camera_prop; + hr = vc->capture_filter->QueryInterface(IID_IAMCameraControl, (void**)&camera_prop); + if (SUCCEEDED(hr)) + { + for (i = 0; i < VC_CAMERACONTROL_MAX; i++) + attrib_list[i+*num_attrib] = all_attrib_list[i+VC_VIDEOPROC_MAX]; + *num_attrib += VC_CAMERACONTROL_MAX; + camera_prop->Release(); + } + + IAMVideoControl* video_ctrl; + hr = vc->capture_filter->QueryInterface(IID_IAMVideoControl, (void**)&video_ctrl); + if (SUCCEEDED(hr)) + { + for (i = 0; i < VC_VIDEOCONTROL_MAX; i++) + attrib_list[i+*num_attrib] = all_attrib_list[i+VC_VIDEOPROC_MAX+VC_CAMERACONTROL_MAX]; + *num_attrib += VC_VIDEOCONTROL_MAX; + video_ctrl->Release(); + } + + IAMAnalogVideoDecoder* video_decoder = NULL; + hr = vc->capture_filter->QueryInterface(IID_IAMAnalogVideoDecoder, (void**)&video_decoder); + if (SUCCEEDED(hr)) + { + for (i = 0; i < VC_VIDEODECODER_MAX; i++) + attrib_list[i+*num_attrib] = all_attrib_list[i+VC_VIDEOPROC_MAX+VC_CAMERACONTROL_MAX+VC_VIDEOCONTROL_MAX]; + *num_attrib += VC_VIDEODECODER_MAX; + video_decoder->Release(); + } + + return (const char**)attrib_list; +} + +//VIDEOINFOHEADER +// AvgTimePerFrame diff --git a/im/src/im_colorhsi.cpp b/im/src/im_colorhsi.cpp new file mode 100755 index 0000000..953bb2c --- /dev/null +++ b/im/src/im_colorhsi.cpp @@ -0,0 +1,265 @@ +/** \file + * \brief HSI Color Manipulation + * + * See Copyright Notice in im_lib.h + * $Id: im_colorhsi.cpp,v 1.2 2008/11/18 13:15:46 scuri Exp $ + */ + + +#include + +#include "im_colorhsi.h" +#include "im_color.h" + +static const float rad60 = 1.0471975f; +static const float rad120 = 2.0943951f; +static const float rad180 = 3.1415926f; +static const float rad240 = 4.1887902f; +static const float rad300 = 5.2359877f; +static const float rad360 = 6.2831853f; +static const float sqrt3 = 1.7320508f; +static const float rad2deg = 57.2957795131f; + + +static double iColorNormHue(double H) +{ + while (H < 0.0) + H += rad360; + + if (H > rad360) + H = fmod(H, (double)rad360); + + return H; +} + +/**********************************/ +/* HSI MAX S */ +/**********************************/ + +static void iColorSmax01(float h, float hr, float hb, float hg, float *h0, float *h1) +{ + if (h < rad60) + { + *h0 = hb; + *h1 = hr; + } + else if (h < rad120) + { + *h0 = hb; + *h1 = hg; + } + else if (h < rad180) + { + *h0 = hr; + *h1 = hg; + } + else if (h < rad240) + { + *h0 = hr; + *h1 = hb; + } + else if (h < rad300) + { + *h0 = hg; + *h1 = hb; + } + else + { + *h0 = hg; + *h1 = hr; + } +} + +static float iColorHSI_Smax(float h, double cosH, double sinH, float i) +{ + float hr, hb, hg, imax, h0, h1; + + /* i here is normalized between 0-1 */ + + if (i == 0 || i == 1) + return 0.0f; + + /* Making r=0, g=0, b=0, r=1, g=1 or b=1 in the parametric equations and + writting s in function of H and I. */ + + hr = (float)(cosH / 1.5); + hg = (float)((-cosH + sinH*sqrt3)/ 3.0); + hb = (float)((-cosH - sinH*sqrt3)/ 3.0); + + /* at bottom */ + if (i <= 1.0f/3.0f) + { + /* face B=0 */ + if (h < rad120) + return -i/hb; + + /* face R=0 */ + if (h < rad240) + return -i/hr; + + /* face G=0 */ + return -i/hg; + } + + /* at top */ + if (i >= 2.0f/3.0f) + { + /* face R=1 */ + if (h < rad60 || h > rad300) + return (1-i)/hr; + + /* face G=1 */ + if (h < rad180) + return (1-i)/hg; + + /* face B=1 */ + return (1-i)/hb; + } + + /* in the middle */ + + iColorSmax01(h, hr, hb, hg, &h0, &h1); + + if (h == 0 || h == rad120 || h == rad240) + imax = 1.0f/3.0f; + else if (h == rad60 || h == rad180 || h == rad300) + imax = 2.0f/3.0f; + else + imax = h0 / (h0 - h1); + + if (i < imax) + return -i/h0; + else + return (1-i)/h1; +} + +float imColorHSI_ImaxS(float h, double cosH, double sinH) +{ + float i, h0, h1; + float hr, hb, hg; + + if (h == 0 || h == rad120 || h == rad240) + return 1.0f/3.0f; + + if (h == rad60 || h == rad180 || h == rad300) + return 2.0f/3.0f; + + hr = (float)(cosH / 1.5f); + hg = (float)((-cosH + sinH*sqrt3)/ 3.0); + hb = (float)((-cosH - sinH*sqrt3)/ 3.0); + + iColorSmax01(h, hr, hb, hg, &h0, &h1); + + i = h0 / (h0 - h1); + + return i; +} + +/**********************************/ +/* RGB 2 HSI */ +/**********************************/ + +void imColorRGB2HSI(float r, float g, float b, float *h, float *s, float *i) +{ + float v, u; + double H; + + /* Parametric equations */ + v = r - (g + b)/2; + u = (g - b) * (sqrt3/2); + + *i = (r + g + b)/3; /* already normalized to 0-1 */ + *s = (float)sqrt(v*v + u*u); /* s is between 0-1, it is linear in the cube and it is in u,v space. */ + + if (*s == 0) + *h = 360.0f; /* by definition */ + else + { + H = atan2(u, v); + H = iColorNormHue(H); + *h = (float)(H * rad2deg); + + /* must scale S from 0-Smax to 0-1 */ + float Smax = iColorHSI_Smax((float)H, cos(H), sin(H), *i); + if (Smax == 0.0f) + *s = 0.0f; + else + { + if (*s > Smax) /* because of round problems when calculating s and Smax */ + *s = Smax; + *s /= Smax; + } + } +} + +void imColorRGB2HSIbyte(unsigned char r, unsigned char g, unsigned char b, float *h, float *s, float *i) +{ + float fr = imColorReconstruct(r, (imbyte)255); + float fg = imColorReconstruct(g, (imbyte)255); + float fb = imColorReconstruct(b, (imbyte)255); + + imColorRGB2HSI(fr, fg, fb, h, s, i); +} + +/**********************************/ +/* HSI 2 RGB */ +/**********************************/ + +void imColorHSI2RGB(float h, float s, float i, float *r, float *g, float *b) +{ + double cosH, sinH, H, v, u; + + if (i < 0) i = 0; + else if (i > 1) i = 1; + + if (s < 0) s = 0; + else if (s > 1) s = 1; + + if (s == 0.0f || i == 1.0f || i == 0.0f || (int)h == 360) + { + *r = i; + *g = i; + *b = i; + return; + } + + H = h/rad2deg; + H = iColorNormHue(H); + + cosH = cos(H); + sinH = sin(H); + + /* must scale S from 0-1 to 0-Smax */ + float Smax = iColorHSI_Smax((float)H, cosH, sinH, i); + s *= Smax; + if (s > 1.0f) /* because of round problems when calculating s and Smax */ + s = 1.0f; + + v = s * cosH; + u = s * sinH; + + /* Inverse of the Parametric equations, using i normalized to 0-1 */ + *r = (float)(i + v/1.5); + *g = (float)(i - (v - u*sqrt3)/3.0); + *b = (float)(i - (v + u*sqrt3)/3.0); + + /* fix round errors */ + if (*r < 0) *r = 0; + if (*g < 0) *g = 0; + if (*b < 0) *b = 0; + + if (*r > 1) *r = 1.0f; + if (*g > 1) *g = 1.0f; + if (*b > 1) *b = 1.0f; +} + +void imColorHSI2RGBbyte(float h, float s, float i, unsigned char *r, unsigned char *g, unsigned char *b) +{ + float fr, fg, fb; + + imColorHSI2RGB(h, s, i, &fr, &fg, &fb); + + *r = imColorQuantize(fr, (imbyte)255); + *g = imColorQuantize(fg, (imbyte)255); + *b = imColorQuantize(fb, (imbyte)255); +} diff --git a/im/src/im_colormode.cpp b/im/src/im_colormode.cpp new file mode 100755 index 0000000..2a99183 --- /dev/null +++ b/im/src/im_colormode.cpp @@ -0,0 +1,87 @@ +/** \file + * \brief Color Mode Utilities + * + * See Copyright Notice in im_lib.h + * $Id: im_colormode.cpp,v 1.1 2008/10/17 06:10:16 scuri Exp $ + */ + + +#include +#include +#include + +#include "im.h" +#include "im_util.h" + +const char* imColorModeSpaceName(int color_mode) +{ + int color_space = imColorModeSpace(color_mode); + switch (color_space) + { + case IM_RGB: return "RGB"; + case IM_MAP: return "Map"; + case IM_GRAY: return "Gray"; + case IM_BINARY: return "Binary"; + case IM_CMYK: return "CMYK"; + case IM_YCBCR: return "Y'CbCr"; + case IM_LAB: return "CIE L*a*b*"; + case IM_LUV: return "CIE L*u*v*"; + case IM_XYZ: return "CIE XYZ"; + } + + return NULL; +} + +int imColorModeDepth(int color_mode) +{ + int depth = 0; + + int color_space = imColorModeSpace(color_mode); + switch (color_space) + { + case IM_GRAY: + case IM_BINARY: + case IM_MAP: + depth = 1; + break; + case IM_CMYK: + depth = 4; + break; + default: + depth = 3; + break; + } + + if (imColorModeHasAlpha(color_mode)) + depth++; + + return depth; +} + +int imColorModeToBitmap(int color_mode) +{ + int color_space = imColorModeSpace(color_mode); + switch (color_space) + { + case IM_BINARY: + case IM_GRAY: + case IM_MAP: + return color_space; + default: + return IM_RGB; + } +} + +int imColorModeIsBitmap(int color_mode, int data_type) +{ + if (imColorModeSpace(color_mode) == IM_BINARY || + imColorModeSpace(color_mode) == IM_MAP) + return 1; + + if ((imColorModeSpace(color_mode) == IM_RGB || + imColorModeSpace(color_mode) == IM_GRAY) && + (data_type == IM_BYTE)) + return 1; + + return 0; +} diff --git a/im/src/im_colorutil.cpp b/im/src/im_colorutil.cpp new file mode 100755 index 0000000..9e96c65 --- /dev/null +++ b/im/src/im_colorutil.cpp @@ -0,0 +1,27 @@ +/** \file + * \brief Color Utilities + * + * See Copyright Notice in im_lib.h + * $Id: im_colorutil.cpp,v 1.1 2008/10/17 06:10:16 scuri Exp $ + */ + + +#include +#include +#include + +#include "im.h" +#include "im_util.h" + +long imColorEncode(unsigned char Red, unsigned char Green, unsigned char Blue) +{ + return (((long)Red) << 16) | (((long)Green) << 8) | ((long)Blue); +} + +void imColorDecode(unsigned char* Red, unsigned char* Green, unsigned char* Blue, long Color) +{ + if (Red) *Red = (imbyte)(Color >> 16); + if (Green) *Green = (imbyte)(Color >> 8); + if (Blue) *Blue = (imbyte)Color; +} + diff --git a/im/src/im_convertbitmap.cpp b/im/src/im_convertbitmap.cpp new file mode 100755 index 0000000..a4f6b70 --- /dev/null +++ b/im/src/im_convertbitmap.cpp @@ -0,0 +1,284 @@ +/** \file + * \brief Image Conversion + * + * See Copyright Notice in im_lib.h + * $Id: im_convertbitmap.cpp,v 1.3 2009/08/18 02:23:33 scuri Exp $ + */ + +#include "im.h" +#include "im_util.h" +#include "im_complex.h" +#include "im_image.h" +#include "im_convert.h" +#include "im_counter.h" + +#include +#include +#include + +int imConvertToBitmap(const imImage* src_image, imImage* dst_image, int cpx2real, float gamma, int abssolute, int cast_mode) +{ + assert(src_image); + assert(dst_image); + + if (!imImageMatchSize(src_image, dst_image) || !imImageIsBitmap(dst_image)) + return IM_ERR_DATA; + + int counter = imCounterBegin("Building Bitmap"); + + int ret; + if (src_image->data_type == IM_BYTE) + { + // NO data type conversion, only color mode conversion + ret = imConvertColorSpace(src_image, dst_image); + } + else + { + if (src_image->color_space == IM_RGB || + src_image->color_space == IM_GRAY) + { + // data type conversion, but NO color mode conversion + ret = imConvertDataType(src_image, dst_image, cpx2real, gamma, abssolute, cast_mode); + } + else + { + // data type conversion AND color mode conversion + imImage* temp_image = imImageCreate(src_image->width, src_image->height, dst_image->color_space, src_image->data_type); + if (!temp_image) + ret = IM_ERR_MEM; + else + { + // first convert color_mode in the bigger precision + ret = imConvertColorSpace(src_image, temp_image); + if (ret == IM_ERR_NONE) + { + // second just convert data type + ret = imConvertDataType(temp_image, dst_image, cpx2real, gamma, abssolute, cast_mode); + } + imImageDestroy(temp_image); + } + } + } + + imCounterEnd(counter); + return ret; +} + + +template +void iDoChangePacking(const T* src_data, T* dst_data, int width, int height, int depth, + int src_is_packed) +{ + int count = width*height; + if (src_is_packed) + { + for (int i = 0; i < count; i++) + { + for (int d = 0; d < depth; d++) + { + *(dst_data + d*count) = *src_data++; + } + + dst_data++; + } + } + else + { + for (int i = 0; i < count; i++) + { + for (int d = 0; d < depth; d++) + { + *dst_data++ = *(src_data + d*count); + } + + src_data++; + } + } +} + +void imConvertPacking(const void* src_data, void* dst_data, int width, int height, int depth, + int data_type, int src_is_packed) +{ + switch(data_type) + { + case IM_BYTE: + iDoChangePacking((const imbyte*)src_data, (imbyte*)dst_data, width, height, depth, src_is_packed); + break; + case IM_USHORT: + iDoChangePacking((const imushort*)src_data, (imushort*)dst_data, width, height, depth, src_is_packed); + break; + case IM_INT: + iDoChangePacking((const int*)src_data, (int*)dst_data, width, height, depth, src_is_packed); + break; + case IM_FLOAT: + iDoChangePacking((const float*)src_data, (float*)dst_data, width, height, depth, src_is_packed); + break; + case IM_CFLOAT: + iDoChangePacking((const imcfloat*)src_data, (imcfloat*)dst_data, width, height, depth, src_is_packed); + break; + } +} + +static void iImageMakeGray(imbyte *map, int count, int step) +{ + for(int i = 0; i < count; i++) + { + if (*map) + *map = 255; + map += step; + } +} + +static void iImageGLCopyMapAlpha(imbyte *map, imbyte *gldata, int depth, int count) +{ + /* gldata can be GL_RGBA or GL_LUMINANCE_ALPHA */ + gldata += depth-1; /* position at first alpha */ + for(int i = 0; i < count; i++) + { + *gldata = *map; + map++; + gldata += depth; /* skip to next alpha */ + } +} + +static void iImageGLSetTranspColor(imbyte *gldata, int count, imbyte r, imbyte g, imbyte b) +{ + /* gldata is GL_RGBA */ + for(int i = 0; i < count; i++) + { + if (*(gldata+0) == r && + *(gldata+1) == g && + *(gldata+2) == b) + *(gldata+3) = 0; /* transparent */ + else + *(gldata+3) = 255; /* opaque */ + gldata += 4; + } +} + +static void iImageGLSetTranspMap(imbyte *map, imbyte *gldata, int count, imbyte *transp_map, int transp_count) +{ + /* gldata is GL_RGBA */ + gldata += 3; /* position at first alpha */ + for(int i = 0; i < count; i++) + { + if (*map < transp_count) + *gldata = transp_map[*map]; + else + *gldata = 255; /* opaque */ + + map++; + gldata += 4; + } +} + +static void iImageGLSetTranspIndex(imbyte *map, imbyte *gldata, int depth, int count, imbyte index) +{ + /* gldata can be GL_RGBA or GL_LUMINANCE_ALPHA */ + gldata += depth-1; /* position at first alpha */ + for(int i = 0; i < count; i++) + { + if (*map == index) + *gldata = 0; /* full transparent */ + else + *gldata = 255; /* opaque */ + + map++; + gldata += depth; /* skip to next alpha */ + } +} + +/* To avoid including gl.h */ +#define GL_RGB 0x1907 +#define GL_RGBA 0x1908 +#define GL_LUMINANCE 0x1909 +#define GL_LUMINANCE_ALPHA 0x190A + +void* imImageGetOpenGLData(const imImage* image, int *format) +{ + if (!imImageIsBitmap(image)) + return NULL; + + int transp_count; + imbyte* transp_index = (imbyte*)imImageGetAttribute(image, "TransparencyIndex", NULL, NULL); + imbyte* transp_map = (imbyte*)imImageGetAttribute(image, "TransparencyMap", NULL, &transp_count); + imbyte* transp_color = (imbyte*)imImageGetAttribute(image, "TransparencyColor", NULL, NULL); + + int glformat; + switch(image->color_space) + { + case IM_MAP: + if (image->has_alpha || transp_map || transp_index) + glformat = GL_RGBA; + else + glformat = GL_RGB; + break; + case IM_RGB: + if (image->has_alpha || transp_color) + glformat = GL_RGBA; + else + glformat = GL_RGB; + break; + case IM_BINARY: + default: /* IM_GRAY */ + if (image->has_alpha || transp_index) + glformat = GL_LUMINANCE_ALPHA; + else + glformat = GL_LUMINANCE; + break; + } + + int depth; + switch (glformat) + { + case GL_RGB: + depth = 3; + break; + case GL_RGBA: + depth = 4; + break; + case GL_LUMINANCE_ALPHA: + depth = 2; + break; + default: /* GL_LUMINANCE */ + depth = 1; + break; + } + + int size = image->count*depth; + imImageSetAttribute(image, "GLDATA", IM_BYTE, size, NULL); + imbyte* gldata = (imbyte*)imImageGetAttribute(image, "GLDATA", NULL, NULL); + + if (image->color_space == IM_RGB) + { + if (image->has_alpha) + imConvertPacking(image->data[0], gldata, image->width, image->height, 4, IM_BYTE, 0); + else + { + imConvertPacking(image->data[0], gldata, image->width, image->height, 3, IM_BYTE, 0); + + if (transp_color) + iImageGLSetTranspColor(gldata, image->count, *(transp_color+0), *(transp_color+1), *(transp_color+2)); + } + } + else + { + memcpy(gldata, image->data[0], image->size); + + if (image->color_space == IM_MAP) + imConvertMapToRGB(gldata, image->count, depth, 1, image->palette, image->palette_count); + else if (image->color_space == IM_BINARY) + iImageMakeGray(gldata, image->count, (glformat==GL_LUMINANCE_ALPHA)? 2: 1); + + if (image->has_alpha) + iImageGLCopyMapAlpha((imbyte*)image->data[1], gldata, depth, image->count); + else if (transp_map) + iImageGLSetTranspMap((imbyte*)image->data[0], gldata, image->count, transp_map, transp_count); + else if (transp_index) + iImageGLSetTranspIndex((imbyte*)image->data[0], gldata, depth, image->count, *transp_index); + } + + if (format) *format = glformat; + return gldata; +} + diff --git a/im/src/im_convertcolor.cpp b/im/src/im_convertcolor.cpp new file mode 100755 index 0000000..e68730f --- /dev/null +++ b/im/src/im_convertcolor.cpp @@ -0,0 +1,985 @@ +/** \file + * \brief Image Conversion + * + * See Copyright Notice in im_lib.h + * $Id: im_convertcolor.cpp,v 1.3 2009/08/18 05:13:18 scuri Exp $ + */ + +#include "im.h" +#include "im_util.h" +#include "im_complex.h" +#include "im_image.h" +#include "im_convert.h" +#include "im_color.h" +#include "im_counter.h" + +#include +#include +#include + +void imConvertMapToRGB(unsigned char* data, int count, int depth, int packed, long* palette, int palette_count) +{ + int c, i, delta; + unsigned char r[256], g[256], b[256]; + unsigned char *r_data, *g_data, *b_data; + + unsigned char* src_data = data + count-1; + if (packed) + { + r_data = data + depth*(count-1); + g_data = r_data + 1; + b_data = r_data + 2; + delta = depth; + } + else + { + r_data = data + count - 1; + g_data = data + 2*count - 1; + b_data = data + 3*count - 1; + delta = 1; + } + + for (c = 0; c < palette_count; c++) + imColorDecode(&r[c], &g[c], &b[c], palette[c]); + + for (i = 0; i < count; i++) + { + int index = *src_data; + *r_data = r[index]; + *g_data = g[index]; + *b_data = b[index]; + + r_data -= delta; + g_data -= delta; + b_data -= delta; + src_data--; + } +} + +static void iConvertSetTranspMap(imbyte *src_map, imbyte *dst_alpha, int count, imbyte *transp_map, int transp_count) +{ + for(int i = 0; i < count; i++) + { + if (*src_map < transp_count) + *dst_alpha = transp_map[*src_map]; + else + *dst_alpha = 255; /* opaque */ + + src_map++; + dst_alpha++; + } +} + +static void iConvertSetTranspIndex(imbyte *src_map, imbyte *dst_alpha, int count, imbyte index) +{ + for(int i = 0; i < count; i++) + { + if (*src_map == index) + *dst_alpha = 0; /* full transparent */ + else + *dst_alpha = 255; /* opaque */ + + src_map++; + dst_alpha++; + } +} + +static void iConvertSetTranspColor(imbyte **dst_data, int count, imbyte r, imbyte g, imbyte b) +{ + imbyte *pr = dst_data[0]; + imbyte *pg = dst_data[1]; + imbyte *pb = dst_data[2]; + imbyte *pa = dst_data[3]; + + for(int i = 0; i < count; i++) + { + if (*pr == r && + *pg == g && + *pb == b) + *pa = 0; /* transparent */ + else + *pa = 255; /* opaque */ + + pr++; + pg++; + pb++; + pa++; + } +} + +// convert bin2gray and gray2bin +inline void iConvertBinary(imbyte* map, int count, imbyte value) +{ + imbyte thres = (value == 255)? 1: 128; + + // if gray2bin, check for invalid gray that already is binary + if (value != 255) + { + imbyte vmax = 0, *pmap = map; + for (int i = 0; i < count; i++) + { + if (*pmap > vmax) + vmax = *pmap; + + pmap++; + } + + if (vmax == 1) + thres = 1; + else + thres = vmax / 2; + } + + for (int i = 0; i < count; i++) + { + if (*map >= thres) + *map = value; + else + *map = 0; + + map++; + } +} + +static void iConvertMap2Gray(const imbyte* src_map, imbyte* dst_map, int count, const long* palette, const int palette_count) +{ + imbyte r, g, b; + imbyte remap[256]; + + for (int c = 0; c < palette_count; c++) + { + imColorDecode(&r, &g, &b, palette[c]); + remap[c] = imColorRGB2Luma(r, g, b); + } + + for (int i = 0; i < count; i++) + { + *dst_map++ = remap[*src_map++]; + } +} + +static void iConvertMapToRGB(const imbyte* src_map, imbyte* red, imbyte* green, imbyte* blue, int count, const long* palette, const int palette_count) +{ + imbyte r[256], g[256], b[256]; + for (int c = 0; c < palette_count; c++) + imColorDecode(&r[c], &g[c], &b[c], palette[c]); + + for (int i = 0; i < count; i++) + { + int index = *src_map++; + *red++ = r[index]; + *green++ = g[index]; + *blue++ = b[index]; + } +} + +template +int iDoConvert2Gray(int count, int data_type, + const T** src_data, int src_color_space, T** dst_data, int counter) +{ + int i; + T max; + + const T* src_map0 = src_data[0]; + const T* src_map1 = src_data[1]; + const T* src_map2 = src_data[2]; + const T* src_map3 = (src_color_space == IM_CMYK)? src_data[3]: 0; + T* dst_map = dst_data[0]; + + imCounterTotal(counter, count, "Converting To Gray..."); + + switch(src_color_space) + { + case IM_XYZ: + max = (T)imColorMax(data_type); + for (i = 0; i < count; i++) + { + // scale to 0-1 + float c1 = imColorReconstruct(*src_map1++, max); // use only Y component + + // do gamma correction then scale back to 0-max + *dst_map++ = imColorQuantize(imColorTransfer2Nonlinear(c1), max); + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + case IM_CMYK: + max = (T)imColorMax(data_type); + for (i = 0; i < count; i++) + { + T r, g, b; + // result is still 0-max + imColorCMYK2RGB(*src_map0++, *src_map1++, *src_map2++, *src_map3++, r, g, b, max); + *dst_map++ = imColorRGB2Luma(r, g, b); + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + case IM_RGB: + for (i = 0; i < count; i++) + { + *dst_map++ = imColorRGB2Luma(*src_map0++, *src_map1++, *src_map2++); + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + case IM_LUV: + case IM_LAB: + max = (T)imColorMax(data_type); + for (i = 0; i < count; i++) + { + // to increase precision do intermediate conversions in float + + float c0 = imColorReconstruct(*src_map0++, max); // scale to 0-1 + c0 = imColorLightness2Luminance(c0); // do the convertion + + // do gamma correction then scale back to 0-max + *dst_map++ = imColorQuantize(imColorTransfer2Nonlinear(c0), max); + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + default: + return IM_ERR_DATA; + } + + return IM_ERR_NONE; +} + +template +int iDoConvert2RGB(int count, int data_type, + const T** src_data, int src_color_space, T** dst_data, int counter) +{ + int i; + T max, zero; + + const T* src_map0 = src_data[0]; + const T* src_map1 = src_data[1]; + const T* src_map2 = src_data[2]; + const T* src_map3 = (src_color_space == IM_CMYK)? src_data[3]: 0; + T* dst_map0 = dst_data[0]; + T* dst_map1 = dst_data[1]; + T* dst_map2 = dst_data[2]; + + imCounterTotal(counter, count, "Converting To RGB..."); + + switch(src_color_space) + { + case IM_XYZ: + max = (T)imColorMax(data_type); + for (i = 0; i < count; i++) + { + // to increase precision do intermediate conversions in float + + // scale to 0-1 + float c0 = imColorReconstruct(*src_map0++, max); + float c1 = imColorReconstruct(*src_map1++, max); + float c2 = imColorReconstruct(*src_map2++, max); + + // result is still 0-1 + imColorXYZ2RGB(c0, c1, c2, + c0, c1, c2, 1.0f); + + // do gamma correction then scale back to 0-max + *dst_map0++ = imColorQuantize(imColorTransfer2Nonlinear(c0), max); + *dst_map1++ = imColorQuantize(imColorTransfer2Nonlinear(c1), max); + *dst_map2++ = imColorQuantize(imColorTransfer2Nonlinear(c2), max); + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + case IM_YCBCR: + max = (T)imColorMax(data_type); + zero = (T)imColorZero(data_type); + for (i = 0; i < count; i++) + { + imColorYCbCr2RGB(*src_map0++, *src_map1++, *src_map2++, + *dst_map0++, *dst_map1++, *dst_map2++, zero, max); + } + break; + case IM_CMYK: + max = (T)imColorMax(data_type); + for (i = 0; i < count; i++) + { + // result is still 0-max + imColorCMYK2RGB(*src_map0++, *src_map1++, *src_map2++, *src_map3++, + *dst_map0++, *dst_map1++, *dst_map2++, max); + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + case IM_LUV: + case IM_LAB: + max = (T)imColorMax(data_type); + for (i = 0; i < count; i++) + { + // to increase precision do intermediate conversions in float + + // scale to 0-1 and -0.5/+0.5 + float c0 = imColorReconstruct(*src_map0++, max); + float c1 = imColorReconstruct(*src_map1++, max) - 0.5f; + float c2 = imColorReconstruct(*src_map2++, max) - 0.5f; + + if (src_color_space == IM_LUV) + imColorLuv2XYZ(c0, c1, c2, // conversion in-place + c0, c1, c2); + else + imColorLab2XYZ(c0, c1, c2, // conversion in-place + c0, c1, c2); + + imColorXYZ2RGB(c0, c1, c2, // conversion in-place + c0, c1, c2, 1.0f); + + // do gamma correction then scale back to 0-max + *dst_map0++ = imColorQuantize(imColorTransfer2Nonlinear(c0), max); + *dst_map1++ = imColorQuantize(imColorTransfer2Nonlinear(c1), max); + *dst_map2++ = imColorQuantize(imColorTransfer2Nonlinear(c2), max); + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + default: + return IM_ERR_DATA; + } + + return IM_ERR_NONE; +} + +template +int iDoConvert2YCbCr(int count, int data_type, + const T** src_data, int src_color_space, T** dst_data, int counter) +{ + int i; + T zero; + + const T* src_map0 = src_data[0]; + const T* src_map1 = src_data[1]; + const T* src_map2 = src_data[2]; + T* dst_map0 = dst_data[0]; + T* dst_map1 = dst_data[1]; + T* dst_map2 = dst_data[2]; + + imCounterTotal(counter, count, "Converting To YCbCr..."); + + switch(src_color_space) + { + case IM_RGB: + zero = (T)imColorZero(data_type); + for (i = 0; i < count; i++) + { + imColorRGB2YCbCr(*src_map0++, *src_map1++, *src_map2++, + *dst_map0++, *dst_map1++, *dst_map2++, zero); + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + default: + return IM_ERR_DATA; + } + + return IM_ERR_NONE; +} + +template +int iDoConvert2XYZ(int count, int data_type, + const T** src_data, int src_color_space, T** dst_data, int counter) +{ + int i; + T max; + + const T* src_map0 = src_data[0]; + const T* src_map1 = (src_color_space == IM_GRAY)? 0: src_data[1]; + const T* src_map2 = (src_color_space == IM_GRAY)? 0: src_data[2]; + T* dst_map0 = dst_data[0]; + T* dst_map1 = dst_data[1]; + T* dst_map2 = dst_data[2]; + + imCounterTotal(counter, count, "Converting To XYZ..."); + + switch(src_color_space) + { + case IM_GRAY: + max = (T)imColorMax(data_type); + for (i = 0; i < count; i++) + { + // scale to 0-1 + float c0 = imColorReconstruct(*src_map0++, max); + + // do gamma correction + c0 = imColorTransfer2Linear(c0); + + // then scale back to 0-max + *dst_map0++ = imColorQuantize(c0*0.9505f, max); // Compensate D65 white point + *dst_map1++ = imColorQuantize(c0, max); + *dst_map2++ = imColorQuantize(c0*1.0890f, max); + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + case IM_RGB: + max = (T)imColorMax(data_type); + for (i = 0; i < count; i++) + { + // to increase precision do intermediate conversions in float + + // scale to 0-1 + float c0 = imColorReconstruct(*src_map0++, max); + float c1 = imColorReconstruct(*src_map1++, max); + float c2 = imColorReconstruct(*src_map2++, max); + + // do gamma correction + c0 = imColorTransfer2Linear(c0); + c1 = imColorTransfer2Linear(c1); + c2 = imColorTransfer2Linear(c2); + + // result is still 0-1 + imColorRGB2XYZ(c0, c1, c2, + c0, c1, c2); + + // then scale back to 0-max + *dst_map0++ = imColorQuantize(c0, max); + *dst_map1++ = imColorQuantize(c1, max); + *dst_map2++ = imColorQuantize(c2, max); + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + case IM_LUV: + case IM_LAB: + max = (T)imColorMax(data_type); + for (i = 0; i < count; i++) + { + // to increase precision do intermediate conversions in float + // scale to 0-1 and -0.5/+0.5 + float c0 = imColorReconstruct(*src_map0++, max); + float c1 = imColorReconstruct(*src_map1++, max) - 0.5f; + float c2 = imColorReconstruct(*src_map2++, max) - 0.5f; + + if (src_color_space == IM_LUV) + imColorLuv2XYZ(c0, c1, c2, // convertion in-place + c0, c1, c2); + else + imColorLab2XYZ(c0, c1, c2, // convertion in-place + c0, c1, c2); + + // scale back to 0-max + *dst_map0++ = imColorQuantize(c0, max); + *dst_map1++ = imColorQuantize(c1, max); + *dst_map2++ = imColorQuantize(c2, max); + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + default: + return IM_ERR_DATA; + } + + return IM_ERR_NONE; +} + +template +int iDoConvert2Lab(int count, int data_type, + const T** src_data, int src_color_space, T** dst_data, int counter) +{ + int i; + T max; + + const T* src_map0 = src_data[0]; + const T* src_map1 = (src_color_space == IM_GRAY)? 0: src_data[1]; + const T* src_map2 = (src_color_space == IM_GRAY)? 0: src_data[2]; + T* dst_map0 = dst_data[0]; + T* dst_map1 = dst_data[1]; + T* dst_map2 = dst_data[2]; + + imCounterTotal(counter, count, "Converting To Lab..."); + + switch(src_color_space) + { + case IM_GRAY: + max = (T)imColorMax(data_type); + for (i = 0; i < count; i++) + { + // scale to 0-1 + float c0 = imColorReconstruct(*src_map0++, max); + + // do gamma correction + c0 = imColorTransfer2Linear(c0); + + // do conversion + c0 = imColorLuminance2Lightness(c0); + + // then scale back to 0-max + *dst_map0++ = imColorQuantize(c0, max); // update only the L component + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + case IM_RGB: + max = (T)imColorMax(data_type); + for (i = 0; i < count; i++) + { + // to increase precision do intermediate conversions in float + + // scale to 0-1 + float c0 = imColorReconstruct(*src_map0++, max); + float c1 = imColorReconstruct(*src_map1++, max); + float c2 = imColorReconstruct(*src_map2++, max); + + // do gamma correction + c0 = imColorTransfer2Linear(c0); + c1 = imColorTransfer2Linear(c1); + c2 = imColorTransfer2Linear(c2); + + imColorRGB2XYZ(c0, c1, c2, // convertion in-place + c0, c1, c2); + + imColorXYZ2Lab(c0, c1, c2, // convertion in-place + c0, c1, c2); + + // then scale back to 0-max + *dst_map0++ = imColorQuantize(c0, max); + *dst_map1++ = imColorQuantize(c1 + 0.5f, max); + *dst_map2++ = imColorQuantize(c2 + 0.5f, max); + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + case IM_XYZ: + max = (T)imColorMax(data_type); + for (i = 0; i < count; i++) + { + // to increase precision do intermediate conversions in float + // scale to 0-1 and -0.5/+0.5 + float c0 = imColorReconstruct(*src_map0++, max); + float c1 = imColorReconstruct(*src_map1++, max); + float c2 = imColorReconstruct(*src_map2++, max); + + imColorXYZ2Lab(c0, c1, c2, // convertion in-place + c0, c1, c2); + + // scale back to 0-max + *dst_map0++ = imColorQuantize(c0, max); + *dst_map1++ = imColorQuantize(c1 + 0.5f, max); + *dst_map2++ = imColorQuantize(c2 + 0.5f, max); + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + case IM_LUV: + max = (T)imColorMax(data_type); + for (i = 0; i < count; i++) + { + // to increase precision do intermediate conversions in float + // scale to 0-1 and -0.5/+0.5 + float c0 = imColorReconstruct(*src_map0++, max); + float c1 = imColorReconstruct(*src_map1++, max) - 0.5f; + float c2 = imColorReconstruct(*src_map2++, max) - 0.5f; + + imColorLuv2XYZ(c0, c1, c2, // convertion in-place + c0, c1, c2); + imColorXYZ2Lab(c0, c1, c2, // convertion in-place + c0, c1, c2); + + // scale back to 0-max + *dst_map0++ = imColorQuantize(c0, max); + *dst_map1++ = imColorQuantize(c1 + 0.5f, max); + *dst_map2++ = imColorQuantize(c2 + 0.5f, max); + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + default: + return IM_ERR_DATA; + } + + return IM_ERR_NONE; +} + +template +int iDoConvert2Luv(int count, int data_type, + const T** src_data, int src_color_space, T** dst_data, int counter) +{ + int i; + T max; + + const T* src_map0 = src_data[0]; + const T* src_map1 = (src_color_space == IM_GRAY)? 0: src_data[1]; + const T* src_map2 = (src_color_space == IM_GRAY)? 0: src_data[2]; + T* dst_map0 = dst_data[0]; + T* dst_map1 = dst_data[1]; + T* dst_map2 = dst_data[2]; + + imCounterTotal(counter, count, "Converting To Luv..."); + + switch(src_color_space) + { + case IM_GRAY: + max = (T)imColorMax(data_type); + for (i = 0; i < count; i++) + { + // scale to 0-1 + float c0 = imColorReconstruct(*src_map0++, max); + + // do gamma correction + c0 = imColorTransfer2Linear(c0); + + // do conversion + c0 = imColorLuminance2Lightness(c0); + + // then scale back to 0-max + *dst_map0++ = imColorQuantize(c0, max); // update only the L component + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + case IM_RGB: + max = (T)imColorMax(data_type); + for (i = 0; i < count; i++) + { + // to increase precision do intermediate conversions in float + + // scale to 0-1 + float c0 = imColorReconstruct(*src_map0++, max); + float c1 = imColorReconstruct(*src_map1++, max); + float c2 = imColorReconstruct(*src_map2++, max); + + // do gamma correction + c0 = imColorTransfer2Linear(c0); + c1 = imColorTransfer2Linear(c1); + c2 = imColorTransfer2Linear(c2); + + imColorRGB2XYZ(c0, c1, c2, // convertion in-place + c0, c1, c2); + + imColorXYZ2Luv(c0, c1, c2, // convertion in-place + c0, c1, c2); + + // then scale back to 0-max + *dst_map0++ = imColorQuantize(c0, max); + *dst_map1++ = imColorQuantize(c1 + 0.5f, max); + *dst_map2++ = imColorQuantize(c2 + 0.5f, max); + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + case IM_XYZ: + max = (T)imColorMax(data_type); + for (i = 0; i < count; i++) + { + // to increase precision do intermediate conversions in float + // scale to 0-1 and -0.5/+0.5 + float c0 = imColorReconstruct(*src_map0++, max); + float c1 = imColorReconstruct(*src_map1++, max); + float c2 = imColorReconstruct(*src_map2++, max); + + imColorXYZ2Luv(c0, c1, c2, // convertion in-place + c0, c1, c2); + + // scale back to 0-max + *dst_map0++ = imColorQuantize(c0, max); + *dst_map1++ = imColorQuantize(c1 + 0.5f, max); + *dst_map2++ = imColorQuantize(c2 + 0.5f, max); + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + case IM_LAB: + max = (T)imColorMax(data_type); + for (i = 0; i < count; i++) + { + // to increase precision do intermediate conversions in float + // scale to 0-1 and -0.5/+0.5 + float c0 = imColorReconstruct(*src_map0++, max); + float c1 = imColorReconstruct(*src_map1++, max) - 0.5f; + float c2 = imColorReconstruct(*src_map2++, max) - 0.5f; + + imColorLab2XYZ(c0, c1, c2, // convertion in-place + c0, c1, c2); + imColorXYZ2Luv(c0, c1, c2, // convertion in-place + c0, c1, c2); + + // scale back to 0-max + *dst_map0++ = imColorQuantize(c0, max); + *dst_map1++ = imColorQuantize(c1 + 0.5f, max); + *dst_map2++ = imColorQuantize(c2 + 0.5f, max); + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + default: + return IM_ERR_DATA; + } + + return IM_ERR_NONE; +} + +template +int iDoConvertColorSpace(int count, int data_type, + const T** src_data, int src_color_space, + T** dst_data, int dst_color_space) +{ + int ret = IM_ERR_DATA, + convert2rgb = 0; + + if ((dst_color_space == IM_XYZ || + dst_color_space == IM_LAB || + dst_color_space == IM_LUV) && + (src_color_space == IM_CMYK || + src_color_space == IM_YCBCR)) + { + convert2rgb = 1; + } + + if (dst_color_space == IM_YCBCR && src_color_space != IM_RGB) + convert2rgb = 1; + + int counter = imCounterBegin("Convert Color Space"); + + if (convert2rgb) + { + ret = iDoConvert2RGB(count, data_type, src_data, src_color_space, dst_data, counter); + + if (ret != IM_ERR_NONE) + { + imCounterEnd(counter); + return ret; + } + + src_data = (const T**)dst_data; + src_color_space = IM_RGB; + } + + switch(dst_color_space) + { + case IM_GRAY: + ret = iDoConvert2Gray(count, data_type, src_data, src_color_space, dst_data, counter); + break; + case IM_RGB: + ret = iDoConvert2RGB(count, data_type, src_data, src_color_space, dst_data, counter); + break; + case IM_YCBCR: + ret = iDoConvert2YCbCr(count, data_type, src_data, src_color_space, dst_data, counter); + break; + case IM_XYZ: + ret = iDoConvert2XYZ(count, data_type, src_data, src_color_space, dst_data, counter); + break; + case IM_LAB: + ret = iDoConvert2Lab(count, data_type, src_data, src_color_space, dst_data, counter); + break; + case IM_LUV: + ret = iDoConvert2Luv(count, data_type, src_data, src_color_space, dst_data, counter); + break; + default: + ret = IM_ERR_DATA; + break; + } + + imCounterEnd(counter); + + return ret; +} + +static int iConvertColorSpace(const imImage* src_image, imImage* dst_image) +{ + switch(src_image->data_type) + { + case IM_BYTE: + return iDoConvertColorSpace(src_image->count, src_image->data_type, + (const imbyte**)src_image->data, src_image->color_space, + (imbyte**)dst_image->data, dst_image->color_space); + case IM_USHORT: + return iDoConvertColorSpace(src_image->count, src_image->data_type, + (const imushort**)src_image->data, src_image->color_space, + (imushort**)dst_image->data, dst_image->color_space); + case IM_INT: + return iDoConvertColorSpace(src_image->count, src_image->data_type, + (const int**)src_image->data, src_image->color_space, + (int**)dst_image->data, dst_image->color_space); + case IM_FLOAT: + return iDoConvertColorSpace(src_image->count, src_image->data_type, + (const float**)src_image->data, src_image->color_space, + (float**)dst_image->data, dst_image->color_space); + case IM_CFLOAT: + /* treat complex as two real values */ + return iDoConvertColorSpace(2*src_image->count, src_image->data_type, + (const float**)src_image->data, src_image->color_space, + (float**)dst_image->data, dst_image->color_space); + } + + return IM_ERR_DATA; +} + +int imConvertColorSpace(const imImage* src_image, imImage* dst_image) +{ + int ret = IM_ERR_NONE; + assert(src_image); + assert(dst_image); + + if (!imImageMatchDataType(src_image, dst_image)) + return IM_ERR_DATA; + + if (src_image->color_space != dst_image->color_space) + { + switch(dst_image->color_space) + { + case IM_RGB: + switch(src_image->color_space) + { + case IM_BINARY: + memcpy(dst_image->data[0], src_image->data[0], dst_image->plane_size); + iConvertBinary((imbyte*)dst_image->data[0], dst_image->count, 255); + memcpy(dst_image->data[1], dst_image->data[0], dst_image->plane_size); + memcpy(dst_image->data[2], dst_image->data[0], dst_image->plane_size); + ret = IM_ERR_NONE; + break; + case IM_MAP: + iConvertMapToRGB((imbyte*)src_image->data[0], (imbyte*)dst_image->data[0], (imbyte*)dst_image->data[1], (imbyte*)dst_image->data[2], dst_image->count, src_image->palette, src_image->palette_count); + ret = IM_ERR_NONE; + break; + case IM_GRAY: + memcpy(dst_image->data[0], src_image->data[0], dst_image->plane_size); + memcpy(dst_image->data[1], src_image->data[0], dst_image->plane_size); + memcpy(dst_image->data[2], src_image->data[0], dst_image->plane_size); + ret = IM_ERR_NONE; + break; + default: + ret = iConvertColorSpace(src_image, dst_image); + break; + } + break; + case IM_GRAY: + switch(src_image->color_space) + { + case IM_BINARY: + memcpy(dst_image->data[0], src_image->data[0], dst_image->size); + iConvertBinary((imbyte*)dst_image->data[0], dst_image->count, 255); + ret = IM_ERR_NONE; + break; + case IM_MAP: + iConvertMap2Gray((imbyte*)src_image->data[0], (imbyte*)dst_image->data[0], dst_image->count, src_image->palette, src_image->palette_count); + ret = IM_ERR_NONE; + break; + case IM_YCBCR: + memcpy(dst_image->data[0], src_image->data[0], dst_image->plane_size); + ret = IM_ERR_NONE; + break; + default: + ret = iConvertColorSpace(src_image, dst_image); + break; + } + break; + case IM_MAP: + switch(src_image->color_space) + { + case IM_BINARY: // no break, same procedure as gray + case IM_GRAY: + memcpy(dst_image->data[0], src_image->data[0], dst_image->size); + dst_image->palette_count = src_image->palette_count; + memcpy(dst_image->palette, src_image->palette, dst_image->palette_count*sizeof(long)); + ret = IM_ERR_NONE; + break; + case IM_RGB: + dst_image->palette_count = 256; + ret = imConvertRGB2Map(src_image->width, src_image->height, + (imbyte*)src_image->data[0], (imbyte*)src_image->data[1], (imbyte*)src_image->data[2], + (imbyte*)dst_image->data[0], dst_image->palette, &dst_image->palette_count); + break; + default: + ret = IM_ERR_DATA; + break; + } + break; + case IM_BINARY: + switch(src_image->color_space) + { + case IM_GRAY: + memcpy(dst_image->data[0], src_image->data[0], dst_image->size); + iConvertBinary((imbyte*)dst_image->data[0], dst_image->count, 1); + ret = IM_ERR_NONE; + break; + case IM_MAP: // convert to gray, then convert to binary + iConvertMap2Gray((imbyte*)src_image->data[0], (imbyte*)dst_image->data[0], dst_image->count, src_image->palette, src_image->palette_count); + iConvertBinary((imbyte*)dst_image->data[0], dst_image->count, 1); + ret = IM_ERR_NONE; + break; + case IM_YCBCR: // convert to gray, then convert to binary + memcpy(dst_image->data[0], src_image->data[0], dst_image->plane_size); + iConvertBinary((imbyte*)dst_image->data[0], dst_image->count, 1); + ret = IM_ERR_NONE; + break; + default: // convert to gray, then convert to binary + dst_image->color_space = IM_GRAY; + ret = iConvertColorSpace(src_image, dst_image); + dst_image->color_space = IM_BINARY; + if (ret == IM_ERR_NONE) + iConvertBinary((imbyte*)dst_image->data[0], dst_image->count, 1); + ret = IM_ERR_NONE; + break; + } + break; + case IM_YCBCR: + switch(src_image->color_space) + { + case IM_GRAY: + memcpy(dst_image->data[0], src_image->data[0], dst_image->plane_size); + ret = IM_ERR_NONE; + break; + default: + ret = iConvertColorSpace(src_image, dst_image); + break; + } + break; + default: + ret = iConvertColorSpace(src_image, dst_image); + break; + } + } + + if (src_image->has_alpha && dst_image->has_alpha) + memcpy(dst_image->data[dst_image->depth], src_image->data[src_image->depth], src_image->plane_size); + else if (dst_image->color_space == IM_RGB && dst_image->data_type == IM_BYTE && dst_image->has_alpha) + { + if (src_image->color_space == IM_RGB) + { + imbyte* transp_color = (imbyte*)imImageGetAttribute(src_image, "TransparencyColor", NULL, NULL); + if (transp_color) + iConvertSetTranspColor((imbyte**)dst_image->data, dst_image->count, *(transp_color+0), *(transp_color+1), *(transp_color+2)); + else + memset(dst_image->data[3], 255, dst_image->count); + } + else + { + int transp_count; + imbyte* transp_index = (imbyte*)imImageGetAttribute(src_image, "TransparencyIndex", NULL, NULL); + imbyte* transp_map = (imbyte*)imImageGetAttribute(src_image, "TransparencyMap", NULL, &transp_count); + if (transp_map) + iConvertSetTranspMap((imbyte*)src_image->data[0], (imbyte*)dst_image->data[3], dst_image->count, transp_map, transp_count); + else if (transp_index) + iConvertSetTranspIndex((imbyte*)src_image->data[0], (imbyte*)dst_image->data[3], dst_image->count, *transp_index); + else + memset(dst_image->data[3], 255, dst_image->count); + } + } + + return ret; +} + diff --git a/im/src/im_converttype.cpp b/im/src/im_converttype.cpp new file mode 100755 index 0000000..ee69b6f --- /dev/null +++ b/im/src/im_converttype.cpp @@ -0,0 +1,555 @@ +/** \file + * \brief Image Data Type Conversion + * + * See Copyright Notice in im_lib.h + * $Id: im_converttype.cpp,v 1.3 2009/09/29 21:30:57 scuri Exp $ + */ + +#include "im.h" +#include "im_util.h" +#include "im_complex.h" +#include "im_image.h" +#include "im_convert.h" +#include "im_color.h" +#include "im_counter.h" + +#include +#include +#include +#include + + +/* IMPORTANT: leave template functions not "static" + because of some weird compiler bizarre errors. + Report on AIX C++. +*/ + +/* if gamma is applied then factor contains two conversions + one for applying gamma, + and other for normal destiny conversion to dst_min-dst_max range. + because gamma(0) = 0 + For EXP: gamma(x) = (e^(g*x))-1 + For LOG: gamma(x) = log((g*x)+1) + because gamma(1) = 1 + gfactor = exp(g)-1 + gfactor = log(g+1) +*/ + +inline float iGammaFactor(float range, float gamma) +{ + if (gamma == 0) + return range; + else if (gamma < 0) + return range/float(log((-gamma) + 1)); + else + return range/float(exp(gamma) - 1); +} + +inline float iGammaFunc(float factor, float min, float gamma, float value) +{ + // Here 0 +inline T iAbs(const T& v) +{ + if (v < 0) + return -1*v; + return v; +} + +template +inline void iDataTypeIntMax(T& max) +{ + int size_of = sizeof(T); + int data_type = (size_of == 1)? IM_BYTE: (size_of == 2)? IM_USHORT: IM_INT; + max = (T)imColorMax(data_type); +} + +template +inline void iMinMaxAbs(int count, const T *map, T& min, T& max, int abssolute) +{ + if (abssolute) + min = iAbs(*map++); + else + min = *map++; + + max = min; + + for (int i = 1; i < count; i++) + { + T value; + + if (abssolute) + value = iAbs(*map++); + else + value = *map++; + + if (value > max) + max = value; + else if (value < min) + min = value; + } + + if (min == max) + { + max = min + 1; + + if (min != 0) + min = min - 1; + } +} + +template +int iCopy(int count, const SRCT *src_map, DSTT *dst_map) +{ + for (int i = 0; i < count; i++) + { + *dst_map++ = (DSTT)(*src_map++); + } + + return IM_ERR_NONE; +} + +template +int iCopyCrop(int count, const SRCT *src_map, DSTT *dst_map, int abssolute) +{ + SRCT value; + DSTT dst_max; + iDataTypeIntMax(dst_max); + + for (int i = 0; i < count; i++) + { + if (abssolute) + value = iAbs(*src_map++); + else + value = *src_map++; + + if (value > dst_max) + value = (SRCT)dst_max; + + if (!(value >= 0)) + value = 0; + + *dst_map++ = (DSTT)(value); + } + + return IM_ERR_NONE; +} + +template +int iPromote2Cpx(int count, const SRCT *src_map, imcfloat *dst_map) +{ + for (int i = 0; i < count; i++) + { + dst_map->real = (float)(*src_map++); + dst_map++; + } + + return IM_ERR_NONE; +} + +template +int iConvertInt2Int(int count, const SRCT *src_map, DSTT *dst_map, int abssolute, int cast_mode, int counter) +{ + SRCT min, max; + + if (cast_mode == IM_CAST_MINMAX) + { + iMinMaxAbs(count, src_map, min, max, abssolute); + + if (min >= 0 && max <= 255) + { + min = 0; + max = 255; + } + } + else + { + min = 0; + iDataTypeIntMax(max); + } + + DSTT dst_max; + iDataTypeIntMax(dst_max); + + float factor = ((float)dst_max + 1.0f) / ((float)max - (float)min + 1.0f); + + for (int i = 0; i < count; i++) + { + SRCT value; + if (abssolute) + value = iAbs(*src_map++); + else + value = *src_map++; + + if (value >= max) + *dst_map++ = dst_max; + else if (value <= min) + *dst_map++ = 0; + else + *dst_map++ = (DSTT)imResample(value - min, factor); + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + + return IM_ERR_NONE; +} + +template +int iPromoteInt2Real(int count, const SRCT *src_map, float *dst_map, float gamma, int abssolute, int cast_mode, int counter) +{ + SRCT min, max; + + if (cast_mode == IM_CAST_MINMAX) + { + iMinMaxAbs(count, src_map, min, max, abssolute); + + if (min >= 0 && max <= 255) + { + min = 0; + max = 255; + } + } + else + { + min = 0; + iDataTypeIntMax(max); + + if (max == 16777215 && !abssolute) /* IM_INT */ + { + min = (SRCT)iIntMin(); + max = (SRCT)iIntMax(); + } + } + + float range = float(max - min + 1); + float dst_min = 0.0f; + float dst_max = 1.0f; + int size_of = sizeof(SRCT); + if (size_of == 4 && !abssolute) + { + dst_min = -0.5f; + dst_max = +0.5f; + } + + gamma = -gamma; // gamma is inverted here, because we are promoting int2real + float factor = iGammaFactor(1.0f, gamma); + + for (int i = 0; i < count; i++) + { + float fvalue; + if (abssolute) + fvalue = (iAbs(*src_map++) - min + 0.5f)/range; + else + fvalue = (*src_map++ - min + 0.5f)/range; + + // Now 0 <= value <= 1 (if min-max are correct) + + if (fvalue >= 1) + *dst_map++ = dst_max; + else if (fvalue <= 0) + *dst_map++ = dst_min; + else + *dst_map++ = iGammaFunc(factor, dst_min, gamma, fvalue); + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + + return IM_ERR_NONE; +} + +template +int iDemoteReal2Int(int count, const float *src_map, DSTT *dst_map, float gamma, int abssolute, int cast_mode, int counter) +{ + float min, max; + + DSTT dst_min = 0, dst_max; + iDataTypeIntMax(dst_max); + if (dst_max == 16777215 && !abssolute) /* IM_INT */ + { + dst_min = (DSTT)iIntMin(); + dst_max = (DSTT)iIntMax(); + } + + if (cast_mode == IM_CAST_MINMAX) + iMinMaxAbs(count, src_map, min, max, abssolute); + else + { + min = 0; + max = 1; + } + + int dst_range = dst_max - dst_min + 1; + float range = max - min; + + float factor = iGammaFactor((float)dst_range, gamma); + + for (int i = 0; i < count; i++) + { + float value; + if (abssolute) + value = ((float)iAbs(*src_map++) - min)/range; + else + value = (*src_map++ - min)/range; + + if (i==3603) + i=i; + + // Now 0 <= value <= 1 (if min-max are correct) + + if (value >= 1) + *dst_map++ = dst_max; + else if (value <= 0) + *dst_map++ = dst_min; + else + { + value = iGammaFunc(factor, (float)dst_min, gamma, value); + int ivalue = imRound(value); + if (ivalue >= dst_max) + *dst_map++ = dst_max; + else if (ivalue <= dst_min) + *dst_map++ = dst_min; + else + *dst_map++ = (DSTT)imRound(value - 0.5f); + } + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + + return IM_ERR_NONE; +} + +int iDemoteCpx2Real(int count, const imcfloat* src_map, float *dst_map, int cpx2real) +{ + float (*CpxCnv)(const imcfloat& cpx) = NULL; + + switch(cpx2real) + { + case IM_CPX_REAL: CpxCnv = cpxreal; break; + case IM_CPX_IMAG: CpxCnv = cpximag; break; + case IM_CPX_MAG: CpxCnv = cpxmag; break; + case IM_CPX_PHASE: CpxCnv = cpxphase; break; + } + + for (int i = 0; i < count; i++) + { + *dst_map++ = CpxCnv(*src_map++); + } + + return IM_ERR_NONE; +} + +template +int iDemoteCpx2Int(int count, const imcfloat* src_map, DSTT *dst_map, int cpx2real, float gamma, int abssolute, int cast_mode, int counter) +{ + float* real_map = (float*)malloc(count*sizeof(float)); + if (!real_map) return IM_ERR_MEM; + + iDemoteCpx2Real(count, src_map, real_map, cpx2real); + + if (iDemoteReal2Int(count, real_map, dst_map, gamma, abssolute, cast_mode, counter) != IM_ERR_NONE) + { + free(real_map); + return IM_ERR_COUNTER; + } + + free(real_map); + return IM_ERR_NONE; +} + +template +int iPromoteInt2Cpx(int count, const SRCT* src_map, imcfloat *dst_map, float gamma, int abssolute, int cast_mode, int counter) +{ + float* real_map = (float*)malloc(count*sizeof(float)); + if (!real_map) return IM_ERR_MEM; + + if (iPromoteInt2Real(count, src_map, real_map, gamma, abssolute, cast_mode, counter) != IM_ERR_NONE) + { + free(real_map); + return IM_ERR_COUNTER; + } + + iPromote2Cpx(count, real_map, dst_map); + + free(real_map); + return IM_ERR_NONE; +} + +int imConvertDataType(const imImage* src_image, imImage* dst_image, int cpx2real, float gamma, int abssolute, int cast_mode) +{ + assert(src_image); + assert(dst_image); + + if (!imImageMatchColorSpace(src_image, dst_image)) + return IM_ERR_DATA; + + if (src_image->data_type == dst_image->data_type) + return IM_ERR_DATA; + + int total_count = src_image->depth * src_image->count; + int ret = IM_ERR_DATA; + int counter = imCounterBegin("Convert Data Type"); + char msg[50]; + sprintf(msg, "Converting to %s...", imDataTypeName(dst_image->data_type)); + imCounterTotal(counter, total_count, msg); + + switch(src_image->data_type) + { + case IM_BYTE: + switch(dst_image->data_type) + { + case IM_USHORT: + if (cast_mode == IM_CAST_DIRECT) + ret = iCopy(total_count, (const imbyte*)src_image->data[0], (imushort*)dst_image->data[0]); + else + ret = iConvertInt2Int(total_count, (const imbyte*)src_image->data[0], (imushort*)dst_image->data[0], abssolute, cast_mode, counter); + break; + case IM_INT: + if (cast_mode == IM_CAST_DIRECT) + ret = iCopy(total_count, (const imbyte*)src_image->data[0], (int*)dst_image->data[0]); + else + ret = iConvertInt2Int(total_count, (const imbyte*)src_image->data[0], (int*)dst_image->data[0], abssolute, cast_mode, counter); + break; + case IM_FLOAT: + if (cast_mode == IM_CAST_DIRECT) + ret = iCopy(total_count, (const imbyte*)src_image->data[0], (float*)dst_image->data[0]); + else + ret = iPromoteInt2Real(total_count, (const imbyte*)src_image->data[0], (float*)dst_image->data[0], gamma, abssolute, cast_mode, counter); + break; + case IM_CFLOAT: + if (cast_mode == IM_CAST_DIRECT) + ret = iPromote2Cpx(total_count, (const imbyte*)src_image->data[0], (imcfloat*)dst_image->data[0]); + else + ret = iPromoteInt2Cpx(total_count, (const imbyte*)src_image->data[0], (imcfloat*)dst_image->data[0], gamma, abssolute, cast_mode, counter); + break; + } + break; + case IM_USHORT: + switch(dst_image->data_type) + { + case IM_BYTE: + if (cast_mode == IM_CAST_DIRECT) + ret = iCopyCrop(total_count, (const imushort*)src_image->data[0], (imbyte*)dst_image->data[0], abssolute); + else + ret = iConvertInt2Int(total_count, (const imushort*)src_image->data[0], (imbyte*)dst_image->data[0], abssolute, cast_mode, counter); + break; + case IM_INT: + if (cast_mode == IM_CAST_DIRECT) + ret = iCopy(total_count, (const imushort*)src_image->data[0], (int*)dst_image->data[0]); + else + ret = iConvertInt2Int(total_count, (const imushort*)src_image->data[0], (int*)dst_image->data[0], abssolute, cast_mode, counter); + break; + case IM_FLOAT: + if (cast_mode == IM_CAST_DIRECT) + ret = iCopy(total_count, (const imushort*)src_image->data[0], (float*)dst_image->data[0]); + else + ret = iPromoteInt2Real(total_count, (const imushort*)src_image->data[0], (float*)dst_image->data[0], gamma, abssolute, cast_mode, counter); + break; + case IM_CFLOAT: + if (cast_mode == IM_CAST_DIRECT) + ret = iPromote2Cpx(total_count, (const imushort*)src_image->data[0], (imcfloat*)dst_image->data[0]); + else + ret = iPromoteInt2Cpx(total_count, (const imushort*)src_image->data[0], (imcfloat*)dst_image->data[0], gamma, abssolute, cast_mode, counter); + break; + } + break; + case IM_INT: + switch(dst_image->data_type) + { + case IM_BYTE: + if (cast_mode == IM_CAST_DIRECT) + ret = iCopyCrop(total_count, (const int*)src_image->data[0], (imbyte*)dst_image->data[0], abssolute); + else + ret = iConvertInt2Int(total_count, (const int*)src_image->data[0], (imbyte*)dst_image->data[0], abssolute, cast_mode, counter); + break; + case IM_USHORT: + if (cast_mode == IM_CAST_DIRECT) + ret = iCopyCrop(total_count, (const int*)src_image->data[0], (imushort*)dst_image->data[0], abssolute); + else + ret = iConvertInt2Int(total_count, (const int*)src_image->data[0], (imushort*)dst_image->data[0], abssolute, cast_mode, counter); + break; + case IM_FLOAT: + if (cast_mode == IM_CAST_DIRECT) + ret = iCopy(total_count, (const int*)src_image->data[0], (float*)dst_image->data[0]); + else + ret = iPromoteInt2Real(total_count, (const int*)src_image->data[0], (float*)dst_image->data[0], gamma, abssolute, cast_mode, counter); + break; + case IM_CFLOAT: + if (cast_mode == IM_CAST_DIRECT) + ret = iPromote2Cpx(total_count, (const int*)src_image->data[0], (imcfloat*)dst_image->data[0]); + else + ret = iPromoteInt2Cpx(total_count, (const int*)src_image->data[0], (imcfloat*)dst_image->data[0], gamma, abssolute, cast_mode, counter); + break; + } + break; + case IM_FLOAT: + switch(dst_image->data_type) + { + case IM_BYTE: + if (cast_mode == IM_CAST_DIRECT) + ret = iCopyCrop(total_count, (const float*)src_image->data[0], (imbyte*)dst_image->data[0], abssolute); + else + ret = iDemoteReal2Int(total_count, (const float*)src_image->data[0], (imbyte*)dst_image->data[0], gamma, abssolute, cast_mode, counter); + break; + case IM_USHORT: + if (cast_mode == IM_CAST_DIRECT) + ret = iCopyCrop(total_count, (const float*)src_image->data[0], (imushort*)dst_image->data[0], abssolute); + else + ret = iDemoteReal2Int(total_count, (const float*)src_image->data[0], (imushort*)dst_image->data[0], gamma, abssolute, cast_mode, counter); + break; + case IM_INT: + if (cast_mode == IM_CAST_DIRECT) + ret = iCopy(total_count, (const float*)src_image->data[0], (int*)dst_image->data[0]); + else + ret = iDemoteReal2Int(total_count, (const float*)src_image->data[0], (int*)dst_image->data[0], gamma, abssolute, cast_mode, counter); + break; + case IM_CFLOAT: + ret = iPromote2Cpx(total_count, (const float*)src_image->data[0], (imcfloat*)dst_image->data[0]); + break; + } + break; + case IM_CFLOAT: + switch(dst_image->data_type) + { + case IM_BYTE: + ret = iDemoteCpx2Int(total_count, (const imcfloat*)src_image->data[0], (imbyte*)dst_image->data[0], cpx2real, gamma, abssolute, cast_mode, counter); + break; + case IM_USHORT: + ret = iDemoteCpx2Int(total_count, (const imcfloat*)src_image->data[0], (imushort*)dst_image->data[0], cpx2real, gamma, abssolute, cast_mode, counter); + break; + case IM_INT: + ret = iDemoteCpx2Int(total_count, (const imcfloat*)src_image->data[0], (int*)dst_image->data[0], cpx2real, gamma, abssolute, cast_mode, counter); + break; + case IM_FLOAT: + ret = iDemoteCpx2Real(total_count, (const imcfloat*)src_image->data[0], (float*)dst_image->data[0], cpx2real); + break; + } + break; + } + + imCounterEnd(counter); + return ret; +} diff --git a/im/src/im_counter.cpp b/im/src/im_counter.cpp new file mode 100755 index 0000000..8c5cd5c --- /dev/null +++ b/im/src/im_counter.cpp @@ -0,0 +1,151 @@ +/** \file + * \brief Processing Counter + * + * See Copyright Notice in im_lib.h + * $Id: im_counter.cpp,v 1.1 2008/10/17 06:10:16 scuri Exp $ + */ + +#include "im_counter.h" + +#include +#include + + +static imCounterCallback iCounterFunc = NULL; +static void* iCounterUserData = NULL; + +imCounterCallback imCounterSetCallback(void* user_data, imCounterCallback counter_func) +{ + imCounterCallback old_counter_func = iCounterFunc; + iCounterFunc = counter_func; + if (user_data) + iCounterUserData = user_data; + return old_counter_func; +} + +struct iCounter +{ + int total; + int current; + int sequence; + const char* message; +}; + +#define MAX_COUNTERS 10 +static iCounter iCounterList[MAX_COUNTERS]; + +int imCounterBegin(const char* title) +{ + static int first = 1; + if (first) + { + memset(iCounterList, 0, MAX_COUNTERS*sizeof(iCounter)); + first = 0; + } + + if (!iCounterFunc) // counter management is useless + return -1; + + int counter = -1; + for (int i = 0; i < MAX_COUNTERS; i++) + { + if (iCounterList[i].sequence == 0 || // the counter is free + iCounterList[i].current == 0) // or we are in a sequence + { + counter = i; + break; + } + } + + if (counter == -1) return -1; // too many counters + + iCounter *ct = &iCounterList[counter]; + + ct->sequence++; + + if (ct->sequence == 1) // top level counter + iCounterFunc(counter, iCounterUserData, title, -1); + + return counter; +} + +void imCounterEnd(int counter) +{ + if (counter == -1 || !iCounterFunc) return; // invalid counter + + iCounter *ct = &iCounterList[counter]; + + if (ct->sequence == 1) // top level counter + { + iCounterFunc(counter, iCounterUserData, NULL, 1001); + memset(ct, 0, sizeof(iCounter)); + } + else + ct->sequence--; +} + +int imCounterInc(int counter) +{ + if (counter == -1 || !iCounterFunc) // invalid counter + return 1; + + iCounter *ct = &iCounterList[counter]; + + if (ct->sequence == 0 || // counter with no begin or no total + ct->total == 0) + return 1; + + const char* msg = NULL; + if (ct->current == 0) + msg = ct->message; + + ct->current++; + + int progress = (int)((ct->current * 1000.0f)/ct->total); + + if (ct->current == ct->total) + ct->current = 0; + + return iCounterFunc(counter, iCounterUserData, msg, progress); +} + +int imCounterIncTo(int counter, int count) +{ + if (counter == -1 || !iCounterFunc) // invalid counter + return 1; + + iCounter *ct = &iCounterList[counter]; + + if (ct->sequence == 0 || // counter with no begin or no total + ct->total == 0) + return 1; + + if (count <= 0) count = 0; + if (count >= ct->total) count = ct->total; + + ct->current = count; + + const char* msg = NULL; + if (ct->current == 0) + msg = ct->message; + + int progress = (int)((ct->current * 1000.0f)/ct->total); + + if (ct->current == ct->total) + ct->current = 0; + + return iCounterFunc(counter, iCounterUserData, msg, progress); +} + +void imCounterTotal(int counter, int total, const char* message) +{ + if (counter == -1 || !iCounterFunc) return; // invalid counter + + iCounter *ct = &iCounterList[counter]; + + if (ct->sequence == 0) return; // counter with no begin + + ct->message = message; + ct->total = total; + ct->current = 0; +} diff --git a/im/src/im_datatype.cpp b/im/src/im_datatype.cpp new file mode 100755 index 0000000..c75483e --- /dev/null +++ b/im/src/im_datatype.cpp @@ -0,0 +1,54 @@ +/** \file + * \brief Data Type Utilities + * + * See Copyright Notice in im_lib.h + * $Id: im_datatype.cpp,v 1.1 2008/10/17 06:10:16 scuri Exp $ + */ + + +#include "im.h" +#include "im_util.h" + +#include + +typedef struct _iTypeInfo +{ + int size; + unsigned long max; + long min; + char* name; +} iTypeInfo; + +static iTypeInfo iTypeInfoTable[] = +{ + {1, 255, 0, "byte"}, + {2, 65535, 0, "ushort"}, + {4, 2147483647, -2147483647-1, "int"}, + {4, 0, 0, "float"}, + {8, 0, 0, "cfloat"} +}; + +const char* imDataTypeName(int data_type) +{ + assert(data_type >= IM_BYTE && data_type <= IM_CFLOAT); + return iTypeInfoTable[data_type].name; +} + +int imDataTypeSize(int data_type) +{ + assert(data_type >= IM_BYTE && data_type <= IM_CFLOAT); + assert(sizeof(int) == 4); + return iTypeInfoTable[data_type].size; +} + +unsigned long imDataTypeIntMax(int data_type) +{ + assert(data_type >= IM_BYTE && data_type <= IM_CFLOAT); + return iTypeInfoTable[data_type].max; +} + +long imDataTypeIntMin(int data_type) +{ + assert(data_type >= IM_BYTE && data_type <= IM_CFLOAT); + return iTypeInfoTable[data_type].min; +} diff --git a/im/src/im_dib.cpp b/im/src/im_dib.cpp new file mode 100755 index 0000000..3dd6780 --- /dev/null +++ b/im/src/im_dib.cpp @@ -0,0 +1,1136 @@ +/** \file + * \brief Windows DIB + * + * See Copyright Notice in im_lib.h + * $Id: im_dib.cpp,v 1.1 2008/10/17 06:10:16 scuri Exp $ + */ + + +#include +#include +#include + +#include "im_dib.h" + +/***************** + Private Funtions +*****************/ + +/* Long returned in getpixel is an array of 4 bytes, not actually a DWORD */ +/* 32 bpp max */ +/* Windows use Little Endian always, this means LSB first: 0xF3F2F1F0 = "F0F1F2F3" */ + +#define iSETDWORD(_vLong, _Line, _Nb) \ + { \ + unsigned char* _pLong = (unsigned char*)&_vLong; \ + int b = _Nb; \ + while(b--) \ + *_pLong++ = *_Line++; \ + } + +#define iGETDWORD(_vLong, _Line, _Nb) \ + { \ + unsigned char* _pLong = (unsigned char*)&_vLong; \ + int b = _Nb; \ + while(b--) \ + *_Line++ = *_pLong++; \ + } + +#define iGETDWORDMASK(_vLong, _vMask, _Line, _Nb) \ + { \ + unsigned char* _pLong = (unsigned char*)&_vLong; \ + unsigned char* _pMask = (unsigned char*)&_vMask; \ + int b = _Nb; \ + while(b--) \ + *_Line++ = *_pLong++ | (~*_pMask++ & *_Line); \ + } + +static unsigned int iMakeBitMask(int bpp) +{ + unsigned int mask = 1; + + while (bpp > 1) + { + mask = (mask << 1) + 1; + bpp--; + } + + return mask; +} + +static unsigned int iLineGetPixel1(unsigned char* line, int col) +{ + return (line[col / 8] >> (7 - col % 8)) & 0x01; /* LSB is filled */ +} + +static void iLineSetPixel1(unsigned char* line, int col, unsigned int pixel) +{ + if (pixel) /* only test 1/0 */ + line[col / 8] |= (0x01 << (7 - (col % 8))); + else + line[col / 8] &= (0xFE << (7 - (col % 8))); +} + +static unsigned int iLineGetPixel4(unsigned char* line, int col) +{ + return (line[col / 2] >> ((1 - col % 2) * 4)) & 0x0F; /* LSB is filled */ +} + +static void iLineSetPixel4(unsigned char* line, int col, unsigned int pixel) +{ + unsigned char mask = (col % 2)? 0xF0: 0x0F; /* LSB is used */ + line[col/2] = (unsigned char)((mask & (((unsigned char)pixel) << ((1 - col % 2) * 4))) | (~mask & line[col/2])); +} + +static unsigned int iLineGetPixel8(unsigned char* line, int col) +{ + return line[col]; /* LSB is filled */ +} + +static void iLineSetPixel8(unsigned char* line, int col, unsigned int pixel) +{ + line[col] = (unsigned char)pixel; /* LSB is used */ +} + +static unsigned int iLineGetPixel16(unsigned char* line, int col) +{ + return ((unsigned short*)line)[col]; /* 0xF1F0 => "F0F10000" */ +} + +static void iLineSetPixel16(unsigned char* line, int col, unsigned int pixel) +{ + ((unsigned short*)line)[col] = (unsigned short)pixel; /* inverse of above */ +} + +static unsigned int iLineGetPixel24(unsigned char* line, int col) +{ + unsigned int pixel = 0; + line += col*3; + iSETDWORD(pixel, line, 3); + return pixel; +} + +static void iLineSetPixel24(unsigned char* line, int col, unsigned int pixel) +{ + line += col*3; + iGETDWORD(pixel, line, 3); +} + +static unsigned int iLineGetPixel32(unsigned char* line, int col) +{ + return ((unsigned int*)line)[col]; /* direct mapping */ +} + +static void iLineSetPixel32(unsigned char* line, int col, unsigned int pixel) +{ + ((unsigned int*)line)[col] = pixel; /* direct mapping */ +} + +static int iGetPixelAnyBpp = 0; +static unsigned int iGetPixelAnyMask = 0; + +static unsigned int iAnyGet(unsigned char* line, int col, int bpp) +{ + int s_byte = (col*bpp) >> 3; + int s_bit = (col*bpp) & 0x7; + unsigned int pixel = 0; + unsigned int mask = (~0) >> (32-bpp); + int n_bytes = (bpp + s_bit + 7) >> 3; + int shift = (n_bytes << 3) - bpp - s_bit; + line += s_byte; + while (n_bytes) + { + pixel |= *line++; + if (--n_bytes > 0) pixel <<= 8; + else break; + } + pixel >>= shift; + return pixel & mask; +} + +static void iAnySet(unsigned char* line, int col, int bpp, unsigned int pixel) +{ + int s_byte = (col*bpp) >> 3; + int s_bit = (col*bpp) & 0x7; + unsigned int mask = (~0) >> (32-bpp); + int n_bytes = (bpp + s_bit + 7) >> 3; + int shift = (n_bytes << 3) - bpp - s_bit; + unsigned char* p_pixel = (unsigned char*) &pixel, *p_mask = (unsigned char*) &mask; + line += s_byte + n_bytes - 1; + pixel <<= shift; + mask <<= shift; + while (n_bytes--) { + *line = (*line & ~(*p_mask)) | (*p_pixel & *p_mask); + p_mask++; p_pixel++; line--; + } +} + +static unsigned int iLineGetPixelAny(unsigned char* line, int col) +{ + return iAnyGet(line, col, iGetPixelAnyBpp); +#if 0 + unsigned int pixel = 0; + int rbits = (col * iGetPixelAnyBpp) % 8; /* calc remaining bits */ + line += (col * iGetPixelAnyBpp) / 8; /* position pointer */ + + /* transfer from pixel line to a DWORD in little endian, so it can be shifted */ + { + int nbytes = (iGetPixelAnyBpp + rbits + 7) / 8; /* bytes used */ + iSETDWORD(pixel, line, nbytes); + } + + /* shift down pixel remaining bits and mask extra non pixel bits */ + return (pixel >> rbits) & iGetPixelAnyMask; +#endif +} + +static int iSetPixelAnyBpp = 0; +static unsigned int iSetPixelAnyMask = 0; + +static void iLineSetPixelAny(unsigned char* line, int col, unsigned int pixel) +{ + iAnySet(line, col, iSetPixelAnyBpp, pixel); +#if 0 + int rbits = (col * iSetPixelAnyBpp) % 8; /* calc remaining bits */ + line += (col * iSetPixelAnyBpp) / 8; /* position pointer */ + + pixel = pixel << rbits; /* position bits */ + + { + unsigned int mask = iSetPixelAnyMask << rbits; /* position mask */ + int nbytes = (iGetPixelAnyBpp + rbits + 7) / 8; /* bytes used */ + iGETDWORDMASK(pixel, mask, line, nbytes); + } +#endif +} + +static long iQuad2Long(RGBQUAD* quad_color) +{ + return (((unsigned long)quad_color->rgbRed) << 16) | + (((unsigned long)quad_color->rgbGreen) << 8) | + (((unsigned long)quad_color->rgbBlue) << 0); +} + +static RGBQUAD iLong2Quad(long long_color) +{ + RGBQUAD quad_color; + + quad_color.rgbRed = (unsigned char)(((long_color) >> 16) & 0xFF); + quad_color.rgbGreen = (unsigned char)(((long_color) >> 8) & 0xFF); + quad_color.rgbBlue = (unsigned char)(((long_color) >> 0) & 0xFF); + + return quad_color; +} + +static int iImageLineSize(int width, int bpp) +{ + return (width * bpp + 7) / 8; /* 1 byte boundary */ +} + +static int iLineSize(int width, int bpp) +{ + return ((width * bpp + 31) / 32) * 4; /* 4 bytes boundary */ +} + +static void iInitHeadersReference(imDib* dib) +{ + dib->bmi = (BITMAPINFO*)dib->dib; + dib->bmih = (BITMAPINFOHEADER*)dib->dib; + dib->bmic = (RGBQUAD*)(dib->dib + sizeof(BITMAPINFOHEADER)); +} + +static void iInitSizes(imDib* dib, int width, int height, int bpp) +{ + dib->line_size = iLineSize(width, bpp); + dib->pad_size = dib->line_size - iImageLineSize(width, bpp); + dib->bits_size = dib->line_size * height; + dib->size = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * dib->palette_count + dib->bits_size; +} + +static void iInitInfoHeader(BITMAPINFOHEADER* bmih, int width, int height, int bpp, int palette_count) +{ + bmih->biSize = sizeof(BITMAPINFOHEADER); + bmih->biWidth = width; + bmih->biHeight = height; + bmih->biPlanes = 1; + bmih->biBitCount = (WORD)bpp; + bmih->biCompression = 0; + bmih->biSizeImage = 0; + bmih->biClrUsed = palette_count; + bmih->biClrImportant = 0; + + { + HDC ScreenDC = GetDC(NULL); + + bmih->biXPelsPerMeter = (unsigned int)(GetDeviceCaps(ScreenDC, LOGPIXELSX) / 0.0254); + bmih->biYPelsPerMeter = (unsigned int)(GetDeviceCaps(ScreenDC, LOGPIXELSY) / 0.0254); + + ReleaseDC(NULL, ScreenDC); + } +} + +static void iInitBits(imDib* dib, BYTE* bits) +{ + if (bits == NULL) + dib->bits = dib->dib + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * dib->palette_count; + else + dib->bits = bits; +} + +static int iGetValidBpp(int bpp) +{ + if (bpp == 1) + bpp = 1; + else if (bpp <= 4) + bpp = 4; + else if (bpp <= 8) + bpp = 8; + else if (bpp <= 16) + bpp = 16; + else if (bpp <= 24) + bpp = 24; + else if (bpp <= 32) + bpp = 32; + else + bpp = 0; + + return bpp; +} + +static int iCheckHeader(BITMAPINFOHEADER *bmih) +{ + if (bmih->biSize != sizeof(BITMAPINFOHEADER)) + return 0; + + if (bmih->biWidth <= 0) + return 0; + + if (bmih->biHeight == 0) + return 0; + + { + int bpp = iGetValidBpp(bmih->biBitCount); + if (!bpp) + return 0; + + if (bmih->biCompression == BI_RLE8 && bpp != 8) + return 0; + + if (bmih->biCompression == BI_RLE4 && bpp != 4) + return 0; + + if (bmih->biCompression == BI_BITFIELDS && (bpp != 16 || bpp != 32)) + return 0; + + if (bmih->biHeight < 0 && (bmih->biCompression == BI_RLE8 || bmih->biCompression == BI_RLE4)) + return 0; + +/* if (bmih->biCompression == BI_JPEG || bmih->biCompression == BI_PNG) + return 0; */ + } + + return 1; +} + +/***************** + Creation +*****************/ + +static void AllocDib(imDib* dib) +{ + dib->dib = NULL; + dib->handle = GlobalAlloc(GMEM_MOVEABLE, dib->size); + if (!dib->handle) return; + dib->dib = (BYTE*)GlobalLock(dib->handle); +} + +imDib* imDibCreate(int width, int height, int bpp) +{ + imDib* dib; + int obpp = bpp; + + bpp = iGetValidBpp(abs(bpp)); + + assert(width > 0 && height > 0); + assert(bpp); + + dib = (imDib*)malloc(sizeof(imDib)); + + if (bpp > 8) + { + if ((bpp == 16 || bpp == 32) && obpp < 0) + dib->palette_count = 3; + else + dib->palette_count = 0; + } + else + dib->palette_count = 1 << bpp; + + iInitSizes(dib, width, height, bpp); + + AllocDib(dib); + if (dib->dib == NULL) + { + free(dib); + return NULL; + } + + iInitHeadersReference(dib); + + iInitInfoHeader(dib->bmih, width, height, bpp, dib->palette_count); + + iInitBits(dib, NULL); + + dib->is_reference = 0; + + return dib; +} + +imDib* imDibCreateSection(HDC hDC, HBITMAP *bitmap, int width, int height, int bpp) +{ + BITMAPINFO* bmi; + BYTE* bits; + int palette_count; + int obpp = bpp; + + bpp = iGetValidBpp(abs(bpp)); + + assert(hDC); + assert(width > 0 && height > 0); + assert(bpp); + + if (bpp > 8) + { + if ((bpp == 16 || bpp == 32) && obpp < 0) + palette_count = 3; + else + palette_count = 0; + } + else + palette_count = 1 << bpp; + + bmi = (BITMAPINFO*)malloc(sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * palette_count); + + iInitInfoHeader(&bmi->bmiHeader, width, height, bpp, palette_count); + + if (bpp > 8 && palette_count == 3) + { + DWORD *masks = (DWORD*)(bmi + sizeof(BITMAPINFOHEADER)); + masks[0] = 0x001F; + masks[1] = 0x03E0; + masks[2] = 0x7C00; + } + + *bitmap = CreateDIBSection(hDC, bmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0); + + { + imDib* dib; + dib = imDibCreateReference((BYTE*)bmi, bits); + dib->is_reference = 0; + return dib; + } +} + + +imDib* imDibCreateCopy(const imDib* src_dib) +{ + imDib* dib; + + assert(src_dib); + + dib = (imDib*)malloc(sizeof(imDib)); + + memcpy(dib, src_dib, sizeof(imDib)); + + AllocDib(dib); + if (dib->dib == NULL) + { + free(dib); + return NULL; + } + + iInitHeadersReference(dib); + + memcpy(dib->dib, src_dib->dib, dib->size - dib->bits_size); + + iInitBits(dib, NULL); + + memcpy(dib->bits, src_dib->bits, dib->bits_size); + + dib->is_reference = 0; + + return dib; +} + +imDib* imDibCreateReference(BYTE* bmi, BYTE* bits) +{ + imDib* dib; + + assert(bmi); + + dib = (imDib*)malloc(sizeof(imDib)); + + dib->dib = bmi; + + iInitHeadersReference(dib); + + if (dib->bmih->biBitCount > 8) + { + dib->palette_count = 0; + + if (dib->bmih->biCompression == BI_BITFIELDS) + dib->palette_count = 3; + } + else + { + if (dib->bmih->biClrUsed != 0) + dib->palette_count = dib->bmih->biClrUsed; + else + dib->palette_count = 1 << dib->bmih->biBitCount; + } + + iInitBits(dib, bits); + + dib->is_reference = 1; + + iInitSizes(dib, dib->bmih->biWidth, abs(dib->bmih->biHeight), dib->bmih->biBitCount); + + return dib; +} + +void imDibDestroy(imDib* dib) +{ + assert(dib); + if (!dib->is_reference) + { + GlobalUnlock(dib->handle); + GlobalFree(dib->handle); + } + free(dib); +} + +/***************** + Line Acess +*****************/ + +imDibLineGetPixel imDibLineGetPixelFunc(int bpp) +{ + switch(bpp) + { + case 1: + return &iLineGetPixel1; + case 4: + return &iLineGetPixel4; + case 8: + return &iLineGetPixel8; + case 16: + return &iLineGetPixel16; + case 24: + return &iLineGetPixel24; + case 32: + return &iLineGetPixel32; + default: + if (bpp > 32) return NULL; + iGetPixelAnyBpp = bpp; + iGetPixelAnyMask = iMakeBitMask(bpp); + return &iLineGetPixelAny; + } +} + +imDibLineSetPixel imDibLineSetPixelFunc(int bpp) +{ + switch(bpp) + { + case 1: + return &iLineSetPixel1; + case 4: + return &iLineSetPixel4; + case 8: + return &iLineSetPixel8; + case 16: + return &iLineSetPixel16; + case 24: + return &iLineSetPixel24; + case 32: + return &iLineSetPixel32; + default: + if (bpp > 32) return NULL; + iSetPixelAnyBpp = bpp; + iSetPixelAnyMask = iMakeBitMask(bpp); + return &iLineSetPixelAny; + } +} + +/***************** + DIB <-> Bitmap +*****************/ + +imDib* imDibFromHBitmap(const HBITMAP bitmap, const HPALETTE hPalette) +{ + imDib* dib; + + assert(bitmap); + + { + BITMAP bmp; + + if (!GetObject(bitmap, sizeof(BITMAP), (LPSTR)&bmp)) + return NULL; + + dib = imDibCreate(bmp.bmWidth, bmp.bmHeight, bmp.bmPlanes * bmp.bmBitsPixel); + } + + if (!dib) + return NULL; + + { + HDC ScreenDC = GetDC(NULL); + HPALETTE hOldPalette = NULL; + if (hPalette) hOldPalette = SelectPalette(ScreenDC, hPalette, FALSE); + RealizePalette(ScreenDC); + + GetDIBits(ScreenDC, bitmap, 0, dib->bmih->biHeight, dib->bits, dib->bmi, DIB_RGB_COLORS); + + if (hOldPalette) SelectPalette(ScreenDC, hOldPalette, FALSE); + ReleaseDC(NULL, ScreenDC); + } + + return dib; +} + +HBITMAP imDibToHBitmap(const imDib* dib) +{ + HBITMAP bitmap; + + assert(dib); + + { + HDC ScreenDC = GetDC(NULL); + bitmap = CreateDIBitmap(ScreenDC, dib->bmih, CBM_INIT, dib->bits, dib->bmi, DIB_RGB_COLORS); + ReleaseDC(NULL, ScreenDC); + } + +/* + Another Way + bitmap = CreateCompatibleBitmap(ScreenDC, dib->bmih->biWidth, dib->bmih->biHeight); + SetDIBits(ScreenDC, bitmap, 0, dib->bmih->biHeight, dib->bits, dib->bmi, DIB_RGB_COLORS); +*/ + + return bitmap; +} + +/******************* + DIB <-> Clipboard +*******************/ + +int imDibIsClipboardAvailable(void) +{ + if (IsClipboardFormatAvailable(CF_DIB) || + IsClipboardFormatAvailable(CF_BITMAP)) + return 1; + + return 0; +} + +imDib* imDibPasteClipboard(void) +{ + int clip_type = 0; + if (IsClipboardFormatAvailable(CF_DIB)) + clip_type = CF_DIB; + else if (IsClipboardFormatAvailable(CF_BITMAP)) + clip_type = CF_BITMAP; + + if (!clip_type) + return NULL; + + OpenClipboard(NULL); + HANDLE Handle = GetClipboardData(clip_type); + if (Handle == NULL) + { + CloseClipboard(); + return NULL; + } + + imDib *dib; + if (clip_type == CF_DIB) + { + BYTE* bmi = (BYTE*)GlobalLock(Handle); + if (!bmi || !iCheckHeader((BITMAPINFOHEADER*)bmi)) + { + CloseClipboard(); + return NULL; + } + + { + imDib* clip_dib = imDibCreateReference(bmi, NULL); + dib = imDibCreateCopy(clip_dib); + imDibDestroy(clip_dib); + GlobalUnlock(Handle); + } + } + else + { + HPALETTE hpal = (HPALETTE)GetClipboardData(CF_PALETTE); + + /* If there is a CF_PALETTE object in the clipboard, this is the palette to assume */ + /* the bitmap is realized against. */ + if (!hpal) + hpal = (HPALETTE)GetStockObject(DEFAULT_PALETTE); + + dib = imDibFromHBitmap((HBITMAP)Handle, hpal); + } + + CloseClipboard(); + + return dib; +} + +void imDibCopyClipboard(imDib* dib) +{ + assert(dib); + + if (!OpenClipboard(NULL)) + return; + EmptyClipboard(); + GlobalUnlock(dib->handle); + SetClipboardData(CF_DIB, dib->handle); + CloseClipboard(); + + dib->dib = NULL; + dib->is_reference = 1; + imDibDestroy(dib); +} + +/******************* + DIB -> Palette +*******************/ + +HPALETTE imDibLogicalPalette(const imDib* dib) +{ + LOGPALETTE* pLogPal; + PALETTEENTRY* pPalEntry; + HPALETTE hPal; + RGBQUAD* bmic; + int c; + + assert(dib); + assert(dib->bmih->biBitCount <= 8); + + pLogPal = (LOGPALETTE*)malloc(sizeof(LOGPALETTE) + dib->palette_count * sizeof(PALETTEENTRY)); + pLogPal->palVersion = 0x300; + pLogPal->palNumEntries = (WORD)dib->palette_count; + + bmic = dib->bmic; + pPalEntry = pLogPal->palPalEntry; + + for (c = 0; c < dib->palette_count; c++) + { + pPalEntry->peRed = bmic->rgbRed; + pPalEntry->peGreen = bmic->rgbGreen; + pPalEntry->peBlue = bmic->rgbBlue; + pPalEntry->peFlags = PC_NOCOLLAPSE; + + pPalEntry++; + bmic++; + } + + hPal = CreatePalette(pLogPal); + free(pLogPal); + + return hPal; +} + +/******************* + DIB <-> RGB Image +*******************/ + +void imDibEncodeFromRGBA(imDib* dib, const unsigned char* red, const unsigned char* green, const unsigned char* blue, const unsigned char* alpha) +{ + int x, y; + BYTE* bits; + + if (dib->bmih->biHeight < 0) + bits = dib->bits + (dib->bits_size - dib->line_size); /* start of last line */ + else + bits = dib->bits; + + assert(dib->bmih->biBitCount > 16); + + for (y = 0; y < abs(dib->bmih->biHeight); y++) + { + for (x = 0; x < dib->bmih->biWidth; x++) + { + *bits++ = *blue++; + *bits++ = *green++; + *bits++ = *red++; + + if (dib->bmih->biBitCount == 32) + { + if (alpha) + *bits++ = *alpha++; + else + *bits++ = 0xFF; /* opaque */ + } + } + + bits += dib->pad_size; + + if (dib->bmih->biHeight < 0) + bits -= 2*dib->line_size; + } +} + +void imDibDecodeToRGBA(const imDib* dib, unsigned char* red, unsigned char* green, unsigned char* blue, unsigned char* alpha) +{ + int x, y, offset; + unsigned short color; + BYTE* bits; + unsigned int rmask = 0, gmask = 0, bmask = 0, + roff = 0, goff = 0, boff = 0; /* pixel bit mask control when reading 16 and 32 bpp images */ + + assert(dib); + assert(dib->bmih->biBitCount > 8); + assert(red && green && blue); + + if (dib->bmih->biHeight < 0) + bits = dib->bits + (dib->bits_size - dib->line_size); /* start of last line */ + else + bits = dib->bits; + + if (dib->bmih->biBitCount == 16) + offset = dib->line_size; /* do not increment for each pixel, jump line */ + else + offset = dib->pad_size; /* increment for each pixel, jump pad */ + + if (dib->bmih->biCompression == BI_BITFIELDS) + { + unsigned int Mask; + unsigned int* palette = (unsigned int*)dib->bmic; + + rmask = Mask = palette[0]; + while (!(Mask & 0x01)) + {Mask >>= 1; roff++;} + + gmask = Mask = palette[1]; + while (!(Mask & 0x01)) + {Mask >>= 1; goff++;} + + bmask = Mask = palette[2]; + while (!(Mask & 0x01)) + {Mask >>= 1; boff++;} + } + else if (dib->bmih->biBitCount == 16) + { + bmask = 0x001F; + gmask = 0x03E0; + rmask = 0x7C00; + boff = 0; + goff = 5; + roff = 10; + } + + for (y = 0; y < abs(dib->bmih->biHeight); y++) + { + for (x = 0; x < dib->bmih->biWidth; x++) + { + if (dib->bmih->biBitCount == 16) + { + color = ((unsigned short*)bits)[x]; + *red++ = (unsigned char)((((rmask & color) >> roff) * 255) / (rmask >> roff)); + *green++ = (unsigned char)((((gmask & color) >> goff) * 255) / (gmask >> goff)); + *blue++ = (unsigned char)((((bmask & color) >> boff) * 255) / (bmask >> boff)); + } + else + { + *blue++ = *bits++; + *green++ = *bits++; + *red++ = *bits++; + + if (dib->bmih->biBitCount == 32) + { + if (alpha) + *alpha++ = *bits++; + else + bits++; + } + } + } + + bits += offset; + + if (dib->bmih->biHeight < 0) + bits -= 2*dib->line_size; + } +} + +/******************* + DIB <-> Map Image +*******************/ + +void imDibEncodeFromMap(imDib* dib, const unsigned char* map, const long* palette, int palette_count) +{ + assert(dib); + assert(map && palette); + assert(dib->bmih->biBitCount <= 8); + assert(dib->bmih->biCompression != BI_RLE8); + + { + int x, y; + BYTE* bits; + + if (dib->bmih->biHeight < 0) + bits = dib->bits + (dib->bits_size - dib->line_size); /* start of last line */ + else + bits = dib->bits; + + for (y = 0; y < abs(dib->bmih->biHeight); y++) + { + for (x = 0; x < dib->bmih->biWidth; x++) + bits[x] = *map++; + + if (dib->bmih->biHeight < 0) + bits -= dib->line_size; + else + bits += dib->line_size; + } + } + + { + int c; + RGBQUAD* bmic = dib->bmic; + + for (c = 0; c < palette_count; c++) + *bmic++ = iLong2Quad(palette[c]); + } + + dib->bmih->biClrUsed = palette_count; + dib->bmih->biClrImportant = 0; + dib->palette_count = palette_count; +} + +void imDibDecodeToMap(const imDib* dib, unsigned char* map, long* palette) +{ + assert(dib); + assert(dib->bmih->biBitCount <= 8); + assert(map && palette); + + { + int x, y; + BYTE* bits; + + if (dib->bmih->biHeight < 0) + bits = dib->bits + (dib->bits_size - dib->line_size); /* start of last line */ + else + bits = dib->bits; + + for (y = 0; y < abs(dib->bmih->biHeight); y++) + { + for (x = 0; x < dib->bmih->biWidth; x++) + { + switch (dib->bmih->biBitCount) + { + case 1: + *map++ = (unsigned char)((bits[x / 8] >> (7 - x % 8)) & 0x01); + break; + case 4: + *map++ = (unsigned char)((bits[x / 2] >> ((1 - x % 2) * 4)) & 0x0F); + break; + case 8: + *map++ = bits[x]; + break; + } + } + + if (dib->bmih->biHeight < 0) + bits -= dib->line_size; + else + bits += dib->line_size; + } + } + + { + int c; + RGBQUAD* bmic = dib->bmic; + + for (c = 0; c < dib->palette_count; c++) + { + palette[c] = iQuad2Long(bmic); + *bmic++; + } + } +} + +/******************* + DIB <-> File +*******************/ + +int imDibSaveFile(const imDib* dib, char* filename) +{ + DWORD dwTmp; + HANDLE hFile; /* file handle */ + BITMAPFILEHEADER file_header; /* bitmap file-header */ + + assert(dib); + assert(filename); + + hFile = CreateFile(filename, GENERIC_WRITE, (DWORD) 0, + (LPSECURITY_ATTRIBUTES)NULL, + CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, (HANDLE) NULL); + + if (hFile == INVALID_HANDLE_VALUE) + return 0; + + /* 0x42 = "B" 0x4d = "M" */ + file_header.bfType = 0x4d42; + + /* Compute the size of the entire file. */ + file_header.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dib->palette_count*sizeof(RGBQUAD) + dib->bits_size); + + file_header.bfReserved1 = 0; + file_header.bfReserved2 = 0; + + /* Compute the offset to the bits array. */ + file_header.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dib->palette_count*sizeof(RGBQUAD); + + /* Copy the BITMAPFILEHEADER into the .BMP file. */ + if (!WriteFile(hFile, (LPVOID)&file_header, sizeof(BITMAPFILEHEADER), (LPDWORD)&dwTmp, (LPOVERLAPPED)NULL)) + goto save_error; + + /* Copy the BITMAPINFOHEADER into the file. */ + if (!WriteFile(hFile, (LPVOID)dib->bmih, sizeof(BITMAPINFOHEADER), (LPDWORD)&dwTmp, (LPOVERLAPPED)NULL)) + goto save_error; + + /* Copy the RGBQUAD array into the file. */ + if (dib->palette_count > 0) + { + if (!WriteFile(hFile, (LPVOID)dib->bmic, dib->palette_count*sizeof(RGBQUAD), (LPDWORD)&dwTmp, (LPOVERLAPPED)NULL)) + goto save_error; + } + + /* Copy the bits array into the .BMP file. */ + if (!WriteFile(hFile, dib->bits, dib->bits_size, (LPDWORD)&dwTmp, (LPOVERLAPPED)NULL)) + goto save_error; + + /* Close the .BMP file. */ + CloseHandle(hFile); + + return 1; + +save_error: + CloseHandle(hFile); + return 0; +} + +imDib* imDibLoadFile(const char* filename) +{ + HANDLE hFile; /* file handle */ + DWORD dwTmp; + imDib* dib = NULL; + BITMAPFILEHEADER file_header; /* bitmap file-header */ + BITMAPINFOHEADER bmih; + + assert(filename); + + hFile = CreateFile(filename, GENERIC_READ, (DWORD) 0, + (LPSECURITY_ATTRIBUTES)NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, (HANDLE) NULL); + + if (hFile == INVALID_HANDLE_VALUE) + return NULL; + + /* Read the BITMAPFILEHEADER from the .BMP file. */ + if (!ReadFile(hFile, (LPVOID)&file_header, sizeof(BITMAPFILEHEADER), (LPDWORD)&dwTmp, (LPOVERLAPPED)NULL)) + goto load_error; + + if (file_header.bfType != 0x4d42) + goto load_error; + + /* Read the BITMAPINFOHEADER from the file. */ + if (!ReadFile(hFile, (LPVOID)&bmih, sizeof(BITMAPINFOHEADER), (LPDWORD)&dwTmp, (LPOVERLAPPED)NULL)) + goto load_error; + + if(!iCheckHeader(&bmih)) + goto load_error; + + dib = imDibCreate(bmih.biWidth, abs(bmih.biHeight), bmih.biCompression==BI_BITFIELDS? -bmih.biBitCount: bmih.biBitCount); + + memcpy(dib->bmih, &bmih, bmih.biSize); + + if (bmih.biSize != sizeof(BITMAPINFOHEADER)) + { + /* skip newer BIH definitions */ + SetFilePointer(hFile, bmih.biSize - sizeof(BITMAPINFOHEADER), NULL, FILE_CURRENT); + dib->bmih->biSize = sizeof(BITMAPINFOHEADER); + } + + /* Read the RGBQUAD array from the file. */ + if (dib->palette_count > 0) + { + if (!ReadFile(hFile, (LPVOID)dib->bmic, dib->palette_count*sizeof(RGBQUAD), (LPDWORD)&dwTmp, (LPOVERLAPPED)NULL)) + goto load_error; + } + + /* Read the Bits array from the .BMP file. */ + SetFilePointer(hFile, file_header.bfOffBits, NULL, FILE_BEGIN); + + { + int bits_size = dib->bits_size; + + if (bmih.biBitCount < 16 && bmih.biCompression != BI_RGB) + bits_size = GetFileSize(hFile, NULL) - file_header.bfOffBits; + + if (bits_size > dib->bits_size) + goto load_error; + + if (!ReadFile(hFile, dib->bits, bits_size, (LPDWORD)&dwTmp, (LPOVERLAPPED)NULL)) + goto load_error; + } + + /* Close the .BMP file. */ + CloseHandle(hFile); + + return dib; + +load_error: + if (dib) imDibDestroy(dib); + CloseHandle(hFile); + return NULL; +} + +/******************* + Screen -> DIB +*******************/ + +imDib* imDibCaptureScreen(int x, int y, int width, int height) +{ + HBITMAP bitmap; + HDC ScreenDC = GetDC(NULL); + HDC hdcCompatible = CreateCompatibleDC(ScreenDC); + + if (width == 0) width = GetDeviceCaps(ScreenDC, HORZRES); + if (height == 0) height = GetDeviceCaps(ScreenDC, VERTRES); + + bitmap = CreateCompatibleBitmap(ScreenDC, width, height); + + if (!bitmap) + { + ReleaseDC(NULL, ScreenDC); + return NULL; + } + + /* Select the bitmaps into the compatible DC. */ + SelectObject(hdcCompatible, bitmap); + + /* Copy color data for the entire display into a */ + /* bitmap that is selected into a compatible DC. */ + BitBlt(hdcCompatible, 0, 0, width, height, ScreenDC, x, y, SRCCOPY); + + ReleaseDC(NULL, ScreenDC); + DeleteDC(hdcCompatible); + + { + imDib* dib = imDibFromHBitmap(bitmap, NULL); + DeleteObject(bitmap); + return dib; + } +} diff --git a/im/src/im_dibxbitmap.cpp b/im/src/im_dibxbitmap.cpp new file mode 100755 index 0000000..8fabd4a --- /dev/null +++ b/im/src/im_dibxbitmap.cpp @@ -0,0 +1,181 @@ +/** \file + * \brief Conversion between imDib and imImage + * + * See Copyright Notice in im_lib.h + * $Id: im_dibxbitmap.cpp,v 1.1 2008/10/17 06:10:16 scuri Exp $ + */ + + +#include +#include + +#include "im.h" +#include "im_image.h" +#include "im_dib.h" +#include "im_util.h" + + +void imDibEncodeFromBitmap(imDib* dib, const unsigned char* data) +{ + int x, y; + BYTE* bits; + + assert(dib); + assert(dib->bmih->biBitCount > 16); + assert(data); + + if (dib->bmih->biHeight < 0) + bits = dib->bits + (dib->bits_size - dib->line_size); /* start of last line */ + else + bits = dib->bits; + + for (y = 0; y < abs(dib->bmih->biHeight); y++) + { + for (x = 0; x < dib->bmih->biWidth; x++) + { + *bits++ = *(data+2); // R + *bits++ = *(data+1); // G + *bits++ = *(data+0); // B + + data += 3; + + if (dib->bmih->biBitCount == 32) + *bits++ = *data++; + } + + bits += dib->pad_size; + + if (dib->bmih->biHeight < 0) + bits -= 2*dib->line_size; + } +} + +void imDibDecodeToBitmap(const imDib* dib, unsigned char* data) +{ + int x, y, offset; + unsigned short color; + BYTE* bits; + unsigned int rmask = 0, gmask = 0, bmask = 0, + roff = 0, goff = 0, boff = 0; /* pixel bit mask control when reading 16 and 32 bpp images */ + + assert(dib); + assert(dib->bmih->biBitCount > 8); + assert(data); + + if (dib->bmih->biHeight < 0) + bits = dib->bits + (dib->bits_size - dib->line_size); /* start of last line */ + else + bits = dib->bits; + + if (dib->bmih->biBitCount == 16) + offset = dib->line_size; /* do not increment for each pixel, jump line */ + else + offset = dib->pad_size; /* increment for each pixel, jump pad */ + + if (dib->bmih->biCompression == BI_BITFIELDS) + { + unsigned int Mask; + unsigned int* palette = (unsigned int*)dib->bmic; + + rmask = Mask = palette[0]; + while (!(Mask & 0x01)) + {Mask >>= 1; roff++;} + + gmask = Mask = palette[1]; + while (!(Mask & 0x01)) + {Mask >>= 1; goff++;} + + bmask = Mask = palette[2]; + while (!(Mask & 0x01)) + {Mask >>= 1; boff++;} + } + else if (dib->bmih->biBitCount == 16) + { + bmask = 0x001F; + gmask = 0x03E0; + rmask = 0x7C00; + boff = 0; + goff = 5; + roff = 10; + } + + for (y = 0; y < abs(dib->bmih->biHeight); y++) + { + for (x = 0; x < dib->bmih->biWidth; x++) + { + if (dib->bmih->biBitCount == 16) + { + color = ((unsigned short*)bits)[x]; + *data++ = (unsigned char)((((rmask & color) >> roff) * 255) / (rmask >> roff)); + *data++ = (unsigned char)((((gmask & color) >> goff) * 255) / (gmask >> goff)); + *data++ = (unsigned char)((((bmask & color) >> boff) * 255) / (bmask >> boff)); + } + else + { + *(data+2) = *bits++; // B + *(data+1) = *bits++; // G + *(data+0) = *bits++; // R + + data += 3; + + if (dib->bmih->biBitCount == 32) + *data++ = *bits++; + } + } + + bits += offset; + + if (dib->bmih->biHeight < 0) + bits -= 2*dib->line_size; + } +} + +imImage* imDibToImage(const imDib* dib) +{ + assert(dib); + + int color_space = IM_RGB; + if (dib->bmih->biBitCount <= 8) + color_space = IM_MAP; + + imImage* image = imImageCreate(dib->bmih->biWidth, abs(dib->bmih->biHeight), color_space, IM_BYTE); + if (!image) + return NULL; + + if (image->color_space == IM_MAP) + { + image->palette_count = dib->palette_count; + imDibDecodeToMap(dib, (imbyte*)image->data[0], image->palette); + } + else + { + imDibDecodeToRGBA(dib, (imbyte*)image->data[0], (imbyte*)image->data[1], (imbyte*)image->data[2], NULL); + } + + return image; +} + +imDib* imDibFromImage(const imImage* image) +{ + assert(image); + assert(imImageIsBitmap(image)); + + if (!imImageIsBitmap(image)) + return NULL; + + int bpp; + if (image->color_space != IM_RGB) + bpp = 8; + else + bpp = 24; + + imDib* dib = imDibCreate(image->width, image->height, bpp); + if (!dib) return NULL; + + if (image->color_space != IM_RGB) + imDibEncodeFromMap(dib, (const imbyte*)image->data[0], image->palette, image->palette_count); + else + imDibEncodeFromRGBA(dib, (const imbyte*)image->data[0], (const imbyte*)image->data[1], (const imbyte*)image->data[2], NULL); + + return dib; +} diff --git a/im/src/im_ecw.def b/im/src/im_ecw.def new file mode 100755 index 0000000..a0c8858 --- /dev/null +++ b/im/src/im_ecw.def @@ -0,0 +1,2 @@ +EXPORTS + imFormatRegisterECW \ No newline at end of file diff --git a/im/src/im_ecw.mak b/im/src/im_ecw.mak new file mode 100755 index 0000000..0894425 --- /dev/null +++ b/im/src/im_ecw.mak @@ -0,0 +1,16 @@ +PROJNAME = im +LIBNAME = im_ecw +OPT = YES + +SRC = im_format_ecw.cpp + +ECWSDKINC = d:/lng/ecw_sdk/include +ECWSDKLIB = d:/lng/ecw_sdk/lib/$(TEC_UNAME) + +INCLUDES = ../include $(ECWSDKINC) + +LDIR = $(ECWSDKLIB) +LIBS = NCSEcw + +IM = .. +USE_IM = Yes diff --git a/im/src/im_file.cpp b/im/src/im_file.cpp new file mode 100755 index 0000000..3bfa779 --- /dev/null +++ b/im/src/im_file.cpp @@ -0,0 +1,465 @@ +/** \file + * \brief File Access + * + * See Copyright Notice in im_lib.h + * $Id: im_file.cpp,v 1.5 2009/08/23 23:57:51 scuri Exp $ + */ + +#include +#include +#include + +#include "im.h" +#include "im_format.h" +#include "im_util.h" +#include "im_attrib.h" +#include "im_counter.h" +#include "im_plus.h" // make shure that this file is compiled + + +void imFileClear(imFile* ifile) +{ + // can not reset compression and image_count + + ifile->is_new = 0; + ifile->attrib_table = 0; + + ifile->line_buffer = 0; + ifile->line_buffer_size = 0; + ifile->line_buffer_extra = 0; + ifile->line_buffer_alloc = 0; + + ifile->convert_bpp = 0; + ifile->switch_type = 0; + + ifile->width = 0; + ifile->height = 0; + ifile->image_index = -1; + ifile->user_data_type = 0; + ifile->user_color_mode = 0; + ifile->file_data_type = 0; + ifile->file_color_mode = 0; + + ifile->palette_count = 256; + for (int i = 0; i < 256; i++) + ifile->palette[i] = imColorEncode((imbyte)i, (imbyte)i, (imbyte)i); +} + +void imFileSetBaseAttributes(imFile* ifile) +{ + imFileFormatBase* ifileformat = (imFileFormatBase*)ifile; + imAttribTable* atable = (imAttribTable*)ifileformat->attrib_table; + + atable->Set("FileFormat", IM_BYTE, -1, ifileformat->iformat->format); + atable->Set("FileCompression", IM_BYTE, -1, ifileformat->compression); + atable->Set("FileImageCount", IM_INT, 1, &ifileformat->image_count); +} + +imFile* imFileOpen(const char* file_name, int *error) +{ + assert(file_name); + + imFileFormatBase* ifileformat = imFileFormatBaseOpen(file_name, error); + if (!ifileformat) + return NULL; + + imFileClear(ifileformat); + + ifileformat->attrib_table = new imAttribTable(599); + imFileSetBaseAttributes(ifileformat); + + ifileformat->counter = imCounterBegin(file_name); + + return ifileformat; +} + +imFile* imFileOpenAs(const char* file_name, const char* format, int *error) +{ + assert(file_name); + + imFileFormatBase* ifileformat = imFileFormatBaseOpenAs(file_name, format, error); + if (!ifileformat) + return NULL; + + imFileClear(ifileformat); + + ifileformat->attrib_table = new imAttribTable(599); + imFileSetBaseAttributes(ifileformat); + + ifileformat->counter = imCounterBegin(file_name); + + return ifileformat; +} + +imFile* imFileNew(const char* file_name, const char* format, int *error) +{ + assert(file_name); + + imFileFormatBase* ifileformat = imFileFormatBaseNew(file_name, format, error); + if (!ifileformat) + return NULL; + + imFileClear(ifileformat); + + ifileformat->is_new = 1; + ifileformat->image_count = 0; + ifileformat->compression[0] = 0; + + ifileformat->attrib_table = new imAttribTable(101); + + ifileformat->counter = imCounterBegin(file_name); + + return ifileformat; +} + +void imFileClose(imFile* ifile) +{ + assert(ifile); + imFileFormatBase* ifileformat = (imFileFormatBase*)ifile; + imAttribTable* attrib_table = (imAttribTable*)ifile->attrib_table; + + imCounterEnd(ifile->counter); + + ifileformat->Close(); + + if (ifile->line_buffer) free(ifile->line_buffer); + + delete attrib_table; +} + +void* imFileHandle(imFile* ifile, int index) +{ + assert(ifile); + imFileFormatBase* ifileformat = (imFileFormatBase*)ifile; + return ifileformat->Handle(index); +} + +void imFileSetAttribute(imFile* ifile, const char* attrib, int data_type, int count, const void* data) +{ + assert(ifile); + assert(attrib); + imFileFormatBase* ifileformat = (imFileFormatBase*)ifile; + imAttribTable* atable = (imAttribTable*)ifileformat->attrib_table; + if (data) + atable->Set(attrib, data_type, count, data); + else + atable->UnSet(attrib); +} + +const void* imFileGetAttribute(imFile* ifile, const char* attrib, int *data_type, int *count) +{ + assert(ifile); + assert(attrib); + imFileFormatBase* ifileformat = (imFileFormatBase*)ifile; + imAttribTable* attrib_table = (imAttribTable*)ifileformat->attrib_table; + return attrib_table->Get(attrib, data_type, count); +} + +static int iAttribCB(void* user_data, int index, const char* name, int data_type, int count, const void* data) +{ + (void)data_type; + (void)data; + (void)count; + char** attrib = (char**)user_data; + attrib[index] = (char*)name; + return 1; +} + +void imFileGetAttributeList(imFile* ifile, char** attrib, int *attrib_count) +{ + assert(ifile); + assert(attrib_count); + + imAttribTable* attrib_table = (imAttribTable*)ifile->attrib_table; + *attrib_count = attrib_table->Count(); + + if (attrib) attrib_table->ForEach((void*)attrib, iAttribCB); +} + +void imFileGetInfo(imFile* ifile, char* format, char* compression, int *image_count) +{ + assert(ifile); + imFileFormatBase* ifileformat = (imFileFormatBase*)ifile; + + if(compression) strcpy(compression, ifile->compression); + if(format) strcpy(format, ifileformat->iformat->format); + if (image_count) *image_count = ifile->image_count; +} + +static int iFileCheckPaletteGray(imFile* ifile) +{ + int i; + imbyte r, g, b; + imbyte remaped[256]; + memset(remaped, 0, 256); + + for (i = 0; i < ifile->palette_count; i++) + { + imColorDecode(&r, &g, &b, ifile->palette[i]); + + /* if there are colors abort */ + if (r != g || g != b) + return 0; + + /* grays out of order, will be remapped, but must be unique, + if there are duplicates maybe they are used for different pourposes */ + if (i != r) + { + if (!remaped[r]) + remaped[r] = 1; + else + return 0; + } + } + + return 1; +} + +static int iFileCheckPaletteBinary(imFile* ifile) +{ + if (ifile->palette_count > 2) + return 0; + + imbyte r, g, b; + + imColorDecode(&r, &g, &b, ifile->palette[0]); + if ((r != 0 || g != 0 || b != 0) && + (r != 1 || g != 1 || b != 1) && + (r != 255 || g != 255 || b != 255)) + return 0; + + imColorDecode(&r, &g, &b, ifile->palette[1]); + if ((r != 0 || g != 0 || b != 0) && + (r != 1 || g != 1 || b != 1) && + (r != 255 || g != 255 || b != 255)) + return 0; + + return 1; +} + +int imFileReadImageInfo(imFile* ifile, int index, int *width, int *height, int *file_color_mode, int *file_data_type) +{ + assert(ifile); + assert(!ifile->is_new); + imFileFormatBase* ifileformat = (imFileFormatBase*)ifile; + + if (index >= ifile->image_count) + return IM_ERR_DATA; + + if (ifile->image_index != -1 && + ifile->image_index == index) + { + if(width) *width = ifile->width; + if(height) *height = ifile->height; + if(file_color_mode) *file_color_mode = ifile->file_color_mode; + if(file_data_type) *file_data_type = ifile->file_data_type; + + return IM_ERR_NONE; + } + + ifile->convert_bpp = 0; + ifile->switch_type = 0; + + int error = ifileformat->ReadImageInfo(index); + if (error) return error; + + if (!imImageCheckFormat(ifile->file_color_mode, ifile->file_data_type)) + return IM_ERR_DATA; + + if (imColorModeSpace(ifile->file_color_mode) == IM_BINARY) + { + ifile->palette_count = 2; + ifile->palette[0] = imColorEncode(0, 0, 0); + ifile->palette[1] = imColorEncode(255, 255, 255); + } + + if (imColorModeSpace(ifile->file_color_mode) == IM_MAP) + { + if (iFileCheckPaletteGray(ifile)) + ifile->file_color_mode = (ifile->file_color_mode & 0xFF00) | IM_GRAY; + + if (iFileCheckPaletteBinary(ifile)) + ifile->file_color_mode = (ifile->file_color_mode & 0xFF00) | IM_BINARY; + } + + if(width) *width = ifile->width; + if(height) *height = ifile->height; + if(file_color_mode) *file_color_mode = ifile->file_color_mode; + if(file_data_type) *file_data_type = ifile->file_data_type; + + ifile->image_index = index; + + return IM_ERR_NONE; +} + +void imFileGetPalette(imFile* ifile, long* palette, int *palette_count) +{ + assert(ifile); + assert(palette); + + if (ifile->palette_count != 0 && palette) + memcpy(palette, ifile->palette, ifile->palette_count*sizeof(long)); + + if (palette_count) *palette_count = ifile->palette_count; +} + +static void iFileCheckConvertGray(imFile* ifile, imbyte* data) +{ + int i, do_remap = 0; + imbyte remap[256], r, g, b; + + // enforce the palette to only have grays in the correct order. + + for (i = 0; i < ifile->palette_count; i++) + { + imColorDecode(&r, &g, &b, ifile->palette[i]); + + if (r != i) + { + ifile->palette[i] = imColorEncode((imbyte)i, (imbyte)i, (imbyte)i); + do_remap = 1; + } + + remap[i] = r; + } + + if (!do_remap) + return; + + int count = ifile->width*ifile->height; + for(i = 0; i < count; i++) + { + *data = remap[*data]; + data++; + } + + int transp_count; + imbyte* transp_map = (imbyte*)imFileGetAttribute(ifile, "TransparencyMap", NULL, &transp_count); + if (transp_map) + { + imbyte new_transp_map[256]; + for (i=0; iwidth*ifile->height; + for(int i = 0; i < count; i++) + { + if (*data) + *data = 1; + data++; + } +} + +int imFileReadImageData(imFile* ifile, void* data, int convert2bitmap, int color_mode_flags) +{ + assert(ifile); + assert(!ifile->is_new); + imFileFormatBase* ifileformat = (imFileFormatBase*)ifile; + + if (ifile->image_index == -1) + return IM_ERR_DATA; + + ifile->user_color_mode = ifile->file_color_mode; + ifile->user_data_type = ifile->file_data_type; + + if (convert2bitmap) + { + ifile->user_data_type = IM_BYTE; + ifile->user_color_mode = imColorModeToBitmap(ifile->file_color_mode); + } + + if (color_mode_flags != -1) + { + ifile->user_color_mode = imColorModeSpace(ifile->user_color_mode); + ifile->user_color_mode |= color_mode_flags; + } + + if (!imImageCheckFormat(ifile->user_color_mode, ifile->user_data_type)) + return IM_ERR_DATA; + + if (!imFileCheckConversion(ifile)) + return IM_ERR_DATA; + + imFileLineBufferInit(ifile); + + int ret = ifileformat->ReadImageData(data); + + // here we can NOT change the file_color_mode we already returned to the user + // so just check for gray and binary consistency + + if (imColorModeSpace(ifile->file_color_mode) == IM_GRAY && ifile->file_data_type == IM_BYTE) + iFileCheckConvertGray(ifile, (imbyte*)data); + + if (imColorModeSpace(ifile->file_color_mode) == IM_BINARY) + iFileCheckConvertBinary(ifile, (imbyte*)data); + + return ret; +} + +void imFileSetInfo(imFile* ifile, const char* compression) +{ + assert(ifile); + assert(ifile->is_new); + + if (!compression) + ifile->compression[0] = 0; + else + strcpy(ifile->compression, compression); +} + +void imFileSetPalette(imFile* ifile, long* palette, int palette_count) +{ + assert(ifile); + assert(palette); + assert(palette_count != 0); + + memcpy(ifile->palette, palette, palette_count*sizeof(long)); + ifile->palette_count = palette_count; +} + +int imFileWriteImageInfo(imFile* ifile, int width, int height, int user_color_mode, int user_data_type) +{ + assert(ifile); + assert(ifile->is_new); + imFileFormatBase* ifileformat = (imFileFormatBase*)ifile; + + if (!imImageCheckFormat(user_color_mode, user_data_type)) + return IM_ERR_DATA; + + int error = ifileformat->iformat->CanWrite(ifile->compression, user_color_mode, user_data_type); + if (error) return error; + + ifile->width = width; + ifile->height = height; + ifile->user_color_mode = user_color_mode; + ifile->user_data_type = user_data_type; + + if (imColorModeSpace(user_color_mode) == IM_BINARY) + { + ifile->palette_count = 2; + ifile->palette[0] = imColorEncode(0, 0, 0); + ifile->palette[1] = imColorEncode(255, 255, 255); + } + + return ifileformat->WriteImageInfo(); +} + +int imFileWriteImageData(imFile* ifile, void* data) +{ + assert(ifile); + assert(ifile->is_new); + assert(data); + imFileFormatBase* ifileformat = (imFileFormatBase*)ifile; + + if (!imFileCheckConversion(ifile)) + return IM_ERR_DATA; + + imFileLineBufferInit(ifile); + + return ifileformat->WriteImageData(data); +} diff --git a/im/src/im_filebuffer.cpp b/im/src/im_filebuffer.cpp new file mode 100755 index 0000000..09c5ad4 --- /dev/null +++ b/im/src/im_filebuffer.cpp @@ -0,0 +1,695 @@ +/** \file + * \brief File Access - Buffer Management + * + * See Copyright Notice in im_lib.h + * $Id: im_filebuffer.cpp,v 1.2 2009/08/13 22:34:25 scuri Exp $ + */ + +#include +#include +#include + +#include "im.h" +#include "im_format.h" +#include "im_util.h" +#include "im_complex.h" +#include "im_color.h" + + +int imFileLineSizeAligned(int width, int bpp, int align) +{ + if (align == 4) + return ((width * bpp + 31) / 32) * 4; + else if (align == 2) + return ((width * bpp + 15) / 16) * 2; + else + return (width * bpp + 7) / 8; +} + +template +static void iDoFillLineBuffer(int width, int height, int line, int plane, + int file_color_mode, T* line_buffer, + int user_color_mode, const T* data) +{ + // (writing) from data to file + // will handle packing and alpha + + int file_depth = imColorModeDepth(file_color_mode); + int data_depth = imColorModeDepth(user_color_mode); + int data_plane_size = width*height; // This will be used in UNpacked data + + if (imColorModeIsPacked(user_color_mode)) + data += line*width*data_depth; + else + data += line*width; + + for (int x = 0; x < width; x++) + { + int x_data_offset = x*data_depth; // This will be used in packed data + + if (imColorModeIsPacked(file_color_mode)) + { + int x_file_offset = x*file_depth; // This will be used in packed data + + // file is packed + // NO color space conversion, color_space must match + // Ignore alpha if necessary. + int depth = IM_MIN(file_depth, data_depth); + for (int d = 0; d < depth; d++) + { + if (imColorModeIsPacked(user_color_mode)) + line_buffer[x_file_offset + d] = data[x_data_offset + d]; + else + line_buffer[x_file_offset + d] = data[d*data_plane_size + x]; + } + } + else + { + // file NOT packed, copy just one plane + // NO color space conversion, color_space must match + + if (plane >= imColorModeDepth(user_color_mode)) + return; + + if (imColorModeIsPacked(user_color_mode)) + line_buffer[x] = data[x_data_offset + plane]; + else + line_buffer[x] = data[plane*data_plane_size + x]; + } + } +} + +template +static void iDoFillData(int width, int height, int line, int plane, + int file_color_mode, const T* line_buffer, + int user_color_mode, T* data) +{ + // (reading) from file to data + // will handle packing and alpha + + int file_depth = imColorModeDepth(file_color_mode); + int data_depth = imColorModeDepth(user_color_mode); + int data_plane_size = width*height; // This will be used in UNpacked data + + if (imColorModeIsPacked(user_color_mode)) + data += line*width*data_depth; + else + data += line*width; + + for (int x = 0; x < width; x++) + { + int x_data_offset = x*data_depth; // This will be used in packed data + + if (imColorModeIsPacked(file_color_mode)) + { + int x_file_offset = x*file_depth; // This will be used in packed data + + // file is packed + // NO color space conversion, color_space must match + // ignore alpha if necessary. + int depth = IM_MIN(file_depth, data_depth); + for (int d = 0; d < depth; d++) + { + if (imColorModeIsPacked(user_color_mode)) + data[x_data_offset + d] = line_buffer[x_file_offset + d]; + else + data[d*data_plane_size + x] = line_buffer[x_file_offset + d]; + } + } + else + { + // file NOT packed, copy just one plane + // NO color space conversion, color_space must match + + if (plane >= imColorModeDepth(user_color_mode)) + return; + + if (imColorModeIsPacked(user_color_mode)) + data[x_data_offset + plane] = line_buffer[x]; + else + data[plane*data_plane_size + x] = line_buffer[x]; + } + } +} + +template +static inline void iConvertColor2RGB(T* data, int color_space, int data_type) +{ + T zero, max = (T)imColorMax(data_type); + + // These are identical procedures to iDoConvert2RGB in "im_filebuffer.cpp". + + switch (color_space) + { + case IM_XYZ: + { + // to increase precision do intermediate conversions in float + + // scale to 0-1 + float c0 = imColorReconstruct(data[0], max); + float c1 = imColorReconstruct(data[1], max); + float c2 = imColorReconstruct(data[2], max); + + // result is still 0-1 + imColorXYZ2RGB(c0, c1, c2, + c0, c1, c2, 1.0f); + + // do gamma correction then scale back to 0-max + data[0] = imColorQuantize(imColorTransfer2Nonlinear(c0), max); + data[1] = imColorQuantize(imColorTransfer2Nonlinear(c1), max); + data[2] = imColorQuantize(imColorTransfer2Nonlinear(c2), max); + } + break; + case IM_YCBCR: + zero = (T)imColorZero(data_type); + imColorYCbCr2RGB(data[0], data[1], data[2], + data[0], data[1], data[2], zero, max); + break; + case IM_CMYK: + imColorCMYK2RGB(data[0], data[1], data[2], data[3], + data[0], data[1], data[2], max); + break; + case IM_LUV: + case IM_LAB: + { + // to increase precision do intermediate conversions in float + // scale to 0-1 and -0.5/+0.5 + float c0 = imColorReconstruct(data[0], max); + float c1 = imColorReconstruct(data[1], max) - 0.5f; + float c2 = imColorReconstruct(data[2], max) - 0.5f; + + if (color_space == IM_LUV) + imColorLuv2XYZ(c0, c1, c2, // conversion in-place + c0, c1, c2); + else + imColorLab2XYZ(c0, c1, c2, // conversion in-place + c0, c1, c2); + + imColorXYZ2RGB(c0, c1, c2, // conversion in-place + c0, c1, c2, 1.0f); + + // do gamma correction then scale back to 0-max + data[0] = imColorQuantize(imColorTransfer2Nonlinear(c0), max); + data[1] = imColorQuantize(imColorTransfer2Nonlinear(c1), max); + data[2] = imColorQuantize(imColorTransfer2Nonlinear(c2), max); + } + break; + } +} + +// These functions will be always converting RGB -> RGB (0-max) -> (0-255) + +static inline imbyte iConvertType2Byte(const imbyte& data) + { return data; } + +static inline imbyte iConvertType2Byte(const imushort& data) + { return imColorQuantize(imColorReconstruct(data, (imushort)65535), (imbyte)255); } + +static inline imbyte iConvertType2Byte(const int& data) + { return imColorQuantize(imColorReconstruct(data, 16777215), (imbyte)255); } + +static inline imbyte iConvertType2Byte(const float& data) + { return imColorQuantize(data, (imbyte)255); } + +// Fake float to avoid erros in the color conversion template rotines. +// Since the color conversion use the double value, they are invalid, +// so the automatic conversion to bitmap for complex images works only for RGB. +static inline imbyte iConvertType2Byte(const double& data) +{ + imcfloat* fdata = (imcfloat*)&data; + return imColorQuantize(cpxmag(*fdata), (imbyte)255); +} + +template +static void iDoFillDataBitmap(int width, int height, int line, int plane, int data_type, + int file_color_mode, const T* line_buffer, + int user_color_mode, imbyte* data) +{ + // (reading) from file to data + // will handle packing, alpha, color space conversion to RGB and data_type to BYTE + + int file_depth = imColorModeDepth(file_color_mode); + int data_depth = imColorModeDepth(user_color_mode); + int copy_alpha = imColorModeHasAlpha(file_color_mode) && imColorModeHasAlpha(user_color_mode); + int data_plane_size = width*height; // This will be used in UNpacked data + + if (imColorModeIsPacked(user_color_mode)) + data += line*width*data_depth; + else + data += line*width; + + for (int x = 0; x < width; x++) + { + int x_data_offset = x*data_depth; // This will be used in packed data + + if (imColorModeIsPacked(file_color_mode)) + { + int x_file_offset = x*file_depth; // This will be used in packed data + + if (imColorModeMatch(file_color_mode, user_color_mode)) + { + // file is packed + // same color space components (in this case means RGB) + // ignore alpha if necessary. + int depth = IM_MIN(file_depth, data_depth); + for (int d = 0; d < depth; d++) + { + if (imColorModeIsPacked(user_color_mode)) + data[x_data_offset + d] = iConvertType2Byte(line_buffer[x_file_offset + d]); + else + data[d*data_plane_size + x] = iConvertType2Byte(line_buffer[x_file_offset + d]); + } + } + else + { + // file is packed + // but different color space components + // only to RGB conversions are accepted + + if (imColorModeSpace(user_color_mode) != IM_RGB) + return; + + T src_data[4]; + src_data[0] = line_buffer[x_file_offset]; + src_data[1] = line_buffer[x_file_offset + 1]; + src_data[2] = line_buffer[x_file_offset + 2]; + if (imColorModeSpace(file_color_mode) == IM_CMYK) + src_data[3] = line_buffer[x_file_offset + 3]; + + // Do conversion in place + iConvertColor2RGB(src_data, imColorModeSpace(file_color_mode), data_type); + + if (imColorModeIsPacked(user_color_mode)) + { + data[x_data_offset] = iConvertType2Byte(src_data[0]); + data[x_data_offset + 1] = iConvertType2Byte(src_data[1]); + data[x_data_offset + 2] = iConvertType2Byte(src_data[2]); + + if (copy_alpha) + { + if (imColorModeSpace(file_color_mode) == IM_CMYK) + data[x_data_offset + 3] = iConvertType2Byte(line_buffer[x_file_offset + 4]); + else + data[x_data_offset + 3] = iConvertType2Byte(line_buffer[x_file_offset + 3]); + } + } + else + { + data[x] = iConvertType2Byte(src_data[0]); + data[data_plane_size + x] = iConvertType2Byte(src_data[1]); + data[2*data_plane_size + x] = iConvertType2Byte(src_data[2]); + + if (copy_alpha) + { + if (imColorModeSpace(file_color_mode) == IM_CMYK) + data[3*data_plane_size + x] = iConvertType2Byte(line_buffer[x_file_offset + 4]); + else + data[3*data_plane_size + x] = iConvertType2Byte(line_buffer[x_file_offset + 3]); + } + } + } + } + else + { + // file NOT packed, copy just one plane + // NO color space conversion possible now + + if (plane >= imColorModeDepth(user_color_mode)) + return; + + if (imColorModeIsPacked(user_color_mode)) + data[x_data_offset + plane] = iConvertType2Byte(line_buffer[x]); + else + data[plane*data_plane_size + x] = iConvertType2Byte(line_buffer[x]); + } + } +} + +static void iFileExpandBits(imFile* ifile) +{ + // conversion will be done in place in backward order (from end to start) + + if (abs(ifile->convert_bpp) < 8) + { + imbyte* byte_buffer = (imbyte*)ifile->line_buffer; + imbyte* bit_buffer = (imbyte*)ifile->line_buffer; + + byte_buffer += ifile->width-1; + int bpp = ifile->convert_bpp; + int expand_range = imColorModeSpace(ifile->file_color_mode) == IM_GRAY? 1: 0; + + for (int i=ifile->width-1; i >= 0; i--) + { + if (bpp == 1) + *byte_buffer = (imbyte)((bit_buffer[i / 8] >> (7 - i % 8)) & 0x01); + else if (bpp == 4) + *byte_buffer = (imbyte)((bit_buffer[i / 2] >> ((1 - i % 2) * 4)) & 0x0F); + else if (bpp == 2) + *byte_buffer = (imbyte)((bit_buffer[i / 4] >> ((3 - i % 4) * 2)) & 0x03); + + if (expand_range) /* if convert_bpp<0 then only expand its range */ + { + if (bpp == 4 || bpp == -4) + *byte_buffer *= 17; + else if (bpp == 2 || bpp == -2) + *byte_buffer *= 85; + } + + byte_buffer--; + } + } + else if (ifile->convert_bpp == 12) + { + imushort* ushort_buffer = (imushort*)ifile->line_buffer; + imbyte* bit_buffer = (imbyte*)ifile->line_buffer; + + for (int i=ifile->width-1; i >= 0; i--) + { + int byte_index = (3*i)/2; + if (i%2) + ushort_buffer[i] = (bit_buffer[byte_index] << 4) | (bit_buffer[byte_index+1] & 0x0F); + else + ushort_buffer[i] = ((bit_buffer[byte_index] & 0x0F) << 8) | (bit_buffer[byte_index+1]); + } + } +} + +static void iFileCompactBits(imFile* ifile) +{ + // conversion will be done in place + imbyte* byte_buffer = (imbyte*)ifile->line_buffer; + imbyte* bit_buffer = (imbyte*)ifile->line_buffer; + + if (ifile->convert_bpp == 1) + { + for (int i = 0; i < ifile->width; i++) + { + if (*byte_buffer) + bit_buffer[i / 8] |= (0x01 << (7 - (i % 8))); + else + bit_buffer[i / 8] &= ~(0x01 << (7 - (i % 8))); + + byte_buffer++; + } + } + else // -1 == expand 1 to 255 + { + for (int i = 0; i < ifile->width; i++) + { + if (*byte_buffer) + *byte_buffer = 255; + + byte_buffer++; + } + } +} + +template +static void iDoSwitchInt(int count, const SRC* src_data, DST* dst_data, int offset) +{ + for (int i = 0; i < count; i++) + { + *dst_data++ = (DST)((int)*src_data++ + offset); + } +} + +template +static void iDoSwitchReal(int count, const SRC* src_data, DST* dst_data) +{ + for (int i = 0; i < count; i++) + { + *dst_data++ = (DST)(*src_data++); + } +} + +static void iFileSwitchFromType(imFile* ifile) +{ + int line_count = imImageLineCount(ifile->width, ifile->file_color_mode); + switch(ifile->file_data_type) + { + case IM_BYTE: // Source is char + iDoSwitchInt(line_count, (const char*)ifile->line_buffer, (imbyte*)ifile->line_buffer, 128); + break; + case IM_USHORT: // Source is short + iDoSwitchInt(line_count, (const short*)ifile->line_buffer, (imushort*)ifile->line_buffer, 32768); + break; + case IM_INT: // Source is uint + iDoSwitchInt(line_count, (const unsigned int*)ifile->line_buffer, (int*)ifile->line_buffer, -8388608); + break; + case IM_FLOAT: // Source is double + iDoSwitchReal(line_count, (const double*)ifile->line_buffer, (float*)ifile->line_buffer); + break; + case IM_CFLOAT: // Source is complex double + iDoSwitchReal(2*line_count, (const double*)ifile->line_buffer, (float*)ifile->line_buffer); + break; + } +} + +static void iFileSwitchToType(imFile* ifile) +{ + int line_count = imImageLineCount(ifile->width, ifile->file_color_mode); + switch(ifile->file_data_type) + { + case IM_BYTE: // Destiny is char + iDoSwitchInt(line_count, (const imbyte*)ifile->line_buffer, (char*)ifile->line_buffer, -128); + break; + case IM_USHORT: // Destiny is short + iDoSwitchInt(line_count, (const imushort*)ifile->line_buffer, (short*)ifile->line_buffer, -32768); + break; + case IM_INT: // Destiny is uint + iDoSwitchInt(line_count, (const int*)ifile->line_buffer, (unsigned int*)ifile->line_buffer, 8388608); + break; + case IM_FLOAT: // Destiny is double + iDoSwitchReal(line_count, (const float*)ifile->line_buffer, (double*)ifile->line_buffer); + break; + case IM_CFLOAT: // Destiny is complex double + iDoSwitchReal(2*line_count, (const float*)ifile->line_buffer, (double*)ifile->line_buffer); + break; + } +} + +void imFileLineBufferWrite(imFile* ifile, const void* data, int line, int plane) +{ + // (writing) from data to file + + if (imColorModeIsTopDown(ifile->file_color_mode) != imColorModeIsTopDown(ifile->user_color_mode)) + line = ifile->height-1 - line; + + if ((ifile->file_color_mode & 0x3FF) == + (ifile->user_color_mode & 0x3FF)) // compare only packing, alpha and color space + { + int data_offset = line*ifile->line_buffer_size; + if (plane != 0) + data_offset += plane*ifile->height*ifile->line_buffer_size; + + memcpy(ifile->line_buffer, (unsigned char*)data + data_offset, ifile->line_buffer_size); + } + else + { + switch(ifile->file_data_type) + { + case IM_BYTE: + iDoFillLineBuffer(ifile->width, ifile->height, line, plane, + ifile->file_color_mode, (imbyte*)ifile->line_buffer, + ifile->user_color_mode, (const imbyte*)data); + break; + case IM_USHORT: + iDoFillLineBuffer(ifile->width, ifile->height, line, plane, + ifile->file_color_mode, (imushort*)ifile->line_buffer, + ifile->user_color_mode, (const imushort*)data); + break; + case IM_INT: + iDoFillLineBuffer(ifile->width, ifile->height, line, plane, + ifile->file_color_mode, (int*)ifile->line_buffer, + ifile->user_color_mode, (const int*)data); + break; + case IM_FLOAT: + iDoFillLineBuffer(ifile->width, ifile->height, line, plane, + ifile->file_color_mode, (float*)ifile->line_buffer, + ifile->user_color_mode, (const float*)data); + break; + case IM_CFLOAT: + iDoFillLineBuffer(ifile->width, ifile->height, line, plane, + ifile->file_color_mode, (imcfloat*)ifile->line_buffer, + ifile->user_color_mode, (const imcfloat*)data); + break; + } + } + + if (ifile->convert_bpp) + iFileCompactBits(ifile); + + if (ifile->switch_type) + iFileSwitchToType(ifile); +} + +void imFileLineBufferRead(imFile* ifile, void* data, int line, int plane) +{ + // (reading) from file to data + + if (imColorModeIsTopDown(ifile->file_color_mode) != imColorModeIsTopDown(ifile->user_color_mode)) + line = ifile->height-1 - line; + + if (ifile->convert_bpp) + iFileExpandBits(ifile); + + if (ifile->switch_type) + iFileSwitchFromType(ifile); + + if ((ifile->file_color_mode & 0x3FF) == (ifile->user_color_mode & 0x3FF) && // compare only packing, alpha and color space, ignore bottom up. + ifile->file_data_type == ifile->user_data_type) // compare data type when reading + { + int data_offset = line*ifile->line_buffer_size; + if (plane != 0) + data_offset += plane*ifile->height*ifile->line_buffer_size; + + memcpy((unsigned char*)data + data_offset, ifile->line_buffer, ifile->line_buffer_size); + } + else + { + // now we have 2 conversions groups + // one to convert only packing and alpha + // and the other to convert packing, alpha, color space and data type + int convert2bitmap = 0; + if (imColorModeSpace(ifile->user_color_mode) != imColorModeSpace(ifile->file_color_mode) || + ifile->file_data_type != IM_BYTE) + convert2bitmap = 1; + + switch(ifile->file_data_type) + { + case IM_BYTE: + if (convert2bitmap) + iDoFillDataBitmap(ifile->width, ifile->height, line, plane, ifile->file_data_type, + ifile->file_color_mode, (const imbyte*)ifile->line_buffer, + ifile->user_color_mode, (imbyte*)data); + else + iDoFillData(ifile->width, ifile->height, line, plane, + ifile->file_color_mode, (const imbyte*)ifile->line_buffer, + ifile->user_color_mode, (imbyte*)data); + break; + case IM_USHORT: + if (convert2bitmap) + iDoFillDataBitmap(ifile->width, ifile->height, line, plane, ifile->file_data_type, + ifile->file_color_mode, (const imushort*)ifile->line_buffer, + ifile->user_color_mode, (imbyte*)data); + else + iDoFillData(ifile->width, ifile->height, line, plane, + ifile->file_color_mode, (const imushort*)ifile->line_buffer, + ifile->user_color_mode, (imushort*)data); + break; + case IM_INT: + if (convert2bitmap) + iDoFillDataBitmap(ifile->width, ifile->height, line, plane, ifile->file_data_type, + ifile->file_color_mode, (const int*)ifile->line_buffer, + ifile->user_color_mode, (imbyte*)data); + else + iDoFillData(ifile->width, ifile->height, line, plane, + ifile->file_color_mode, (const int*)ifile->line_buffer, + ifile->user_color_mode, (int*)data); + break; + case IM_FLOAT: + if (convert2bitmap) + iDoFillDataBitmap(ifile->width, ifile->height, line, plane, ifile->file_data_type, + ifile->file_color_mode, (const float*)ifile->line_buffer, + ifile->user_color_mode, (imbyte*)data); + else + iDoFillData(ifile->width, ifile->height, line, plane, + ifile->file_color_mode, (const float*)ifile->line_buffer, + ifile->user_color_mode, (float*)data); + break; + case IM_CFLOAT: + if (convert2bitmap) + iDoFillDataBitmap(ifile->width, ifile->height, line, plane, ifile->file_data_type, + ifile->file_color_mode, (const double*)ifile->line_buffer, + ifile->user_color_mode, (imbyte*)data); + else + iDoFillData(ifile->width, ifile->height, line, plane, + ifile->file_color_mode, (const imcfloat*)ifile->line_buffer, + ifile->user_color_mode, (imcfloat*)data); + break; + } + } +} + +void imFileLineBufferInit(imFile* ifile) +{ + ifile->line_buffer_size = imImageLineSize(ifile->width, ifile->file_color_mode, ifile->file_data_type); + + if (ifile->switch_type && (ifile->file_data_type == IM_FLOAT || ifile->file_data_type == IM_CFLOAT)) + ifile->line_buffer_extra += ifile->line_buffer_size; // double the size at least + + if (ifile->line_buffer_size + ifile->line_buffer_extra > ifile->line_buffer_alloc) + { + ifile->line_buffer_alloc = ifile->line_buffer_size + ifile->line_buffer_extra; + ifile->line_buffer = realloc(ifile->line_buffer, ifile->line_buffer_alloc); + } +} + +int imFileLineBufferCount(imFile* ifile) +{ + int count = ifile->height; + if (!imColorModeIsPacked(ifile->file_color_mode)) + { + if (imColorModeHasAlpha(ifile->file_color_mode) && imColorModeHasAlpha(ifile->user_color_mode)) + count *= imColorModeDepth(ifile->file_color_mode); + else + count *= imColorModeDepth(imColorModeSpace(ifile->file_color_mode)); + } + return count; +} + +void imFileLineBufferInc(imFile* ifile, int *row, int *plane) +{ + if (!imColorModeIsPacked(ifile->file_color_mode)) + { + if (*row == ifile->height-1) + { + *row = 0; + (*plane)++; + return; + } + } + + (*row)++; +} + +int imFileCheckConversion(imFile* ifile) +{ + if ((ifile->file_color_mode & 0x3FF) == (ifile->user_color_mode & 0x3FF) && // compare only packing, alpha and color space + ifile->file_data_type == ifile->user_data_type) + return 1; + + int user_color_space = imColorModeSpace(ifile->user_color_mode); + int file_color_space = imColorModeSpace(ifile->file_color_mode); + + // NO color space conversion if file is not packed. + if(user_color_space != file_color_space && + imColorModeDepth(file_color_space) > 1 && + !imColorModeIsPacked(ifile->file_color_mode)) + return 0; + + if (ifile->is_new) + { + // (writing) from data to file + + // NO data type conversions when writing. + if (ifile->file_data_type != ifile->user_data_type) + return 0; + + // NO color space conversions when writing. + // If there is a necessary conversion the format driver will do it. + if (user_color_space != file_color_space) + return 0; + } + else + { + // (reading) from file to data + + // Data type conversions only to byte + if (ifile->file_data_type != ifile->user_data_type && + ifile->user_data_type != IM_BYTE) + return 0; + } + + return 1; +} diff --git a/im/src/im_fileraw.cpp b/im/src/im_fileraw.cpp new file mode 100755 index 0000000..91be826 --- /dev/null +++ b/im/src/im_fileraw.cpp @@ -0,0 +1,66 @@ +/** \file + * \brief RAW File Format Open/New Functions + * + * See Copyright Notice in im_lib.h + * $Id: im_fileraw.cpp,v 1.3 2009/09/10 17:33:35 scuri Exp $ + */ + +#include "im.h" +#include "im_image.h" +#include "im_util.h" +#include "im_counter.h" +#include "im_raw.h" +#include "im_format.h" +#include "im_format_raw.h" + +#include +#include + + +imFile* imFileOpenRaw(const char* file_name, int *error) +{ + assert(file_name); + + imFormat* iformat = imFormatInitRAW(); + imFileFormatBase* ifileformat = iformat->Create(); + *error = ifileformat->Open(file_name); + if (*error) + { + delete ifileformat; + return NULL; + } + + imFileClear(ifileformat); + + ifileformat->attrib_table = new imAttribTable(599); + + ifileformat->counter = imCounterBegin(file_name); + + return ifileformat; +} + +imFile* imFileNewRaw(const char* file_name, int *error) +{ + assert(file_name); + + imFormat* iformat = imFormatInitRAW(); + imFileFormatBase* ifileformat = iformat->Create(); + *error = ifileformat->New(file_name); + if (*error) + { + delete ifileformat; + return NULL; + } + + imFileClear(ifileformat); + + ifileformat->is_new = 1; + ifileformat->image_count = 0; + ifileformat->compression[0] = 0; + + ifileformat->attrib_table = new imAttribTable(101); + + ifileformat->counter = imCounterBegin(file_name); + + return ifileformat; +} diff --git a/im/src/im_format.cpp b/im/src/im_format.cpp new file mode 100755 index 0000000..d389743 --- /dev/null +++ b/im/src/im_format.cpp @@ -0,0 +1,299 @@ +/** \file + * \brief File Format Access + * + * See Copyright Notice in im_lib.h + * $Id: im_format.cpp,v 1.2 2008/12/03 15:45:34 scuri Exp $ + */ + + +#include +#include +#include +#include +#include + +#include "im.h" +#include "im_format.h" +#include "im_util.h" + + +static imFormat* iFormatList[50]; +static int iFormatCount = 0; +static int iFormatRegistredAll = 0; + +void imFormatRemoveAll(void) +{ + for (int i = 0; i < iFormatCount; i++) + { + imFormat* iformat = iFormatList[i]; + delete iformat; + iFormatList[i] = NULL; + } + iFormatCount = 0; + iFormatRegistredAll = 0; +} + +void imFormatRegister(imFormat* iformat) +{ + iFormatList[iFormatCount] = iformat; + iFormatCount++; +} + +static imFormat* iFormatFind(const char* format) +{ + assert(format); + + if (!iFormatRegistredAll) + { + imFormatRegisterInternal(); + iFormatRegistredAll = 1; + } + + for (int i = 0; i < iFormatCount; i++) + { + imFormat* iformat = iFormatList[i]; + if (imStrEqual(format, iformat->format)) + return iformat; + } + return NULL; +} + +void imFormatList(char** format_list, int *format_count) +{ + assert(format_list); + assert(format_count); + + if (!iFormatRegistredAll) + { + imFormatRegisterInternal(); + iFormatRegistredAll = 1; + } + + static char format_list_buffer[50][50]; + + *format_count = iFormatCount; + for (int i = 0; i < iFormatCount; i++) + { + imFormat* iformat = iFormatList[i]; + strcpy(format_list_buffer[i], iformat->format); + format_list[i] = format_list_buffer[i]; + } +} + +int imFormatInfo(const char* format, char* desc, char* ext, int *can_sequence) +{ + imFormat* iformat = iFormatFind(format); + if (!iformat) return IM_ERR_FORMAT; + + if (desc) strcpy(desc, iformat->desc); + if (ext) strcpy(ext, iformat->ext); + if (can_sequence) *can_sequence = iformat->can_sequence; + + return IM_ERR_NONE; +} + +int imFormatCompressions(const char* format, char** comp, int *comp_count, int color_mode, int data_type) +{ + imFormat* iformat = iFormatFind(format); + if (!iformat) return IM_ERR_FORMAT; + + int count = 0; + + static char comp_buffer[50][50]; + + for (int i = 0; i < iformat->comp_count; i++) + { + if (color_mode == -1 || data_type == -1 || + iformat->CanWrite(iformat->comp[i], color_mode, data_type) == IM_ERR_NONE) + { + strcpy(comp_buffer[count], iformat->comp[i]); + comp[count] = comp_buffer[count]; + count++; + } + } + + *comp_count = count; + + return IM_ERR_NONE; +} + +int imFormatCanWriteImage(const char* format, const char* compression, int color_mode, int data_type) +{ + assert(format); + + imFormat* iformat = iFormatFind(format); + if (!iformat) return IM_ERR_FORMAT; + + int error = iformat->CanWrite(compression, color_mode, data_type); + return error; +} + +static char* utlFileGetExt(const char *file_name) +{ + int len = strlen(file_name); + + // Starts at the last character + int offset = len - 1; + while (offset != 0) + { + // if found a path separator, no extension found + if (file_name[offset] == '\\' || file_name[offset] == '/') + return NULL; + + if (file_name[offset] == '.') + { + offset++; + break; + } + + offset--; + } + + // if at the first character, no extension found + if (offset == 0) + return NULL; + + int ext_size = len - offset + 1; + char* file_ext = (char*)malloc(ext_size); + + for (int i = 0; i < ext_size-1; i++) + file_ext[i] = (char)tolower(file_name[i+offset]); + file_ext[ext_size-1] = 0; + + return file_ext; +} + +imFileFormatBase* imFileFormatBaseOpen(const char* file_name, int *error) +{ + int i; + + assert(file_name); + assert(error); + + if (!iFormatRegistredAll) + { + imFormatRegisterInternal(); + iFormatRegistredAll = 1; + } + + int* ext_mark = new int [iFormatCount]; + memset(ext_mark, 0, sizeof(int)*iFormatCount); + + // Search for the extension first, this usually is going to speed the search + char* extension = utlFileGetExt(file_name); + if (extension) + { + for(i = 0; i < iFormatCount; i++) + { + imFormat* iformat = iFormatList[i]; + + if (strstr(iformat->ext, extension) != NULL) + { + ext_mark[i] = 1; // Mark this format to avoid testing it again in the next phase + + imFileFormatBase* ifileformat = iformat->Create(); + *error = ifileformat->Open(file_name); + if (*error != IM_ERR_NONE && *error != IM_ERR_FORMAT) // Error situation that must abort + { // Only IM_ERR_FORMAT is a valid error here + free(extension); + delete [] ext_mark; + delete ifileformat; + return NULL; + } + else if (*error == IM_ERR_NONE) // Sucessfully oppened the file + { + free(extension); + delete [] ext_mark; + return ifileformat; + } + } + } + + free(extension); + } + + // If the search did not work, try all the formats + // except those already tested. + + for(i = 0; i < iFormatCount; i++) + { + if (!ext_mark[i]) + { + imFormat* iformat = iFormatList[i]; + imFileFormatBase* ifileformat = iformat->Create(); + *error = ifileformat->Open(file_name); + if (*error != IM_ERR_NONE && *error != IM_ERR_FORMAT) // Error situation that must abort + { // Only IM_ERR_FORMAT is a valid error here + delete [] ext_mark; + delete ifileformat; + return NULL; + } + else if (*error == IM_ERR_NONE) // Sucessfully oppened the file + { + delete [] ext_mark; + return ifileformat; + } + } + } + + *error = IM_ERR_FORMAT; + delete [] ext_mark; + return NULL; +} + +imFileFormatBase* imFileFormatBaseOpenAs(const char* file_name, const char* format, int *error) +{ + assert(file_name); + assert(format); + assert(error); + + if (!iFormatRegistredAll) + { + imFormatRegisterInternal(); + iFormatRegistredAll = 1; + } + + imFormat* iformat = iFormatFind(format); + if (!format) + { + *error = IM_ERR_FORMAT; + return NULL; + } + + imFileFormatBase* ifileformat = iformat->Create(); + *error = ifileformat->Open(file_name); + if (*error != IM_ERR_NONE && *error != IM_ERR_FORMAT) // Error situation that must abort + { + delete ifileformat; + return NULL; + } + else if (*error == IM_ERR_NONE) // Sucessfully oppened the file + return ifileformat; + + *error = IM_ERR_FORMAT; + return NULL; +} + +imFileFormatBase* imFileFormatBaseNew(const char* file_name, const char* format, int *error) +{ + assert(file_name); + assert(format); + assert(error); + + imFormat* iformat = iFormatFind(format); + if (!iformat) + { + *error = IM_ERR_FORMAT; + return NULL; + } + + imFileFormatBase* ifileformat = iformat->Create(); + *error = ifileformat->New(file_name); + if (*error) + { + delete ifileformat; + return NULL; + } + + return ifileformat; +} diff --git a/im/src/im_format_all.cpp b/im/src/im_format_all.cpp new file mode 100755 index 0000000..c10b30a --- /dev/null +++ b/im/src/im_format_all.cpp @@ -0,0 +1,34 @@ +/** \file + * \brief Register all the internal File Format Classes + * + * See Copyright Notice in im_lib.h + * $Id: im_format_all.cpp,v 1.1 2008/10/17 06:10:16 scuri Exp $ + */ + + +#include +#include +#include +#include + +#include "im.h" +#include "im_format.h" +#include "im_format_all.h" + +void imFormatRegisterInternal(void) +{ + // IMPORTANT: RAW format is not registered. + + // The internal formats registration + imFormatRegisterGIF(); + imFormatRegisterBMP(); + imFormatRegisterRAS(); + imFormatRegisterICO(); + imFormatRegisterPNM(); + imFormatRegisterKRN(); + imFormatRegisterLED(); + imFormatRegisterSGI(); + imFormatRegisterPCX(); + imFormatRegisterTGA(); +} + diff --git a/im/src/im_format_bmp.cpp b/im/src/im_format_bmp.cpp new file mode 100755 index 0000000..5cfe013 --- /dev/null +++ b/im/src/im_format_bmp.cpp @@ -0,0 +1,949 @@ +/** \file + * \brief BMP - Windows Device Independent Bitmap + * + * See Copyright Notice in im_lib.h + * $Id: im_format_bmp.cpp,v 1.4 2009/10/01 14:15:47 scuri Exp $ + */ + +#include "im_format.h" +#include "im_format_all.h" +#include "im_util.h" +#include "im_counter.h" + +#include "im_binfile.h" + +#include +#include +#include + + +#define BMP_ID 0x4d42 /* BMP "magic" number */ + +#define BMP_COMPRESS_RGB 0L /* No compression */ +#define BMP_COMPRESS_RLE8 1L /* 8 bits per pixel compression */ +#define BMP_COMPRESS_RLE4 2L /* 4 bits per pixel compression */ +#define BMP_BITFIELDS 3L /* no compression, palette is mask for 16 and 32 bits images */ + +/* State-machine definitions */ +#define BMP_READING 0 /* General READING mode */ +#define BMP_ENCODING 1 /* Encoding same-color pixel runs */ +#define BMP_ABSMODE 2 /* Absolute-mode encoding */ +#define BMP_SINGLE 3 /* Encoding short absolute-mode runs */ +#define BMP_ENDOFLINE 4 /* End of scan line detected */ + +#define BMP_LSN(value) (unsigned char)((value) & 0x0f) /* Least-significant nibble */ +#define BMP_MSN(value) (unsigned char)(((value) & 0xf0) >> 4) /* Most-significant nibble */ + + +/* File Header Structure. + * 2 Type; File Type Identifier + * 4 FileSize; Size of File + * 2 Reserved1; Reserved (should be 0) + * 2 Reserved2; Reserved (should be 0) + * 4 Offset; Offset to bitmap data + * 14 TOTAL */ + +/* Information Header Structure. + * 4 Size; Size of Remaining Header + * 4 Width; Width of Bitmap in Pixels + * 4 Height; Height of Bitmap in Pixels + * 2 Planes; Number of Planes + * 2 BitCount; Bits Per Pixel + * 4 Compression; Compression Scheme + * 4 SizeImage; Size of bitmap + * 4 XPelsPerMeter; Horz. Resolution in Pixels/Meter + * 4 YPelsPerMeter; Vert. Resolution in Pixels/Meter + * 4 ClrUsed; Number of Colors in Color Table + * 4 ClrImportant; Number of Important Colors + * 40 TOTAL V3 + * 4 RedMask; + * 4 GreenMask; + * 4 BlueMask; + * 4 AlphaMask; + * 4 CSType; + * 12 ciexyzRed(x, y, z); [3*FXPT2DOT30] + * 12 ciexyzGreen(x, y, z); " + * 12 ciexyzBlue(x, y, z); " + * 4 GammaRed; + * 4 GammaGreen; + * 4 GammaBlue; + * 108 TOTAL V4 (not supported here) + * 4 Intent; + * 4 ProfileData; + * 4 ProfileSize; + * 4 Reserved; + * 120 TOTAL V5 (not supported here) + */ + +/* RGB Color Quadruple Structure. */ +/* 1 rgbBlue; Blue Intensity Value */ +/* 1 rgbGreen; Green Intensity Value */ +/* 1 rgbRed; Red Intensity Value */ +/* 1 rgbReserved; Reserved (should be 0) */ +/* 4 */ + +static int iBMPDecodeScanLine(imBinFile* handle, unsigned char* DecodedBuffer, int Width) +{ + unsigned char runCount; /* Number of pixels in the run */ + unsigned char runValue; /* Value of pixels in the run */ + int Index = 0; /* The index of DecodedBuffer */ + int cont = 1, remain; + + while (cont) + { + imBinFileRead(handle, &runCount, 1, 1); /* Number of pixels in the run */ + imBinFileRead(handle, &runValue, 1, 1); /* Value of pixels in the run */ + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + if (runCount) + { + while (runCount-- && Index < Width) + DecodedBuffer[Index++] = runValue; + } + else /* Abssolute Mode or Escape Code */ + { + switch(runValue) + { + case 0: /* End of Scan Line Escape Code */ + case 1: /* End of Bitmap Escape Code */ + cont = 0; + break; + case 2: /* Delta Escape Code (ignored) */ + imBinFileRead(handle, &runCount, 1, 1); + imBinFileRead(handle, &runCount, 1, 1); + break; + default: /* Abssolute Mode */ + remain = runValue % 2; + runValue = (unsigned char)(Index + runValue < (Width + 1)? runValue: (Width - 1) - Index); + imBinFileRead(handle, DecodedBuffer + Index, runValue, 1); + if (remain) + imBinFileSeekOffset(handle, 1); + Index += runValue; + } + } + + if (imBinFileError(handle) || Index > Width) + return IM_ERR_ACCESS; + } + + return IM_ERR_NONE; +} + +static int iBMPEncodeScanLine(unsigned char* EncodedBuffer, unsigned char* sl, int np) +{ + int slx = 0; /* Scan line index */ + int state = BMP_READING; /* State machine control variable */ + int count = 0; /* Used by various states */ + unsigned char pixel; /* Holds single pixels from sl */ + int done = 0; /* Ends while loop when true */ + int oldcount, oldslx; /* Copies of count and slx */ + int BufSize = 0; + + while (!done) + { + switch (state) + { + case BMP_READING: + /* Input: */ + /* np == number of pixels in scan line */ + /* sl == scan line */ + /* sl[slx] == next pixel to process */ + + if (slx >= np) /* No pixels left */ + state = BMP_ENDOFLINE; + else if (slx == np - 1) /* One pixel left */ + { + count = 1; + state = BMP_SINGLE; + } + else if (sl[slx] == sl[slx + 1]) /* Next 2 pixels equal */ + state = BMP_ENCODING; + else /* Next 2 pixels differ */ + state = BMP_ABSMODE; + + break; + case BMP_ENCODING: + /* Input: */ + /* slx <= np - 2 (at least 2 pixels in run) */ + /* sl[slx] == first pixel of run */ + /* sl[slx] == sl[slx + 1] */ + + count = 2; + pixel = sl[slx]; + slx += 2; + + while ((slx < np) && (pixel == sl[slx]) && (count < 255)) + { + count++; + slx++; + } + + *EncodedBuffer++ = (unsigned char)count; + BufSize++; + *EncodedBuffer++ = pixel; + BufSize++; + state = BMP_READING; + + break; + case BMP_ABSMODE: + /* Input: */ + /* slx <= np - 2 (at least 2 pixels in run) */ + /* sl[slx] == first pixel of run */ + /* sl[slx] != sl[slx + 1] */ + + oldslx = slx; + count = 2; + slx += 2; + + /* Compute number of bytes in run */ + while ((slx < np) && (sl[slx] != sl[slx - 1]) && (count < 255)) + { + count++; + slx++; + } + + /* If same-color run found, back up one byte */ + if ((slx < np) && (sl[slx] == sl[slx - 1])) + if (count > 1) + count--; + + slx = oldslx; /* Restore scan-line index */ + + /* Output short absolute runs of less than 3 pixels */ + if (count < 3 ) + state = BMP_SINGLE; + else + { + /* Output absolute-mode run */ + *EncodedBuffer++ = 0; + BufSize++; + *EncodedBuffer++ = (unsigned char)count; + BufSize++; + oldcount = count; + + while (count > 0) + { + *EncodedBuffer++ = sl[slx]; + BufSize++; + slx++; + count--; + } + + if (oldcount % 2) + { + *EncodedBuffer++ = 0; + BufSize++; + } + + state = BMP_READING; + } + break; + + case BMP_SINGLE: + /* Input: */ + /* count == number of pixels to output */ + /* slx < np */ + /* sl[slx] == first pixel of run */ + /* sl[slx] != sl[slx + 1] */ + + while (count > 0) + { + *EncodedBuffer++ = (unsigned char)1; + BufSize++; + *EncodedBuffer++ = sl[slx]; + BufSize++; + slx++; + count--; + } + + state = BMP_READING; + + break; + case BMP_ENDOFLINE: + *EncodedBuffer++ = (unsigned char)0; + BufSize++; + *EncodedBuffer++ = (unsigned char)0; + BufSize++; + done = 1; + + break; + default: + break; + } + } + + return BufSize; +} + +static const char* iBMPCompTable[2] = +{ + "NONE", + "RLE" +}; + +class imFileFormatBMP: public imFileFormatBase +{ + imBinFile* handle; /* the binary file handle */ + unsigned short bpp; /* number of bits per pixel */ + unsigned int offset, /* image data offset, used only when reading */ + comp_type; /* bmp compression information */ + int is_os2, /* indicates an os2 1.x BMP */ + line_raw_size; // raw line size + unsigned int rmask, gmask, bmask, + roff, goff, boff; /* pixel bit mask control when reading 16 and 32 bpp images */ + + int ReadPalette(); + int WritePalette(); + void FixRGBOrder(); + +public: + imFileFormatBMP(const imFormat* _iformat): imFileFormatBase(_iformat) {} + ~imFileFormatBMP() {} + + int Open(const char* file_name); + int New(const char* file_name); + void Close(); + void* Handle(int index); + int ReadImageInfo(int index); + int ReadImageData(void* data); + int WriteImageInfo(); + int WriteImageData(void* data); +}; + +class imFormatBMP: public imFormat +{ +public: + imFormatBMP() + :imFormat("BMP", + "Windows Device Independent Bitmap", + "*.bmp;*.dib;", + iBMPCompTable, + 2, + 0) + {} + ~imFormatBMP() {} + + imFileFormatBase* Create(void) const { return new imFileFormatBMP(this); } + int CanWrite(const char* compression, int color_mode, int data_type) const; +}; + + +void imFormatRegisterBMP(void) +{ + imFormatRegister(new imFormatBMP()); +} + +int imFileFormatBMP::Open(const char* file_name) +{ + unsigned short id; + unsigned int dword; + + /* opens the binary file for reading with intel byte order */ + handle = imBinFileOpen(file_name); + if (!handle) + return IM_ERR_OPEN; + + imBinFileByteOrder(handle, IM_LITTLEENDIAN); + + /* reads the BMP format identifier */ + imBinFileRead(handle, &id, 1, 2); + if (imBinFileError(handle)) + { + imBinFileClose(handle); + return IM_ERR_ACCESS; + } + + if (id != BMP_ID) + { + imBinFileClose(handle); + return IM_ERR_FORMAT; + } + + /* jump 8 bytes (file size,reserved) */ + imBinFileSeekOffset(handle, 8); + + /* reads the image offset */ + imBinFileRead(handle, &this->offset, 1, 4); + + /* reads the header size */ + imBinFileRead(handle, &dword, 1, 4); + + if (dword == 40) + this->is_os2 = 0; + else if (dword == 12) + this->is_os2 = 1; + else + { + imBinFileClose(handle); + return IM_ERR_FORMAT; + } + + this->image_count = 1; + + /* reads the compression information */ + if (this->is_os2) + { + this->comp_type = BMP_COMPRESS_RGB; + strcpy(this->compression, "NONE"); + } + else + { + imBinFileSeekOffset(handle, 12); + + imBinFileRead(handle, &this->comp_type, 1, 4); + + switch (this->comp_type) + { + case BMP_COMPRESS_RGB: + strcpy(this->compression, "NONE"); + break; + case BMP_COMPRESS_RLE8: + strcpy(this->compression, "RLE"); + break; + case BMP_COMPRESS_RLE4: + default: + imBinFileClose(handle); + return IM_ERR_COMPRESS; + } + + imBinFileSeekOffset(handle, -16); + } + + return IM_ERR_NONE; +} + +int imFileFormatBMP::New(const char* file_name) +{ + /* opens the binary file for writing with intel byte order */ + handle = imBinFileNew(file_name); + if (!handle) + return IM_ERR_OPEN; + + imBinFileByteOrder(handle, IM_LITTLEENDIAN); + + this->image_count = 1; + + return IM_ERR_NONE; +} + +void imFileFormatBMP::Close() +{ + imBinFileClose(handle); +} + +void* imFileFormatBMP::Handle(int index) +{ + if (index == 0) + return (void*)this->handle; + else + return NULL; +} + +int imFileFormatBMP::ReadImageInfo(int index) +{ + (void)index; + unsigned int dword; + + this->file_data_type = IM_BYTE; + + if (this->is_os2) + { + short word; + + /* reads the image width */ + imBinFileRead(handle, &word, 1, 2); + this->width = (int)word; + + /* reads the image height */ + imBinFileRead(handle, &word, 1, 2); + this->height = (int)((word < 0)? -word: word); + + dword = word; // it will be used later + } + else + { + /* reads the image width */ + imBinFileRead(handle, &dword, 1, 4); + this->width = (int)dword; + + /* reads the image height */ + imBinFileRead(handle, &dword, 1, 4); + this->height = (int)dword; + if (this->height < 0) + this->height = -this->height; + } + + /* jump 2 bytes (planes) */ + imBinFileSeekOffset(handle, 2); + + /* reads the number of bits per pixel */ + imBinFileRead(handle, &this->bpp, 1, 2); + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + // sanity check + if (this->bpp != 1 && this->bpp != 4 && this->bpp != 8 && + this->bpp != 16 && this->bpp != 24 && this->bpp != 32) + return IM_ERR_DATA; + + // another sanity check + if (this->comp_type == BMP_BITFIELDS && this->bpp != 16 && this->bpp != 32) + return IM_ERR_DATA; + + if (this->bpp > 8) + { + this->file_color_mode = IM_RGB; + this->file_color_mode |= IM_PACKED; + } + else + { + this->palette_count = 1 << bpp; + this->file_color_mode = IM_MAP; + } + + if (this->bpp < 8) + this->convert_bpp = this->bpp; + + if (this->bpp == 32) + this->file_color_mode |= IM_ALPHA; + + if (dword < 0) + this->file_color_mode |= IM_TOPDOWN; + + this->line_raw_size = imFileLineSizeAligned(this->width, this->bpp, 4); + this->line_buffer_extra = 4; // room enough for padding + + if (this->is_os2) + { + if (this->bpp < 24) + return ReadPalette(); + + return IM_ERR_NONE; + } + + /* we already read the compression information */ + /* jump 8 bytes (compression, image size) */ + imBinFileSeekOffset(handle, 8); + + /* read the x resolution */ + imBinFileRead(handle, &dword, 1, 4); + float xres = (float)dword / 100.0f; + + /* read the y resolution */ + imBinFileRead(handle, &dword, 1, 4); + float yres = (float)dword / 100.0f; + + if (xres && yres) + { + imAttribTable* attrib_table = AttribTable(); + attrib_table->Set("XResolution", IM_FLOAT, 1, &xres); + attrib_table->Set("YResolution", IM_FLOAT, 1, &yres); + attrib_table->Set("ResolutionUnit", IM_BYTE, -1, "DPC"); + } + + if (this->bpp <= 8) + { + /* reads the number of colors used */ + imBinFileRead(handle, &dword, 1, 4); + + /* updates the palette_count based on the number of colors used */ + if (dword != 0 && dword < (unsigned int)this->palette_count) + this->palette_count = dword; + + /* jump 4 bytes (important colors) */ + imBinFileSeekOffset(handle, 4); + } + else + { + /* jump 8 bytes (used colors, important colors) */ + imBinFileSeekOffset(handle, 8); + } + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + if (this->bpp <= 8) + return ReadPalette(); + + if (this->bpp == 16 || this->bpp == 32) + { + if (this->comp_type == BMP_BITFIELDS) + { + unsigned int Mask; + unsigned int PalMask[3]; + + imBinFileRead(handle, PalMask, 3, 4); + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + this->roff = 0; + this->rmask = Mask = PalMask[0]; + while (!(Mask & 0x01) && (Mask != 0)) + {Mask >>= 1; this->roff++;} + + this->goff = 0; + this->gmask = Mask = PalMask[1]; + while (!(Mask & 0x01) && (Mask != 0)) + {Mask >>= 1; this->goff++;} + + this->boff = 0; + this->bmask = Mask = PalMask[2]; + while (!(Mask & 0x01) && (Mask != 0)) + {Mask >>= 1; this->boff++;} + } + else + { + if (this->bpp == 16) + { + this->rmask = 0x7C00; + this->roff = 10; + + this->gmask = 0x03E0; + this->goff = 5; + + this->bmask = 0x001F; + this->boff = 0; + } + else + { + this->rmask = 0x00FF0000; + this->roff = 16; + + this->gmask = 0x0000FF00; + this->goff = 8; + + this->bmask = 0x000000FF; + this->boff = 0; + } + } + } + + return IM_ERR_NONE; +} + +int imFileFormatBMP::WriteImageInfo() +{ + // force bottom up orientation + this->file_data_type = IM_BYTE; + this->file_color_mode = imColorModeSpace(this->user_color_mode); + + if (imStrEqual(this->compression, "RLE")) + this->comp_type = BMP_COMPRESS_RLE8; + else + this->comp_type = BMP_COMPRESS_RGB; + + if (this->file_color_mode == IM_BINARY) + { + this->bpp = 1; + this->convert_bpp = 1; + } + else if (this->file_color_mode == IM_RGB) + { + this->file_color_mode |= IM_PACKED; + this->bpp = 24; + + if (imColorModeHasAlpha(this->user_color_mode)) + { + this->file_color_mode |= IM_ALPHA; + this->bpp = 32; + + this->rmask = 0x00FF0000; + this->roff = 16; + + this->gmask = 0x0000FF00; + this->goff = 8; + + this->bmask = 0x000000FF; + this->boff = 0; + } + } + else + this->bpp = 8; + + this->line_raw_size = imFileLineSizeAligned(this->width, this->bpp, 4); + this->line_buffer_extra = 4; // room enough for padding + + if (this->comp_type == BMP_COMPRESS_RLE8) + { + // allocates more than enough since compression algoritm can be ineficient + this->line_buffer_extra += 2*this->line_raw_size; + } + + /* writes the BMP file header */ + int palette_size = (this->bpp > 8)? 0: palette_count*4; + short word_value = BMP_ID; + imBinFileWrite(handle, &word_value, 1, 2); /* identifier */ + unsigned int dword_value = 14 + 40 + palette_size + line_raw_size * this->height; + imBinFileWrite(handle, &dword_value, 1, 4); /* file size for uncompressed images */ + word_value = 0; + imBinFileWrite(handle, &word_value, 1, 2); /* reserved 1 */ + imBinFileWrite(handle, &word_value, 1, 2); /* reserved 2 */ + dword_value = 14 + 40 + palette_size; + imBinFileWrite(handle, &dword_value, 1, 4); /* data offset */ + + /* writes the BMP info header */ + + dword_value = 40; + imBinFileWrite(handle, &dword_value, 1, 4); /* header size */ + dword_value = this->width; + imBinFileWrite(handle, &dword_value, 1, 4); /* width */ + dword_value = this->height; + imBinFileWrite(handle, &dword_value, 1, 4); /* height */ + word_value = 1; + imBinFileWrite(handle, &word_value, 1, 2); /* planes */ + word_value = this->bpp; + imBinFileWrite(handle, &word_value, 1, 2); /* bpp */ + dword_value = this->comp_type; + imBinFileWrite(handle, &dword_value, 1, 4); /* compression */ + dword_value = line_raw_size * this->height; + imBinFileWrite(handle, &dword_value, 1, 4); /* image size */ + + imAttribTable* attrib_table = AttribTable(); + unsigned int xppm = 0, yppm = 0; + + const void* attrib_data = attrib_table->Get("ResolutionUnit"); + if (attrib_data) + { + char* res_unit = (char*)attrib_data; + + float* xres = (float*)attrib_table->Get("XResolution"); + float* yres = (float*)attrib_table->Get("YResolution"); + + if (xres && yres) + { + if (imStrEqual(res_unit, "DPI")) + { + xppm = (unsigned int)(*xres * 100. / 2.54); + yppm = (unsigned int)(*yres * 100. / 2.54); + } + else + { + xppm = (unsigned int)(*xres * 100.); + yppm = (unsigned int)(*yres * 100.); + } + } + } + + imBinFileWrite(handle, &xppm, 1, 4); /* x dpm */ + imBinFileWrite(handle, &yppm, 1, 4); /* y dpm */ + + dword_value = (this->bpp > 8)? 0: this->palette_count; + imBinFileWrite(handle, &dword_value, 1, 4); /* colors used */ + dword_value = 0; + imBinFileWrite(handle, &dword_value, 1, 4); /* colors important (all) */ + + /* tests if everything was ok */ + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + if (this->bpp < 24) + return WritePalette(); + + return IM_ERR_NONE; +} + +int imFileFormatBMP::ReadPalette() +{ + int nc; + if (this->is_os2) + nc = 3; + else + nc = 4; + + /* reads the color palette */ + unsigned char bmp_colors[256 * 4]; + imBinFileRead(handle, bmp_colors, this->palette_count * nc, 1); + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + /* convert the color map to the IM format */ + for (int c = 0; c < this->palette_count; c++) + { + int i = c * nc; + this->palette[c] = imColorEncode(bmp_colors[i + 2], + bmp_colors[i + 1], + bmp_colors[i]); + } + + return IM_ERR_NONE; +} + +int imFileFormatBMP::WritePalette() +{ + unsigned char bmp_colors[256 * 4]; + + /* convert the color map to the IM format */ + for (int c = 0; c < this->palette_count; c++) + { + int i = c * 4; + imColorDecode(&bmp_colors[i + 2], &bmp_colors[i + 1], &bmp_colors[i], this->palette[c]); + bmp_colors[i + 3] = 0; + } + + /* writes the color palette */ + imBinFileWrite(handle, bmp_colors, this->palette_count * 4, 1); + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + return IM_ERR_NONE; +} + +void imFileFormatBMP::FixRGBOrder() +{ + int x; + + switch (this->bpp) + { + case 16: + { + /* inverts the WORD values if not intel */ + if (imBinCPUByteOrder() == IM_BIGENDIAN) + imBinSwapBytes2(this->line_buffer, this->width); + + imushort* word_data = (imushort*)this->line_buffer; + imbyte* byte_data = (imbyte*)this->line_buffer; + + // from end to start + for (x = this->width-1; x >= 0; x--) + { + imushort word_value = word_data[x]; + int c = x*3; + byte_data[c] = (imbyte)((((this->rmask & word_value) >> this->roff) * 255) / (this->rmask >> this->roff)); + byte_data[c+1] = (imbyte)((((this->gmask & word_value) >> this->goff) * 255) / (this->gmask >> this->goff)); + byte_data[c+2] = (imbyte)((((this->bmask & word_value) >> this->boff) * 255) / (this->bmask >> this->boff)); + } + } + break; + case 32: + { + /* inverts the DWORD values if not intel */ + if (imBinCPUByteOrder() == IM_BIGENDIAN) + imBinSwapBytes4(this->line_buffer, this->width); + + unsigned int* dword_data = (unsigned int*)this->line_buffer; + imbyte* byte_data = (imbyte*)this->line_buffer; + + for (x = 0; x < this->width; x++) + { + unsigned int dword_value = dword_data[x]; + int c = x*4; + byte_data[c] = (imbyte)((this->rmask & dword_value) >> this->roff); + byte_data[c+1] = (imbyte)((this->gmask & dword_value) >> this->goff); + byte_data[c+2] = (imbyte)((this->bmask & dword_value) >> this->boff); + byte_data[c+3] = (imbyte)((0xFF000000 & dword_value) >> 24); + } + } + break; + default: // 24 + { + imbyte* byte_data = (imbyte*)this->line_buffer; + for (x = 0; x < this->width; x++) + { + int c = x*3; + imbyte temp = byte_data[c]; // swap R and B + byte_data[c] = byte_data[c+2]; + byte_data[c+2] = temp; + } + } + break; + } +} + +int imFileFormatBMP::ReadImageData(void* data) +{ + imCounterTotal(this->counter, this->height, "Reading BMP..."); + + /* jump to the begin of image data */ + imBinFileSeekTo(handle, this->offset); + + for (int row = 0; row < this->height; row++) + { + /* read and decompress the data */ + if (this->comp_type == BMP_COMPRESS_RGB) + { + imBinFileRead(handle, this->line_buffer, this->line_raw_size, 1); + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + } + else + { + if (iBMPDecodeScanLine(handle, (imbyte*)this->line_buffer, this->width) == IM_ERR_ACCESS) + return IM_ERR_ACCESS; + } + + if (this->bpp > 8) + FixRGBOrder(); + + imFileLineBufferRead(this, data, row, 0); + + if (!imCounterInc(this->counter)) + return IM_ERR_COUNTER; + } + + return IM_ERR_NONE; +} + +int imFileFormatBMP::WriteImageData(void* data) +{ + imCounterTotal(this->counter, this->height, "Writing BMP..."); + + imbyte* compressed_buffer = NULL; + if (this->comp_type == BMP_COMPRESS_RLE8) // point to the extra buffer + compressed_buffer = (imbyte*)this->line_buffer + this->line_buffer_size+4; + + for (int row = 0; row < this->height; row++) + { + imFileLineBufferWrite(this, data, row, 0); + + if (this->bpp > 8) + FixRGBOrder(); + + if (this->comp_type == BMP_COMPRESS_RGB) + { + imBinFileWrite(handle, this->line_buffer, this->line_raw_size, 1); + } + else + { + int compressed_size = iBMPEncodeScanLine(compressed_buffer, (imbyte*)this->line_buffer, this->width); + imBinFileWrite(handle, compressed_buffer, compressed_size, 1); + } + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + if (!imCounterInc(this->counter)) + return IM_ERR_COUNTER; + } + + return IM_ERR_NONE; +} + +int imFormatBMP::CanWrite(const char* compression, int color_mode, int data_type) const +{ + int color_space = imColorModeSpace(color_mode); + + if (color_space == IM_YCBCR || color_space == IM_LAB || + color_space == IM_LUV || color_space == IM_XYZ || + color_space == IM_CMYK) + return IM_ERR_DATA; + + if (data_type != IM_BYTE) + return IM_ERR_DATA; + + if (!compression || compression[0] == 0) + return IM_ERR_NONE; + + if (!imStrEqual(compression, "NONE") && !imStrEqual(compression, "RLE")) + return IM_ERR_COMPRESS; + + if (imStrEqual(compression, "RLE") && (color_space == IM_RGB || color_space == IM_BINARY)) + return IM_ERR_COMPRESS; + + return IM_ERR_NONE; +} diff --git a/im/src/im_format_ecw.cpp b/im/src/im_format_ecw.cpp new file mode 100755 index 0000000..bba99b0 --- /dev/null +++ b/im/src/im_format_ecw.cpp @@ -0,0 +1,385 @@ +/** \file + * \brief ECW - ECW JPEG 2000 + * + * See Copyright Notice in im_lib.h + */ + +#include "im_format.h" +#include "im_util.h" +#include "im_format_ecw.h" +#include "im_counter.h" + +#include +// #include + +#include +#include +#include +#include + +static const char* iECWCompTable[2] = +{ + "ECW", + "JPEG-2000", +}; + +class imFileFormatECW: public imFileFormatBase +{ + NCSFileView *pNCSFileView; +// NCSEcwCompressClient *pClient; + +public: + imFileFormatECW(const imFormat* _iformat): imFileFormatBase(_iformat) {} + ~imFileFormatECW() {} + + int Open(const char* file_name); + int New(const char* file_name); + void Close(); + void* Handle(int index); + int ReadImageInfo(int index); + int ReadImageData(void* data); + int WriteImageInfo(){return 0;} // do nothing for now; + int WriteImageData(void* data){(void)data; return 0;} // do nothing for now; +}; + +class imFormatECW: public imFormat +{ +public: + imFormatECW() + :imFormat("ECW", + "ECW JPEG-2000 File Format", + "*.ecw;*.jp2;*.j2k;*.jpc;*.j2c;", + iECWCompTable, + 2, + 0) + {} + ~imFormatECW() {} + + imFileFormatBase* Create(void) const { return new imFileFormatECW(this); } + int CanWrite(const char* compression, int color_mode, int data_type) const; +}; + +void imFormatRegisterECW(void) +{ + imFormatRegister(new imFormatECW()); +} + +int imFileFormatECW::Open(const char* file_name) +{ + NCSError eError = NCScbmOpenFileView((char*)file_name, &this->pNCSFileView, NULL); + if (eError != NCS_SUCCESS) + { + if (eError == NCS_FILE_OPEN_ERROR || + eError == NCS_FILE_NOT_FOUND || + eError == NCS_FILE_INVALID) + return IM_ERR_OPEN; + else if (eError == NCS_FILE_OPEN_FAILED) + return IM_ERR_FORMAT; + else + return IM_ERR_ACCESS; + } + + NCSFileType fileType = NCScbmGetFileType(this->pNCSFileView); + if (fileType == NCS_FILE_ECW) + strcpy(this->compression, "ECW"); + else if (fileType == NCS_FILE_JP2) + strcpy(this->compression, "JPEG-2000"); + else + return IM_ERR_COMPRESS; + + this->image_count = 1; + + return IM_ERR_NONE; +} + +int imFileFormatECW::New(const char* file_name) +{ + strcpy(this->compression, "JPEG-2000"); + this->image_count = 1; + + (void)file_name; + return IM_ERR_FORMAT; +} + +void imFileFormatECW::Close() +{ + if (this->is_new) + ;// NCSEcwCompressClose(this->pClient); + else + NCScbmCloseFileView(this->pNCSFileView); +} + +void* imFileFormatECW::Handle(int index) +{ + (void)index; + + if (this->is_new) + return NULL; // return (void*)this->pClient; + else + return (void*)this->pNCSFileView; +} + +int imFileFormatECW::ReadImageInfo(int index) +{ + NCSFileViewFileInfoEx *pNCSFileInfo; + imAttribTable* attrib_table = AttribTable(); + (void)index; + + if (NCScbmGetViewFileInfoEx(this->pNCSFileView, &pNCSFileInfo) != NCS_SUCCESS) + return IM_ERR_ACCESS; + + this->width = pNCSFileInfo->nSizeX; + this->height = pNCSFileInfo->nSizeY; + + switch(pNCSFileInfo->eColorSpace) + { + case NCSCS_GREYSCALE: + this->file_color_mode = IM_GRAY; + break; + case NCSCS_YUV: + case NCSCS_sRGB: + this->file_color_mode = IM_RGB; + break; + case NCSCS_YCbCr: + this->file_color_mode = IM_YCBCR; + break; + case NCSCS_MULTIBAND: + /* multiband data, we read only one band */ + this->file_color_mode = IM_GRAY; + attrib_table->Set("MultiBandCount", IM_USHORT, 1, (void*)&pNCSFileInfo->nBands); + break; + default: + return IM_ERR_DATA; + } + + switch(pNCSFileInfo->eCellType) + { + case NCSCT_INT8: + case NCSCT_UINT8: + this->file_data_type = IM_BYTE; + break; + case NCSCT_INT16: + case NCSCT_UINT16: + this->file_data_type = IM_USHORT; + break; + case NCSCT_UINT64: + case NCSCT_INT64: + case NCSCT_UINT32: + case NCSCT_INT32: + // Should be: this->file_data_type = IM_INT; + // but 32bits ints are not supported by the NCScbmReadViewLineBILEx function + this->file_data_type = IM_USHORT; + break; + case NCSCT_IEEE4: + case NCSCT_IEEE8: + this->file_data_type = IM_FLOAT; + break; + default: + return IM_ERR_DATA; + } + + int prec = pNCSFileInfo->pBands->nBits; + if (prec < 8) + this->convert_bpp = -prec; // just expand to 0-255 + + if (prec == 1 && this->file_color_mode == IM_GRAY) + this->file_color_mode = IM_BINARY; + + if (pNCSFileInfo->nBands > imColorModeDepth(this->file_color_mode)) + this->file_color_mode |= IM_ALPHA; + + if (this->file_color_mode != IM_GRAY) + this->file_color_mode |= IM_PACKED; + + this->file_color_mode |= IM_TOPDOWN; + + float float_value = (float)pNCSFileInfo->fOriginX; + attrib_table->Set("OriginX", IM_FLOAT, 1, (void*)&float_value); + + float_value = (float)pNCSFileInfo->fOriginY; + attrib_table->Set("OriginY", IM_FLOAT, 1, (void*)&float_value); + + float_value = (float)pNCSFileInfo->fCWRotationDegrees; + attrib_table->Set("Rotation", IM_FLOAT, 1, (void*)&float_value); + + float_value = (float)pNCSFileInfo->fCellIncrementX; + attrib_table->Set("CellIncrementX", IM_FLOAT, 1, (void*)&float_value); + + float_value = (float)pNCSFileInfo->fCellIncrementY; + attrib_table->Set("CellIncrementY", IM_FLOAT, 1, (void*)&float_value); + + attrib_table->Set("Datum", IM_BYTE, strlen(pNCSFileInfo->szDatum)+1, pNCSFileInfo->szDatum); + attrib_table->Set("Projection", IM_BYTE, strlen(pNCSFileInfo->szProjection)+1, pNCSFileInfo->szProjection); + + switch (pNCSFileInfo->eCellSizeUnits) + { + case ECW_CELL_UNITS_INVALID: + attrib_table->Set("CellUnits", IM_BYTE, 8, "INVALID"); + break; + case ECW_CELL_UNITS_METERS: + attrib_table->Set("CellUnits", IM_BYTE, 7, "METERS"); + break; + case ECW_CELL_UNITS_DEGREES: + attrib_table->Set("CellUnits", IM_BYTE, 7, "DEGREES"); + break; + case ECW_CELL_UNITS_FEET: + attrib_table->Set("CellUnits", IM_BYTE, 5, "FEET"); + break; + case ECW_CELL_UNITS_UNKNOWN: + attrib_table->Set("CellUnits", IM_BYTE, 8, "UNKNOWN"); + break; + } + + float_value = (float)pNCSFileInfo->nCompressionRate; + attrib_table->Set("CompressionRatio", IM_FLOAT, 1, (void*)&float_value); + + return IM_ERR_NONE; +} + +static void iCopyDataBuffer(UINT8 **ppOutputLine, imbyte* line_buffer, int nBands, int view_width, int type_size) +{ + if (nBands > 1) + { + for(int i = 0; i < view_width; i++) + { + for(int j = 0; j < nBands; j++) + { + for(int k = 0; k < type_size; k++) + { + *line_buffer++ = (ppOutputLine[j])[i*type_size + k]; + } + } + } + } + else + memcpy(line_buffer, ppOutputLine[0], nBands*type_size*view_width); +} + +int imFileFormatECW::ReadImageData(void* data) +{ + imAttribTable* attrib_table = AttribTable(); + int i, *attrib_data, view_width, view_height, + nBands = imColorModeDepth(this->file_color_mode); + + // this size is free, can be anything, but we restricted to less than the image size + attrib_data = (int*)attrib_table->Get("ViewWidth"); + view_width = attrib_data? *attrib_data: this->width; + if (view_width > this->width) view_width = this->width; + + attrib_data = (int*)attrib_table->Get("ViewHeight"); + view_height = attrib_data? *attrib_data: this->height; + if (view_height > this->height) view_height = this->height; + + imCounterTotal(this->counter, view_height, "Reading ECW..."); + + { + int xmin, xmax, ymin, ymax, band_start; + + // full image if not defined. + // this size must be inside the image + attrib_data = (int*)attrib_table->Get("ViewXmin"); + xmin = attrib_data? *attrib_data: 0; + if (xmin < 0) xmin = 0; + + attrib_data = (int*)attrib_table->Get("ViewYmin"); + ymin = attrib_data? *attrib_data: 0; + if (ymin < 0) ymin = 0; + + attrib_data = (int*)attrib_table->Get("ViewXmax"); + xmax = attrib_data? *attrib_data: this->width-1; + if (xmax > this->width-1) xmax = this->width-1; + + attrib_data = (int*)attrib_table->Get("ViewYmax"); + ymax = attrib_data? *attrib_data: this->height-1; + if (ymax > this->height-1) ymax = this->height-1; + + band_start = 0; + UINT16* start_plane = (UINT16*)attrib_table->Get("MultiBandSelect"); + if (start_plane) + band_start = *start_plane; + + UINT32 *pBandList = (UINT32*)malloc(sizeof(UINT32)*nBands); + for(i = 0; i < nBands; i++) + pBandList[i] = i+band_start; + + NCSError eError = NCScbmSetFileView(this->pNCSFileView, nBands, pBandList, + xmin, ymin, xmax, ymax, + view_width, view_height); + free(pBandList); + + if( eError != NCS_SUCCESS) + return IM_ERR_DATA; + } + + // this is necessary to fool line buffer management + this->width = view_width; + this->height = view_height; + this->line_buffer_size = imImageLineSize(this->width, this->file_color_mode, this->file_data_type); + + NCSEcwCellType eType = NCSCT_UINT8; + int type_size = 1; + if (this->file_data_type == IM_USHORT) + { + eType = NCSCT_UINT16; + type_size = 2; + } + else if (this->file_data_type == IM_FLOAT) + { + eType = NCSCT_IEEE4; + type_size = 4; + } + UINT8 **ppOutputLine = (UINT8**)malloc(sizeof(UINT8*)*nBands); + UINT8 *ppOutputBuffer = (UINT8*)malloc(type_size*view_width*nBands); + for(i = 0; i < nBands; i++) + ppOutputLine[i] = ppOutputBuffer + i*type_size*view_width; + + for (int row = 0; row < view_height; row++) + { + NCSEcwReadStatus eError = NCScbmReadViewLineBILEx(this->pNCSFileView, eType, (void**)ppOutputLine); + if( eError != NCS_SUCCESS) + { + free(ppOutputLine); + free(ppOutputBuffer); + return IM_ERR_DATA; + } + + iCopyDataBuffer(ppOutputLine, (imbyte*)this->line_buffer, nBands, view_width, type_size); + + imFileLineBufferRead(this, data, row, 0); + + if (!imCounterInc(this->counter)) + { + free(ppOutputLine); + free(ppOutputBuffer); + return IM_ERR_COUNTER; + } + } + + free(ppOutputLine); + free(ppOutputBuffer); + return IM_ERR_NONE; +} + +int imFormatECW::CanWrite(const char* compression, int color_mode, int data_type) const +{ + (void)compression; + (void)color_mode; + (void)data_type; + return IM_ERR_DATA; + + //int color_space = imColorModeSpace(color_mode); + + //if (color_space != IM_GRAY && color_space != IM_RGB)// && color_space != IM_LUV) + // return IM_ERR_DATA; + // + //if (data_type != IM_BYTE && data_type != IM_USHORT && data_type != IM_FLOAT) + // return IM_ERR_DATA; + + //if (!compression || compression[0] == 0) + // return IM_ERR_NONE; + + //if (!imStrEqual(compression, "JPEG-2000")) + // return IM_ERR_COMPRESS; + + //return IM_ERR_NONE; +} diff --git a/im/src/im_format_gif.cpp b/im/src/im_format_gif.cpp new file mode 100755 index 0000000..caadd0f --- /dev/null +++ b/im/src/im_format_gif.cpp @@ -0,0 +1,1510 @@ +/** \file + * \brief GIF - Graphics Interchange Format + * + * See Copyright Notice in im_lib.h + * $Id: im_format_gif.cpp,v 1.5 2009/08/23 23:57:51 scuri Exp $ + */ + +#include "im_format.h" +#include "im_format_all.h" +#include "im_util.h" +#include "im_counter.h" + +#include "im_binfile.h" + +#include +#include +#include + +static const int InterlacedOffset[4] = { 0, 4, 2, 1 }, /* The way Interlaced image should */ + InterlacedJumps[4] = { 8, 8, 4, 2 }; /* be read - offsets and jumps... */ + +#define GIF_STAMP "GIF" /* First chars in file - GIF stamp. */ +#define GIF_VERSION "89a" /* First chars in file - GIF stamp. */ + +#define GIF_LZ_BITS 12 + +#define GIF_LZ_MAX_CODE 4095 /* Biggest code possible in 12 bits. */ +#define GIF_FLUSH_OUTPUT 4096 /* Impossible code, to signal flush. */ +#define GIF_FIRST_CODE 4097 /* Impossible code, to signal first. */ +#define GIF_NO_SUCH_CODE 4098 /* Impossible code, to signal empty. */ + +#define GIF_HT_KEY_MASK 0x1FFF /* 13bits keys */ +#define GIF_HT_KEY_NUM_BITS 13 /* 13bits keys */ +#define GIF_HT_MAX_KEY 8191 /* 13bits - 1, maximal code possible */ +#define GIF_HT_SIZE 8192 /* 12bits = 4096 or twice as big! */ + +/* GIF89 extension function codes */ +#define COMMENT_EXT_FUNC_CODE 0xFE /* comment */ +#define GRAPHICS_EXT_FUNC_CODE 0xF9 /* graphics control */ +#define PLAINTEXT_EXT_FUNC_CODE 0x01 /* plaintext */ +#define APPLICATION_EXT_FUNC_CODE 0xFF /* application block */ + +/* The 32 bits of the integer are divided into two parts for the key & code: */ +/* 1. The code is 12 bits as our compression algorithm is limited to 12bits */ +/* 2. The key is 12 bits Prefix code + 8 bit new char or 20 bits. */ +#define GIF_HT_GET_KEY(l) (l >> 12) +#define GIF_HT_GET_CODE(l) (l & 0x0FFF) +#define GIF_HT_PUT_KEY(l) (l << 12) +#define GIF_HT_PUT_CODE(l) (l & 0x0FFF) + +struct iGIFData +{ + unsigned char global_colors[256 * 3]; /* global color table if any */ + int global_num_colors, /* global color table number of colors */ + offset, /* image offset */ + step, /* interlaced step */ + interlaced, /* image is interlaced or not */ + screen_width, + screen_height, + start_offset[512], /* offset of first block */ + ClearCode, /* The CLEAR LZ code. */ + BitsPerPixel, /* Bits per pixel (Codes uses at list this + 1). */ + EOFCode, /* The EOF LZ code. */ + RunningCode, /* The next code algorithm can generate. */ + RunningBits, /* The number of bits required to represent RunningCode. */ + MaxCode1, /* 1 bigger than max. possible code, in RunningBits bits. */ + LastCode, /* The code before the current code. */ + CrntCode, /* Current algorithm code. */ + StackPtr, /* For character stack (see below). */ + CrntShiftState; /* Number of bits in CrntShiftDWord. */ + unsigned char Buf[256]; /* Compressed input is buffered here. */ + unsigned int CrntShiftDWord; /* For bytes decomposition into codes. */ + unsigned char Stack[GIF_LZ_MAX_CODE]; /* Decoded pixels are stacked here. */ + unsigned char Suffix[GIF_LZ_MAX_CODE+1]; /* So we can trace the codes. */ + unsigned int Prefix[GIF_LZ_MAX_CODE+1]; + unsigned int HTable[GIF_HT_SIZE]; /* hash table for the compression only, when using LZW */ +}; + +/****************************************************************************** +* Routine to generate an HKey for the hashtable out of the given unique key. * +* The given Key is assumed to be 20 bits as follows: lower 8 bits are the * +* new postfix character, while the upper 12 bits are the prefix code. * +* Because the average hit ratio is only 2 (2 hash references per entry), * +* evaluating more complex keys (such as twin prime keys) does not worth it! * +******************************************************************************/ +static int iGIFHashKeyItem(unsigned int Item) +{ + return ((Item >> 12) ^ Item) & GIF_HT_KEY_MASK; +} + +/****************************************************************************** +* Routine to insert a new Item into the HashTable. The data is assumed to be * +* new one. * +******************************************************************************/ +static void iGIFInsertHashTable(unsigned int *HTable, unsigned int Key, int Code) +{ + int HKey = iGIFHashKeyItem(Key); + + while (GIF_HT_GET_KEY(HTable[HKey]) != 0xFFFFFL) + { + HKey = (HKey + 1) & GIF_HT_KEY_MASK; + } + + HTable[HKey] = GIF_HT_PUT_KEY(Key) | GIF_HT_PUT_CODE(Code); +} + +/****************************************************************************** +* Routine to test if given Key exists in HashTable and if so returns its code * +* Returns the Code if key was found, -1 if not. * +******************************************************************************/ +static int iGIFExistsHashTable(unsigned int *HTable, unsigned int Key) +{ + int HKey = iGIFHashKeyItem(Key); + unsigned int HTKey; + + while ((HTKey = GIF_HT_GET_KEY(HTable[HKey])) != 0xFFFFFL) + { + if (Key == HTKey) + return GIF_HT_GET_CODE(HTable[HKey]); + + HKey = (HKey + 1) & GIF_HT_KEY_MASK; + } + + return -1; +} + +/****************************************************************************** +* This routines buffers the given characters until 255 characters are ready * +* to be output. If Code is equal to -1 the buffer is flushed (EOF). * +* The buffer is Dumped with first byte as its size, as GIF format requires. * +******************************************************************************/ +static int iGIFBufferedOutput(imBinFile* handle, unsigned char *Buf, int c) +{ + if (c == GIF_FLUSH_OUTPUT) + { + /* Flush everything out. */ + if (Buf[0] != 0) + imBinFileWrite(handle, Buf, Buf[0] + 1, 1); + + /* Mark end of compressed data, by an empty block (see GIF doc): */ + Buf[0] = 0; + imBinFileWrite(handle, Buf, 1, 1); + } + else + { + if (Buf[0] == 255) + { + /* Dump out this buffer - it is full: */ + imBinFileWrite(handle, Buf, Buf[0] + 1, 1); + Buf[0] = 0; + } + + Buf[++Buf[0]] = (unsigned char)c; + } + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + return IM_ERR_NONE; +} + +static int iGIFWriteNetscapeApplication(imBinFile* handle, short iterations) +{ + /* record type byte */ + imBinFileWrite(handle, (void*)"!", 1, 1); + + /* block label */ + imBinFileWrite(handle, (void*)"\xFF", 1, 1); + + /* block size */ + imBinFileWrite(handle, (void*)"\x0B", 1, 1); + + /* application identifier + athentication code */ + imBinFileWrite(handle, (void*)"NETSCAPE2.0", 11, 1); + + /* sub block size */ + imBinFileWrite(handle, (void*)"\x3", 1, 1); + + /* ??? */ + imBinFileWrite(handle, (void*)"\x1", 1, 1); + + /* iterations */ + imBinFileWrite(handle, &iterations, 1, 2); + + /* block terminator */ + imBinFileWrite(handle, (void*)"\0", 1, 1); + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + return IM_ERR_NONE; +} + +/****************************************************************************** +* The LZ compression output routine: * +* This routine is responsable for the compression of the bit stream into * +* 8 bits (bytes) packets. * +******************************************************************************/ +static int iGIFCompressOutput(iGIFData* igif, imBinFile* handle, int Code) +{ + int error = IM_ERR_NONE; + + if (Code == GIF_FLUSH_OUTPUT) + { + while (igif->CrntShiftState > 0) + { + /* Get Rid of what is left in DWord, and flush it. */ + error = iGIFBufferedOutput(handle, igif->Buf, igif->CrntShiftDWord & 0xff); + igif->CrntShiftDWord >>= 8; + igif->CrntShiftState -= 8; + } + igif->CrntShiftState = 0; /* For next time. */ + error = iGIFBufferedOutput(handle, igif->Buf, GIF_FLUSH_OUTPUT); + } + else + { + igif->CrntShiftDWord |= ((int) Code) << igif->CrntShiftState; + igif->CrntShiftState += igif->RunningBits; + while (igif->CrntShiftState >= 8) + { + /* Dump out full bytes: */ + error = iGIFBufferedOutput(handle, igif->Buf, igif->CrntShiftDWord & 0xff); + igif->CrntShiftDWord >>= 8; + igif->CrntShiftState -= 8; + } + } + + /* If code cannt fit into RunningBits bits, must raise its size. Note */ + /* however that codes above 4095 are used for special signaling. */ + if (igif->RunningCode >= igif->MaxCode1 && Code <= GIF_LZ_MAX_CODE) + { + igif->MaxCode1 = 1 << ++igif->RunningBits; + } + + return error; +} + +/****************************************************************************** +* The LZ compression routine: * +* This version compress the given buffer Line of length LineLen. * +* This routine can be called few times (one per scan line, for example), in * +* order the complete the whole image. * +******************************************************************************/ +static int iGIFCompressLine(iGIFData* igif, imBinFile* handle, unsigned char *Line, int LineLen) +{ + int i = 0, CrntCode, NewCode; + unsigned int NewKey; + unsigned char Pixel; + + if (igif->CrntCode == GIF_FIRST_CODE) /* Its first time! */ + CrntCode = Line[i++]; + else + CrntCode = igif->CrntCode; /* Get last code in compression. */ + + while (i < LineLen) + { /* Decode LineLen items. */ + Pixel = Line[i++]; /* Get next pixel from stream. */ + /* Form a new unique key to search hash table for the code combines */ + /* CrntCode as Prefix string with Pixel as postfix char. */ + NewKey = (((unsigned int) CrntCode) << 8) + Pixel; + + if ((NewCode = iGIFExistsHashTable(igif->HTable, NewKey)) >= 0) + { + /* This Key is already there, or the string is old one, so */ + /* simple take new code as our CrntCode: */ + CrntCode = NewCode; + } + else + { + /* Put it in hash table, output the prefix code, and make our */ + /* CrntCode equal to Pixel. */ + if (iGIFCompressOutput(igif, handle, CrntCode) != IM_ERR_NONE) + return IM_ERR_ACCESS; + + CrntCode = Pixel; + + /* If however the HashTable if full, we send a clear first and */ + /* Clear the hash table. */ + if (igif->RunningCode >= GIF_LZ_MAX_CODE) + { + /* Time to do some clearance: */ + if (iGIFCompressOutput(igif, handle, igif->ClearCode) != IM_ERR_NONE) + return IM_ERR_ACCESS; + + igif->RunningCode = igif->EOFCode + 1; + igif->RunningBits = igif->BitsPerPixel + 1; + igif->MaxCode1 = 1 << igif->RunningBits; + memset(igif->HTable, 0xFF, GIF_HT_SIZE * sizeof(int)); + } + else + { + /* Put this unique key with its relative Code in hash table: */ + iGIFInsertHashTable(igif->HTable, NewKey, igif->RunningCode++); + } + } + } + + /* Preserve the current state of the compression algorithm: */ + igif->CrntCode = CrntCode; + + return IM_ERR_NONE; +} + +/****************************************************************************** +* This routines read one gif data block at a time and buffers it internally * +* so that the decompression routine could access it. * +* The routine returns the next byte from its internal buffer (or read next * +* block in if buffer empty). * +******************************************************************************/ +static int iGIFBufferedInput(imBinFile* handle, unsigned char *Buf, unsigned char *NextByte) +{ + if (Buf[0] == 0) + { + /* Needs to read the next buffer - this one is empty: */ + imBinFileRead(handle, Buf, 1, 1); + imBinFileRead(handle, &Buf[1], Buf[0], 1); + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + *NextByte = Buf[1]; + Buf[1] = 2; /* We use now the second place as last char read! */ + Buf[0]--; + } + else + { + *NextByte = Buf[Buf[1]++]; + Buf[0]--; + } + + return IM_ERR_NONE; +} + +/****************************************************************************** +* The LZ decompression input routine: * +* This routine is responsable for the decompression of the bit stream from * +* 8 bits (bytes) packets, into the real codes. * +******************************************************************************/ +static int iGIFDecompressInput(iGIFData* igif, imBinFile* handle, int *Code) +{ + unsigned char NextByte; + static unsigned int CodeMasks[] = + { + 0x0000, 0x0001, 0x0003, 0x0007, + 0x000f, 0x001f, 0x003f, 0x007f, + 0x00ff, 0x01ff, 0x03ff, 0x07ff, + 0x0fff + }; + + while (igif->CrntShiftState < igif->RunningBits) + { + /* Needs to get more bytes from input stream for next code: */ + if (iGIFBufferedInput(handle, igif->Buf, &NextByte) != IM_ERR_NONE) + return IM_ERR_ACCESS; + + igif->CrntShiftDWord |= ((unsigned int) NextByte) << igif->CrntShiftState; + igif->CrntShiftState += 8; + } + + *Code = igif->CrntShiftDWord & CodeMasks[igif->RunningBits]; + + igif->CrntShiftDWord >>= igif->RunningBits; + igif->CrntShiftState -= igif->RunningBits; + + /* If code cannt fit into RunningBits bits, must raise its size. Note */ + /* however that codes above 4095 are used for special signaling. */ + if (++(igif->RunningCode) > igif->MaxCode1 && igif->RunningBits < GIF_LZ_BITS) + { + igif->MaxCode1 <<= 1; + igif->RunningBits++; + } + + return IM_ERR_NONE; +} + +/****************************************************************************** +* Routine to trace the Prefixes linked list until we get a prefix which is * +* not code, but a pixel value (less than ClearCode). Returns that pixel value.* +* If image is defective, we might loop here forever, so we limit the loops to * +* the maximum possible if image O.k. - LZ_MAX_CODE times. * +******************************************************************************/ +static int iGIFGetPrefixChar(unsigned int *Prefix, int Code, int ClearCode) +{ + int i = 0; + + while (Code > ClearCode && i++ <= GIF_LZ_MAX_CODE) + Code = Prefix[Code]; + + return Code; +} + +static int iGIFDecompressLine(iGIFData* igif, imBinFile* handle, unsigned char *Line, int LineLen) +{ + int i = 0, j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr; + unsigned char *Stack, *Suffix; + unsigned int *Prefix; + + StackPtr = igif->StackPtr; + Prefix = igif->Prefix; + Suffix = igif->Suffix; + Stack = igif->Stack; + EOFCode = igif->EOFCode; + ClearCode = igif->ClearCode; + LastCode = igif->LastCode; + + if (StackPtr != 0) + { + /* Let pop the stack off before continueing to read the gif file: */ + while (StackPtr != 0 && i < LineLen) + Line[i++] = Stack[--StackPtr]; + } + + while (i < LineLen) + { + /* Decode LineLen items. */ + if (iGIFDecompressInput(igif, handle, &CrntCode)) + return IM_ERR_ACCESS; + + if (CrntCode == EOFCode) + { + /* Note however that usually we will not be here as we will stop */ + /* decoding as soon as we got all the pixel, or EOF code will */ + /* not be read at all, and DGifGetLine/Pixel clean everything. */ + if (i != LineLen - 1) + return IM_ERR_ACCESS; + + i++; + } + else if (CrntCode == ClearCode) + { + /* We need to start over again: */ + for (j = 0; j <= GIF_LZ_MAX_CODE; j++) + Prefix[j] = GIF_NO_SUCH_CODE; + + igif->RunningCode = igif->EOFCode + 1; + igif->RunningBits = igif->BitsPerPixel + 1; + igif->MaxCode1 = 1 << igif->RunningBits; + LastCode = igif->LastCode = GIF_NO_SUCH_CODE; + } + else + { + /* Its regular code - if in pixel range simply add it to output */ + /* stream, otherwise trace to codes linked list until the prefix */ + /* is in pixel range: */ + if (CrntCode < ClearCode) + { + /* This is simple - its pixel scalar, so add it to output: */ + Line[i++] = (unsigned char)CrntCode; + } + else + { + /* Its a code to needed to be traced: trace the linked list */ + /* until the prefix is a pixel, while pushing the suffix */ + /* pixels on our stack. If we done, pop the stack in reverse */ + /* (thats what stack is good for!) order to output. */ + if (Prefix[CrntCode] == GIF_NO_SUCH_CODE) + { + /* Only allowed if CrntCode is exactly the running code: */ + /* In that case CrntCode = XXXCode, CrntCode or the */ + /* prefix code is last code and the suffix char is */ + /* exactly the prefix of last code! */ + if (CrntCode == igif->RunningCode - 2) + { + CrntPrefix = LastCode; + Suffix[igif->RunningCode - 2] = + Stack[StackPtr++] = (unsigned char)iGIFGetPrefixChar(Prefix, LastCode, ClearCode); + } + else + return IM_ERR_ACCESS; + } + else + CrntPrefix = CrntCode; + + /* Now (if image is O.K.) we should not get an NO_SUCH_CODE */ + /* During the trace. As we might loop forever, in case of */ + /* defective image, we count the number of loops we trace */ + /* and stop if we got LZ_MAX_CODE. obviously we can not */ + /* loop more than that. */ + j = 0; + while (j++ <= GIF_LZ_MAX_CODE && CrntPrefix > ClearCode && CrntPrefix <= GIF_LZ_MAX_CODE) + { + Stack[StackPtr++] = Suffix[CrntPrefix]; + CrntPrefix = Prefix[CrntPrefix]; + } + + if (j >= GIF_LZ_MAX_CODE || CrntPrefix > GIF_LZ_MAX_CODE) + return IM_ERR_ACCESS; + + /* Push the last character on stack: */ + Stack[StackPtr++] = (unsigned char)CrntPrefix; + + /* Now lets pop all the stack into output: */ + while (StackPtr != 0 && i < LineLen) + Line[i++] = Stack[--StackPtr]; + } + + if (LastCode != GIF_NO_SUCH_CODE) + { + Prefix[igif->RunningCode - 2] = LastCode; + + if (CrntCode == igif->RunningCode - 2) + { + /* Only allowed if CrntCode is exactly the running code: */ + /* In that case CrntCode = XXXCode, CrntCode or the */ + /* prefix code is last code and the suffix char is */ + /* exactly the prefix of last code! */ + Suffix[igif->RunningCode - 2] = (unsigned char)iGIFGetPrefixChar(Prefix, LastCode, ClearCode); + } + else + { + Suffix[igif->RunningCode - 2] = (unsigned char)iGIFGetPrefixChar(Prefix, CrntCode, ClearCode); + } + } + + LastCode = CrntCode; + } + } + + igif->LastCode = LastCode; + igif->StackPtr = StackPtr; + + return IM_ERR_NONE; +} + +/******************************************* +* Skip sub-blocks until terminator found * +********************************************/ +static int iGIFSkipSubBlocks(imBinFile* handle) +{ + unsigned char byte_value; + do + { + /* reads the number of bytes of the block or the terminator */ + imBinFileRead(handle, &byte_value, 1, 1); + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + /* jump number of bytes, ignores the contents */ + if (byte_value) imBinFileSeekOffset(handle, byte_value); + }while (byte_value != 0); + + return IM_ERR_NONE; +} + +static int iGIFSkipImage(imBinFile* handle, int *image_count, int *terminate) +{ + int found_image = 0; + unsigned char byte_value; + + *terminate = 0; + do + { + /* reads the record type byte */ + byte_value = 0; + imBinFileRead(handle, &byte_value, 1, 1); + + switch (byte_value) + { + case ',': /* image description */ + /* jump 8 bytes */ + imBinFileSeekOffset(handle, 8); + + /* reads the image information byte */ + imBinFileRead(handle, &byte_value, 1, 1); + + if (byte_value & 0x80) + { + int bpp = (byte_value & 0x07) + 1; + int num_colors = 1 << bpp; + + /* skip the color table */ + imBinFileSeekOffset(handle, 3*num_colors); + } + + /* jump 1 byte (LZW Min Code) */ + imBinFileSeekOffset(handle, 1); + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + /* skip sub blocks */ + if (iGIFSkipSubBlocks(handle) != IM_ERR_NONE) + return IM_ERR_ACCESS; + + /* one more image */ + found_image = 1; + (*image_count)++; + break; + case '!': /* extension */ + /* jump 1 byte (label) */ + imBinFileSeekOffset(handle, 1); + + /* skip sub blocks */ + if (iGIFSkipSubBlocks(handle) != IM_ERR_NONE) + return IM_ERR_ACCESS; + break; + case ';': /* terminate */ + default: /* probably EOF */ + *terminate = 1; + break; + } + + } while (!(*terminate) && (!found_image)); + + if (!found_image && *image_count == 0) + return IM_ERR_FORMAT; + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + return IM_ERR_NONE; +} + +static void iGIFReadGraphicsControl(imBinFile* handle, imAttribTable* attrib_table) +{ + unsigned char byte_value; + unsigned short word_value; + + /* jump 1 bytes (size) */ + imBinFileSeekOffset(handle, 1); + + /* reads the packed descrition */ + imBinFileRead(handle, &byte_value, 1, 1); + if (imBinFileError(handle)) + return; + + /* user input */ + if (byte_value & 0x02) + attrib_table->Set("UserInput", IM_BYTE, 1, "\x1"); + + /* disposal */ + if (byte_value & 0x1C) + { + char* disposal; + int disp = (byte_value & 0x1C) >> 2; + + switch (disp) + { + default: + disposal = "UNDEF"; + break; + case 0x01: + disposal = "LEAVE"; + break; + case 0x02: + disposal = "RBACK"; + break; + case 0x04: + disposal = "RPREV"; + break; + } + + attrib_table->Set("Disposal", IM_BYTE, -1, disposal); + } + + /* delay time */ + imBinFileRead(handle, &word_value, 1, 2); + if (word_value) + attrib_table->Set("Delay", IM_USHORT, 1, &word_value); + + /* transparency index */ + if (byte_value & 0x01) + { + imBinFileRead(handle, &byte_value, 1, 1); + attrib_table->Set("TransparencyIndex", IM_BYTE, 1, &byte_value); + } + else + imBinFileSeekOffset(handle, 1); + + /* jump 1 bytes (terminator) */ + imBinFileSeekOffset(handle, 1); +} + +static int iGIFReadApplication(imBinFile* handle, imAttribTable* attrib_table) +{ + char identifier[9]; + + /* jump 1 byte (size) */ + imBinFileSeekOffset(handle, 1); + + /* reads the application identifier */ + imBinFileRead(handle, identifier, 8, 1); + if (identifier[7] != 0) + identifier[8] = 0; + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + if (imStrEqual(identifier, "NETSCAPE")) + { + unsigned char authentication[4]; + /* reads the application authentication code */ + imBinFileRead(handle, authentication, 3, 1); + authentication[3] = 0; + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + if (strcmp((char*)authentication, "2.0") == 0) + { + unsigned short word_value; + + /* jump 2 bytes (size + 1) */ + imBinFileSeekOffset(handle, 2); + + /* reads the number of iterations */ + imBinFileRead(handle, &word_value, 1, 2); + + attrib_table->Set("Iterations", IM_USHORT, 1, &word_value); + + /* jump 1 byte (terminator) */ + imBinFileSeekOffset(handle, 1); + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + } + else + { + /* Skip remaining blocks */ + if (iGIFSkipSubBlocks(handle) != IM_ERR_NONE) + return IM_ERR_ACCESS; + } + } + else + { + /* jump 3 bytes (authentication code) */ + imBinFileSeekOffset(handle, 3); + + /* Skip remaining blocks */ + if (iGIFSkipSubBlocks(handle) != IM_ERR_NONE) + return IM_ERR_ACCESS; + } + + return IM_ERR_NONE; +} + +static int iGIFReadComment(imBinFile* handle, imAttribTable* attrib_table) +{ + unsigned char byte_value, buffer[255*100] = "", *buffer_ptr; + int size = 0; + + buffer_ptr = &buffer[0]; + + do + { + /* reads the number of bytes of the block or the terminator */ + imBinFileRead(handle, &byte_value, 1, 1); + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + /* reads data */ + if (byte_value) + { + imBinFileRead(handle, buffer_ptr, byte_value, 1); + + if (buffer_ptr[byte_value-1] == 0) + { + size += byte_value-1; + buffer_ptr += byte_value-1; + } + else + { + size += byte_value; + buffer_ptr += byte_value; + } + } + + }while (byte_value != 0); + + if (buffer[0] != 0) + attrib_table->Set("Description", IM_BYTE, size, buffer); + + return IM_ERR_NONE; +} + +static int iGIFReadExtension(imBinFile* handle, imAttribTable* attrib_table) +{ + unsigned char byte_value; + + /* read block label */ + imBinFileRead(handle, &byte_value, 1, 1); + + if (byte_value == 0xF9) + { + /* Graphics Control Extension */ + iGIFReadGraphicsControl(handle, attrib_table); + } + else if (byte_value == 0xFE) + { + /* Comment Extension */ + if (iGIFReadComment(handle, attrib_table) != IM_ERR_NONE) + return IM_ERR_ACCESS; + } + else if (byte_value == 0xFF) + { + /* Application Extension */ + if (iGIFReadApplication(handle, attrib_table) != IM_ERR_NONE) + return IM_ERR_ACCESS; + } + else + { + /* skip sub blocks */ + if (iGIFSkipSubBlocks(handle) != IM_ERR_NONE) + return IM_ERR_ACCESS; + } + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + return IM_ERR_NONE; +} + +static int iGIFWriteComment(imBinFile* handle, unsigned char *buffer, int size) +{ + unsigned char byte_value; + + /* record type byte */ + imBinFileWrite(handle, (void*)"!", 1, 1); + + /* block label */ + imBinFileWrite(handle, (void*)"\xFE", 1, 1); + + while (size > 0) + { + if (size > 255) + byte_value = 255; + else + byte_value = (unsigned char)size; + + /* sub block size */ + imBinFileWrite(handle, &byte_value, 1, 1); + + /* sub block data */ + imBinFileWrite(handle, buffer, byte_value, 1); + + buffer += byte_value; + size -= byte_value; + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + } + + /* block terminator */ + imBinFileWrite(handle, (void*)"\0", 1, 1); + + return IM_ERR_NONE; +} + +static int iGIFWriteGraphicsControl(imBinFile* handle, imAttribTable* attrib_table) +{ + const void *attrib_user_input, *attrib_disposal, *attrib_delay, *attrib_transparency; + unsigned char byte_value; + + attrib_user_input = attrib_table->Get("UserInput"); + attrib_disposal = attrib_table->Get("Disposal"); + attrib_delay = attrib_table->Get("Delay"); + attrib_transparency = attrib_table->Get("TransparencyIndex"); + + /* Writes the Graphics Control Extension */ + if (attrib_user_input || attrib_disposal || attrib_delay || attrib_transparency) + { + unsigned short word_value; + + /* record type byte */ + imBinFileWrite(handle, (void*)"!", 1, 1); + + /* block label */ + imBinFileWrite(handle, (void*)"\xF9", 1, 1); + + /* block size */ + imBinFileWrite(handle, (void*)"\x04", 1, 1); + + byte_value = 0; + + /* user input flag */ + if (attrib_user_input && *(unsigned char*)attrib_user_input == 1) + byte_value |= 0x02; + + /* transparency flag */ + if (attrib_transparency) + byte_value |= 0x01; + + /* disposal flag */ + if (attrib_disposal) + { + int disp = 0; + if (imStrEqual((char*)attrib_disposal, "LEAVE")) + disp = 0x01; + else if (imStrEqual((char*)attrib_disposal, "RBACK")) + disp = 0x02; + else if (imStrEqual((char*)attrib_disposal, "RPREV")) + disp = 0x04; + + disp = disp << 2; + byte_value |= disp; + } + + /* packed */ + imBinFileWrite(handle, &byte_value, 1, 1); + + /* delay time */ + if (attrib_delay) + word_value = *(unsigned short*)attrib_delay; + else + word_value = 0; + + imBinFileWrite(handle, &word_value, 1, 2); + + /* transparency index */ + if (attrib_transparency) + { + byte_value = *(unsigned char*)attrib_transparency; + imBinFileWrite(handle, &byte_value, 1, 1); + } + else + imBinFileWrite(handle, (void*)"\0", 1, 1); + + /* terminator */ + imBinFileWrite(handle, (void*)"\0", 1, 1); + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + } + + return IM_ERR_NONE; +} + +static const char* iGIFCompTable[1] = +{ + "LZW" +}; + +class imFileFormatGIF: public imFileFormatBase +{ + imBinFile* handle; + iGIFData gif_data; + + int GIFReadImageInfo(); + int GIFWriteImageInfo(); + +public: + imFileFormatGIF(const imFormat* _iformat): imFileFormatBase(_iformat) {} + ~imFileFormatGIF() {} + + int Open(const char* file_name); + int New(const char* file_name); + void Close(); + void* Handle(int index); + int ReadImageInfo(int index); + int ReadImageData(void* data); + int WriteImageInfo(); + int WriteImageData(void* data); +}; + +class imFormatGIF: public imFormat +{ +public: + imFormatGIF() + :imFormat("GIF", + "Graphics Interchange Format", + "*.gif;", + iGIFCompTable, + 1, + 1) + {} + ~imFormatGIF() {} + + imFileFormatBase* Create(void) const { return new imFileFormatGIF(this); } + int CanWrite(const char* compression, int color_mode, int data_type) const; +}; + +void imFormatRegisterGIF(void) +{ + imFormatRegister(new imFormatGIF()); +} + +int imFileFormatGIF::Open(const char* file_name) +{ + this->handle = imBinFileOpen(file_name); + if (this->handle == NULL) + return IM_ERR_OPEN; + + imBinFileByteOrder(handle, IM_LITTLEENDIAN); + + unsigned char sig[4]; + if (!imBinFileRead(this->handle, sig, 3, 1)) + { + imBinFileClose(handle); + return IM_ERR_ACCESS; + } + + sig[3] = 0; + if (!imStrEqual((char*)sig, GIF_STAMP)) + { + imBinFileClose(handle); + return IM_ERR_FORMAT; + } + + /* ignore version */ + imBinFileSeekOffset(handle, 3); + + strcpy(this->compression, "LZW"); + + /* reads screen width and screen height */ + imushort word_value; + imBinFileRead(handle, &word_value, 1, 2); + gif_data.screen_width = word_value; + + imBinFileRead(handle, &word_value, 1, 2); + gif_data.screen_height = word_value; + + /* reads color table information byte */ + imbyte byte_value; + imBinFileRead(handle, &byte_value, 1, 1); + + /* jump 2 bytes (bgcolor + aspect ratio) */ + imBinFileSeekOffset(handle, 2); + + /* global color table, if exists */ + if (byte_value & 0x80) + { + int bpp = (byte_value & 0x07) + 1; + gif_data.global_num_colors = 1 << bpp; + + /* reads the color palette */ + imBinFileRead(handle, gif_data.global_colors, gif_data.global_num_colors * 3, 1); + } + + if (imBinFileError(handle)) + { + imBinFileClose(handle); + return IM_ERR_ACCESS; + } + + /* count number of images */ + int error, terminate; + this->image_count = 0; + do + { + // store each offset before counting images + gif_data.start_offset[this->image_count] = imBinFileTell(handle); + error = iGIFSkipImage(handle, &this->image_count, &terminate); + } while (!terminate && error == IM_ERR_NONE); + + if (this->image_count == 0 || error != IM_ERR_NONE) + { + imBinFileClose(handle); + return error; + } + + return IM_ERR_NONE; +} + +int imFileFormatGIF::New(const char* file_name) +{ + this->handle = imBinFileNew(file_name); + if (this->handle == NULL) + return IM_ERR_OPEN; + + imBinFileByteOrder(handle, IM_LITTLEENDIAN); + + /* writes the GIF STAMP and version - header */ + imBinFileWrite(handle, (void*)GIF_STAMP, 3, 1); /* identifier */ + imBinFileWrite(handle, (void*)GIF_VERSION, 3, 1); /* format version */ + + // File header will be written at the first image + + /* tests if everything was ok */ + if (imBinFileError(handle)) + { + imBinFileClose(this->handle); + return IM_ERR_ACCESS; + } + + strcpy(this->compression, "LZW"); + + return IM_ERR_NONE; +} + +void imFileFormatGIF::Close() +{ + if (this->is_new && !imBinFileError(this->handle)) + imBinFileWrite(this->handle, (void*)";", 1, 1); + + imBinFileClose(this->handle); +} + +void* imFileFormatGIF::Handle(int index) +{ + if (index == 0) + return (void*)this->handle; + else + return NULL; +} + +int imFileFormatGIF::GIFReadImageInfo() +{ + imbyte byte_value; + imushort word_value; + int int_value; + + imAttribTable* attrib_table = AttribTable(); + + /* reads the image left position */ + imBinFileRead(handle, &word_value, 1, 2); + if (word_value) + attrib_table->Set("XScreen", IM_USHORT, 1, &word_value); + + /* reads the image top position */ + imBinFileRead(handle, &word_value, 1, 2); + if (word_value) + attrib_table->Set("YScreen", IM_USHORT, 1, &word_value); + + /* reads the image width */ + imBinFileRead(handle, &word_value, 1, 2); + this->width = word_value; + + /* reads the image height */ + imBinFileRead(handle, &word_value, 1, 2); + this->height = word_value; + + /* reads the image information byte */ + imBinFileRead(handle, &byte_value, 1, 1); + + gif_data.interlaced = (byte_value & 0x40)? 1: 0; + if (gif_data.interlaced) + { + int_value = 1; + attrib_table->Set("Interlaced", IM_INT, 1, &int_value); + } + + this->file_color_mode = IM_MAP; + this->file_data_type = IM_BYTE; + + /* local color table */ + int num_colors; + unsigned char *colors; + unsigned char local_colors[256 * 3]; + + if (byte_value & 0x80) + { + int bpp = (byte_value & 0x07) + 1; + num_colors = 1 << bpp; + colors = local_colors; + + /* reads the color table */ + imBinFileRead(handle, local_colors, num_colors * 3, 1); + } + else if (gif_data.global_num_colors) + { + colors = gif_data.global_colors; + num_colors = gif_data.global_num_colors; + } + else + return IM_ERR_FORMAT; + + long palette[256]; + for (int c = 0; c < num_colors; c++) + { + palette[c] = imColorEncode(colors[c*3], + colors[c*3+1], + colors[c*3+2]); + } + + imFileSetPalette(this, palette, num_colors); + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + this->file_color_mode |= IM_TOPDOWN; + + return IM_ERR_NONE; +} + +int imFileFormatGIF::GIFWriteImageInfo() +{ + this->file_data_type = IM_BYTE; + this->file_color_mode = imColorModeSpace(this->user_color_mode); + this->file_color_mode |= IM_TOPDOWN; + + imAttribTable* attrib_table = AttribTable(); + const void* attrib = attrib_table->Get("Interlaced"); + if (attrib) + gif_data.interlaced = *(int*)attrib; + + imBinFileWrite(handle, (void*)",", 1, 1); /* Image separator character. */ + + imushort word_value; + + attrib = attrib_table->Get("XScreen"); + if (attrib) + word_value = *(unsigned short*)attrib; + else + word_value = 0; + imBinFileWrite(handle, &word_value, 1, 2); /* image left */ + + attrib = attrib_table->Get("YScreen"); + if (attrib) + word_value = *(unsigned short*)attrib; + else + word_value = 0; + imBinFileWrite(handle, &word_value, 1, 2); /* image top */ + + word_value = (unsigned short)this->width; + imBinFileWrite(handle, &word_value, 1, 2); /* image width */ + word_value = (unsigned short)this->height; + imBinFileWrite(handle, &word_value, 1, 2); /* image height */ + + /* local color table */ + imbyte byte_value = 0x80; + if (gif_data.interlaced) + byte_value |= 0x40; + + int num_colors = 256; + if (imColorModeSpace(this->user_color_mode) == IM_MAP) + { + int bpp = 0, c = this->palette_count-1; + while (c) {c = c >> 1;bpp++;} + byte_value |= (bpp-1); + num_colors = 1 << bpp; + } + else + byte_value |= 0x07; /* 8 bits = 256 grays */ + + imBinFileWrite(handle, &byte_value, 1, 1); /* image information */ + + /* write color table */ + unsigned char local_colors[256*3]; + for (int c = 0; c < num_colors; c++) // write all data, even not used colors + { + unsigned char r, g, b; + imColorDecode(&r, &g, &b, this->palette[c]); + local_colors[c*3] = r; + local_colors[c*3+1] = g; + local_colors[c*3+2] = b; + } + imBinFileWrite(handle, local_colors, num_colors*3, 1); + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + return IM_ERR_NONE; +} + +int imFileFormatGIF::ReadImageInfo(int index) +{ + imAttribTable* attrib_table = AttribTable(); + + /* must clear the attribute list, because it can have multiple images and + has many attributes that may exists only for specific images. */ + attrib_table->RemoveAll(); + imFileSetBaseAttributes(this); + + if (gif_data.screen_width) + { + imushort word_value = (imushort)gif_data.screen_width; + attrib_table->Set("ScreenWidth", IM_USHORT, 1, &word_value); + } + + if (gif_data.screen_height) + { + imushort word_value = (imushort)gif_data.screen_height; + attrib_table->Set("ScreenHeight", IM_USHORT, 1, &word_value); + } + + /* jump to start offset of the image */ + imBinFileSeekTo(handle, gif_data.start_offset[index]); + + int found_image = 0; + imbyte byte_value; + + int terminate = 0; + do + { + /* reads the record type byte */ + byte_value = 0; + imBinFileRead(handle, &byte_value, 1, 1); + + switch (byte_value) + { + case '!': /* 0x21 extension (appears before the image) */ + if (iGIFReadExtension(handle, attrib_table) != IM_ERR_NONE) + return IM_ERR_ACCESS; + break; + case ',': /* 0x2C image description and color table */ + if (GIFReadImageInfo() != IM_ERR_NONE) + return IM_ERR_ACCESS; + + /* we will read only this image for now, so break the loop */ + found_image = 1; + break; + case ';': /* if terminate before find image return error */ + default: + terminate = 1; + break; + } + } while (!terminate && !found_image); + + if (!found_image) + return IM_ERR_ACCESS; + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + /* reads the LZW Min code byte */ + imBinFileRead(handle, &byte_value, 1, 1); + + /* now initialize the compression control data */ + + gif_data.BitsPerPixel = byte_value; + gif_data.ClearCode = (1 << byte_value); + gif_data.EOFCode = gif_data.ClearCode + 1; + gif_data.RunningCode = gif_data.EOFCode + 1; + gif_data.RunningBits = byte_value + 1; /* Number of bits per code. */ + gif_data.MaxCode1 = 1 << gif_data.RunningBits; /* Max. code + 1. */ + gif_data.StackPtr = 0; /* No pixels on the pixel stack. */ + gif_data.LastCode = GIF_NO_SUCH_CODE; + gif_data.CrntShiftState = 0; /* No information in CrntShiftDWord. */ + gif_data.CrntShiftDWord = 0; + gif_data.Buf[0] = 0; /* Input Buffer empty. */ + + for (int i = 0; i <= GIF_LZ_MAX_CODE; i++) + gif_data.Prefix[i] = GIF_NO_SUCH_CODE; + + gif_data.step = 0; + + return IM_ERR_NONE; +} + +int imFileFormatGIF::WriteImageInfo() +{ + this->file_color_mode = imColorModeSpace(this->user_color_mode); + this->file_color_mode |= IM_TOPDOWN; + this->file_data_type = this->user_data_type; + + imAttribTable* attrib_table = AttribTable(); + const void* attrib_data; + int attrib_size; + + if (this->image_count == 0) + { + imushort word_value; + + // write file header + + /* logical screen descriptor */ + attrib_data = attrib_table->Get("ScreenWidth"); + if (attrib_data) word_value = *(imushort*)attrib_data; + else word_value = (imushort)this->width; + imBinFileWrite(handle, &word_value, 1, 2); + + attrib_data = attrib_table->Get("ScreenHeight"); + if (attrib_data) word_value = *(imushort*)attrib_data; + else word_value = (imushort)this->height; + imBinFileWrite(handle, &word_value, 1, 2); + + imbyte byte_value = 0; /* no global color table, 0 colors */ + imBinFileWrite(handle, &byte_value, 1, 1); /* screen information */ + imBinFileWrite(handle, (void*)"\0\0", 2, 1); /* (bgcolor + aspect ratio) */ + } + + attrib_data = attrib_table->Get("Description", NULL, &attrib_size); + if (attrib_data) + { + if (iGIFWriteComment(handle, (imbyte*)attrib_data, attrib_size) != IM_ERR_NONE) + return IM_ERR_ACCESS; + } + + attrib_data = attrib_table->Get("Iterations"); + if (attrib_data) + { + if (iGIFWriteNetscapeApplication(handle, *(short*)attrib_data) != IM_ERR_NONE) + return IM_ERR_ACCESS; + } + + if (iGIFWriteGraphicsControl(handle, attrib_table) != IM_ERR_NONE) + return IM_ERR_ACCESS; + + if (GIFWriteImageInfo() != IM_ERR_NONE) + return IM_ERR_ACCESS; + + /* initializes the hash table */ + memset(gif_data.HTable, 0xFF, GIF_HT_SIZE * sizeof(int)); + + /* initializes compression data */ + + imbyte byte_value = 8; + imBinFileWrite(handle, &byte_value, 1, 1); /* Write the Code size to file. */ + + gif_data.Buf[0] = 0; /* Nothing was output yet. */ + gif_data.BitsPerPixel = 8; + gif_data.ClearCode = (1 << 8); + gif_data.EOFCode = gif_data.ClearCode + 1; + gif_data.RunningBits = 8 + 1; /* Number of bits per code. */ + gif_data.MaxCode1 = 1 << gif_data.RunningBits; /* Max. code + 1. */ + gif_data.CrntCode = GIF_FIRST_CODE; /* Signal that this is first one! */ + gif_data.CrntShiftState = 0; /* No information in CrntShiftDWord. */ + gif_data.CrntShiftDWord = 0; + + gif_data.RunningCode = gif_data.EOFCode + 1; + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + gif_data.step = 0; /* interlaced step */ + + return iGIFCompressOutput(&gif_data, handle, gif_data.ClearCode); +} + +int imFileFormatGIF::ReadImageData(void* data) +{ + imCounterTotal(this->counter, this->height, "Reading GIF..."); + + int row = 0, error; + for (int i = 0; i < this->height; i++) + { + error = iGIFDecompressLine(&gif_data, handle, (imbyte*)this->line_buffer, this->width); + if (error != IM_ERR_NONE) + return IM_ERR_ACCESS; + + imFileLineBufferRead(this, data, row, 0); + + if (!imCounterInc(this->counter)) + return IM_ERR_COUNTER; + + if (gif_data.interlaced) + { + row += InterlacedJumps[gif_data.step]; + + if (row > this->height-1) + { + gif_data.step++; + row = InterlacedOffset[gif_data.step]; + } + } + else + row++; + } + + /* Skip remaining empty blocks of the image data */ + if (iGIFSkipSubBlocks(handle) != IM_ERR_NONE) + return IM_ERR_ACCESS; + + return IM_ERR_NONE; +} + +int imFileFormatGIF::WriteImageData(void* data) +{ + imCounterTotal(this->counter, this->height, "Writing GIF..."); + + int row = 0, error; + for (int i = 0; i < this->height; i++) + { + imFileLineBufferWrite(this, data, row, 0); + + error = iGIFCompressLine(&gif_data, handle, (imbyte*)this->line_buffer, this->width); + + if (error != IM_ERR_NONE) + return IM_ERR_ACCESS; + + if (!imCounterInc(this->counter)) + return IM_ERR_COUNTER; + + if (gif_data.interlaced) + { + row += InterlacedJumps[gif_data.step]; + + if (row > this->height-1) + { + gif_data.step++; + row = InterlacedOffset[gif_data.step]; + } + } + else + row++; + } + + /* writes the end picture code */ + iGIFCompressOutput(&gif_data, handle, gif_data.CrntCode); + iGIFCompressOutput(&gif_data, handle, gif_data.EOFCode); + iGIFCompressOutput(&gif_data, handle, GIF_FLUSH_OUTPUT); + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + this->image_count++; + return IM_ERR_NONE; +} + +int imFormatGIF::CanWrite(const char* compression, int color_mode, int data_type) const +{ + int color_space = imColorModeSpace(color_mode); + + if (color_space != IM_MAP && color_space != IM_GRAY && color_space != IM_BINARY) + return IM_ERR_DATA; + + if (data_type != IM_BYTE) + return IM_ERR_DATA; + + if (!compression || compression[0] == 0) + return IM_ERR_NONE; + + if (!imStrEqual(compression, "LZW")) + return IM_ERR_COMPRESS; + + return IM_ERR_NONE; +} + diff --git a/im/src/im_format_ico.cpp b/im/src/im_format_ico.cpp new file mode 100755 index 0000000..b10f30e --- /dev/null +++ b/im/src/im_format_ico.cpp @@ -0,0 +1,660 @@ +/** \file + * \brief ICO - Windows Icon + * + * See Copyright Notice in im_lib.h + * $Id: im_format_ico.cpp,v 1.2 2008/12/03 15:45:34 scuri Exp $ + */ + +#include "im_format.h" +#include "im_format_all.h" +#include "im_util.h" +#include "im_counter.h" + +#include "im_binfile.h" + +#include +#include +#include + +/* +typedef struct +{ + WORD idReserved; // Reserved (must be 0) + WORD idType; // Resource Type (1 for icons) + WORD idCount; // How many images? + ICONDIRENTRY idEntries[1]; // An entry for each image (idCount of 'em) +} ICONDIR, *LPICONDIR; // 6 +typedef struct +{ + BYTE bWidth; // Width, in pixels, of the image + BYTE bHeight; // Height, in pixels, of the image + BYTE bColorCount; // Number of colors in image (0 if >=8bpp) + BYTE bReserved; // Reserved ( must be 0) + WORD wPlanes; // Color Planes + WORD wBitCount; // Bits per pixel + DWORD dwBytesInRes; // How many bytes in this resource? + DWORD dwImageOffset; // Where in the file is this image? +} ICONDIRENTRY, *LPICONDIRENTRY; // 16 +typdef struct +{ + BITMAPINFOHEADER icHeader; // DIB header + RGBQUAD icColors[1]; // Color table + BYTE icXOR[1]; // DIB bits for XOR mask + BYTE icAND[1]; // DIB bits for AND mask (1 bpp) +} ICONIMAGE, *LPICONIMAGE; +*/ + +static const char* iICOCompTable[1] = +{ + "NONE" +}; + +class imFileFormatICO: public imFileFormatBase +{ + imBinFile* handle; /* the binary file handle */ + unsigned short bpp; /* number of bits per pixel */ + unsigned int offset[10], + next_offset; + int line_raw_size; // raw line size + + int ReadPalette(); + int WritePalette(); + void FixRGBOrder(); + +public: + imFileFormatICO(const imFormat* _iformat): imFileFormatBase(_iformat) {} + ~imFileFormatICO() {} + + int Open(const char* file_name); + int New(const char* file_name); + void Close(); + void* Handle(int index); + int ReadImageInfo(int index); + int ReadImageData(void* data); + int WriteImageInfo(); + int WriteImageData(void* data); +}; + +class imFormatICO: public imFormat +{ +public: + imFormatICO() + :imFormat("ICO", + "Windows Icon", + "*.ico;", + iICOCompTable, + 1, + 1) + {} + ~imFormatICO() {} + + imFileFormatBase* Create(void) const { return new imFileFormatICO(this); } + int CanWrite(const char* compression, int color_mode, int data_type) const; +}; + + +void imFormatRegisterICO(void) +{ + imFormatRegister(new imFormatICO()); +} + +int imFileFormatICO::Open(const char* file_name) +{ + unsigned short word; + + /* opens the binary file for reading with intel byte order */ + handle = imBinFileOpen(file_name); + if (!handle) + return IM_ERR_OPEN; + + imBinFileByteOrder(handle, IM_LITTLEENDIAN); + + /* reads the reserved value */ + imBinFileRead(handle, &word, 1, 2); + if (imBinFileError(handle)) + { + imBinFileClose(handle); + return IM_ERR_ACCESS; + } + + if (word != 0) + { + imBinFileClose(handle); + return IM_ERR_FORMAT; + } + + /* reads the resource type */ + imBinFileRead(handle, &word, 1, 2); + if (word != 1) + { + imBinFileClose(handle); + return IM_ERR_FORMAT; + } + + /* reads the number of images */ + imBinFileRead(handle, &word, 1, 2); + + this->image_count = word > 10? 10: word; + strcpy(this->compression, "NONE"); + + for (int i = 0; i < this->image_count; i++) + { + /* skip ICONDIRENTRY data except image offset */ + imBinFileSeekOffset(handle, 12); + + /* reads the image offset */ + imBinFileRead(handle, &this->offset[i], 1, 4); + + if (imBinFileError(handle)) + { + imBinFileClose(handle); + return IM_ERR_ACCESS; + } + } + + return IM_ERR_NONE; +} + +int imFileFormatICO::New(const char* file_name) +{ + /* opens the binary file for writing with intel byte order */ + handle = imBinFileNew(file_name); + if (!handle) + return IM_ERR_OPEN; + + imBinFileByteOrder(handle, IM_LITTLEENDIAN); + + imushort word_value = 0; + imBinFileWrite(handle, &word_value, 1, 2); /* reserved */ + word_value = 1; + imBinFileWrite(handle, &word_value, 1, 2); /* resource type */ + imBinFileWrite(handle, &word_value, 1, 2); /* number of images, at least one, must update at close */ + + this->next_offset = 6 + 5 * 16; // offset to the first image, room for 5 ICONDIRENTRY + + return IM_ERR_NONE; +} + +void imFileFormatICO::Close() +{ + if (this->is_new) + { + if (this->image_count > 1) + { + imBinFileSeekTo(handle, 4); + imushort word_value = (imushort)this->image_count; + imBinFileWrite(handle, &word_value, 1, 2); /* number of images */ + } + } + + imBinFileClose(handle); +} + +void* imFileFormatICO::Handle(int index) +{ + if (index == 0) + return (void*)this->handle; + else + return NULL; +} + +int imFileFormatICO::ReadImageInfo(int index) +{ + this->file_data_type = IM_BYTE; + unsigned int dword_value; + + if (index >= image_count) + return IM_ERR_DATA; + + // offset + size + imBinFileSeekTo(handle, this->offset[index] + 4); + + /* reads the image width */ + imBinFileRead(handle, &dword_value, 1, 4); + this->width = (int)dword_value; + + /* reads the image height */ + imBinFileRead(handle, &dword_value, 1, 4); + this->height = (int)(dword_value / 2); + + /* jump 2 bytes (planes) */ + imBinFileSeekOffset(handle, 2); + + // bpp + imBinFileRead(handle, &this->bpp, 1, 2); + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + // sanity check + if (this->bpp != 1 && this->bpp != 4 && this->bpp != 8 && + this->bpp != 24 && this->bpp != 32) + return IM_ERR_DATA; + + if (this->bpp > 8) + { + this->file_color_mode = IM_RGB; + this->file_color_mode |= IM_PACKED; + if (this->bpp == 32) + this->file_color_mode |= IM_ALPHA; + } + else + { + this->file_color_mode = IM_MAP; + this->palette_count = 1 << bpp; + } + + if (this->bpp < 8) + this->convert_bpp = this->bpp; + + this->line_raw_size = imFileLineSizeAligned(this->width, this->bpp, 4); + this->line_buffer_extra = 4; // room enough for padding + + /* jump 8 bytes (compression, image size, resolution) */ + imBinFileSeekOffset(handle, 16); + + if (this->bpp <= 8) + { + /* reads the number of colors used */ + imBinFileRead(handle, &dword_value, 1, 4); + + /* updates the palette_count based on the number of colors used */ + if (dword_value != 0 && (int)dword_value < this->palette_count) + this->palette_count = dword_value; + + /* jump 4 bytes (important colors) */ + imBinFileSeekOffset(handle, 4); + } + else + { + /* jump 8 bytes (used colors, important colors) */ + imBinFileSeekOffset(handle, 8); + } + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + if (this->bpp <= 8) + return ReadPalette(); + + return IM_ERR_NONE; +} + +int imFileFormatICO::WriteImageInfo() +{ + this->file_data_type = IM_BYTE; + this->file_color_mode = imColorModeSpace(this->user_color_mode); + + if (this->image_count == 5) + return IM_ERR_DATA; + + if (this->width > 255 || this->height > 255) + return IM_ERR_DATA; + + if (this->file_color_mode == IM_BINARY) + { + this->bpp = 1; + this->convert_bpp = 1; + } + else if (this->file_color_mode == IM_RGB) + { + this->file_color_mode |= IM_PACKED; + if (imColorModeHasAlpha(this->user_color_mode)) + { + this->file_color_mode |= IM_ALPHA; + this->bpp = 32; + } + else + this->bpp = 24; + } + else + this->bpp = 8; + + this->line_raw_size = imFileLineSizeAligned(this->width, this->bpp, 4); + this->line_buffer_extra = 4; // room enough for padding + int palette_size = (this->bpp > 8)? 0: this->palette_count*4; + + imbyte byte_value; + imushort word_value; + + /* updates the ICON directory entry */ + + imBinFileSeekTo(handle, 6 + this->image_count * 16); // ICONDIR + i * ICONDIRENTRY + + byte_value = (imbyte)this->width; + imBinFileWrite(handle, &byte_value, 1, 1); /* width */ + byte_value = (imbyte)this->height; + imBinFileWrite(handle, &byte_value, 1, 1); /* height */ + byte_value = (imbyte)((this->bpp > 8)? 0: this->palette_count); + imBinFileWrite(handle, &byte_value, 1, 1); /* color count */ + imBinFileWrite(handle, (void*)"\0", 1, 1); /* reserved */ + word_value = 1; + imBinFileWrite(handle, &word_value, 1, 2); /* planes */ + word_value = this->bpp; + imBinFileWrite(handle, &word_value, 1, 2); /* bit count */ + int and_line_size = imFileLineSizeAligned(this->width, 1, 4); + int resource_size = 40 + palette_size + (line_raw_size + and_line_size) * this->height; + unsigned int dword_value = resource_size; + imBinFileWrite(handle, &dword_value, 1, 4); /* resource size */ + dword_value = this->next_offset; + imBinFileWrite(handle, &dword_value, 1, 4); /* data offset */ + + this->offset[this->image_count] = this->next_offset; + this->next_offset += resource_size; + + /* writes the image */ + + imBinFileSeekTo(handle, this->offset[this->image_count]); + + dword_value = 40; + imBinFileWrite(handle, &dword_value, 1, 4); /* header size */ + dword_value = this->width; + imBinFileWrite(handle, &dword_value, 1, 4); /* width */ + dword_value = this->height*2; + imBinFileWrite(handle, &dword_value, 1, 4); /* height */ + word_value = 1; + imBinFileWrite(handle, &word_value, 1, 2); /* planes */ + word_value = this->bpp; + imBinFileWrite(handle, &word_value, 1, 2); /* bpp */ + dword_value = 0; + imBinFileWrite(handle, &dword_value, 1, 4); /* compression */ + dword_value = line_raw_size * this->height; + imBinFileWrite(handle, &dword_value, 1, 4); /* data size */ + + imBinFileWrite(handle, (void*)"\0\0\0\0\0\0\0\0", 8, 1); /* resolution */ + + dword_value = (this->bpp > 8)? 0: this->palette_count; + imBinFileWrite(handle, &dword_value, 1, 4); /* colors used */ + dword_value = 0; + imBinFileWrite(handle, &dword_value, 1, 4); /* colors important (all) */ + + /* tests if everything was ok */ + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + if (this->bpp < 24) + return WritePalette(); + + return IM_ERR_NONE; +} + +int imFileFormatICO::ReadPalette() +{ + /* reads the color palette */ + unsigned char bmp_colors[256 * 4]; + imBinFileRead(handle, bmp_colors, this->palette_count * 4, 1); + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + /* convert the color map to the IM format */ + for (int c = 0; c < this->palette_count; c++) + { + int i = c * 4; + this->palette[c] = imColorEncode(bmp_colors[i + 2], + bmp_colors[i + 1], + bmp_colors[i]); + } + + return IM_ERR_NONE; +} + +int imFileFormatICO::WritePalette() +{ + unsigned char bmp_colors[256 * 4]; + + /* convert the color map to the IM format */ + for (int c = 0; c < this->palette_count; c++) + { + int i = c * 4; + imColorDecode(&bmp_colors[i + 2], &bmp_colors[i + 1], &bmp_colors[i], this->palette[c]); + bmp_colors[i + 3] = 0; + } + + /* writes the color palette */ + imBinFileWrite(handle, bmp_colors, this->palette_count * 4, 1); + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + return IM_ERR_NONE; +} + +void imFileFormatICO::FixRGBOrder() +{ + if (this->bpp == 24) + { + imbyte* byte_data = (imbyte*)this->line_buffer; + for (int x = 0; x < this->width; x++) + { + int c = x*3; + imbyte temp = byte_data[c]; // swap R and B + byte_data[c] = byte_data[c+2]; + byte_data[c+2] = temp; + } + } + else /* bpp == 32 */ + { + /* inverts the DWORD values if not intel */ + if (imBinCPUByteOrder() == IM_BIGENDIAN) + imBinSwapBytes4(this->line_buffer, this->width); + + unsigned int* dword_data = (unsigned int*)this->line_buffer; + imbyte* byte_data = (imbyte*)this->line_buffer; + + for (int x = 0; x < this->width; x++) + { + unsigned int dword_value = dword_data[x]; + int c = x*4; + byte_data[c] = (imbyte)((0x00FF0000 & dword_value) >> 16); + byte_data[c+1] = (imbyte)((0x0000FF00 & dword_value) >> 8); + byte_data[c+2] = (imbyte)((0x000000FF & dword_value) >> 0); + byte_data[c+3] = (imbyte)((0xFF000000 & dword_value) >> 24); + } + } +} + +static inline int PixelOffset(int is_top_down, int is_packed, int width, int height, int depth, int col, int row, int plane) +{ + if (is_top_down) + row = height-1 - row; + + if (is_packed) + return row*width*depth + col*depth + plane; + else + return plane*width*height + row*width + col; +} + +int imFileFormatICO::ReadImageData(void* data) +{ + imCounterTotal(this->counter, this->height, "Reading ICO..."); + + for (int row = 0; row < this->height; row++) + { + imBinFileRead(handle, this->line_buffer, this->line_raw_size, 1); + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + if (this->bpp > 8) + FixRGBOrder(); + + imFileLineBufferRead(this, data, row, 0); + + if (!imCounterInc(this->counter)) + return IM_ERR_COUNTER; + } + + if ((imColorModeHasAlpha(this->user_color_mode) && this->bpp!=32) || /* user has alpha and file does not have alpha -> alpha came from AND data */ + imColorModeSpace(this->user_color_mode) == IM_MAP) /* or MAP */ + { + int line_size = imFileLineSizeAligned(this->width, 1, 4); + int image_size = this->height*line_size; + imbyte* and_data = new imbyte[image_size]; + + imBinFileRead(handle, and_data, image_size, 1); + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + imbyte* and_data_line = and_data; + imbyte* user_data = (imbyte*)data; + unsigned long histo[256]; + int depth = imColorModeDepth(this->user_color_mode); + int alpha_plane = 0; + if (imColorModeHasAlpha(this->user_color_mode)) + alpha_plane = depth - 1; + else + memset(histo, 0, 256*sizeof(unsigned long)); + + for (int j = 0; j < this->height; j++) + { + for (int i = 0; i < this->width; i++) + { + int offset = PixelOffset(imColorModeIsTopDown(this->user_color_mode), + imColorModeIsPacked(this->user_color_mode), + this->width, this->height, depth, i, j, alpha_plane); + + if (imColorModeHasAlpha(this->user_color_mode)) + { + if (((and_data_line[i / 8] >> (7 - i % 8)) & 0x01)) + user_data[offset] = 0; + else + user_data[offset] = 255; + } + else + { + /* the most repeated index with transparency will be the transparent index. */ + if (((and_data_line[i / 8] >> (7 - i % 8)) & 0x01)) + histo[user_data[offset]]++; + } + } + and_data_line += line_size; + } + + if (imColorModeSpace(this->user_color_mode) == IM_MAP) + { + imbyte transp_index = 0; + unsigned long histo_max = histo[0]; + + for (int i = 1; i < 256; i++) + { + if (histo_max < histo[i]) + { + histo_max = histo[i]; + transp_index = (imbyte)i; + } + } + AttribTable()->Set("TransparencyIndex", IM_BYTE, 1, &transp_index); + } + + delete [] and_data; + } + + return IM_ERR_NONE; +} + +int imFileFormatICO::WriteImageData(void* data) +{ + imCounterTotal(this->counter, this->height, "Writing ICO..."); + + /* Image Data */ + + for (int row = 0; row < this->height; row++) + { + imFileLineBufferWrite(this, data, row, 0); + + if (this->bpp > 8) + FixRGBOrder(); + + imBinFileWrite(handle, this->line_buffer, this->line_raw_size, 1); + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + if (!imCounterInc(this->counter)) + return IM_ERR_COUNTER; + } + + /* AND Data */ + + int and_line_size = imFileLineSizeAligned(this->width, 1, 4); + int and_size = this->height*and_line_size; + imbyte* and_data = new imbyte[and_size]; + memset(and_data, 0, and_size); /* zero = opaque */ + + if (imColorModeHasAlpha(this->user_color_mode)) + { + imbyte* and_data_line = and_data; + imbyte* user_data = (imbyte*)data; + int depth = imColorModeDepth(this->user_color_mode); + int alpha_plane = depth - 1; + + for (int j = 0; j < this->height; j++) + { + for (int i = 0; i < this->width; i++) + { + int offset = PixelOffset(imColorModeIsTopDown(this->user_color_mode), + imColorModeIsPacked(this->user_color_mode), + this->width, this->height, depth, i, j, alpha_plane); + + if (user_data[offset] == 0) /* mark only full transparent pixels */ + and_data_line[i / 8] |= (0x01 << (7 - (i % 8))); + } + and_data_line += and_line_size; + } + } + else + { + const imbyte* transp_index = (const imbyte*)AttribTable()->Get("TransparencyIndex"); + if (imColorModeSpace(this->user_color_mode) == IM_MAP && transp_index) + { + imbyte* and_data_line = and_data; + imbyte* user_data = (imbyte*)data; + int depth = imColorModeDepth(this->user_color_mode); + + for (int j = 0; j < this->height; j++) + { + for (int i = 0; i < this->width; i++) + { + int offset = PixelOffset(imColorModeIsTopDown(this->user_color_mode), + imColorModeIsPacked(this->user_color_mode), + this->width, this->height, depth, i, j, 0); + + if (user_data[offset] == *transp_index) + and_data_line[i / 8] |= (0x01 << (7 - (i % 8))); + } + and_data_line += and_line_size; + } + } + } + + imBinFileWrite(handle, and_data, and_size, 1); + delete [] and_data; + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + this->image_count++; + + return IM_ERR_NONE; +} + +int imFormatICO::CanWrite(const char* compression, int color_mode, int data_type) const +{ + int color_space = imColorModeSpace(color_mode); + + if (color_space == IM_YCBCR || color_space == IM_LAB || + color_space == IM_LUV || color_space == IM_XYZ || + color_space == IM_CMYK) + return IM_ERR_DATA; + + if (data_type != IM_BYTE) + return IM_ERR_DATA; + + if (!compression || compression[0] == 0) + return IM_ERR_NONE; + + if (!imStrEqual(compression, "NONE")) + return IM_ERR_COMPRESS; + + return IM_ERR_NONE; +} diff --git a/im/src/im_format_krn.cpp b/im/src/im_format_krn.cpp new file mode 100755 index 0000000..a47d650 --- /dev/null +++ b/im/src/im_format_krn.cpp @@ -0,0 +1,325 @@ +/** \file + * \brief KRN - IM Kernel File Format + * + * See Copyright Notice in im_lib.h + * $Id: im_format_krn.cpp,v 1.3 2009/10/01 14:15:47 scuri Exp $ + */ + +#include "im_format.h" +#include "im_format_all.h" +#include "im_util.h" +#include "im_counter.h" + +#include "im_binfile.h" + +#include +#include +#include +#include + +static int iKRNReadDescription(imBinFile* handle, char* comment, int *size) +{ + imbyte byte_value = 0; + + // find the first \n + while(byte_value != '\n') + { + imBinFileRead(handle, &byte_value, 1, 1); + if (imBinFileError(handle)) + return 0; + } + + *size = 0; + + // Read up to the next \n + + imBinFileRead(handle, &byte_value, 1, 1); + if (imBinFileError(handle)) + return 0; + + while(byte_value != '\n') + { + if (byte_value != '\r') + { + comment[*size] = byte_value; + (*size)++; + } + + imBinFileRead(handle, &byte_value, 1, 1); + if (imBinFileError(handle)) + return 0; + } + + if (*size != 0) + { + comment[*size] = 0; + (*size)++; + } + + return 1; +} + +static const char* iKRNCompTable[1] = +{ + "NONE" +}; + +class imFileFormatKRN: public imFileFormatBase +{ + imBinFile* handle; /* the binary file handle */ + +public: + imFileFormatKRN(const imFormat* _iformat): imFileFormatBase(_iformat) {} + ~imFileFormatKRN() {} + + int Open(const char* file_name); + int New(const char* file_name); + void Close(); + void* Handle(int index); + int ReadImageInfo(int index); + int ReadImageData(void* data); + int WriteImageInfo(); + int WriteImageData(void* data); +}; + +class imFormatKRN: public imFormat +{ +public: + imFormatKRN() + :imFormat("KRN", + "IM Kernel File Format", + "*.krn;", + iKRNCompTable, + 1, + 0) + {} + ~imFormatKRN() {} + + imFileFormatBase* Create(void) const { return new imFileFormatKRN(this); } + int CanWrite(const char* compression, int color_mode, int data_type) const; +}; + +void imFormatRegisterKRN(void) +{ + imFormatRegister(new imFormatKRN()); +} + +int imFileFormatKRN::Open(const char* file_name) +{ + char sig[9]; + + /* opens the binary file for reading */ + handle = imBinFileOpen(file_name); + if (!handle) + return IM_ERR_OPEN; + + /* reads the KRN format identifier */ + imBinFileRead(handle, sig, 8, 1); + if (imBinFileError(handle)) + { + imBinFileClose(handle); + return IM_ERR_ACCESS; + } + + sig[8] = 0; + + if (!imStrEqual(sig, "IMKERNEL")) + { + imBinFileClose(handle); + return IM_ERR_FORMAT; + } + + this->image_count = 1; + strcpy(this->compression, "NONE"); + + return IM_ERR_NONE; +} + +int imFileFormatKRN::New(const char* file_name) +{ + /* opens the binary file for writing */ + handle = imBinFileNew(file_name); + if (!handle) + return IM_ERR_OPEN; + + this->image_count = 1; + if (!imBinFileWrite(handle, (void*)"IMKERNEL\n", 9, 1)) + { + imBinFileClose(handle); + return IM_ERR_ACCESS; + } + + return IM_ERR_NONE; +} + +void imFileFormatKRN::Close() +{ + imBinFileClose(handle); +} + +void* imFileFormatKRN::Handle(int index) +{ + if (index == 0) + return (void*)this->handle; + else + return NULL; +} + +int imFileFormatKRN::ReadImageInfo(int index) +{ + (void)index; + this->file_color_mode = IM_GRAY|IM_TOPDOWN; + + char desc[512]; + int desc_size; + if (!iKRNReadDescription(handle, desc, &desc_size)) + return IM_ERR_ACCESS; + + imAttribTable* attrib_table = AttribTable(); + if (desc_size) + attrib_table->Set("Description", IM_BYTE, desc_size, desc); + + if (!imBinFileReadInteger(handle, &this->width)) + return IM_ERR_ACCESS; + + if (!imBinFileReadInteger(handle, &this->height)) + return IM_ERR_ACCESS; + + int type; + if (!imBinFileReadInteger(handle, &type)) + return IM_ERR_ACCESS; + + if (type == 0) + this->file_data_type = IM_INT; + else + this->file_data_type = IM_FLOAT; + + return IM_ERR_NONE; +} + +int imFileFormatKRN::WriteImageInfo() +{ + this->file_data_type = this->user_data_type; + this->file_color_mode = IM_GRAY|IM_TOPDOWN; + + imAttribTable* attrib_table = AttribTable(); + + int attrib_size; + const void* attrib_data = attrib_table->Get("Description", NULL, &attrib_size); + if (attrib_data) + { + char* desc = (char*)attrib_data; + int size = 0; + while(size < (attrib_size-1) && (desc[size] != '\r' && desc[size] != '\n')) + size++; + + imBinFileWrite(handle, desc, size, 1); + } + imBinFileWrite(handle, (void*)"\n", 1, 1); + + imBinFilePrintf(handle, "%d\n", this->width); + imBinFilePrintf(handle, "%d\n", this->height); + + if (this->file_data_type == IM_INT) + imBinFileWrite(handle, (void*)"0\n", 1, 1); + else + imBinFileWrite(handle, (void*)"1\n", 1, 1); + + /* tests if everything was ok */ + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + return IM_ERR_NONE; +} + +int imFileFormatKRN::ReadImageData(void* data) +{ + imCounterTotal(this->counter, this->height, "Reading KRN..."); + + for (int row = 0; row < this->height; row++) + { + for (int col = 0; col < this->width; col++) + { + if (this->file_data_type == IM_INT) + { + int value; + if (!imBinFileReadInteger(handle, &value)) + return IM_ERR_ACCESS; + + ((int*)this->line_buffer)[col] = value; + } + else + { + float value; + if (!imBinFileReadFloat(handle, &value)) + return IM_ERR_ACCESS; + + ((float*)this->line_buffer)[col] = value; + } + } + + imFileLineBufferRead(this, data, row, 0); + + if (!imCounterInc(this->counter)) + return IM_ERR_COUNTER; + } + + return IM_ERR_NONE; +} + +int imFileFormatKRN::WriteImageData(void* data) +{ + imCounterTotal(this->counter, this->height, "Writing KRN..."); + + for (int row = 0; row < this->height; row++) + { + imFileLineBufferWrite(this, data, row, 0); + + for (int col = 0; col < this->width; col++) + { + if (this->file_data_type == IM_INT) + { + int value = ((int*)this->line_buffer)[col]; + + if (!imBinFilePrintf(handle, "%d ", value)) + return IM_ERR_ACCESS; + } + else + { + float value = ((float*)this->line_buffer)[col]; + + if (!imBinFilePrintf(handle, "%f ", (double)value)) + return IM_ERR_ACCESS; + } + } + + imBinFileWrite(handle, (void*)"\n", 1, 1); + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + if (!imCounterInc(this->counter)) + return IM_ERR_COUNTER; + } + + return IM_ERR_NONE; +} + +int imFormatKRN::CanWrite(const char* compression, int color_mode, int data_type) const +{ + int color_space = imColorModeSpace(color_mode); + + if (color_space != IM_GRAY) + return IM_ERR_DATA; + + if (data_type != IM_INT && data_type != IM_FLOAT) + return IM_ERR_DATA; + + if (!compression || compression[0] == 0) + return IM_ERR_NONE; + + if (!imStrEqual(compression, "NONE")) + return IM_ERR_COMPRESS; + + return IM_ERR_NONE; +} diff --git a/im/src/im_format_led.cpp b/im/src/im_format_led.cpp new file mode 100755 index 0000000..7b75443 --- /dev/null +++ b/im/src/im_format_led.cpp @@ -0,0 +1,341 @@ +/** \file + * \brief LED - IUP image in LED + * + * See Copyright Notice in im_lib.h + * $Id: im_format_led.cpp,v 1.3 2009/10/01 14:15:47 scuri Exp $ + */ + +#include "im_format.h" +#include "im_format_all.h" +#include "im_util.h" +#include "im_counter.h" + +#include "im_binfile.h" + +#include +#include +#include +#include + +/* Sample LED Image +LEDImage = IMAGE[ +0 = "0 0 0", +1 = "192 192 192", +2 = "0 0 128", +3 = "255 255 255"] +(20, 19 +,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 +,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 +,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 +,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1 +,1,1,0,3,3,3,3,0,0,1,1,1,1,1,1,1,1,1,1,1 +,1,1,0,3,3,3,3,0,3,0,1,1,1,1,1,1,1,1,1,1 +,1,1,0,3,0,0,3,0,2,2,2,2,2,2,1,1,1,1,1,1 +,1,1,0,3,3,3,3,3,2,3,3,3,3,2,2,1,1,1,1,1 +,1,1,0,3,0,0,0,0,2,3,3,3,3,2,3,2,1,1,1,1 +,1,1,0,3,3,3,3,3,2,3,0,0,3,2,2,2,2,1,1,1 +,1,1,0,3,0,0,0,0,2,3,3,3,3,3,3,3,2,1,1,1 +,1,1,0,3,3,3,3,3,2,3,0,0,0,0,0,3,2,1,1,1 +,1,1,0,0,0,0,0,0,2,3,3,3,3,3,3,3,2,1,1,1 +,1,1,1,1,1,1,1,1,2,3,0,0,0,0,0,3,2,1,1,1 +,1,1,1,1,1,1,1,1,2,3,3,3,3,3,3,3,2,1,1,1 +,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1 +,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 +,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 +,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 +) +*/ + +static const char* iLEDCompTable[1] = +{ + "NONE" +}; + +class imFileFormatLED: public imFileFormatBase +{ + imBinFile* handle; /* the binary file handle */ + int pal_count; + + int ReadPalette(); + int WritePalette(); + +public: + imFileFormatLED(const imFormat* _iformat): imFileFormatBase(_iformat) {} + ~imFileFormatLED() {} + + int Open(const char* file_name); + int New(const char* file_name); + void Close(); + void* Handle(int index); + int ReadImageInfo(int index); + int ReadImageData(void* data); + int WriteImageInfo(); + int WriteImageData(void* data); +}; + +class imFormatLED: public imFormat +{ +public: + imFormatLED() + :imFormat("LED", + "IUP image in LED special format", + "*.led;", + iLEDCompTable, + 1, + 0) + {} + ~imFormatLED() {} + + imFileFormatBase* Create(void) const { return new imFileFormatLED(this); } + int CanWrite(const char* compression, int color_mode, int data_type) const; +}; + + +void imFormatRegisterLED(void) +{ + imFormatRegister(new imFormatLED()); +} + +int imFileFormatLED::Open(const char* file_name) +{ + char sig[4]; + unsigned char byte_value; + int found = 0; + + /* opens the binary file for reading */ + handle = imBinFileOpen(file_name); + if (!handle) + return IM_ERR_OPEN; + + this->image_count = 1; + strcpy(this->compression, "NONE"); + + imBinFileRead(handle, sig, 3, 1); + sig[3] = 0; + + if (imBinFileError(handle)) + { + imBinFileClose(handle); + return IM_ERR_ACCESS; + } + + if (!imStrEqual(sig, "LED")) + { + imBinFileClose(handle); + return IM_ERR_FORMAT; + } + + unsigned long offset = imBinFileTell(handle); + + /* count the number of colors */ + this->pal_count = -1; // will count the first '=' that is not a color + while (!found) + { + imBinFileRead(handle, &byte_value, 1, 1); + + if (byte_value == '(') + found = 1; + + if (byte_value == '=') + this->pal_count++; + + if (imBinFileError(handle)) + { + imBinFileClose(handle); + return IM_ERR_ACCESS; + } + } + + imBinFileSeekTo(handle, offset); + + return IM_ERR_NONE; +} + +int imFileFormatLED::New(const char* file_name) +{ + /* opens the binary file for writing */ + handle = imBinFileNew(file_name); + if (!handle) + return IM_ERR_OPEN; + + imBinFileWrite(handle, (void*)"LEDImage = IMAGE", 16, 1); + + /* tests if everything was ok */ + if (imBinFileError(handle)) + { + imBinFileClose(handle); + return IM_ERR_ACCESS; + } + + return IM_ERR_NONE; +} + +void imFileFormatLED::Close() +{ + imBinFileClose(handle); +} + +void* imFileFormatLED::Handle(int index) +{ + if (index == 0) + return (void*)this->handle; + else + return NULL; +} + +int imFileFormatLED::ReadImageInfo(int index) +{ + (void)index; + + this->palette_count = this->pal_count; + + if (ReadPalette() != IM_ERR_NONE) + return IM_ERR_ACCESS; + + imBinFileReadInteger(handle, &this->width); + imBinFileReadInteger(handle, &this->height); + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + this->file_data_type = IM_BYTE; + this->file_color_mode = IM_MAP; + this->file_color_mode |= IM_TOPDOWN; + + return IM_ERR_NONE; +} + +int imFileFormatLED::WriteImageInfo() +{ + this->file_data_type = IM_BYTE; + this->file_color_mode = imColorModeSpace(this->user_color_mode); + this->file_color_mode |= IM_TOPDOWN; + + if (WritePalette() != IM_ERR_NONE) + return IM_ERR_ACCESS; + + imBinFilePrintf(handle, "(%d, %d\n", this->width, this->height); + + return IM_ERR_NONE; +} + +int imFileFormatLED::ReadPalette() +{ + int c, r, g, b, i; + + /* convert the color map to the IM format */ + for (c = 0; c < this->palette_count; c++) + { + imBinFileReadInteger(handle, &i); + imBinFileReadInteger(handle, &r); + imBinFileReadInteger(handle, &g); + imBinFileReadInteger(handle, &b); + + this->palette[i] = imColorEncode((unsigned char)r, (unsigned char)g, (unsigned char)b); + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + } + + return IM_ERR_NONE; +} + +int imFileFormatLED::WritePalette() +{ + int c; + unsigned char r, g, b; + + imBinFileWrite(handle, (void*)"[\n", 2, 1); + + /* convert the color map from the IM format */ + for (c = 0; c < this->palette_count; c++) + { + imColorDecode(&r, &g, &b, this->palette[c]); + imBinFilePrintf(handle, "%d = \"%d %d %d\"", c, (int)r, (int)g, (int)b); + + if (c != this->palette_count - 1) + imBinFileWrite(handle, (void*)",\n", 2, 1); + } + + imBinFileWrite(handle, (void*)"]\n", 2, 1); + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + return IM_ERR_NONE; +} + +int imFileFormatLED::ReadImageData(void* data) +{ + int value; + + imCounterTotal(this->counter, this->height, "Reading LED..."); + + for (int row = 0; row < this->height; row++) + { + for (int col = 0; col < this->width; col++) + { + if (!imBinFileReadInteger(handle, &value)) + return IM_ERR_ACCESS; + + ((imbyte*)this->line_buffer)[col] = (unsigned char)value; + } + + imFileLineBufferRead(this, data, row, 0); + + if (!imCounterInc(this->counter)) + return IM_ERR_COUNTER; + } + + return IM_ERR_NONE; +} + +int imFileFormatLED::WriteImageData(void* data) +{ + imCounterTotal(this->counter, this->height, "Writing LED..."); + + for (int row = 0; row < this->height; row++) + { + imFileLineBufferWrite(this, data, row, 0); + + for (int col = 0; col < this->width; col++) + { + if (!imBinFilePrintf(handle, ",%d", (int)((imbyte*)this->line_buffer)[col])) + return IM_ERR_ACCESS; + } + + imBinFileWrite(handle, (void*)"\n", 1, 1); + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + if (!imCounterInc(this->counter)) + return IM_ERR_COUNTER; + } + + imBinFileWrite(handle, (void*)")", 1, 1); + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + return IM_ERR_NONE; +} + +int imFormatLED::CanWrite(const char* compression, int color_mode, int data_type) const +{ + int color_space = imColorModeSpace(color_mode); + + if (color_space == IM_YCBCR || color_space == IM_LAB || + color_space == IM_LUV || color_space == IM_XYZ || + color_space == IM_CMYK) + return IM_ERR_DATA; + + if (data_type != IM_BYTE) + return IM_ERR_DATA; + + if (!compression || compression[0] == 0) + return IM_ERR_NONE; + + if (!imStrEqual(compression, "NONE")) + return IM_ERR_COMPRESS; + + return IM_ERR_NONE; +} diff --git a/im/src/im_format_pcx.cpp b/im/src/im_format_pcx.cpp new file mode 100755 index 0000000..d340927 --- /dev/null +++ b/im/src/im_format_pcx.cpp @@ -0,0 +1,711 @@ +/** \file + * \brief PCX - ZSoft Picture + * + * See Copyright Notice in im_lib.h + * $Id: im_format_pcx.cpp,v 1.3 2009/08/19 18:39:43 scuri Exp $ + */ + +#include "im_format.h" +#include "im_format_all.h" +#include "im_util.h" +#include "im_counter.h" + +#include "im_binfile.h" + +#include +#include +#include + +#define PCX_ID 0x0A + + +/* PCX file header */ +/* 1 Id; Manufacturer ID */ +/* 1 Version; Version */ +/* 1 Encoding; Encoding Scheme */ +/* 1 BitsPerPixel; Bits/Pixel/Plane */ +/* 2 Xmin; X Start (upper left) */ +/* 2 Ymin; Y Start (top) */ +/* 2 Xmax; X End (lower right) */ +/* 2 Ymax; Y End (bottom) */ +/* 2 Hdpi; Horizontal Resolution */ +/* 2 Vdpi; Vertical Resolution */ +/* 3*16 Colormap; 16-Color EGA Palette */ +/* 1 Reserved; Reserved */ +/* 1 NPlanes; Number of Color Planes */ +/* 2 BytesPerLine; Bytes/Line/Plane */ +/* 2 PaletteInfo; Palette Interpretation */ +/* 2 HScreenSize; Horizontal Screen Size */ +/* 2 VScreenSize; Vertical Screen Size */ +/* 54 Filler; Reserved */ +/* 128 */ + +/* Default 16 color VGA palette */ +static unsigned char iPCXDefaultPalette[3*16] = +{ + 0, 0, 0, + 0, 0, 255, + 0, 255, 0, + 0, 255, 255, + 255, 0, 0, + 255, 0, 255, + 255, 255, 0, + 255, 255, 255, + 85, 85, 255, + 85, 85, 85, + 0, 170, 0, + 170, 0, 0, + 85, 255, 255, + 255, 85, 255, + 255, 255, 85, + 255, 255, 255 +}; + +static int iPCXEncodeScanLine(unsigned char* EncodedBuffer, const unsigned char* DecodedBuffer, int BufferSize) +{ + int index = 0; /* Index into uncompressed data buffer */ + int scanindex = 0; /* Index into compressed data buffer */ + unsigned char runcount; /* Length of encoded pixel run */ + unsigned char runvalue; /* Value of encoded pixel run */ + + while (index < BufferSize) + { + /** Get the run count of the next pixel value run. + ** Pixel value runs are encoded until a different pixel value + ** is encountered, the end of the scan line is reached, or 63 + ** pixel values have been counted. */ + for (runcount = 1, runvalue = DecodedBuffer[index]; + index + runcount < BufferSize && runvalue == DecodedBuffer[index + runcount] && runcount < 63; + runcount++); + + /** Encode the run into a one or two-unsigned char code. + ** Multiple pixel runs are stored in two-unsigned char codes. If a single + ** pixel run has a value of less than 64 then it is stored in a + ** one-unsigned char code. If a single pixel run has a value of 64 to 255 + ** then it is stored in a two-unsigned char code. */ + + if (runcount > 1) /* Multiple pixel run */ + { + EncodedBuffer[scanindex++] = (unsigned char)(runcount | 0xC0); + EncodedBuffer[scanindex++] = runvalue; + } + else /* Single pixel run */ + { + if (DecodedBuffer[index] < 64) /* Value is 0 to 63 */ + EncodedBuffer[scanindex++] = runvalue; + else /* Value is 64 to 255 */ + { + EncodedBuffer[scanindex++] = (unsigned char)(runcount | 0xC0); + EncodedBuffer[scanindex++] = runvalue; + } + } + + index += runcount; /* Jump ahead to next pixel run value */ + } + + return scanindex; /* Return the number of unsigned chars written to buffer */ +} + +static int iPCXDecodeScanLine(imBinFile* handle, unsigned char* DecodedBuffer, int BufferSize) +{ + int index = 0; /* Index into compressed scan line buffer */ + unsigned char data; /* Data byte read from PCX file */ + unsigned char runcount = 0; /* Length of decoded pixel run */ + unsigned char runvalue = 0; /* Value of decoded pixel run */ + + while (index < BufferSize) /* Read until the end of the buffer */ + { + imBinFileRead(handle, &data, 1, 1); + + if ((data & 0xC0) == 0xC0) /* Two-unsigned char code */ + { + runcount = (unsigned char)(data & 0x3F); /* Get run count */ + imBinFileRead(handle, &runvalue, 1, 1); + } + else /* One unsigned char code */ + { + runcount = 1; /* Run count is one */ + runvalue = data; /* Pixel value */ + } + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + /* Write the pixel run to the buffer */ + for (;runcount && (index < BufferSize); runcount--, index++) + DecodedBuffer[index] = runvalue; /* Assign value to buffer */ + } + + return IM_ERR_NONE; +} + +static const char* iPCXCompTable[2] = +{ + "NONE", + "RLE" +}; + +class imFileFormatPCX: public imFileFormatBase +{ + imBinFile* handle; /* the binary file handle */ + int bpp; /* number of bits per pixel */ + unsigned char version; /* format version */ + unsigned char comp_type; /* PCX compression information */ + int line_raw_size; /* bytes per line per plane */ + + int ReadPalette(); + int WritePalette(); + void Expand4bpp(); + void Pack24bpp(); + void Unpack24bpp(); + +public: + imFileFormatPCX(const imFormat* _iformat): imFileFormatBase(_iformat) {} + ~imFileFormatPCX() {} + + int Open(const char* file_name); + int New(const char* file_name); + void Close(); + void* Handle(int index); + int ReadImageInfo(int index); + int ReadImageData(void* data); + int WriteImageInfo(); + int WriteImageData(void* data); +}; + +class imFormatPCX: public imFormat +{ +public: + imFormatPCX() + :imFormat("PCX", + "ZSoft Picture", + "*.pcx;", + iPCXCompTable, + 2, + 0) + {} + ~imFormatPCX() {} + + imFileFormatBase* Create(void) const { return new imFileFormatPCX(this); } + int CanWrite(const char* compression, int color_mode, int data_type) const; +}; + + +void imFormatRegisterPCX(void) +{ + imFormatRegister(new imFormatPCX()); +} + +int imFileFormatPCX::Open(const char* file_name) +{ + unsigned char id; + + /* opens the binary file for reading with intel unsigned char order */ + handle = imBinFileOpen(file_name); + if (!handle) + return IM_ERR_OPEN; + + imBinFileByteOrder(handle, IM_LITTLEENDIAN); + + /* reads the PCX format identifier */ + imBinFileRead(handle, &id, 1, 1); + if (imBinFileError(handle)) + { + imBinFileClose(handle); + return IM_ERR_ACCESS; + } + + if (id != PCX_ID) + { + imBinFileClose(handle); + return IM_ERR_FORMAT; + } + + /* reads the format version */ + imBinFileRead(handle, &this->version, 1, 1); + + /* reads the compression comp_type */ + imBinFileRead(handle, &this->comp_type, 1, 1); + if (this->comp_type) + strcpy(this->compression, "RLE"); + else + strcpy(this->compression, "NONE"); + + this->image_count = 1; + + return IM_ERR_NONE; +} + +int imFileFormatPCX::New(const char* file_name) +{ + /* opens the binary file for writing with intel byte order */ + handle = imBinFileNew(file_name); + if (!handle) + return IM_ERR_OPEN; + + imBinFileByteOrder(handle, IM_LITTLEENDIAN); + + return IM_ERR_NONE; +} + +void imFileFormatPCX::Close() +{ + imBinFileClose(handle); +} + +void* imFileFormatPCX::Handle(int index) +{ + if (index == 0) + return (void*)this->handle; + else + return NULL; +} + +int imFileFormatPCX::ReadImageInfo(int index) +{ + unsigned char bppp, planes; + unsigned short xmin, xmax, ymax, ymin, word, bplp; + (void)index; + + this->file_data_type = IM_BYTE; + + /* reads the Number of bits/pixel per plane */ + imBinFileRead(handle, &bppp, 1, 1); + + /* reads the image width and height */ + imBinFileRead(handle, &xmin, 1, 2); + imBinFileRead(handle, &ymin, 1, 2); + imBinFileRead(handle, &xmax, 1, 2); + imBinFileRead(handle, &ymax, 1, 2); + this->width = xmax - xmin + 1; + this->height = ymax - ymin + 1; + + imAttribTable* attrib_table = AttribTable(); + + if (xmin && ymin) + { + attrib_table->Set("XScreen", IM_USHORT, 1, &xmin); + attrib_table->Set("YScreen", IM_USHORT, 1, &ymin); + } + + /* read the x resolution */ + imBinFileRead(handle, &word, 1, 2); + float xres = word; + + /* read the y resolution */ + imBinFileRead(handle, &word, 1, 2); + float yres = word; + + if (xres && yres) + { + attrib_table->Set("XResolution", IM_FLOAT, 1, &xres); + attrib_table->Set("YResolution", IM_FLOAT, 1, &yres); + attrib_table->Set("ResolutionUnit", IM_BYTE, -1, "DPI"); + } + + /* jump 3*16+1 bytes (colormap + reserved) */ + imBinFileSeekOffset(handle, 3*16+1); + + /* reads the Number of color planes */ + imBinFileRead(handle, &planes, 1, 1); + this->bpp = bppp * planes; + + /* reads the Number of bytes per scan line per color planes */ + imBinFileRead(handle, &bplp, 1, 2); + this->line_raw_size = bplp * planes; + this->line_buffer_extra = 2; // room enough for padding + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + // sanity check + if (this->bpp != 1 && this->bpp != 4 && + this->bpp != 8 && this->bpp != 24) + return IM_ERR_DATA; + + if (this->bpp > 8) + { + this->file_color_mode = IM_RGB; + this->file_color_mode |= IM_PACKED; + this->line_buffer_extra += 3*this->width; // room for 24 bpp packing + } + else + { + this->file_color_mode = IM_MAP; + this->palette_count = 1 << this->bpp; + + if (this->bpp == 1) // only 1 bpp, 4 bpp will be expanded here + this->convert_bpp = 1; + + if (this->bpp == 4) + this->line_buffer_extra += this->width; // room for 4 bpp expansion + } + + this->file_color_mode |= IM_TOPDOWN; + + if (this->bpp <= 8) + return ReadPalette(); + + return IM_ERR_NONE; +} + +int imFileFormatPCX::WriteImageInfo() +{ + unsigned short word_value, bplp; + unsigned char byte_value, filler[54+3*2]; + + this->file_data_type = IM_BYTE; + + this->file_color_mode = imColorModeSpace(this->user_color_mode); + + if (imStrEqual(this->compression, "NONE")) + this->comp_type = (unsigned char)0; + else + this->comp_type = (unsigned char)1; + + if (this->file_color_mode == IM_BINARY) + { + this->bpp = 1; + this->convert_bpp = 1; + } + else if (this->file_color_mode == IM_RGB) + { + this->bpp = 24; + this->file_color_mode |= IM_PACKED; + } + else + this->bpp = 8; + + this->file_color_mode |= IM_TOPDOWN; + + int planes = imColorModeDepth(this->file_color_mode); + bplp = (unsigned short)imFileLineSizeAligned(this->width, this->bpp/planes, 2); + this->line_raw_size = bplp * planes; + this->line_buffer_extra = 2; // room enough for padding + + if (this->comp_type || this->bpp == 24) + { + // allocates room for 24 bpp packing/unpacking and/or compression + // allocates more than enough since compression algoritm can be ineficient + this->line_buffer_extra += 2*this->line_raw_size; + } + + this->version = 5; + + imAttribTable* attrib_table = AttribTable(); + /* writes the PCX file header */ + + unsigned short xmin = 0, ymin = 0; + const void* attrib_data = attrib_table->Get("XScreen"); + if (attrib_data) xmin = *(unsigned short*)attrib_data; + attrib_data = attrib_table->Get("YScreen"); + if (attrib_data) ymin = *(unsigned short*)attrib_data; + + byte_value = PCX_ID; + imBinFileWrite(handle, &byte_value, 1, 1); /* identifier */ + imBinFileWrite(handle, &this->version, 1, 1); /* format version */ + imBinFileWrite(handle, &this->comp_type, 1, 1); /* compression comp_type */ + byte_value = (imbyte)(this->bpp/planes); + imBinFileWrite(handle, &byte_value, 1, 1); /* bits/pixel/plane */ + word_value = xmin; + imBinFileWrite(handle, &word_value, 1, 2); /* xmin */ + word_value = ymin; + imBinFileWrite(handle, &word_value, 1, 2); /* ymin */ + word_value = (unsigned short)(this->width - 1) + xmin; + imBinFileWrite(handle, &word_value, 1, 2); /* xmax */ + word_value = (unsigned short)(this->height - 1) + ymin; + imBinFileWrite(handle, &word_value, 1, 2); /* ymax */ + + unsigned short hdpi = 0, vdpi = 0; + attrib_data = attrib_table->Get("ResolutionUnit"); + if (attrib_data) + { + char* res_unit = (char*)attrib_data; + + float* xres = (float*)attrib_table->Get("XResolution"); + float* yres = (float*)attrib_table->Get("YResolution"); + + if (imStrEqual(res_unit, "DPC")) + { + hdpi = (unsigned short)(*xres * 2.54); + vdpi = (unsigned short)(*yres * 2.54); + } + } + + /* write the x resolution */ + word_value = hdpi; + imBinFileWrite(handle, &word_value, 1, 2); /* hdpi */ + + /* write the y resolution */ + word_value = vdpi; + imBinFileWrite(handle, &word_value, 1, 2); /* vdpi */ + + imBinFileWrite(handle, iPCXDefaultPalette, 3*16, 1); /* 16 colors palette */ + byte_value = 0; + imBinFileWrite(handle, &byte_value, 1, 1); /* reserved */ + byte_value = (imbyte)planes; + imBinFileWrite(handle, &byte_value, 1, 1); /* planes */ + word_value = bplp; + imBinFileWrite(handle, &word_value, 1, 2); /* bytes per line per plane */ + memset(filler, 0, 54+3*2); + imBinFileWrite(handle, filler, 54+3*2, 1); /* palette info, hscreen size, vscreen size, filler */ + + /* tests if everything was ok */ + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + return IM_ERR_NONE; +} + +int imFileFormatPCX::ReadPalette() +{ + unsigned char pcx_colors[256 * 3]; + + if (this->version == 5 && this->bpp == 1) + { + pcx_colors[0] = 0; pcx_colors[1] = 0; pcx_colors[2] = 0; + pcx_colors[3] = 255; pcx_colors[4] = 255; pcx_colors[5] = 255; + } + else if (this->version == 5 && this->bpp == 8) + { + unsigned char ExtPal; + + /* jump to the end of file minus the palette data */ + imBinFileSeekFrom(handle, -769); + + /* reads palette identifier */ + imBinFileRead(handle, &ExtPal, 1, 1); + + if (ExtPal != 12) + return IM_ERR_ACCESS; + + /* reads palette colors */ + imBinFileRead(handle, pcx_colors, 768, 1); + } + else if (this->version == 3) + { + memcpy(pcx_colors, iPCXDefaultPalette, this->palette_count * 3); + } + else + { + /* jump to the begining of the file at the start of the palette data */ + imBinFileSeekTo(handle, 4+6*2); + + /* reads palette colors */ + imBinFileRead(handle, pcx_colors, 3 * 16, 1); + } + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + /* convert the color map to the IM format */ + for (int c = 0; c < this->palette_count; c++) + { + int i = c * 3; + this->palette[c] = imColorEncode(pcx_colors[i], pcx_colors[i+1], pcx_colors[i+2]); + } + + return IM_ERR_NONE; +} + +int imFileFormatPCX::WritePalette() +{ + unsigned char ExtPal = (unsigned char)12; + unsigned char pcx_colors[256 * 3]; + + /* convert the color map to the IM format */ + for (int c = 0; c < this->palette_count; c++) + { + int i = c * 3; + imColorDecode(&pcx_colors[i], &pcx_colors[i+1], &pcx_colors[i+2], this->palette[c]); + } + + /* writes the palette identifier */ + imBinFileWrite(handle, &ExtPal, 1, 1); + + /* writes the color palette */ + imBinFileWrite(handle, pcx_colors, 256 * 3, 1); + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + return IM_ERR_NONE; +} + +void imFileFormatPCX::Expand4bpp() +{ + int num_bits = 8, WidthDiv8 = (this->width + 7) / 8; + + int line_plane_size = this->line_raw_size / 4; + imbyte *in_data = (unsigned char*)this->line_buffer; + imbyte *out_data = in_data + this->line_buffer_size+2; + + for (int x = 0; x < WidthDiv8; x++) + { + imbyte b1 = in_data[x]; + imbyte b2 = (in_data + line_plane_size)[x]; + imbyte b3 = (in_data + 2 * line_plane_size)[x]; + imbyte b4 = (in_data + 3 * line_plane_size)[x]; + + if (x == WidthDiv8-1) + num_bits = this->width % 8; + + for (int b = 0; b < num_bits; b++) + { + imbyte byte_value = 0; + + /* If the most significant bit is set... */ + /* Set the appropriate bit in the higher order nibble */ + if (b1 & '\x80') byte_value |= 0x01; + if (b2 & '\x80') byte_value |= 0x02; + if (b3 & '\x80') byte_value |= 0x04; + if (b4 & '\x80') byte_value |= 0x08; + b1<<=1; b2<<=1; b3<<=1; b4<<=1; + + *out_data++ = byte_value; + } + } + + memcpy(this->line_buffer, in_data + this->line_buffer_size+2, this->width); +} + +void imFileFormatPCX::Pack24bpp() +{ + imbyte *in_data = (unsigned char*)this->line_buffer; + imbyte *out_data = in_data + this->line_buffer_size+2; + + int line_plane_size = this->line_raw_size / 3; + + imbyte *red = in_data; + imbyte *green = in_data + line_plane_size; + imbyte *blue = in_data + 2*line_plane_size; + + for (int i = 0; i < this->width; i++) + { + *out_data++ = *red++; + *out_data++ = *green++; + *out_data++ = *blue++; + } + + memcpy(in_data, in_data + this->line_buffer_size+2, this->line_raw_size); +} + +void imFileFormatPCX::Unpack24bpp() +{ + imbyte *in_data = (unsigned char*)this->line_buffer; + imbyte *out_data = in_data + this->line_buffer_size+2; + + int line_plane_size = this->line_raw_size / 3; + + imbyte *red = out_data; + imbyte *green = out_data + line_plane_size; + imbyte *blue = out_data + 2*line_plane_size; + + for (int i = 0; i < this->width; i++) + { + *red++ = *in_data++; + *green++ = *in_data++; + *blue++ = *in_data++; + } + + memcpy(out_data - (this->line_buffer_size+2), out_data, this->line_raw_size); +} + +int imFileFormatPCX::ReadImageData(void* data) +{ + imCounterTotal(this->counter, this->height, "Reading PCX..."); + + imBinFileSeekTo(handle, 128); + + for (int row = 0; row < this->height; row++) + { + /* read and decompress the data */ + if (this->comp_type) + { + if (iPCXDecodeScanLine(handle, (imbyte*)this->line_buffer, this->line_raw_size) == IM_ERR_ACCESS) + return IM_ERR_ACCESS; + } + else + { + imBinFileRead(handle, this->line_buffer, this->line_raw_size, 1); + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + } + + if (this->bpp == 4) + Expand4bpp(); + + if (this->bpp == 24) + Pack24bpp(); + + imFileLineBufferRead(this, data, row, 0); + + if (!imCounterInc(this->counter)) + return IM_ERR_COUNTER; + } + + return IM_ERR_NONE; +} + +int imFileFormatPCX::WriteImageData(void* data) +{ + imCounterTotal(this->counter, this->height, "Writing PCX..."); + + imBinFileSeekTo(handle, 128); + + imbyte* compressed_buffer = NULL; + if (this->comp_type) // point to the extra buffer + compressed_buffer = (imbyte*)this->line_buffer + this->line_buffer_size+2; + + for (int row = 0; row < this->height; row++) + { + imFileLineBufferWrite(this, data, row, 0); + + if (this->bpp == 24) + Unpack24bpp(); + + /* compress and writes the data */ + /* the compressed buffer size will probably be diferent from the uncompressed buffer size */ + if (this->comp_type) + { + int compressed_size = iPCXEncodeScanLine(compressed_buffer, (imbyte*)this->line_buffer, this->line_raw_size); + imBinFileWrite(handle, compressed_buffer, compressed_size, 1); + } + else + { + imBinFileWrite(handle, this->line_buffer, this->line_raw_size, 1); + } + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + if (!imCounterInc(this->counter)) + return IM_ERR_COUNTER; + } + + if (this->bpp == 8) + return WritePalette(); + + return IM_ERR_NONE; +} + +int imFormatPCX::CanWrite(const char* compression, int color_mode, int data_type) const +{ + int color_space = imColorModeSpace(color_mode); + + if (color_space == IM_YCBCR || color_space == IM_LAB || + color_space == IM_LUV || color_space == IM_XYZ || + color_space == IM_CMYK) + return IM_ERR_DATA; + + if (data_type != IM_BYTE) + return IM_ERR_DATA; + + if (!compression || compression[0] == 0) + return IM_ERR_NONE; + + if (!imStrEqual(compression, "NONE") && !imStrEqual(compression, "RLE")) + return IM_ERR_COMPRESS; + + return IM_ERR_NONE; +} diff --git a/im/src/im_format_pnm.cpp b/im/src/im_format_pnm.cpp new file mode 100755 index 0000000..9347ddc --- /dev/null +++ b/im/src/im_format_pnm.cpp @@ -0,0 +1,483 @@ +/** \file + * \brief PNM - Netpbm Portable Image Map + * + * See Copyright Notice in im_lib.h + * $Id: im_format_pnm.cpp,v 1.3 2009/10/01 14:15:47 scuri Exp $ + */ + +#include "im_format.h" +#include "im_format_all.h" +#include "im_util.h" +#include "im_counter.h" + +#include "im_binfile.h" + +#include +#include +#include + + +/* comments start with '#' after the first \n */ +static int iPNMReadComment(imBinFile* handle, char* comment, int *size) +{ + imbyte byte_value = 0; + + // find the first \n + while(byte_value != '\n') + { + imBinFileRead(handle, &byte_value, 1, 1); + if (imBinFileError(handle)) + return 0; + } + + *size = 0; + + imBinFileRead(handle, &byte_value, 1, 1); + if (imBinFileError(handle)) + return 0; + + if (byte_value == '#') + { + while(byte_value != '\n') + { + imBinFileRead(handle, &byte_value, 1, 1); + if (imBinFileError(handle)) + return 0; + + if (byte_value != '\r') + { + comment[*size] = byte_value; + (*size)++; + } + } + } + else + imBinFileSeekOffset(handle, -1); + + if (*size != 0) + { + comment[*size] = 0; + (*size)++; + } + + return 1; +} + +static const char* iPNMCompTable[2] = +{ + "NONE", + "ASCII" +}; + +class imFileFormatPNM: public imFileFormatBase +{ + imBinFile* handle; /* the binary file handle */ + unsigned char image_type; + + void FixBinary(); + +public: + imFileFormatPNM(const imFormat* _iformat): imFileFormatBase(_iformat) {} + ~imFileFormatPNM() {} + + int Open(const char* file_name); + int New(const char* file_name); + void Close(); + void* Handle(int index); + int ReadImageInfo(int index); + int ReadImageData(void* data); + int WriteImageInfo(); + int WriteImageData(void* data); +}; + +class imFormatPNM: public imFormat +{ +public: + imFormatPNM() + :imFormat("PNM", + "Netpbm Portable Image Map", + "*.pnm;*.pbm;*.ppm;*.pgm;", + iPNMCompTable, + 2, + 1) + {} + ~imFormatPNM() {} + + imFileFormatBase* Create(void) const { return new imFileFormatPNM(this); } + int CanWrite(const char* compression, int color_mode, int data_type) const; +}; + + +void imFormatRegisterPNM(void) +{ + imFormatRegister(new imFormatPNM()); +} + +int imFileFormatPNM::Open(const char* file_name) +{ + unsigned char sig[2]; + + /* opens the binary file for reading */ + handle = imBinFileOpen(file_name); + if (!handle) + return IM_ERR_OPEN; + + /* reads the PNM format identifier */ + imBinFileRead(handle, sig, 2, 1); + if (imBinFileError(handle)) + { + imBinFileClose(handle); + return IM_ERR_ACCESS; + } + + if (sig[0] != 'P' || (sig[1] != '1' && sig[1] != '2' && + sig[1] != '3' && sig[1] != '4' && + sig[1] != '5' && sig[1] != '6')) + { + imBinFileClose(handle); + return IM_ERR_FORMAT; + } + + this->image_type = sig[1]; + this->image_count = 1; // increment this if found image after data + + if (this->image_type == '1' || this->image_type == '2' || this->image_type == '3') + strcpy(this->compression, "ASCII"); + else + strcpy(this->compression, "NONE"); + + return IM_ERR_NONE; +} + +int imFileFormatPNM::New(const char* file_name) +{ + /* opens the binary file for writing */ + handle = imBinFileNew(file_name); + if (!handle) + return IM_ERR_OPEN; + + this->image_count = 1; + + return IM_ERR_NONE; +} + +void imFileFormatPNM::Close() +{ + imBinFileClose(handle); +} + +void* imFileFormatPNM::Handle(int index) +{ + if (index == 0) + return (void*)this->handle; + else + return NULL; +} + +int imFileFormatPNM::ReadImageInfo(int index) +{ + (void)index; + + switch (this->image_type) + { + case '4': + this->convert_bpp = 1; + case '1': + this->file_color_mode = IM_BINARY; + break; + case '2': + case '5': + this->file_color_mode = IM_GRAY; + break; + case '3': + case '6': + this->file_color_mode = IM_RGB | IM_PACKED; + break; + } + + this->file_color_mode |= IM_TOPDOWN; + + imAttribTable* attrib_table = AttribTable(); + + char comment[4096]; + int size; + if (!iPNMReadComment(handle, comment, &size)) + return IM_ERR_ACCESS; + + if (size) + attrib_table->Set("Description", IM_BYTE, size, comment); + + if (!imBinFileReadInteger(handle, &this->width)) + return IM_ERR_ACCESS; + + if (!imBinFileReadInteger(handle, &this->height)) + return IM_ERR_ACCESS; + + if (this->height <= 0 || this->width <= 0) + return IM_ERR_DATA; + + int max_val = 255; + if (this->image_type != '4' && this->image_type != '1') + { + if (!imBinFileReadInteger(handle, &max_val)) + return IM_ERR_ACCESS; + } + + this->file_data_type = IM_BYTE; + if (max_val > 255) + this->file_data_type = IM_USHORT; + + return IM_ERR_NONE; +} + +int imFileFormatPNM::WriteImageInfo() +{ + this->file_data_type = this->user_data_type; + this->file_color_mode = imColorModeSpace(this->user_color_mode); + + int ascii; + if (imStrEqual(this->compression, "ASCII")) + ascii = 1; + else + ascii = 0; + + switch (this->file_color_mode) + { + case IM_BINARY: + if (ascii) + this->image_type = '1'; + else + { + this->image_type = '4'; + this->convert_bpp = 1; + } + break; + case IM_GRAY: + if (ascii) + this->image_type = '2'; + else + this->image_type = '5'; + break; + case IM_RGB: + if (ascii) + this->image_type = '3'; + else + this->image_type = '6'; + this->file_color_mode |= IM_PACKED; + break; + } + + this->file_color_mode |= IM_TOPDOWN; + + imBinFilePrintf(handle, "P%c\n", (int)this->image_type); + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + imAttribTable* attrib_table = AttribTable(); + + int attrib_size; + const void* attrib_data = attrib_table->Get("Description", NULL, &attrib_size); + if (attrib_data) + { + char* desc = (char*)attrib_data; + int size = 0; + while(size < (attrib_size-1) && (desc[size] != '\r' && desc[size] != '\n')) + size++; + + imBinFileWrite(handle, (void*)"#", 1, 1); + imBinFileWrite(handle, desc, size, 1); + imBinFileWrite(handle, (void*)"\n", 1, 1); + } + + imBinFilePrintf(handle, "%d\n", this->width); + imBinFilePrintf(handle, "%d\n", this->height); + + if (this->image_type != '4' && this->image_type != '1') + { + int max_val = 255; + if (this->file_data_type == IM_USHORT) + max_val = 65535; + + imBinFilePrintf(handle, "%d\n", max_val); + } + + /* tests if everything was ok */ + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + return IM_ERR_NONE; +} + +void imFileFormatPNM::FixBinary() +{ + unsigned char* buf = (unsigned char*)this->line_buffer; + for (int b = 0; b < this->line_buffer_size; b++) + { + *buf = ~(*buf); + buf++; + } +} + +int imFileFormatPNM::ReadImageData(void* data) +{ + imCounterTotal(this->counter, this->height, "Reading PNM..."); + + int line_count = imImageLineCount(this->width, this->file_color_mode); + + int line_raw_size; + if (this->image_type == '4') + line_raw_size = imFileLineSizeAligned(this->width, 1, 1); + else + line_raw_size = imImageLineSize(this->width, this->file_color_mode, this->file_data_type); + + int ascii = 0; + if (this->image_type == '1' || this->image_type == '2' || this->image_type == '3') + ascii = 1; + + for (int row = 0; row < this->height; row++) + { + if (ascii) + { + int value; + for (int col = 0; col < line_count; col++) + { + if (!imBinFileReadInteger(handle, &value)) + return IM_ERR_ACCESS; + + if (this->image_type == '1' && value < 2) + value = 1 - value; + + if (this->file_data_type == IM_USHORT) + ((imushort*)this->line_buffer)[col] = (imushort)value; + else + ((imbyte*)this->line_buffer)[col] = (unsigned char)value; + } + } + else + { + imBinFileRead(handle, this->line_buffer, line_raw_size, 1); + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + if (this->image_type == '4') + FixBinary(); + } + + imFileLineBufferRead(this, data, row, 0); + + if (!imCounterInc(this->counter)) + return IM_ERR_COUNTER; + } + + // try to find another image, ignore errors from here + + /* reads the PNM format identifier */ + unsigned char sig[2]; + imBinFileRead(handle, sig, 2, 1); + if (imBinFileError(handle)) + return IM_ERR_NONE; + + if (sig[0] != 'P' || (sig[1] != '1' && sig[1] != '2' && + sig[1] != '3' && sig[1] != '4' && + sig[1] != '5' && sig[1] != '6')) + return IM_ERR_NONE; + + this->image_type = sig[1]; + this->image_count++; + + if (this->image_type == '1' || this->image_type == '2' || this->image_type == '3') + strcpy(this->compression, "ASCII"); + else + strcpy(this->compression, "NONE"); + + return IM_ERR_NONE; +} + +int imFileFormatPNM::WriteImageData(void* data) +{ + imCounterTotal(this->counter, this->height, "Writing PNM..."); + + int line_count = imImageLineCount(this->width, this->file_color_mode); + + int line_raw_size; + if (this->image_type == '4') + line_raw_size = imFileLineSizeAligned(this->width, 1, 1); + else + line_raw_size = imImageLineSize(this->width, this->file_color_mode, this->file_data_type); + + int ascii = 0; + if (this->image_type == '1' || this->image_type == '2' || this->image_type == '3') + ascii = 1; + + for (int row = 0; row < this->height; row++) + { + imFileLineBufferWrite(this, data, row, 0); + + if (ascii) + { + int line_size = 0; + for (int col = 0; col < line_count; col++) + { + int value; + if (this->file_data_type == IM_USHORT) + value = ((imushort*)this->line_buffer)[col]; + else + value = ((imbyte*)this->line_buffer)[col]; + + if (this->image_type == '1' && value < 2) + value = 1 - value; + + int write_size = imBinFilePrintf(handle, "%d ", value); + if (!write_size) + return IM_ERR_ACCESS; + + line_size += write_size; + + // No line should be longer than 70 characters. + if (line_size > 60 || col == line_count-1) + { + line_size = 0; + imBinFileWrite(handle, (void*)"\n", 1, 1); + } + } + } + else + { + if (this->image_type == '4') + FixBinary(); + + imBinFileWrite(handle, this->line_buffer, line_raw_size, 1); + } + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + if (!imCounterInc(this->counter)) + return IM_ERR_COUNTER; + } + + return IM_ERR_NONE; +} + +int imFormatPNM::CanWrite(const char* compression, int color_mode, int data_type) const +{ + int color_space = imColorModeSpace(color_mode); + + if (color_space == IM_YCBCR || color_space == IM_LAB || + color_space == IM_LUV || color_space == IM_XYZ || + color_space == IM_CMYK || color_space == IM_MAP) + return IM_ERR_DATA; + + if (data_type != IM_BYTE && data_type != IM_USHORT) + return IM_ERR_DATA; + + if (!compression || compression[0] == 0) + return IM_ERR_NONE; + + if (!imStrEqual(compression, "NONE") && !imStrEqual(compression, "ASCII")) + return IM_ERR_COMPRESS; + + return IM_ERR_NONE; +} diff --git a/im/src/im_format_ras.cpp b/im/src/im_format_ras.cpp new file mode 100755 index 0000000..1960c49 --- /dev/null +++ b/im/src/im_format_ras.cpp @@ -0,0 +1,608 @@ +/** \file + * \brief RAS - Sun Raster File + * + * See Copyright Notice in im_lib.h + * $Id: im_format_ras.cpp,v 1.2 2008/12/03 15:45:34 scuri Exp $ + */ + +#include "im_format.h" +#include "im_format_all.h" +#include "im_util.h" +#include "im_counter.h" + +#include "im_binfile.h" + +#include +#include +#include + +/* File Header Structure. */ +/* 4 Magic; magic number */ +/* 4 BufferSize; width (pixels) of image */ +/* 4 Height; height (pixels) of image */ +/* 4 Depth; depth (1, 8, 24, or 32) of pixel */ +/* 4 Length; length (bytes) of image */ +/* 4 Type; type of file; see RT_OLD below */ +/* 4 MapType; type of colormap; see RAS_NONE below */ +/* 4 MapLength; length (bytes) of following map */ +/* 32 */ + +#define RAS_ID 0x59A66A95 + +/* Sun supported ras_type's */ +#define RAS_OLD 0 /* Raw pixrect image in 68000 byte order */ +#define RAS_STANDARD 1 /* Raw pixrect image in 68000 byte order */ +#define RAS_BYTE_ENCODED 2 /* Run-length compression of bytes */ +#define RAS_EXPERIMENTAL 0xffff /* Reserved for testing */ + +#define RAS_ESCAPE 0x80 + +/* Sun supported ras_maptype's */ +#define RAS_NONE 0 /* ras_maplength is expected to be 0 */ +#define RAS_EQUAL_RGB 1 /* red[ras_maplength/3],green[],blue[] */ +#define RAS_RAW 2 /* Sun registered ras_maptype's */ + + +/* NOTES: + * Each line of the image is rounded out to a multiple of 16 bits. + * This corresponds to the rounding convention used by the memory pixrect + * package (/usr/include/pixrect/memvar.h) of the SunWindows system. + * The ras_encoding field (always set to 0 by Sun's supported software) + * was renamed to ras_length in release 2.0. As a result, rasterfiles + * of type 0 generated by the old software claim to have 0 length; for + * compatibility, code reading rasterfiles must be prepared to compute the + * true length from the width, height, and depth fields. */ + +static int iRASDecodeScanLine(imBinFile* handle, unsigned char* DecodedBuffer, int BufferSize) +{ + int index = 0; + unsigned char count = 0; + unsigned char value = 0; + + while (index < BufferSize) + { + imBinFileRead(handle, &value, 1, 1); + + if (value == RAS_ESCAPE) + { + imBinFileRead(handle, &count, 1, 1); + + if (count != 0) + { + imBinFileRead(handle, &value, 1, 1); + + count++; + while (count-- && index < BufferSize) + { + *DecodedBuffer++ = value; + index++; + } + } + else + { + *DecodedBuffer++ = RAS_ESCAPE; + index++; + } + } + else + { + *DecodedBuffer++ = value; + index++; + } + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + } + + return IM_ERR_NONE; +} + +static int iRASEncodeScanLine(imbyte* EncodedBuffer, const imbyte* DecodedBuffer, int BufferSize) +{ + int index = 0; /* Index into uncompressed data buffer */ + int scanindex = 0; /* Index into compressed data buffer */ + int runcount; /* Length of encoded pixel run */ + unsigned char runvalue; /* Value of encoded pixel run */ + + while (index < BufferSize) + { + for (runcount = 1, runvalue = DecodedBuffer[index]; + index + runcount < BufferSize && runvalue == DecodedBuffer[index + runcount] && runcount < 256; + runcount++); + + if (runcount > 2) /* Multiple pixel run */ + { + EncodedBuffer[scanindex++] = RAS_ESCAPE; + EncodedBuffer[scanindex++] = (imbyte)(runcount-1); + EncodedBuffer[scanindex++] = runvalue; + } + else if (runcount == 2) + { + if (runvalue == RAS_ESCAPE) /* Two Escapes */ + { + EncodedBuffer[scanindex++] = RAS_ESCAPE; + EncodedBuffer[scanindex++] = 1; + EncodedBuffer[scanindex++] = RAS_ESCAPE; + } + else /* Two Single runs */ + { + EncodedBuffer[scanindex++] = runvalue; + EncodedBuffer[scanindex++] = runvalue; + } + } + else /* Single run */ + { + if (runvalue == RAS_ESCAPE) + { + EncodedBuffer[scanindex++] = RAS_ESCAPE; + EncodedBuffer[scanindex++] = 0; + } + else + EncodedBuffer[scanindex++] = runvalue; + } + + index += runcount; /* Jump ahead to next pixel run value */ + } + + return scanindex; /* Return the number of unsigned chars written to buffer */ +} + +static const char* iRASCompTable[2] = +{ + "NONE", + "RLE" +}; + +class imFileFormatRAS: public imFileFormatBase +{ + imBinFile* handle; /* the binary file handle */ + unsigned int bpp, /* number of bits per pixel */ + comp_type, /* ras compression information */ + map_type, /* palette information */ + line_raw_size; /* line buffer size */ + + int ReadPalette(); + int WritePalette(); + void FixRGB(); + +public: + imFileFormatRAS(const imFormat* _iformat): imFileFormatBase(_iformat) {} + ~imFileFormatRAS() {} + + int Open(const char* file_name); + int New(const char* file_name); + void Close(); + void* Handle(int index); + int ReadImageInfo(int index); + int ReadImageData(void* data); + int WriteImageInfo(); + int WriteImageData(void* data); +}; + +class imFormatRAS: public imFormat +{ +public: + imFormatRAS() + :imFormat("RAS", + "Sun Raster File", + "*.ras;", + iRASCompTable, + 2, + 0) + {} + ~imFormatRAS() {} + + imFileFormatBase* Create(void) const { return new imFileFormatRAS(this); } + int CanWrite(const char* compression, int color_mode, int data_type) const; +}; + + +void imFormatRegisterRAS(void) +{ + imFormatRegister(new imFormatRAS()); +} + +int imFileFormatRAS::Open(const char* file_name) +{ + unsigned int dword_value; + + /* opens the binary file for reading with motorola byte order */ + handle = imBinFileOpen(file_name); + if (!handle) + return IM_ERR_OPEN; + + imBinFileByteOrder(handle, IM_BIGENDIAN); + + /* reads the RAS format identifier */ + imBinFileRead(handle, &dword_value, 1, 4); + if (imBinFileError(handle)) + { + imBinFileClose(handle); + return IM_ERR_ACCESS; + } + + if (dword_value != RAS_ID) + { + imBinFileClose(handle); + return IM_ERR_FORMAT; + } + + /* reads the compression information */ + imBinFileSeekOffset(handle, 16); + + imBinFileRead(handle, &this->comp_type, 1, 4); + if (this->comp_type == RAS_BYTE_ENCODED) + strcpy(this->compression, "RLE"); + else if (this->comp_type == RAS_OLD || this->comp_type == RAS_STANDARD) + strcpy(this->compression, "NONE"); + else + { + imBinFileClose(handle); + return IM_ERR_COMPRESS; + } + + imBinFileSeekOffset(handle, -20); + + this->image_count = 1; + + return IM_ERR_NONE; +} + +int imFileFormatRAS::New(const char* file_name) +{ + /* opens the binary file for writing with motorola byte order */ + handle = imBinFileNew(file_name); + if (!handle) + return IM_ERR_OPEN; + + imBinFileByteOrder(handle, IM_BIGENDIAN); + + this->image_count = 1; + + return IM_ERR_NONE; +} + +void imFileFormatRAS::Close() +{ + imBinFileClose(handle); +} + +void* imFileFormatRAS::Handle(int index) +{ + if (index == 0) + return (void*)this->handle; + else + return NULL; +} + +int imFileFormatRAS::ReadImageInfo(int index) +{ + (void)index; + unsigned int dword_value; + + this->file_data_type = IM_BYTE; + + /* reads the image width */ + imBinFileRead(handle, &dword_value, 1, 4); + this->width = (int)dword_value; + + /* reads the image height */ + imBinFileRead(handle, &dword_value, 1, 4); + this->height = (int)dword_value; + + /* reads the number of bits per pixel */ + imBinFileRead(handle, &this->bpp, 1, 4); + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + // sanity check + if (this->bpp != 1 && this->bpp != 8 && + this->bpp != 24 && this->bpp != 32) + return IM_ERR_DATA; + + if (this->bpp > 8) + { + this->file_color_mode = IM_RGB; + this->file_color_mode |= IM_PACKED; + + if (this->bpp == 32) + this->file_color_mode |= IM_ALPHA; + } + else + { + this->file_color_mode = IM_MAP; + + if (this->bpp == 1) + { + this->convert_bpp = 1; + this->palette_count = 2; + } + } + + this->file_color_mode |= IM_TOPDOWN; + + this->line_raw_size = imFileLineSizeAligned(this->width, this->bpp, 2); + this->line_buffer_extra = 2; // room enough for padding + + /* jump 8 bytes (Length+Compression) */ + imBinFileSeekOffset(handle, 8); + + /* reads the palette information */ + imBinFileRead(handle, &this->map_type, 1, 4); + + /* reads the palette size */ + imBinFileRead(handle, &dword_value, 1, 4); + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + /* updates the pal_size based on the palette size */ + if (this->bpp <= 8 && this->map_type != RAS_NONE) + { + this->palette_count = dword_value / 3; + return ReadPalette(); + } + + if (this->bpp <= 8 && this->map_type == RAS_NONE) + { + if (this->bpp == 1) + this->file_color_mode = IM_BINARY; + else + this->file_color_mode = IM_GRAY; + + this->file_color_mode |= IM_TOPDOWN; + } + + return IM_ERR_NONE; +} + +int imFileFormatRAS::WriteImageInfo() +{ + this->file_data_type = IM_BYTE; + this->file_color_mode = imColorModeSpace(this->user_color_mode); + + if (imStrEqual(this->compression, "RLE")) + this->comp_type = RAS_BYTE_ENCODED; + else + this->comp_type = RAS_STANDARD; + + // Force the palette, even for Binary and Gray. + this->map_type = RAS_EQUAL_RGB; + + if (this->file_color_mode == IM_BINARY) + { + this->bpp = 1; + this->convert_bpp = 1; + } + else if (this->file_color_mode == IM_RGB) + { + this->file_color_mode |= IM_PACKED; + this->map_type = RAS_NONE; + this->bpp = 24; + + if (imColorModeHasAlpha(this->user_color_mode)) + { + this->file_color_mode |= IM_ALPHA; + this->bpp = 32; + } + } + else + this->bpp = 8; + + this->file_color_mode |= IM_TOPDOWN; + + this->line_raw_size = imFileLineSizeAligned(this->width, this->bpp, 2); + this->line_buffer_extra = 2; // room enough for padding + + if (this->comp_type == RAS_BYTE_ENCODED) + { + // allocates more than enough since compression algoritm can be ineficient + this->line_buffer_extra += 2*this->line_raw_size; + } + + /* writes the RAS file header */ + + unsigned int dword_value = RAS_ID; + imBinFileWrite(handle, &dword_value, 1, 4); /* identifier */ + dword_value = this->width; + imBinFileWrite(handle, &dword_value, 1, 4); /* image width */ + dword_value = this->height; + imBinFileWrite(handle, &dword_value, 1, 4); /* image height */ + dword_value = this->bpp; + imBinFileWrite(handle, &dword_value, 1, 4); /* bits per pixel */ + dword_value = this->height * this->line_raw_size; + imBinFileWrite(handle, &dword_value, 1, 4); /* image lenght */ + dword_value = this->comp_type; + imBinFileWrite(handle, &dword_value, 1, 4); /* compression information */ + dword_value = this->map_type; + imBinFileWrite(handle, &dword_value, 1, 4); /* palette information */ + dword_value = (this->map_type == RAS_NONE)? 0: this->palette_count * 3; + imBinFileWrite(handle, &dword_value, 1, 4); /* palette lenght */ + + /* tests if everything was ok */ + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + if (this->map_type != RAS_NONE) + return WritePalette(); + + return IM_ERR_NONE; +} + +int imFileFormatRAS::ReadPalette() +{ + unsigned char ras_colors[256 * 3]; + + /* reads the color palette */ + imBinFileRead(handle, ras_colors, this->palette_count * 3, 1); + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + /* convert the color map to the IM format */ + for (int c = 0; c < this->palette_count; c++) + { + if (this->map_type == RAS_RAW) + { + int i = c * 3; + this->palette[c] = imColorEncode(ras_colors[i], + ras_colors[i+1], + ras_colors[i+2]); + } + else + { + this->palette[c] = imColorEncode(ras_colors[c], + ras_colors[c+this->palette_count], + ras_colors[c+2*this->palette_count]); + } + } + + return IM_ERR_NONE; +} + +int imFileFormatRAS::WritePalette() +{ + int c; + unsigned char ras_colors[256 * 3]; + + /* convert the color map to the IM format */ + for (c = 0; c < this->palette_count; c++) + { + imColorDecode(&ras_colors[c], &ras_colors[c+this->palette_count], &ras_colors[c+2*this->palette_count], this->palette[c]); + } + + /* writes the color palette */ + imBinFileWrite(handle, ras_colors, this->palette_count * 3, 1); + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + return IM_ERR_NONE; +} + +void imFileFormatRAS::FixRGB() +{ + int x; + imbyte* byte_data = (imbyte*)this->line_buffer; + + switch (this->bpp) + { + case 32: + { + // convert ABGR <-> RGBA + for (x = 0; x < this->width; x++) + { + int c = x*4; + imbyte temp = byte_data[c]; // swap R and A + byte_data[c] = byte_data[c+3]; + byte_data[c+3] = temp; + + temp = byte_data[c+1]; // swap G and B + byte_data[c+1] = byte_data[c+2]; + byte_data[c+2] = temp; + } + } + break; + default: // 24 + { + // convert BGR <-> RGB + for (x = 0; x < this->width; x++) + { + int c = x*3; + imbyte temp = byte_data[c]; // swap R and B + byte_data[c] = byte_data[c+2]; + byte_data[c+2] = temp; + } + } + break; + } +} + +int imFileFormatRAS::ReadImageData(void* data) +{ + imCounterTotal(this->counter, this->height, "Reading RAS..."); + + for (int row = 0; row < this->height; row++) + { + /* read and decompress the data */ + if (this->comp_type != RAS_BYTE_ENCODED) + { + imBinFileRead(handle, this->line_buffer, this->line_raw_size, 1); + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + } + else + { + if (iRASDecodeScanLine(handle, (imbyte*)this->line_buffer, this->line_raw_size) == IM_ERR_ACCESS) + return IM_ERR_ACCESS; + } + + if (this->bpp > 8) + FixRGB(); + + imFileLineBufferRead(this, data, row, 0); + + if (!imCounterInc(this->counter)) + return IM_ERR_COUNTER; + } + + return IM_ERR_NONE; +} + +int imFileFormatRAS::WriteImageData(void* data) +{ + imCounterTotal(this->counter, this->height, "Writing RAS..."); + + imbyte* compressed_buffer = NULL; + if (this->comp_type == RAS_BYTE_ENCODED) // point to the extra buffer + compressed_buffer = (imbyte*)this->line_buffer + this->line_buffer_size+2; + + for (int row = 0; row < this->height; row++) + { + imFileLineBufferWrite(this, data, row, 0); + + if (this->bpp > 8) + FixRGB(); + + if (this->comp_type == RAS_BYTE_ENCODED) + { + int compressed_size = iRASEncodeScanLine(compressed_buffer, (imbyte*)this->line_buffer, this->line_raw_size); + imBinFileWrite(handle, compressed_buffer, compressed_size, 1); + } + else + { + imBinFileWrite(handle, this->line_buffer, this->line_raw_size, 1); + } + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + if (!imCounterInc(this->counter)) + return IM_ERR_COUNTER; + } + + return IM_ERR_NONE; +} + +int imFormatRAS::CanWrite(const char* compression, int color_mode, int data_type) const +{ + int color_space = imColorModeSpace(color_mode); + + if (color_space == IM_YCBCR || color_space == IM_LAB || + color_space == IM_LUV || color_space == IM_XYZ || + color_space == IM_CMYK) + return IM_ERR_DATA; + + if (data_type != IM_BYTE) + return IM_ERR_DATA; + + if (!compression || compression[0] == 0) + return IM_ERR_NONE; + + if (!imStrEqual(compression, "NONE") && !imStrEqual(compression, "RLE")) + return IM_ERR_COMPRESS; + + return IM_ERR_NONE; +} diff --git a/im/src/im_format_raw.cpp b/im/src/im_format_raw.cpp new file mode 100755 index 0000000..56a2096 --- /dev/null +++ b/im/src/im_format_raw.cpp @@ -0,0 +1,366 @@ +/** \file + * \brief RAW File Format + * + * See Copyright Notice in im_lib.h + * $Id: im_format_raw.cpp,v 1.5 2009/10/01 14:15:47 scuri Exp $ + */ + +#include "im_format.h" +#include "im_util.h" +#include "im_format_raw.h" +#include "im_counter.h" + +#include "im_binfile.h" + +#include +#include + +static const char* iRAWCompTable[2] = +{ + "NONE", + "ASCII" +}; + +class imFileFormatRAW: public imFileFormatBase +{ + imBinFile* handle; + int padding; + + int iRawUpdateParam(int index); + +public: + imFileFormatRAW(const imFormat* _iformat): imFileFormatBase(_iformat) {} + ~imFileFormatRAW() {} + + int Open(const char* file_name); + int New(const char* file_name); + void Close(); + void* Handle(int index); + int ReadImageInfo(int index); + int ReadImageData(void* data); + int WriteImageInfo(); + int WriteImageData(void* data); +}; + +class imFormatRAW: public imFormat +{ +public: + imFormatRAW() + :imFormat("RAW", + "RAW File Format", + "*.*;", + iRAWCompTable, + 2, + 1) + {} + ~imFormatRAW() {} + + imFileFormatBase* Create(void) const { return new imFileFormatRAW(this); } + int CanWrite(const char* compression, int color_mode, int data_type) const; +}; + +static imFormat* raw_format = NULL; + +void imFormatFinishRAW(void) +{ + if (raw_format) + { + delete raw_format; + raw_format = NULL; + } +} + +imFormat* imFormatInitRAW(void) +{ + if (!raw_format) + raw_format = new imFormatRAW(); + + return raw_format; +} + +int imFileFormatRAW::Open(const char* file_name) +{ + this->handle = imBinFileOpen(file_name); + if (this->handle == NULL) + return IM_ERR_OPEN; + + strcpy(this->compression, "NONE"); + + this->image_count = 1; /* at least one image */ + this->padding = 0; + + return IM_ERR_NONE; +} + +int imFileFormatRAW::New(const char* file_name) +{ + this->handle = imBinFileNew(file_name); + if (this->handle == NULL) + return IM_ERR_OPEN; + + this->padding = 0; + + return IM_ERR_NONE; +} + +void imFileFormatRAW::Close() +{ + imBinFileClose(this->handle); +} + +void* imFileFormatRAW::Handle(int index) +{ + if (index == 0) + return (void*)this->handle; + else + return NULL; +} + +static int iCalcPad(int padding, int line_size) +{ + if (padding == 1) + return 0; + + { + int rest = line_size % padding; + if (rest == 0) + return 0; + + return padding - rest; + } +} + +int imFileFormatRAW::iRawUpdateParam(int index) +{ + (void)index; + + imAttribTable* attrib_table = AttribTable(); + + // update image count + int* icount = (int*)attrib_table->Get("ImageCount"); + if (icount) + this->image_count = *icount; + else + this->image_count = 1; + + // update file byte order + int* byte_order = (int*)attrib_table->Get("ByteOrder"); + if (byte_order) + imBinFileByteOrder(this->handle, *byte_order); + + // position at start offset, the default is at 0 + int* start_offset = (int*)attrib_table->Get("StartOffset"); + if (!start_offset) + imBinFileSeekOffset(this->handle, 0); + else + imBinFileSeekOffset(this->handle, *start_offset); + + if (imBinFileError(this->handle)) + return IM_ERR_ACCESS; + + int* stype = (int*)attrib_table->Get("SwitchType"); + if (stype) + this->switch_type = *stype; + + // The following attributes MUST exist + this->width = *(int*)attrib_table->Get("Width"); + this->height = *(int*)attrib_table->Get("Height"); + this->file_color_mode = *(int*)attrib_table->Get("ColorMode"); + this->file_data_type = *(int*)attrib_table->Get("DataType"); + + int* pad = (int*)attrib_table->Get("Padding"); + if (pad) + { + int line_size = imImageLineSize(this->width, this->file_color_mode, this->file_data_type); + if (this->switch_type && (this->file_data_type == IM_FLOAT || this->file_data_type == IM_CFLOAT)) + line_size *= 2; + this->padding = iCalcPad(*pad, line_size); + } + + return IM_ERR_NONE; +} + +int imFileFormatRAW::ReadImageInfo(int index) +{ + return iRawUpdateParam(index); +} + +int imFileFormatRAW::WriteImageInfo() +{ + this->file_color_mode = this->user_color_mode; + this->file_data_type = this->user_data_type; + + return iRawUpdateParam(this->image_count); +} + +static int iFileDataTypeSize(int file_data_type, int switch_type) +{ + int type_size = imDataTypeSize(file_data_type); + if ((file_data_type == IM_FLOAT || file_data_type == IM_CFLOAT) && switch_type) + type_size *= 2; + return type_size; +} + +int imFileFormatRAW::ReadImageData(void* data) +{ + int count = imFileLineBufferCount(this); + int line_count = imImageLineCount(this->width, this->file_color_mode); + int type_size = iFileDataTypeSize(this->file_data_type, this->switch_type); + + // treat complex as 2 real + if (this->file_data_type == IM_CFLOAT) + { + type_size /= 2; + line_count *= 2; + } + + int ascii; + if (imStrEqual(this->compression, "ASCII")) + ascii = 1; + else + ascii = 0; + + imCounterTotal(this->counter, count, "Reading RAW..."); + + int row = 0, plane = 0; + for (int i = 0; i < count; i++) + { + if (ascii) + { + for (int col = 0; col < line_count; col++) + { + if (this->file_data_type == IM_FLOAT) + { + float value; + if (!imBinFileReadFloat(handle, &value)) + return IM_ERR_ACCESS; + + ((float*)this->line_buffer)[col] = value; + } + else + { + int value; + if (!imBinFileReadInteger(handle, &value)) + return IM_ERR_ACCESS; + + if (this->file_data_type == IM_INT) + ((int*)this->line_buffer)[col] = value; + else if (this->file_data_type == IM_USHORT) + ((imushort*)this->line_buffer)[col] = (imushort)value; + else + ((imbyte*)this->line_buffer)[col] = (unsigned char)value; + } + } + } + else + { + imBinFileRead(this->handle, (imbyte*)this->line_buffer, line_count, type_size); + + if (imBinFileError(this->handle)) + return IM_ERR_ACCESS; + } + + imFileLineBufferRead(this, data, row, plane); + + if (!imCounterInc(this->counter)) + return IM_ERR_COUNTER; + + imFileLineBufferInc(this, &row, &plane); + + if (this->padding) + imBinFileSeekOffset(this->handle, this->padding); + } + + return IM_ERR_NONE; +} + +int imFileFormatRAW::WriteImageData(void* data) +{ + int count = imFileLineBufferCount(this); + int line_count = imImageLineCount(this->width, this->file_color_mode); + int type_size = iFileDataTypeSize(this->file_data_type, this->switch_type); + + // treat complex as 2 real + if (this->file_data_type == IM_CFLOAT) + { + type_size /= 2; + line_count *= 2; + } + + int ascii; + if (imStrEqual(this->compression, "ASCII")) + ascii = 1; + else + ascii = 0; + + imCounterTotal(this->counter, count, "Writing RAW..."); + + int row = 0, plane = 0; + for (int i = 0; i < count; i++) + { + imFileLineBufferWrite(this, data, row, plane); + + if (ascii) + { + for (int col = 0; col < line_count; col++) + { + if (this->file_data_type == IM_FLOAT) + { + float value = ((float*)this->line_buffer)[col]; + + if (!imBinFilePrintf(handle, "%f ", (double)value)) + return IM_ERR_ACCESS; + } + else + { + int value; + if (this->file_data_type == IM_INT) + value = ((int*)this->line_buffer)[col]; + else if (this->file_data_type == IM_USHORT) + value = ((imushort*)this->line_buffer)[col]; + else + value = ((imbyte*)this->line_buffer)[col]; + + if (!imBinFilePrintf(handle, "%d ", value)) + return IM_ERR_ACCESS; + } + } + + imBinFileWrite(handle, (void*)"\n", 1, 1); + } + else + { + imBinFileWrite(this->handle, (imbyte*)this->line_buffer, line_count, type_size); + } + + if (imBinFileError(this->handle)) + return IM_ERR_ACCESS; + + if (!imCounterInc(this->counter)) + return IM_ERR_COUNTER; + + imFileLineBufferInc(this, &row, &plane); + + if (this->padding) + imBinFileSeekOffset(this->handle, this->padding); + } + + this->image_count++; + return IM_ERR_NONE; +} + +int imFormatRAW::CanWrite(const char* compression, int color_mode, int data_type) const +{ + (void)data_type; + + if (imColorSpace(color_mode) == IM_MAP) + return IM_ERR_DATA; + + if (!compression || compression[0] == 0) + return IM_ERR_NONE; + + if (!imStrEqual(compression, "NONE") && !imStrEqual(compression, "ASCII")) + return IM_ERR_COMPRESS; + + return IM_ERR_NONE; +} diff --git a/im/src/im_format_sgi.cpp b/im/src/im_format_sgi.cpp new file mode 100755 index 0000000..08bbf4d --- /dev/null +++ b/im/src/im_format_sgi.cpp @@ -0,0 +1,616 @@ +/** \file + * \brief SGI - Silicon Graphics Image File Format + * + * See Copyright Notice in im_lib.h + * $Id: im_format_sgi.cpp,v 1.2 2008/12/03 15:45:34 scuri Exp $ + */ + +#include "im_format.h" +#include "im_util.h" +#include "im_format_all.h" +#include "im_counter.h" + +#include "im_binfile.h" + +#include +#include +#include + +/* File Header Structure. */ +/* 2 Magic; 474 */ +/* 1 Storage; 0 ou 1 Compression */ +/* 1 BPC; 1 ou 2 Bytes Per Pixel Component */ +/* 2 Dimension; 1 ou 2 ou 3 */ +/* 2 XSize; Width */ +/* 2 YSize; Height */ +/* 2 ZSize; Number of Channels. B/W=1, RGB=3, RGBA=4 */ +/* 4 PixMin; Minimum Pixel Value */ +/* 4 PixMax; Maximum Pixel Value */ +/* 4 Dummy1; */ +/* 80 ImageName;*/ +/* 4 ColorMap; 0 ou 1 ou 2 ou 3 */ +/* 404 Dummy2;*/ +/* 512 */ + +#define SGI_ID 474 + +/* Compression */ +#define SGI_VERBATIM 0 +#define SGI_RLE 1 + +/* ColorMap Ids */ +#define SGI_NORMAL 0 +#define SGI_DITHERED 1 +#define SGI_SCREEN 2 +#define SGI_COLORMAP 3 + +template +static int iSGIDecodeScanLine(T *optr, const T *iptr, int width) +{ + T pixel; + int c = 0, count; + + while (c < width) + { + pixel = *iptr++; + + count = pixel & 0x7f; + if (!count) + break; + + c += count; + if (c > width) + return IM_ERR_ACCESS; + + if (pixel & 0x80) + { + while (count--) + *optr++ = *iptr++; + } + else + { + pixel = *iptr++; + while (count--) + *optr++ = pixel; + } + } + + if (c < width) + return IM_ERR_ACCESS; + + return IM_ERR_NONE; +} + +template +static int iSGIEncodeScanLine(T *optr, const T *iptr, int width) +{ + const T *ibufend = iptr + width, + *sptr; + T *start_optr = optr; + int todo, cc, count; + + while(iptr < ibufend) + { + sptr = iptr; + iptr += 2; + while ((iptr < ibufend) && + ((iptr[-2] != iptr[-1]) || (iptr[-1] != iptr[0]))) + iptr++; + iptr -= 2; + count = iptr-sptr; + + while (count) + { + todo = (count > 126) ? 126: count; + count -= todo; + *optr++ = (T)(0x80 | todo); + while(todo--) + *optr++ = *sptr++; + } + sptr = iptr; + cc = *iptr++; + + while((iptr < ibufend) && (*iptr == cc)) + iptr++; + count = iptr-sptr; + + while(count) + { + todo = (count > 126)? 126: count; + count -= todo; + *optr++ = (T)todo; + *optr++ = (T)cc; + } + } + *optr++ = 0; + + return optr-start_optr; +} + +static const char* iSGICompTable[2] = +{ + "NONE", + "RLE" +}; + +class imFileFormatSGI: public imFileFormatBase +{ + imBinFile* handle; /* the binary file handle */ + unsigned char comp_type, /* sgi compression information */ + bpc; /* bytes per channels */ + unsigned int *starttab, /* compression control buffer */ + *lengthtab; /* compression control buffer */ + +public: + imFileFormatSGI(const imFormat* _iformat): imFileFormatBase(_iformat) {} + ~imFileFormatSGI() {} + + int Open(const char* file_name); + int New(const char* file_name); + void Close(); + void* Handle(int index); + int ReadImageInfo(int index); + int ReadImageData(void* data); + int WriteImageInfo(); + int WriteImageData(void* data); +}; + +class imFormatSGI: public imFormat +{ +public: + imFormatSGI() + :imFormat("SGI", + "Silicon Graphics Image File Format", + "*.rgb;*.rgba;*.bw;*.sgi;", + iSGICompTable, + 2, + 0) + {} + ~imFormatSGI() {} + + imFileFormatBase* Create(void) const { return new imFileFormatSGI(this); } + int CanWrite(const char* compression, int color_mode, int data_type) const; +}; + +void imFormatRegisterSGI(void) +{ + imFormatRegister(new imFormatSGI()); +} + +int imFileFormatSGI::Open(const char* file_name) +{ + unsigned short word_value; + + /* opens the binary file for reading with motorola byte order */ + handle = imBinFileOpen(file_name); + if (!handle) + return IM_ERR_OPEN; + + imBinFileByteOrder(handle, IM_BIGENDIAN); + + /* reads the SGI format identifier */ + imBinFileRead(handle, &word_value, 1, 2); + if (imBinFileError(handle)) + { + imBinFileClose(handle); + return IM_ERR_ACCESS; + } + + if (word_value != SGI_ID) + { + imBinFileClose(handle); + return IM_ERR_FORMAT; + } + + /* reads the compression information */ + imBinFileRead(handle, &this->comp_type, 1, 1); + if (this->comp_type == SGI_RLE) + strcpy(this->compression, "RLE"); + else if (this->comp_type == SGI_VERBATIM) + strcpy(this->compression, "NONE"); + else + { + imBinFileClose(handle); + return IM_ERR_COMPRESS; + } + + this->starttab = NULL; + this->lengthtab = NULL; + + this->image_count = 1; + + return IM_ERR_NONE; +} + +int imFileFormatSGI::New(const char* file_name) +{ + /* opens the binary file for writing with motorola byte order */ + handle = imBinFileNew(file_name); + if (!handle) + return IM_ERR_OPEN; + + imBinFileByteOrder(handle, IM_BIGENDIAN); + + this->starttab = NULL; + this->lengthtab = NULL; + + this->image_count = 1; + + return IM_ERR_NONE; +} + +void imFileFormatSGI::Close() +{ + if (this->starttab) free(this->starttab); + if (this->lengthtab) free(this->lengthtab); + imBinFileClose(handle); +} + +void* imFileFormatSGI::Handle(int index) +{ + if (index == 0) + return (void*)this->handle; + else + return NULL; +} + +int imFileFormatSGI::ReadImageInfo(int index) +{ + (void)index; + unsigned short word_value, dimension, depth; + + /* reads the number of bits per channel */ + imBinFileRead(handle, &this->bpc, 1, 1); + + /* reads the number of dimensions */ + imBinFileRead(handle, &dimension, 1, 2); + + /* reads the image width */ + imBinFileRead(handle, &word_value, 1, 2); + this->width = word_value; + + /* reads the image height */ + imBinFileRead(handle, &word_value, 1, 2); + this->height = word_value; + + /* reads the number of channels */ + imBinFileRead(handle, &depth, 1, 2); + + /* jump 12 bytes (min, max, dummy) */ + imBinFileSeekOffset(handle, 12); + + /* reads the image name */ + char image_name[80]; + imBinFileRead(handle, image_name, 80, 1); + + if (image_name[0] != 0) + AttribTable()->Set("Description", IM_BYTE, imStrNLen(image_name, 80)+1, image_name); + + /* reads the color map information */ + unsigned int color_map_id; + imBinFileRead(handle, &color_map_id, 1, 4); + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + this->file_data_type = IM_BYTE; + if (this->bpc == 2) + this->file_data_type = IM_USHORT; + + switch (dimension) + { + case 1: + this->height = 1; + depth = 1; + case 2: + depth = 1; + break; + case 3: + break; + default: + return IM_ERR_DATA; + } + + switch (color_map_id) + { + case SGI_NORMAL: + switch(depth) + { + case 1: + this->file_color_mode = IM_GRAY; + break; + case 3: + this->file_color_mode = IM_RGB; + break; + case 4: + this->file_color_mode = IM_RGB | IM_ALPHA; + break; + default: + return IM_ERR_DATA; + } + break; + case SGI_DITHERED: + this->file_color_mode = IM_MAP; + break; + case SGI_COLORMAP: + this->file_color_mode = IM_RGB; + break; + case SGI_SCREEN: + this->file_color_mode = IM_GRAY; + break; + default: + return IM_ERR_DATA; + } + + /* jump 404 bytes (dummy) */ + imBinFileSeekOffset(handle, 404); + + if (this->comp_type == SGI_RLE) + { + int tablen = this->height * depth; + this->starttab = (unsigned int *)malloc(tablen * sizeof(int)); + this->lengthtab = (unsigned int *)malloc(tablen * sizeof(int)); + + /* reads the compression control information */ + imBinFileRead(handle, this->starttab, tablen, 4); + imBinFileRead(handle, this->lengthtab, tablen, 4); + + // allocates more than enough since compression algoritm can be ineficient + this->line_buffer_extra = 2*imImageLineSize(this->width, this->file_color_mode, this->file_data_type); + } + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + if (color_map_id == SGI_DITHERED) + { + static int red[8] = {0, 36, 73, 109, 146, 182, 218, 255}; + static int green[8] = {0, 36, 73, 109, 146, 182, 218, 255}; + static int blue[4] = {0, 85, 170, 255}; + + int c = 0; + for (int b = 0; b < 4; b++) + { + for (int g = 0; g < 8; g++) + { + for (int r = 0; r < 8; r++) + { + this->palette[c] = imColorEncode((imbyte)red[r], + (imbyte)green[g], + (imbyte)blue[b]); + c++; + } + } + } + } + + return IM_ERR_NONE; +} + +int imFileFormatSGI::WriteImageInfo() +{ + unsigned int dword_value; + unsigned short word_value; + unsigned char dummy[404]; + memset(dummy, 0, 404); + + this->comp_type = SGI_VERBATIM; + if (imStrEqual(this->compression, "RLE")) + this->comp_type = SGI_RLE; + + unsigned int color_map_id = SGI_NORMAL; + + this->file_color_mode = imColorModeSpace(this->user_color_mode); + + int dimension = 2; + if (this->file_color_mode == IM_BINARY) + this->convert_bpp = -1; // expand 1 to 255 + else if (this->file_color_mode == IM_RGB) + { + dimension = 3; + if (imColorModeHasAlpha(this->user_color_mode)) + this->file_color_mode |= IM_ALPHA; + } + + this->file_data_type = this->user_data_type; + + this->bpc = 1; + int max = 255; + if (this->file_data_type == IM_USHORT) + { + max = 65535; + this->bpc = 2; + } + + this->starttab = NULL; + this->lengthtab = NULL; + + /* writes the SGI file header */ + word_value = SGI_ID; + imBinFileWrite(handle, &word_value, 1, 2); /* identifier */ + imBinFileWrite(handle, &this->comp_type, 1, 1); /* storage */ + imBinFileWrite(handle, &this->bpc, 1, 1); /* bpc */ + word_value = (imushort)dimension; + imBinFileWrite(handle, &word_value, 1, 2); /* dimension */ + word_value = (unsigned short)this->width; + imBinFileWrite(handle, &word_value, 1, 2); /* image width */ + word_value = (unsigned short)this->height; + imBinFileWrite(handle, &word_value, 1, 2); /* image height */ + word_value = (imushort)imColorModeDepth(this->file_color_mode); + imBinFileWrite(handle, &word_value, 1, 2); /* depth */ + dword_value = 0; + imBinFileWrite(handle, &dword_value, 1, 4); /* min */ + dword_value = max; + imBinFileWrite(handle, &dword_value, 1, 4); /* max */ + imBinFileWrite(handle, dummy, 4, 1); /* dummy */ + + /* tests if everything was ok */ + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + int size; + char* image_name = (char*)AttribTable()->Get("Description", NULL, &size); + if (image_name) + { + if (size < 80) + { + imBinFileWrite(handle, image_name, size, 1); + imBinFileWrite(handle, dummy, 80-size, 1); + } + else + { + imBinFileWrite(handle, image_name, 79, 1); + imBinFileWrite(handle, (void*)"\0", 1, 1); + } + } + else + imBinFileWrite(handle, dummy, 80, 1); /* empty image name */ + + dword_value = color_map_id; + imBinFileWrite(handle, &dword_value, 1, 4); /* color_map_id */ + imBinFileWrite(handle, dummy, 404, 1); /* dummy */ + + /* tests if everything was ok */ + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + if (this->comp_type == SGI_RLE) + { + int tablen = this->height * imColorModeDepth(this->file_color_mode); + this->starttab = (unsigned int *)malloc(tablen*4); + this->lengthtab = (unsigned int *)malloc(tablen*4); + + /* writes the empty compression control information */ + /* we will write again at the end */ + imBinFileWrite(handle, this->starttab, tablen*4, 1); + imBinFileWrite(handle, this->lengthtab, tablen*4, 1); + + // allocates more than enough since compression algoritm can be ineficient + this->line_buffer_extra = 2*imImageLineSize(this->width, this->file_color_mode, this->file_data_type); + } + + /* tests if everything was ok */ + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + return IM_ERR_NONE; +} + +int imFileFormatSGI::ReadImageData(void* data) +{ + int count = imFileLineBufferCount(this); + + imCounterTotal(this->counter, count, "Reading SGI..."); + + imbyte* compressed_buffer = NULL; + if (this->comp_type == SGI_RLE) // point to the extra buffer + compressed_buffer = (imbyte*)this->line_buffer + this->line_buffer_size; + + int row = 0, plane = 0; + for (int i = 0; i < count; i++) + { + if (this->comp_type == SGI_VERBATIM) + { + imBinFileRead(handle, this->line_buffer, this->line_buffer_size/this->bpc, this->bpc); + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + } + else + { + int row_index = row + plane*this->height; + imBinFileSeekTo(handle, this->starttab[row_index]); + imBinFileRead(handle, compressed_buffer, this->lengthtab[row_index] / this->bpc, this->bpc); + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + if (this->bpc == 1) + iSGIDecodeScanLine((imbyte*)this->line_buffer, compressed_buffer, this->width); + else + iSGIDecodeScanLine((imushort*)this->line_buffer, (imushort*)compressed_buffer, this->width); + } + + imFileLineBufferRead(this, data, row, plane); + + if (!imCounterInc(this->counter)) + return IM_ERR_COUNTER; + + imFileLineBufferInc(this, &row, &plane); + } + + return IM_ERR_NONE; +} + +int imFileFormatSGI::WriteImageData(void* data) +{ + int count = imFileLineBufferCount(this); + + imCounterTotal(this->counter, count, "Writing SGI..."); + + imbyte* compressed_buffer = NULL; + if (this->comp_type == SGI_RLE) // point to the extra buffer + compressed_buffer = (imbyte*)this->line_buffer + this->line_buffer_size; + + int row = 0, plane = 0; + for (int i = 0; i < count; i++) + { + imFileLineBufferWrite(this, data, row, plane); + + if (this->comp_type == SGI_VERBATIM) + imBinFileWrite(handle, this->line_buffer, this->line_buffer_size/this->bpc, this->bpc); + else + { + int length; + if (this->bpc == 1) + length = iSGIEncodeScanLine(compressed_buffer, (imbyte*)this->line_buffer, this->width); + else + length = iSGIEncodeScanLine((imushort*)compressed_buffer, (imushort*)this->line_buffer, this->width); + + int row_index = row + plane*this->height; + this->starttab[row_index] = imBinFileTell(handle); + this->lengthtab[row_index] = length*this->bpc; + + imBinFileWrite(handle, compressed_buffer, length, this->bpc); + } + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + if (!imCounterInc(this->counter)) + return IM_ERR_COUNTER; + + imFileLineBufferInc(this, &row, &plane); + } + + if (this->comp_type == SGI_RLE) + { + imBinFileSeekTo(this->handle, 512); + int tablen = this->height * imColorModeDepth(this->file_color_mode); + imBinFileWrite(handle, this->starttab, tablen, 4); + imBinFileWrite(handle, this->lengthtab, tablen, 4); + } + + return IM_ERR_NONE; +} + +int imFormatSGI::CanWrite(const char* compression, int color_mode, int data_type) const +{ + int color_space = imColorModeSpace(color_mode); + + if (color_space == IM_YCBCR || color_space == IM_LAB || + color_space == IM_LUV || color_space == IM_XYZ || + color_space == IM_CMYK || color_space == IM_MAP) + return IM_ERR_DATA; + + if (data_type != IM_BYTE && data_type != IM_USHORT) + return IM_ERR_DATA; + + if (!compression || compression[0] == 0) + return IM_ERR_NONE; + + if (!imStrEqual(compression, "NONE") && !imStrEqual(compression, "RLE")) + return IM_ERR_COMPRESS; + + return IM_ERR_NONE; +} diff --git a/im/src/im_format_tga.cpp b/im/src/im_format_tga.cpp new file mode 100755 index 0000000..86e968a --- /dev/null +++ b/im/src/im_format_tga.cpp @@ -0,0 +1,1113 @@ +/** \file + * \brief TGA - Truevision Graphics Adapter File + * + * See Copyright Notice in im_lib.h + * $Id: im_format_tga.cpp,v 1.2 2008/12/03 15:45:34 scuri Exp $ + */ + +#include "im_format.h" +#include "im_util.h" +#include "im_format_all.h" +#include "im_counter.h" +#include "im_math.h" + +#include "im_binfile.h" + +#include +#include +#include +#include +#include +#include + + +/* +|--------|--------|------------------------------------------------------------| +| 0 | 1 | Number of Characters in Identification Field. | +| | | This field is a one-byte unsigned integer, specifying | +| | | the length of the Image Identification Field. Its range | +| | | is 0 to 255. A value of 0 means that no Image | +| | | Identification Field is included. | +|--------|--------|------------------------------------------------------------| +| 1 | 1 | Color Map Type. | +|--------|--------|------------------------------------------------------------| +| 2 | 1 | Image Type Code. | +|--------|--------|------------------------------------------------------------| +| 3 | 5 | Color Map Specification. | +| 3 | 2 | Color Map Origin. | +| | | Integer ( lo-hi ) index of first color map entry. | +| 5 | 2 | Color Map Length. | +| | | Integer ( lo-hi ) count of color map entries. | +| 7 | 1 | Color Map Entry Size. | +| | | Number of bits in each color map entry. 16 for | +| | | the Targa 16, 24 for the Targa 24, 32 for the Targa 32. | +|--------|--------|------------------------------------------------------------| +| 8 | 10 | Image Specification. | +| 8 | 2 | X Origin of Image. | +| | | Integer ( lo-hi ) X coordinate of the lower left corner | +| | | of the image. | +| 10 | 2 | Y Origin of Image. | +| | | Integer ( lo-hi ) Y coordinate of the lower left corner | +| | | of the image. | +| 12 | 2 | Width of Image. | +| | | Integer ( lo-hi ) width of the image in pixels. | +| 14 | 2 | Height of Image. | +| | | Integer ( lo-hi ) height of the image in pixels. | +| 16 | 1 | Image Pixel Size. | +| | | Number of bits in a stored pixel index. | +| 17 | 1 | Image Descriptor Byte. | +| | | Bits 3-0 - number of attribute bits associated with each | +| | | pixel. | +| | | Bit 4 - reserved. Must be set to 0. | +| | | Bit 5 - screen origin bit. | +| | | 0 = Origin in lower left-hand corner. | +| | | 1 = Origin in upper left-hand corner. | +| | | Must be 0 for Truevision images. | +| | | Bits 7-6 - Data storage interleaving flag. | +| | | 00 = non-interleaved. | +| | | 01 = two-way (even/odd) interleaving. | +| | | 10 = four way interleaving. | +| | | 11 = reserved. | +| | | This entire byte should be set to 0. Don't ask me. | +|--------|--------|------------------------------------------------------------| +| 18 | varies | Image Identification Field. | +| | | Contains a free-form identification field of the length | +| | | specified in byte 1 of the image record. It's usually | +| | | omitted ( length in byte 1 = 0 ), but can be up to 255 | +| | | characters. If more identification information is | +| | | required, it can be stored after the image data. | +|--------|--------|------------------------------------------------------------| + +Extension Area: + +* The inclusion of a scaled-down “postage stamp” copy of the image +* Date and Time of image file creation +* Author Name +* Author Comments +* Job Name +* Job Accumulated Time +* Gamma Value +* Correct Color LUT +* Pixel Aspect Ratio +* Scan Line Offset Table +* Key Color +* Software Package Name and Version Number +* Developer Definable Areas +* Attribute (Alpha) channel Type +* The ability for simple expansion +*/ + +static int iTGADecodeScanLine(imBinFile* handle, imbyte *DecodedBuffer, int width, int pixel_size) +{ + int i=0; + unsigned char runcount; /* repetition count field */ + imbyte pixel_buffer[4]; + + while (i < width) + { + imBinFileRead(handle, &runcount, 1, 1); + + if (runcount & 0x80) + { + imBinFileRead(handle, pixel_buffer, pixel_size, 1); + runcount &= 0x7F; + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + runcount++; + while (runcount-- && i < width) + { + memcpy(DecodedBuffer, pixel_buffer, pixel_size); + i++; + DecodedBuffer += pixel_size; + } + } + else + { + runcount++; + while (runcount-- && i < width) + { + imBinFileRead(handle, pixel_buffer, pixel_size, 1); + memcpy(DecodedBuffer, pixel_buffer, pixel_size); + i++; + DecodedBuffer += pixel_size; + } + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + } + } + + return IM_ERR_NONE; +} + +static inline int iTGAEqualPixel(const imbyte* Buffer1, const imbyte* Buffer2, int pixel_size) +{ + while(pixel_size--) + { + if (*Buffer1++ != *Buffer2++) + return 0; + } + return 1; +} + +static int iTGAEncodeScanLine(imbyte* EncodedBuffer, const imbyte* DecodedBuffer, int width, int pixel_size) +{ + imbyte pixel_buffer[4]; + unsigned char runcount; /* Length of encoded pixel run */ + int x = 0; /* Index into uncompressed data buffer */ + imbyte* StartBuffer = EncodedBuffer; + + while (x < width) + { + runcount = 1; + memcpy(pixel_buffer, &DecodedBuffer[x*pixel_size], pixel_size); + + // count equal pixels + while (x+runcount < width && runcount < 128 && + iTGAEqualPixel(pixel_buffer, &DecodedBuffer[(x+runcount)*pixel_size], pixel_size)) + runcount++; + + if (runcount == 1) + { + // count different pixels + while (x+runcount+1 < width && runcount < 128) + { + memcpy(pixel_buffer, &DecodedBuffer[(x+runcount)*pixel_size], pixel_size); + + if (!iTGAEqualPixel(pixel_buffer, &DecodedBuffer[(x+runcount+1)*pixel_size], pixel_size)) + runcount++; + else + break; + } + + *EncodedBuffer++ = (imbyte)(runcount-1); + + memcpy(EncodedBuffer, &DecodedBuffer[x*pixel_size], runcount*pixel_size); + EncodedBuffer += runcount*pixel_size; + } + else + { + *EncodedBuffer++ = (imbyte)(0x80 | (runcount-1)); + + memcpy(EncodedBuffer, pixel_buffer, pixel_size); + EncodedBuffer += pixel_size; + } + + x += runcount; + } + + return EncodedBuffer-StartBuffer; /* Return the number of unsigned chars written to buffer */ +} + +static const char* iTGACompTable[2] = +{ + "NONE", + "RLE" +}; + +class imFileFormatTGA: public imFileFormatBase +{ + imBinFile* handle; /* the binary file handle */ + unsigned char id_lenght; + unsigned char map_type, image_type, map_bpp, bpp; + + int ReadPalette(); + int WritePalette(); + void FixRGB(); + int LoadExtensionArea(); + int SaveExtensionArea(); + +public: + imFileFormatTGA(const imFormat* _iformat): imFileFormatBase(_iformat) {} + ~imFileFormatTGA() {} + + int Open(const char* file_name); + int New(const char* file_name); + void Close(); + void* Handle(int index); + int ReadImageInfo(int index); + int ReadImageData(void* data); + int WriteImageInfo(); + int WriteImageData(void* data); +}; + +class imFormatTGA: public imFormat +{ +public: + imFormatTGA() + :imFormat("TGA", + "Truevision Graphics Adapter File", + "*.tga;*.icb;*.vst;*.tpic;", + iTGACompTable, + 2, + 0) + {} + ~imFormatTGA() {} + + imFileFormatBase* Create(void) const { return new imFileFormatTGA(this); } + int CanWrite(const char* compression, int color_mode, int data_type) const; +}; + +void imFormatRegisterTGA(void) +{ + imFormatRegister(new imFormatTGA()); +} + +int imFileFormatTGA::Open(const char* file_name) +{ + /* opens the binary file for reading with intel byte order */ + handle = imBinFileOpen(file_name); + if (!handle) + return IM_ERR_OPEN; + + imBinFileByteOrder(handle, IM_LITTLEENDIAN); + + imBinFileRead(handle, &this->id_lenght, 1, 1); + imBinFileRead(handle, &this->map_type, 1, 1); + imBinFileRead(handle, &this->image_type, 1, 1); + + if (imBinFileError(handle)) + { + imBinFileClose(handle); + return IM_ERR_ACCESS; + } + + if (this->image_type != 1 && this->image_type != 2 && this->image_type != 3 && + this->image_type != 9 && this->image_type != 10 && this->image_type != 11) + { + imBinFileClose(handle); + return IM_ERR_FORMAT; + } + + if (this->map_type != 0 && this->map_type != 1) + { + imBinFileClose(handle); + return IM_ERR_FORMAT; + } + + if (this->map_type == 0 && (this->image_type == 1 || this->image_type == 9)) + { + imBinFileClose(handle); + return IM_ERR_FORMAT; + } + + if (this->image_type == 9 || this->image_type == 10 || this->image_type == 11) + strcpy(this->compression, "RLE"); + else + strcpy(this->compression, "NONE"); + + this->image_count = 1; + + return IM_ERR_NONE; +} + +int imFileFormatTGA::New(const char* file_name) +{ + /* opens the binary file for writing with intel byte order */ + handle = imBinFileNew(file_name); + if (!handle) + return IM_ERR_OPEN; + + imBinFileByteOrder(handle, IM_LITTLEENDIAN); + + return IM_ERR_NONE; +} + +void imFileFormatTGA::Close() +{ + imBinFileClose(handle); +} + +void* imFileFormatTGA::Handle(int index) +{ + if (index == 0) + return (void*)this->handle; + else + return NULL; +} + +int imFileFormatTGA::ReadImageInfo(int index) +{ + (void)index; + unsigned char byte_value; + unsigned short word_value; + + this->file_data_type = IM_BYTE; + + if (this->image_type == 1 || this->image_type == 9) + this->file_color_mode = IM_MAP; + else if (this->image_type == 2 || this->image_type == 10) + { + this->file_color_mode = IM_RGB; + this->file_color_mode |= IM_PACKED; + } + else if (this->image_type == 3 || this->image_type == 11) + this->file_color_mode = IM_GRAY; + else + return IM_ERR_DATA; + + if (this->map_type == 0) + imBinFileSeekOffset(handle, 5); // jump color map information + else + { + /* jump 2 bytes (first entry index) */ + imBinFileSeekOffset(handle, 2); + + imBinFileRead(handle, &word_value, 1, 2); + this->palette_count = word_value; + + imBinFileRead(handle, &this->map_bpp, 1, 1); + + if (this->map_bpp == 15) this->map_bpp = 16; + + if (this->map_bpp != 16 && this->map_bpp != 24 && this->map_bpp != 32) + return IM_ERR_DATA; + } + + /* jump 4 bytes (X-Origin, Y-Origin) */ + unsigned short xmin, ymin; + imBinFileRead(handle, &xmin, 1, 2); + imBinFileRead(handle, &ymin, 1, 2); + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + imAttribTable* attrib_table = AttribTable(); + + if (xmin && ymin) + { + attrib_table->Set("XScreen", IM_USHORT, 1, &xmin); + attrib_table->Set("YScreen", IM_USHORT, 1, &ymin); + } + + /* reads the image width */ + imBinFileRead(handle, &word_value, 1, 2); + this->width = word_value; + + /* reads the image height */ + imBinFileRead(handle, &word_value, 1, 2); + this->height = word_value; + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + imBinFileRead(handle, &this->bpp, 1, 1); + + if (this->bpp > 8 && imColorModeSpace(this->file_color_mode) != IM_RGB) + return IM_ERR_DATA; + + if (this->bpp == 15) this->bpp = 16; + + if (this->bpp != 8 && this->bpp != 16 && + this->bpp != 24 && this->bpp != 32) + return IM_ERR_DATA; + + if (this->bpp == 32) + this->file_color_mode |= IM_ALPHA; + + // image descriptor + imBinFileRead(handle, &byte_value, 1, 1); + + if (byte_value & 0x20) + this->file_color_mode |= IM_TOPDOWN; + + // image ID + if (this->id_lenght) + { + char desc[256]; + imBinFileRead(handle, desc, this->id_lenght, 1); + desc[this->id_lenght] = 0; + attrib_table->Set("Title", IM_BYTE, this->id_lenght+1, desc); + } + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + if (this->map_type) + { + if (!ReadPalette()) + return IM_ERR_ACCESS; + } + + long cur_offset = imBinFileTell(handle); + imBinFileSeekFrom(handle, -18); + char ext_sig[18]; + imBinFileRead(handle, ext_sig, 18, 1); + if (ext_sig[17] == 0 && imStrEqual(ext_sig, "TRUEVISION-XFILE.")) + { + if (!LoadExtensionArea()) + return IM_ERR_ACCESS; + } + imBinFileSeekTo(handle, cur_offset); + + return IM_ERR_NONE; +} + +int imFileFormatTGA::WriteImageInfo() +{ + unsigned char byte_value; + unsigned short word_value; + + this->map_bpp = 0; + this->map_type = 0; + + this->file_color_mode = imColorModeSpace(this->user_color_mode); + switch (this->file_color_mode) + { + case IM_BINARY: + this->convert_bpp = -1; // expand 1 to 255 + case IM_GRAY: + this->bpp = 8; + if (imStrEqual(this->compression, "RLE")) + this->image_type = 11; + else + this->image_type = 3; + break; + case IM_MAP: + this->bpp = 8; + this->map_bpp = 24; + this->map_type = 1; + if (imStrEqual(this->compression, "RLE")) + this->image_type = 9; + else + this->image_type = 1; + break; + case IM_RGB: + this->bpp = 24; + this->file_color_mode |= IM_PACKED; + if (imStrEqual(this->compression, "RLE")) + this->image_type = 10; + else + this->image_type = 2; + break; + } + + if (this->image_type > 3) + { + // allocates more than enough since compression algoritm can be ineficient + this->line_buffer_extra += 2*this->width*imColorModeDepth(this->file_color_mode); + } + + imAttribTable* attrib_table = AttribTable(); + + /* writes the TGA file header */ + + int length = 0; + const char* desc_attrib = (const char*)attrib_table->Get("Title", NULL, &length); + if (desc_attrib) + { + if (length > 255) + this->id_lenght = 255; + else + this->id_lenght = (imbyte)length; + } + else + this->id_lenght = 0; + + /* IDLength */ + imBinFileWrite(handle, &this->id_lenght, 1, 1); + + /* Color Map Type */ + imBinFileWrite(handle, &this->map_type, 1, 1); + + /* Image Type */ + imBinFileWrite(handle, &this->image_type, 1, 1); + + /* Color Map Specification - 1st entry index */ + word_value = 0; + imBinFileWrite(handle, &word_value, 1, 2); + + /* Color map length */ + word_value = (unsigned short) this->palette_count; + imBinFileWrite(handle, &word_value, 1, 2); + + /* Color Map Entry size */ + byte_value = this->map_type? this->map_bpp: (imbyte)0; + imBinFileWrite(handle, &byte_value, 1, 1); + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + unsigned short xmin = 0, ymin = 0; + const void* attrib_data = attrib_table->Get("XScreen"); + if (attrib_data) xmin = *(unsigned short*)attrib_data; + attrib_data = attrib_table->Get("YScreen"); + if (attrib_data) ymin = *(unsigned short*)attrib_data; + + /* X-orign of image */ + word_value = xmin; + imBinFileWrite(handle, &word_value, 1, 2); + + /* Y-orign of image */ + word_value = ymin; + imBinFileWrite(handle, &word_value, 1, 2); + + /* Image Width */ + word_value = (imushort)this->width; + imBinFileWrite(handle, &word_value, 1, 2); + + /* Image Height */ + word_value = (imushort)this->height; + imBinFileWrite(handle, &word_value, 1, 2); + + /* Pixel Depth */ + imBinFileWrite(handle, &this->bpp, 1, 1); + + /* Image Descriptor */ + byte_value = 0x00; + imBinFileWrite(handle, &byte_value, 1, 1); + + /* image ID */ + if (this->id_lenght) + { + if (length > 255) + { + imBinFileWrite(handle, (void*)desc_attrib, 254, 1); + byte_value = 0x00; + imBinFileWrite(handle, &byte_value, 1, 1); + } + else + imBinFileWrite(handle, (void*)desc_attrib, this->id_lenght, 1); + } + + /* tests if everything was ok */ + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + if (this->map_type) + { + if (!WritePalette()) + return IM_ERR_ACCESS; + } + + return IM_ERR_NONE; +} + +static long iTGARGB2Color(int c, unsigned char *colors, int map_bpp) +{ + unsigned char r,g,b; + + if (map_bpp == 16) + { + unsigned short word_value = ((unsigned short*)colors)[c]; + + r = (imbyte)(((word_value & 0x7C00) >> 10)*8); + g = (imbyte)(((word_value & 0x03E0) >> 5)*8); + b = (imbyte)( (word_value & 0x001F) *8); + } + else // 24 or 32 + { + int i = c * (map_bpp / 8); + + r = colors[i+2]; + g = colors[i+1]; + b = colors[i]; + } + + return imColorEncode(r, g, b); +} + +int imFileFormatTGA::ReadPalette() +{ + int map_size = imFileLineSizeAligned(this->palette_count, this->map_bpp, 1); + unsigned char* tga_colors = (unsigned char*) malloc(map_size); + + /* reads the color palette */ + imBinFileRead(handle, tga_colors, map_size, 1); + if (imBinFileError(handle)) + return 0; + + if (imBinCPUByteOrder() == IM_BIGENDIAN && this->map_bpp == 16) + imBinSwapBytes2(tga_colors, map_size/2); + + /* convert the color map to the IM format */ + for (int c = 0; c < this->palette_count; c++) + this->palette[c] = iTGARGB2Color(c, tga_colors, this->map_bpp); + + free(tga_colors); + + return 1; +} + +int imFileFormatTGA::WritePalette() +{ + unsigned char tga_color[256*3]; + + /* convert the color map from the IM format */ + for (int c = 0; c < this->palette_count; c++) + { + int i = 3*c; + imColorDecode(&tga_color[i+2], &tga_color[i+1], &tga_color[i], this->palette[c]); + } + + /* writes the color palette */ + imBinFileWrite(handle, tga_color, this->palette_count * 3, 1); + + if (imBinFileError(handle)) + return 0; + + return 1; +} + +int imFileFormatTGA::LoadExtensionArea() +{ + unsigned int dword_value; + imBinFileSeekFrom(handle, -26); + + // extension offset + imBinFileRead(handle, &dword_value, 1, 4); + if (imBinFileError(handle)) + return 0; + + imBinFileSeekTo(handle, dword_value); + if (imBinFileError(handle)) + return 0; + + unsigned short word_value; + imbyte buffer[512]; + imAttribTable* attrib_table = AttribTable(); + + // extension size + imBinFileSeekOffset(handle, 2); + + // author name + imBinFileRead(handle, buffer, 41, 1); + if (buffer[0] != 0) + attrib_table->Set("Author", IM_BYTE, imStrNLen((char*)buffer, 41)+1, buffer); + + // author comments + imBinFileRead(handle, buffer, 324, 1); + if (buffer[0] != 0) + { + int size1 = imStrNLen((char*)buffer, 81); + for (int i = 1; i < 4; i++) + { + int sizei = imStrNLen((char*)buffer + i*81, 81); + if (sizei) + { + memcpy(buffer + size1, buffer + i*81, sizei); + size1 += sizei; + } + } + buffer[size1] = 0; + + attrib_table->Set("Description", IM_BYTE, size1+1, buffer); + } + + if (imBinFileError(handle)) + return 0; + + { + tm ttm; + ttm.tm_wday = 0; + ttm.tm_yday = 0; + ttm.tm_isdst = -1; + + int valid = 0; + imBinFileRead(handle, &word_value, 1, 2); // moth + ttm.tm_mon = word_value-1; + if (word_value) valid = 1; + imBinFileRead(handle, &word_value, 1, 2); // day + ttm.tm_mday = word_value; + if (word_value) valid = 1; + imBinFileRead(handle, &word_value, 1, 2); // year + ttm.tm_year = word_value-1900; + if (word_value) valid = 1; + imBinFileRead(handle, &word_value, 1, 2); // hour + ttm.tm_hour = word_value; + imBinFileRead(handle, &word_value, 1, 2); // minute + ttm.tm_min = word_value; + imBinFileRead(handle, &word_value, 1, 2); // seconds + ttm.tm_sec = word_value; + + if (imBinFileError(handle)) + return 0; + + if (valid) + { + time_t tt = mktime(&ttm); + char* str = ctime(&tt); + if (str) + { + int size = strlen(str); + str[size-1] = 0; // remove "\n" + attrib_table->Set("DateTimeModified", IM_BYTE, size, str); + } + } + } + + // job name + imBinFileRead(handle, buffer, 41, 1); + if (buffer[0] != 0) + attrib_table->Set("JobName", IM_BYTE, imStrNLen((char*)buffer, 41)+1, buffer); + + // job time + imBinFileSeekOffset(handle, 6); + + // Software + imBinFileRead(handle, buffer, 41, 1); + if (buffer[0] != 0) + attrib_table->Set("Software", IM_BYTE, imStrNLen((char*)buffer, 41)+1, buffer); + + if (imBinFileError(handle)) + return 0; + + // Software Version + imBinFileRead(handle, &word_value, 1, 2); + if (word_value) + { + int size = sprintf((char*)buffer, "%f", (double)word_value / 100.0); + imBinFileRead(handle, &buffer[size], 1, 1); + buffer[size+1] = 0; + attrib_table->Set("SoftwareVersion", IM_BYTE, size+1, buffer); + } + + // key color, aspect ratio + imBinFileSeekOffset(handle, 8); + + // gamma + imBinFileRead(handle, &word_value, 1, 2); // num + if (word_value) + { + float gamma = (float)word_value; + imBinFileRead(handle, &word_value, 1, 2); // den + if (word_value) + { + gamma /= (float)word_value; + attrib_table->Set("Gamma", IM_FLOAT, 1, &gamma); + } + } + + if (imBinFileError(handle)) + return 0; + + return 1; +} + +static void iGetRational(float fvalue, int *num, int *den) +{ + if (floorf(fvalue) == fvalue) + { + *num = (int)floorf(fvalue); + *den = 1; + return; + } + + float ivalue = 1.0f/fvalue; + if (floorf(ivalue) == ivalue) + { + *den = (int)floorf(ivalue); + *num = 1; + return; + } + + *den = 1; + if (fvalue > 0) + { + while (fvalue < 1L<<(31-3) && *den < 1L<<(31-3)) + { + fvalue *= 1<<3; + *den *= 1<<3; + } + } + + *num = imRound(fvalue); +} + +int imFileFormatTGA::SaveExtensionArea() +{ + unsigned int dword_value; + unsigned short word_value; + + // get offset before write + long ext_offset = imBinFileTell(handle); + + imbyte buffer[512]; + memset(buffer, 0, 512); + + imAttribTable* attrib_table = AttribTable(); + + // extension size + word_value = 495; + imBinFileWrite(handle, &word_value, 1, 2); + + // author name + int attrib_size; + const void* attrib_data = attrib_table->Get("Author", NULL, &attrib_size); + if (attrib_data) + { + int size = attrib_size > 41? 40: attrib_size; + imBinFileWrite(handle, (void*)attrib_data, size, 1); + if (size < 41) + imBinFileWrite(handle, buffer, 41-size, 1); + } + else + imBinFileWrite(handle, buffer, 41, 1); + + // author comments + attrib_data = attrib_table->Get("Description", NULL, &attrib_size); + if (attrib_data) + { + int size = 0, size2 = 0, i = 0; + while(attrib_size && i < 4) + { + int line_size; + if (attrib_size > 81) + line_size = 80; + else + line_size = attrib_size; + + memcpy(buffer + size, (imbyte*)attrib_data + size2, line_size); + + attrib_size -= line_size; + size2 += line_size; + size += line_size; + i++; + + int remain = 81-line_size; + if (remain) + { + memset(buffer + size, 0, remain); + size += remain; + } + } + + imBinFileWrite(handle, buffer, 324, 1); + memset(buffer, 0, 512); + } + else + imBinFileWrite(handle, buffer, 324, 1); + + if (imBinFileError(handle)) + return 0; + + attrib_data = attrib_table->Get("DateTimeModified"); + if (attrib_data) + { + time_t cur_time; + time(&cur_time); + tm* ttm = localtime(&cur_time); + + word_value = (imushort)ttm->tm_mon+1; + imBinFileWrite(handle, &word_value, 1, 2); // moth + word_value = (imushort)ttm->tm_mday; + imBinFileWrite(handle, &word_value, 1, 2); // day + word_value = (imushort)ttm->tm_year+1900; + imBinFileWrite(handle, &word_value, 1, 2); // year + word_value = (imushort)ttm->tm_hour; + imBinFileWrite(handle, &word_value, 1, 2); // hour + word_value = (imushort)ttm->tm_min; + imBinFileWrite(handle, &word_value, 1, 2); // minute + word_value = (imushort)ttm->tm_sec; + imBinFileWrite(handle, &word_value, 1, 2); // seconds + + if (imBinFileError(handle)) + return 0; + } + else + imBinFileWrite(handle, buffer, 12, 1); + + // job name + attrib_data = attrib_table->Get("JobName", NULL, &attrib_size); + if (attrib_data) + { + int size = attrib_size > 41? 40: attrib_size; + imBinFileWrite(handle, (void*)attrib_data, size, 1); + if (size < 41) + imBinFileWrite(handle, buffer, 41-size, 1); + } + else + imBinFileWrite(handle, buffer, 41, 1); + + // job time + imBinFileWrite(handle, buffer, 6, 1); + + // Software + attrib_data = attrib_table->Get("Software", NULL, &attrib_size); + if (attrib_data) + { + int size = attrib_size > 41? 40: attrib_size; + imBinFileWrite(handle, (void*)attrib_data, size, 1); + if (size < 41) + imBinFileWrite(handle, buffer, 41-size, 1); + } + else + imBinFileWrite(handle, buffer, 41, 1); + + if (imBinFileError(handle)) + return 0; + + // Software Version, key color, aspect ratio + imBinFileWrite(handle, buffer, 11, 1); + + // gamma + attrib_data = attrib_table->Get("Gamma"); + if (attrib_data) + { + float gamma = *(float*)attrib_data; + + int num, den; + iGetRational(gamma, &num, &den); + + word_value = (imushort)num; + imBinFileWrite(handle, &word_value, 1, 2); // num + word_value = (imushort)den; + imBinFileWrite(handle, &word_value, 1, 2); // den + } + else + imBinFileWrite(handle, buffer, 4, 1); + + // Color Correction, Postage Stamp, Scanline Offset, Attributes Type + imBinFileWrite(handle, buffer, 13, 1); + + // FOOTER + + // extension offset + dword_value = ext_offset; + imBinFileWrite(handle, &dword_value, 1, 4); + + // Developer Directory Offset + imBinFileWrite(handle, buffer, 4, 1); + + // signature, reserved, zero string terminator + imBinFileWrite(handle, (void*)"TRUEVISION-XFILE.\0", 18, 1); + + if (imBinFileError(handle)) + return 0; + + return 1; +} + +void imFileFormatTGA::FixRGB() +{ + int x; + imbyte* byte_data = (imbyte*)this->line_buffer; + + if (this->bpp == 16) + { + /* inverts the WORD values if not intel */ + if (imBinCPUByteOrder() == IM_BIGENDIAN) + imBinSwapBytes2(this->line_buffer, this->width); + + imushort* word_data = (imushort*)this->line_buffer; + + // from end to start + for (x = this->width-1; x >= 0; x--) + { + imushort word_value = word_data[x]; + int c = x*3; + byte_data[c] = (imbyte)(((word_value & 0x7C00) >> 10)*8); + byte_data[c+1] = (imbyte)(((word_value & 0x03E0) >> 5)*8); + byte_data[c+2] = (imbyte)( (word_value & 0x001F) *8); + } + } + else // 24 and 32 + { + // convert BGR <-> RGB + // convert BGRA <-> RGBA + imbyte* byte_data = (imbyte*)this->line_buffer; + int planes = this->bpp/8; + for (x = 0; x < this->width; x++) + { + int c = x*planes; + imbyte temp = byte_data[c]; // swap R and B + byte_data[c] = byte_data[c+2]; + byte_data[c+2] = temp; + } + } +} + +int imFileFormatTGA::ReadImageData(void* data) +{ + imCounterTotal(this->counter, this->height, "Reading TGA..."); + + int line_size = this->line_buffer_size; + if (this->bpp == 16) + line_size = this->width*2; + + for (int row = 0; row < this->height; row++) + { + if (this->image_type > 3) + { + if (iTGADecodeScanLine(handle, (imbyte*)this->line_buffer, this->width, this->bpp/8) == IM_ERR_ACCESS) + return IM_ERR_ACCESS; + } + else + { + imBinFileRead(handle, this->line_buffer, line_size, 1); + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + } + + if (this->bpp > 8) + FixRGB(); + + imFileLineBufferRead(this, data, row, 0); + + if (!imCounterInc(this->counter)) + return IM_ERR_COUNTER; + } + + return IM_ERR_NONE; +} + +int imFileFormatTGA::WriteImageData(void* data) +{ + imCounterTotal(this->counter, this->height, "Writing TGA..."); + + imbyte* compressed_buffer = NULL; + if (this->image_type > 3) // point to the extra buffer + compressed_buffer = (imbyte*)this->line_buffer + this->line_buffer_size; + + for (int row = 0; row < this->height; row++) + { + imFileLineBufferWrite(this, data, row, 0); + + if (this->bpp > 8) + FixRGB(); + + if (this->image_type > 3) + { + int compressed_size = iTGAEncodeScanLine(compressed_buffer, (imbyte*)this->line_buffer, this->width, this->bpp/8); + imBinFileWrite(handle, compressed_buffer, compressed_size, 1); + } + else + { + imBinFileWrite(handle, this->line_buffer, this->line_buffer_size, 1); + } + + if (imBinFileError(handle)) + return IM_ERR_ACCESS; + + if (!imCounterInc(this->counter)) + return IM_ERR_COUNTER; + } + + if (!SaveExtensionArea()) + return IM_ERR_ACCESS; + + return IM_ERR_NONE; +} + +int imFormatTGA::CanWrite(const char* compression, int color_mode, int data_type) const +{ + int color_space = imColorModeSpace(color_mode); + + if (color_space == IM_YCBCR || color_space == IM_LAB || + color_space == IM_LUV || color_space == IM_XYZ || + color_space == IM_CMYK) + return IM_ERR_DATA; + + if (data_type != IM_BYTE) + return IM_ERR_DATA; + + if (!compression || compression[0] == 0) + return IM_ERR_NONE; + + if (!imStrEqual(compression, "NONE") && !imStrEqual(compression, "RLE")) + return IM_ERR_COMPRESS; + + return IM_ERR_NONE; +} diff --git a/im/src/im_format_wmv.cpp b/im/src/im_format_wmv.cpp new file mode 100755 index 0000000..4f3b31b --- /dev/null +++ b/im/src/im_format_wmv.cpp @@ -0,0 +1,1633 @@ +/** \file + * \brief WMV - Windows Media Video Format + * + * See Copyright Notice in im_lib.h + * $Id: im_format_wmv.cpp,v 1.3 2009/08/23 23:57:52 scuri Exp $ + */ + +#include "im_format.h" +#include "im_util.h" +#include "im_format_wmv.h" +#include "im_counter.h" + +#include + +//#include +#define AMINTERLACE_1FieldPerSample 0x00000002 +#define AMINTERLACE_Field1First 0x00000004 + +#include "im_dib.h" + +#include +#include +#include +#include + + +#define SAFE_RELEASE( x ) \ + if ( x ) \ + { \ + x->Release(); \ + x = NULL; \ + } + +#define SAFE_ARRAYDELETE( x ) \ + if ( x ) \ + { \ + delete[] x; \ + x = NULL; \ + } + +static HRESULT iConfigCompressedStream( IWMStreamConfig * pStreamConfig, + IWMProfile * pIWMProfile, + BOOL fIsVBR, DWORD dwBitrate, DWORD dwQuality, DWORD dwSecPerKey, + WM_MEDIA_TYPE * pmt ) +{ + WORD wFALSE = 0; + HRESULT hr = S_OK; + + do + { + // This is used just to get the stream number, it will be released and + // NOT added to the profile + IWMStreamConfig * pStreamConfig2 = NULL; + hr = pIWMProfile->CreateNewStream( WMMEDIATYPE_Video, &pStreamConfig2 ); + if (FAILED(hr)) + break; + + WORD wStreamNum = 0; + hr = pStreamConfig2->GetStreamNumber( &wStreamNum ); + + SAFE_RELEASE( pStreamConfig2 ); + + if (FAILED(hr)) + break; + + // Configure the stream + + hr = pStreamConfig->SetStreamNumber( wStreamNum ); + if (FAILED(hr)) + break; + + hr = pStreamConfig->SetStreamName( L"Video Stream" ); + if (FAILED(hr)) + break; + + // Each stream in the profile has to have a unique connection name. + // Let's use the stream number to create it. + + WCHAR pwszConnectionName[10]; + swprintf( pwszConnectionName, L"Video%d", (DWORD)wStreamNum ); + + hr = pStreamConfig->SetConnectionName( pwszConnectionName ); + if (FAILED(hr)) + break; + + hr = pStreamConfig->SetBitrate( dwBitrate ); + if (FAILED(hr)) + break; + + hr = pStreamConfig->SetBufferWindow( (DWORD)-1 ); + if (FAILED(hr)) + break; + + IWMVideoMediaProps * pIWMMediaProps = NULL; + hr = pStreamConfig->QueryInterface( IID_IWMVideoMediaProps, (void **) &pIWMMediaProps ); + if (FAILED(hr)) + break; + + hr = pIWMMediaProps->SetQuality( dwQuality ); + hr = pIWMMediaProps->SetMaxKeyFrameSpacing( 10000 * (QWORD)dwSecPerKey ); + + hr = pIWMMediaProps->SetMediaType( pmt ); + + SAFE_RELEASE( pIWMMediaProps ); + + if (FAILED(hr)) + break; + + IWMPropertyVault* pPropertyVault = NULL; + hr = pStreamConfig->QueryInterface( IID_IWMPropertyVault, (void**)&pPropertyVault ); + if (FAILED(hr)) + break; + + hr = pPropertyVault->SetProperty( g_wszVBREnabled, WMT_TYPE_BOOL, (BYTE*)&fIsVBR, sizeof( BOOL ) ); + if ( SUCCEEDED( hr ) && fIsVBR) + pPropertyVault->SetProperty( g_wszVBRQuality, WMT_TYPE_DWORD, (BYTE*)&dwQuality, sizeof( DWORD ) ); + + SAFE_RELEASE( pPropertyVault ); + + hr = S_OK; + + } while( wFALSE ); + + return( hr ); +} + +static HRESULT iCreateCompressedStream(IWMProfileManager * pManager, + IWMStreamConfig* *pNewStreamConfig, + WM_MEDIA_TYPE* *pNewMediaType, + WORD biBitCount, GUID subtype) +{ + IWMCodecInfo * pCodecInfo = NULL; + IWMMediaProps * pMediaProps = NULL; + + IWMStreamConfig* pStreamConfig = NULL; + WM_MEDIA_TYPE* pMediaType = NULL; + + HRESULT hr = S_OK; + WORD wFALSE = 0; + + do + { + hr = pManager->QueryInterface(IID_IWMCodecInfo, (void **) &pCodecInfo); + if (FAILED(hr)) + break; + + DWORD cCodecs; + hr = pCodecInfo->GetCodecInfoCount( WMMEDIATYPE_Video, &cCodecs ); + if (FAILED(hr)) + break; + + for( int i = cCodecs-1; i >= 0; i-- ) + { + DWORD cFormats; + hr = pCodecInfo->GetCodecFormatCount( WMMEDIATYPE_Video, i, &cFormats ); + if (FAILED(hr)) + break; + + for(DWORD j = 0; j < cFormats; j++ ) + { + SAFE_RELEASE( pStreamConfig ); + + hr = pCodecInfo->GetCodecFormat( WMMEDIATYPE_Video, i, j, &pStreamConfig ); + if (FAILED(hr)) + break; + + SAFE_RELEASE( pMediaProps ); + + hr = pStreamConfig->QueryInterface( IID_IWMMediaProps, (void **) &pMediaProps ); + if (FAILED(hr)) + break; + + DWORD cbMT; + hr = pMediaProps->GetMediaType( NULL, &cbMT ); + if (FAILED(hr)) + break; + + SAFE_ARRAYDELETE( pMediaType ); + + pMediaType = (WM_MEDIA_TYPE *) new BYTE[ cbMT ]; + if( !pMediaType ) + { + hr = E_OUTOFMEMORY; + break; + } + + hr = pMediaProps->GetMediaType( pMediaType, &cbMT ); + if (FAILED(hr)) + break; + + if( pMediaType->formattype != WMFORMAT_VideoInfo || + pMediaType->subtype != subtype) // This is our main target + { + SAFE_RELEASE( pStreamConfig ); + continue; + } + + WMVIDEOINFOHEADER* pVIH = (WMVIDEOINFOHEADER*) pMediaType->pbFormat; + + if( pVIH->bmiHeader.biBitCount >= biBitCount ) + break; // SUCCESS !!!!! + + SAFE_RELEASE( pStreamConfig ); + } + + if( FAILED( hr ) || NULL != pStreamConfig ) + break; + } + + if (FAILED(hr)) + break; + + if( NULL == pStreamConfig ) + { + hr = NS_E_VIDEO_CODEC_NOT_INSTALLED; + break; + } + + } while( wFALSE ); + + SAFE_RELEASE( pCodecInfo ); + SAFE_RELEASE( pMediaProps ); + + *pNewStreamConfig = pStreamConfig; + *pNewMediaType = pMediaType; + + return( hr ); +} + +static HRESULT iAddCompressedVideoStream( IWMProfileManager * pManager, IWMProfile * pIWMProfile, + GUID subtype, BITMAPINFOHEADER * bmiHeader, float fps, + BOOL fIsVBR, DWORD dwBitRate, DWORD dwQuality, DWORD dwSecPerKey) +{ + HRESULT hr = S_OK; + WORD wFALSE = 0; + + IWMStreamConfig* pStreamConfig = NULL; + WM_MEDIA_TYPE* pMediaType = NULL; + + do + { + hr = iCreateCompressedStream(pManager, &pStreamConfig, &pMediaType, + bmiHeader->biBitCount, subtype); + if (FAILED(hr)) + break; + + WMVIDEOINFOHEADER * pVIH = (WMVIDEOINFOHEADER *) pMediaType->pbFormat; + + pVIH->dwBitRate = dwBitRate; + + // Video content does not play correctly unless it is encoded + // to a size that is a multiple of four for both width and height. + pVIH->bmiHeader.biWidth = ((bmiHeader->biWidth + 3) / 4) * 4; + pVIH->bmiHeader.biHeight = ((bmiHeader->biHeight + 3) / 4) * 4; + + pVIH->rcSource.left = 0; + pVIH->rcSource.top = 0; + pVIH->rcSource.bottom = pVIH->bmiHeader.biHeight; + pVIH->rcSource.right = pVIH->bmiHeader.biWidth; + pVIH->rcTarget = pVIH->rcSource; + pVIH->dwBitErrorRate = 0; + pVIH->AvgTimePerFrame = (LONGLONG)(10000000.0f / fps); + + hr = iConfigCompressedStream( pStreamConfig, pIWMProfile, + fIsVBR, dwBitRate, dwQuality, + dwSecPerKey, pMediaType ); + if (FAILED(hr)) + break; + + hr = pIWMProfile->AddStream( pStreamConfig ); + if (FAILED(hr)) + break; + } + while( wFALSE ); + + SAFE_RELEASE( pStreamConfig ); + SAFE_ARRAYDELETE( pMediaType ); + + return( hr ); +} + +static HRESULT iConfigUncompressedStream( IWMStreamConfig * pStreamConfig, + DWORD dwBitrate, + WM_MEDIA_TYPE * pmt ) +{ + WORD wFALSE = 0; + HRESULT hr = S_OK; + + do + { + // Configure the stream + + hr = pStreamConfig->SetStreamName( L"Video Stream" ); + if (FAILED(hr)) + break; + + // Each stream in the profile has to have a unique connection name. + // Let's use the stream number to create it. + + WORD wStreamNum = 0; + hr = pStreamConfig->GetStreamNumber( &wStreamNum ); + if (FAILED(hr)) + break; + + WCHAR pwszConnectionName[10]; + swprintf( pwszConnectionName, L"Video%d", (DWORD)wStreamNum ); + + hr = pStreamConfig->SetConnectionName( pwszConnectionName ); + if (FAILED(hr)) + break; + + hr = pStreamConfig->SetBitrate( dwBitrate ); + if (FAILED(hr)) + break; + + hr = pStreamConfig->SetBufferWindow( 0 ); + if (FAILED(hr)) + break; + + IWMMediaProps * pIWMMediaProps = NULL; + hr = pStreamConfig->QueryInterface( IID_IWMMediaProps, (void **) &pIWMMediaProps ); + if (FAILED(hr)) + break; + + hr = pIWMMediaProps->SetMediaType( pmt ); + + SAFE_RELEASE( pIWMMediaProps ); + + if (FAILED(hr)) + break; + + IWMPropertyVault* pPropertyVault = NULL; + hr = pStreamConfig->QueryInterface( IID_IWMPropertyVault, (void**)&pPropertyVault ); + if (FAILED(hr)) + break; + + BOOL fFalse = FALSE; + hr = pPropertyVault->SetProperty( g_wszVBREnabled, WMT_TYPE_BOOL, (BYTE*)&fFalse, sizeof( BOOL ) ); + + SAFE_RELEASE( pPropertyVault ); + + hr = S_OK; + + } while( wFALSE ); + + return( hr ); +} + +static HRESULT iAddUncompressedVideoStream( IWMProfile * pProfile, + BITMAPINFOHEADER * bmiHeader, + int BitmapInfoSize, int BitmapDataSize, + float fps) +{ + HRESULT hr = S_OK; + WORD wFALSE = 0; + + IWMStreamConfig* pStreamConfig = NULL; + WM_MEDIA_TYPE* pMediaType = NULL; + + do + { + hr = pProfile->CreateNewStream( WMMEDIATYPE_Video, &pStreamConfig ); + if ( FAILED( hr ) ) + break; + + DWORD cbVideoInfo = sizeof(WMVIDEOINFOHEADER) - sizeof(BITMAPINFOHEADER) + BitmapInfoSize; + + // Create a new Media Type + pMediaType = (WM_MEDIA_TYPE*) new BYTE[ sizeof( WM_MEDIA_TYPE ) + cbVideoInfo ]; + if ( !pMediaType) + { + hr = E_OUTOFMEMORY; + break; + } + + switch (bmiHeader->biBitCount) + { + case 32: + pMediaType->subtype = WMMEDIASUBTYPE_RGB32; + break; + case 24: + pMediaType->subtype = WMMEDIASUBTYPE_RGB24; + break; + case 8: + pMediaType->subtype = WMMEDIASUBTYPE_RGB8; + break; + } + + pMediaType->majortype = WMMEDIATYPE_Video; + pMediaType->bFixedSizeSamples = TRUE; + pMediaType->bTemporalCompression = FALSE; + pMediaType->lSampleSize = BitmapDataSize; + pMediaType->formattype = WMFORMAT_VideoInfo; + pMediaType->pUnk = NULL; + pMediaType->cbFormat = cbVideoInfo; + pMediaType->pbFormat = ( ((BYTE*) pMediaType) + sizeof( WM_MEDIA_TYPE ) ); // Format data is immediately after media type + + WMVIDEOINFOHEADER * pVIH = (WMVIDEOINFOHEADER *) pMediaType->pbFormat; + + pVIH->rcSource.left = 0; + pVIH->rcSource.top = 0; + pVIH->rcSource.bottom = bmiHeader->biHeight; + pVIH->rcSource.right = bmiHeader->biWidth; + pVIH->rcTarget = pVIH->rcSource; + pVIH->dwBitRate = (DWORD)(BitmapDataSize * fps); + pVIH->dwBitErrorRate = 0; + pVIH->AvgTimePerFrame = (LONGLONG)(10000000.0f / fps); + + CopyMemory(&pVIH->bmiHeader, bmiHeader, BitmapInfoSize); + + hr = iConfigUncompressedStream( pStreamConfig, pVIH->dwBitRate, pMediaType ); + if (FAILED(hr)) + break; + + hr = pProfile->AddStream( pStreamConfig ); + if (FAILED(hr)) + break; + } + while( wFALSE ); + + SAFE_RELEASE( pStreamConfig ); + SAFE_ARRAYDELETE( pMediaType ); + + return( hr ); +} + +#define WMV_COMPRESS_COUNT 7 +#define WMV_UNCOMPRESS_COUNT 9 + +static GUID iWMVCompSubtypeTable[WMV_COMPRESS_COUNT+WMV_UNCOMPRESS_COUNT]; + +static void iInitGuid() +{ + iWMVCompSubtypeTable[0] = WMMEDIASUBTYPE_MP43; + iWMVCompSubtypeTable[1] = WMMEDIASUBTYPE_MP4S; + iWMVCompSubtypeTable[2] = WMMEDIASUBTYPE_WMV1; + iWMVCompSubtypeTable[3] = WMMEDIASUBTYPE_MSS1; + iWMVCompSubtypeTable[4] = WMMEDIASUBTYPE_WMV2; + iWMVCompSubtypeTable[5] = WMMEDIASUBTYPE_MSS2; + iWMVCompSubtypeTable[6] = WMMEDIASUBTYPE_WMV3; + + iWMVCompSubtypeTable[WMV_COMPRESS_COUNT+0] = WMMEDIASUBTYPE_RGB555; + iWMVCompSubtypeTable[WMV_COMPRESS_COUNT+1] = WMMEDIASUBTYPE_RGB24; + iWMVCompSubtypeTable[WMV_COMPRESS_COUNT+2] = WMMEDIASUBTYPE_RGB32; + iWMVCompSubtypeTable[WMV_COMPRESS_COUNT+3] = WMMEDIASUBTYPE_I420; + iWMVCompSubtypeTable[WMV_COMPRESS_COUNT+4] = WMMEDIASUBTYPE_IYUV; + iWMVCompSubtypeTable[WMV_COMPRESS_COUNT+5] = WMMEDIASUBTYPE_YV12; + iWMVCompSubtypeTable[WMV_COMPRESS_COUNT+6] = WMMEDIASUBTYPE_YUY2; + iWMVCompSubtypeTable[WMV_COMPRESS_COUNT+7] = WMMEDIASUBTYPE_UYVY; + iWMVCompSubtypeTable[WMV_COMPRESS_COUNT+8] = WMMEDIASUBTYPE_YVYU; +} + +static const char* iWMVCompTable[WMV_COMPRESS_COUNT+1] = +{ + "NONE", + "MPEG-4v3", + "MPEG-4v1", + "WMV7", + "WMV7Screen", + "WMV8", + "WMV9Screen", + "WMV9" +}; + +static const char* iWMFCompFindName(GUID SubType) +{ + int i; + for(i = 0; i < WMV_COMPRESS_COUNT; i++) + { + if (SubType == iWMVCompSubtypeTable[i]) + return iWMVCompTable[i+1]; + } + + for(; i < WMV_COMPRESS_COUNT+WMV_UNCOMPRESS_COUNT; i++) + { + if (SubType == iWMVCompSubtypeTable[i]) + return iWMVCompTable[0]; + } + + return "Unknown"; +} + +static GUID iWMFCompFindSubType(const char* compression) +{ + if (compression[0] == 0) + return WMMEDIASUBTYPE_WMV3; + + for(int i = 0; i < WMV_COMPRESS_COUNT; i++) + { + if (imStrEqual(compression, iWMVCompTable[i+1])) + return iWMVCompSubtypeTable[i]; + } + + return WMMEDIASUBTYPE_Base; +} + +class imFileFormatWMV: public imFileFormatBase +{ + IWMSyncReader* Reader; // When reading + WM_MEDIA_TYPE* MediaType; + WORD stream_number; + DWORD seekable; + int current_frame; + + IWMWriter* Writer; // When writing + DWORD input_number; + DWORD BitmapDataSize; + DWORD BitmapInfoSize; + + float fps; + WCHAR wfile_name[4096]; + IWMHeaderInfo* HeaderInfo; + BITMAPINFOHEADER* bmiHeader; + unsigned int rmask, gmask, bmask, + roff, goff, boff; /* pixel bit mask control when reading 16 and 32 bpp images */ + + void ReadPalette(unsigned char* bmp_colors); + void WritePalette(unsigned char* bmp_colors); + void FixRGB(int bpp); + void InitMasks(imDib* dib); + void iReadAttrib(imAttribTable* attrib_table); + void iWriteAttrib(imAttribTable* attrib_table); + void CalcFPS(); + void SetOutputProps(); + int SetInputProps(); + int SetProfile(); + +public: + imFileFormatWMV(const imFormat* _iformat): imFileFormatBase(_iformat) {} + ~imFileFormatWMV() {} + + int Open(const char* file_name); + int New(const char* file_name); + void Close(); + void* Handle(int index); + int ReadImageInfo(int index); + int ReadImageData(void* data); + int WriteImageInfo(); + int WriteImageData(void* data); +}; + +class imFormatWMV: public imFormat +{ +public: + imFormatWMV() + :imFormat("WMV", + "Windows Media Video Format", + "*.wmv;*.asf;", + iWMVCompTable, + WMV_COMPRESS_COUNT+1, + 1) + {} + ~imFormatWMV() {} + + imFileFormatBase* Create(void) const { return new imFileFormatWMV(this); } + int CanWrite(const char* compression, int color_mode, int data_type) const; +}; + +void imFormatRegisterWMV(void) +{ + imFormatRegister(new imFormatWMV()); +} + +int imFileFormatWMV::Open(const char* file_name) +{ + /* initializes COM */ + CoInitialize(NULL); + iInitGuid(); + + HRESULT hr = WMCreateSyncReader(NULL, 0, &Reader); + if (hr != 0) + { + CoUninitialize(); + return IM_ERR_MEM; + } + + /* open existing file */ + MultiByteToWideChar(CP_ACP, 0, file_name, -1, wfile_name, 4096); + hr = Reader->Open(wfile_name); + if (hr != 0) + { + Reader->Release(); + CoUninitialize(); + + if (hr == NS_E_FILE_OPEN_FAILED || + hr == NS_E_FILE_NOT_FOUND || + hr == NS_E_INVALID_DATA) + return IM_ERR_OPEN; + else if (hr == NS_E_UNRECOGNIZED_STREAM_TYPE) + return IM_ERR_FORMAT; + else + return IM_ERR_ACCESS; + } + + IWMProfile* pProfile = NULL; + Reader->QueryInterface(IID_IWMProfile, (VOID**)&pProfile); + + DWORD stream_count; + pProfile->GetStreamCount(&stream_count); + + this->stream_number = (WORD)-1; + for (int i = 0; i < (int)stream_count; i++) + { + IWMStreamConfig* StreamConfig; + pProfile->GetStream(i, &StreamConfig); + + GUID StreamType; + StreamConfig->GetStreamType(&StreamType); + + if (StreamType == WMMEDIATYPE_Video || + StreamType == WMMEDIATYPE_Image) + { + hr = StreamConfig->GetStreamNumber(&this->stream_number); + + IWMMediaProps* Props; + StreamConfig->QueryInterface(IID_IWMMediaProps, (VOID**)&Props); + + DWORD pcbType; + Props->GetMediaType(NULL, &pcbType); + MediaType = (WM_MEDIA_TYPE*)malloc(pcbType); + Props->GetMediaType(MediaType, &pcbType); + + Props->Release(); + + const char* comp_name = iWMFCompFindName(MediaType->subtype); + strcpy(this->compression, comp_name); + break; + } + + StreamConfig->Release(); + } + + if (this->stream_number == (WORD)-1) + { + pProfile->Release(); + Reader->Close(); + Reader->Release(); + CoUninitialize(); + return IM_ERR_DATA; + } + + hr = Reader->QueryInterface(IID_IWMHeaderInfo, (VOID**)&HeaderInfo); + + CalcFPS(); + + WMT_ATTR_DATATYPE attrib_type; + WORD attrib_length; + WORD StreamNumber = 0; + + seekable = 0; + attrib_length = 4; + attrib_type = WMT_TYPE_BOOL; + hr = HeaderInfo->GetAttributeByName(&StreamNumber, g_wszWMSeekable, + &attrib_type, (BYTE*)&seekable, &attrib_length); + + QWORD num_frame = 0; + attrib_length = 8; + attrib_type = WMT_TYPE_QWORD; + hr = HeaderInfo->GetAttributeByName(&stream_number, g_wszWMNumberOfFrames, + &attrib_type, (BYTE*)&num_frame, &attrib_length); + + if (num_frame == 0) + { + QWORD duration = 0; + attrib_length = 8; + attrib_type = WMT_TYPE_QWORD; + hr = HeaderInfo->GetAttributeByName(&StreamNumber, g_wszWMDuration, + &attrib_type, (BYTE*)&duration, &attrib_length); + + num_frame = (int)(((double)(unsigned int)duration * (double)fps) / 10000000.0); + } + + this->image_count = (int)num_frame; + + SetOutputProps(); + + WMT_STREAM_SELECTION wmtSS = WMT_ON; + hr = Reader->SetStreamsSelected(1, &stream_number, &wmtSS); + hr = Reader->SetReadStreamSamples(stream_number, FALSE); + + this->bmiHeader = NULL; + this->current_frame = 0; + + return IM_ERR_NONE; +} + +int imFileFormatWMV::New(const char* file_name) +{ + /* initializes COM */ + CoInitialize(NULL); + iInitGuid(); + + HRESULT hr = WMCreateWriter(NULL, &Writer); + if (hr != 0) + { + CoUninitialize(); + return IM_ERR_MEM; + } + + MultiByteToWideChar(CP_ACP, 0, file_name, -1, wfile_name, 4096); + + Writer->QueryInterface(IID_IWMHeaderInfo, (VOID**)&HeaderInfo); + + this->bmiHeader = NULL; + this->current_frame = 0; + + return IM_ERR_NONE; +} + +void imFileFormatWMV::Close() +{ + HeaderInfo->Release(); + + if (this->is_new) + { + free(this->bmiHeader); + + Writer->EndWriting(); + Writer->Release(); + } + else + { + free(MediaType); + + Reader->Close(); + Reader->Release(); + } + + CoUninitialize(); +} + +void* imFileFormatWMV::Handle(int index) +{ + if (index == 1) + { + if (this->is_new) + return (void*)this->Writer; + else + return (void*)this->Reader; + } + else + return NULL; +} + +void imFileFormatWMV::iReadAttrib(imAttribTable* attrib_table) +{ + WORD StreamNumber = 0; + WORD attrib_list_count = 0; + HeaderInfo->GetAttributeCount(StreamNumber, &attrib_list_count); + + WCHAR* attrib_name = NULL; + int name_max_size = 0; + char* name = NULL; + WORD attrib_name_count; + WMT_ATTR_DATATYPE attrib_type; + BYTE* attrib_data = NULL; + WORD attrib_length; + int data_max_size = 0; + HRESULT hr; + int data_type, data_count; + + for (WORD i = 0; i < attrib_list_count; i++) + { + attrib_name_count = 0; + attrib_length = 0; + + hr = HeaderInfo->GetAttributeByIndex(i, &StreamNumber, NULL, &attrib_name_count, + &attrib_type, NULL, &attrib_length); + + if (FAILED(hr)) + continue; + + if (attrib_length == 0) + continue; + + if (name_max_size < attrib_name_count) + { + attrib_name = (WCHAR*)realloc(attrib_name, attrib_name_count*2); + name = (char*)realloc(name, attrib_name_count); + name_max_size = attrib_name_count; + } + + if (data_max_size < attrib_length) + { + attrib_data = (BYTE*)realloc(attrib_data, attrib_length); + data_max_size = attrib_length; + } + + HeaderInfo->GetAttributeByIndex(i, &StreamNumber, attrib_name, &attrib_name_count, + &attrib_type, attrib_data, &attrib_length); + + WideCharToMultiByte(CP_ACP, 0, attrib_name, attrib_name_count, name, attrib_name_count, NULL, NULL); + + switch (attrib_type) + { + case WMT_TYPE_BOOL: + { + DWORD* ddata = (DWORD*)attrib_data; + if (*ddata == 0) + continue; + } + case WMT_TYPE_DWORD: + data_type = IM_INT; + data_count = attrib_length/4; + break; + case WMT_TYPE_STRING: + data_type = IM_BYTE; + data_count = attrib_length/2; + { + WCHAR* wdata = (WCHAR*)attrib_data; + CHAR* sdata = (CHAR*)attrib_data; + for (int j = 0; j < data_count; j++) + { + CHAR cvalue; + WideCharToMultiByte(CP_ACP, 0, &wdata[j], 1, &cvalue, 1, NULL, NULL); + sdata[j] = cvalue; + } + } + break; + case WMT_TYPE_BINARY: + data_type = IM_BYTE; + data_count = attrib_length; + break; + case WMT_TYPE_QWORD: + { + data_type = IM_INT; + data_count = attrib_length/8; + // convert to int in-place + QWORD* qdata = (QWORD*)attrib_data; + DWORD* ddata = (DWORD*)attrib_data; + for (int j = 0; j < data_count; j++) + { + ddata[j] = (DWORD)qdata[j]; + } + } + break; + case WMT_TYPE_WORD: + data_type = IM_USHORT; + data_count = attrib_length/2; + break; + default: + continue; + } + + attrib_table->Set(name, data_type, data_count, attrib_data); + } + + if (name) free(name); + if (attrib_name) free(attrib_name); + if (attrib_data) free(attrib_data); +} + +static int iAttribSet(void* user_data, int index, const char* name, int data_type, int data_count, const void* data) +{ + (void)index; + WORD StreamNumber = 0; + IWMHeaderInfo* HeaderInfo = (IWMHeaderInfo*)user_data; + + WCHAR wName[50]; + WMT_ATTR_DATATYPE Type; + BYTE* Value = NULL; + WORD ValueSize = 0; + + MultiByteToWideChar(CP_ACP, 0, name, -1, wName, 50); + + switch(data_type) + { + case IM_BYTE: + if (imStrCheck(data, data_count)) + Type = WMT_TYPE_STRING; + else + Type = WMT_TYPE_BINARY; + break; + case IM_USHORT: + Type = WMT_TYPE_WORD; + break; + case IM_INT: + Type = WMT_TYPE_DWORD; + break; + default: + return 1; + } + + switch (Type) + { + case WMT_TYPE_BOOL: + case WMT_TYPE_DWORD: + ValueSize = (WORD)(data_count*4); + break; + case WMT_TYPE_STRING: + ValueSize = (WORD)(data_count*2); + Value = (BYTE*)malloc(ValueSize); + MultiByteToWideChar(CP_ACP, 0, (char*)data, data_count, (WCHAR*)Value, data_count); + break; + case WMT_TYPE_BINARY: + ValueSize = (WORD)data_count; + break; + case WMT_TYPE_QWORD: + { + ValueSize = (WORD)(data_count*8); + Value = (BYTE*)malloc(ValueSize); + + QWORD* qdata = (QWORD*)Value; + int* idata = (int*)data; + for (int j = 0; j < data_count; j++) + { + qdata[j] = (QWORD)idata[j]; + } + } + break; + case WMT_TYPE_WORD: + ValueSize = (WORD)(data_count*2); + break; + } + + if (Value) + { + HeaderInfo->SetAttribute(StreamNumber, wName, Type, + Value, ValueSize); + free(Value); + } + else + HeaderInfo->SetAttribute(StreamNumber, wName, Type, + (BYTE*)data, ValueSize); + return 1; +} + +void imFileFormatWMV::iWriteAttrib(imAttribTable* attrib_table) +{ + attrib_table->ForEach((void*)HeaderInfo, iAttribSet); +} + +void imFileFormatWMV::CalcFPS() +{ + LONGLONG AvgTimePerFrame = 0; + + if (MediaType->formattype == WMFORMAT_VideoInfo) + { + WMVIDEOINFOHEADER* info_header = (WMVIDEOINFOHEADER*)MediaType->pbFormat; + bmiHeader = &info_header->bmiHeader; + AvgTimePerFrame = info_header->AvgTimePerFrame; + } + else if (MediaType->formattype == WMFORMAT_MPEG2Video) + { + WMVIDEOINFOHEADER2* info_header = (WMVIDEOINFOHEADER2*)MediaType->pbFormat; + bmiHeader = &info_header->bmiHeader; + AvgTimePerFrame = info_header->AvgTimePerFrame; + } + + WMT_ATTR_DATATYPE attrib_type; + WORD attrib_length; + + DWORD frame_rate = 0; + attrib_length = 4; + HeaderInfo->GetAttributeByName(&stream_number, g_wszWMVideoFrameRate, // V9 Only + &attrib_type, (BYTE*)&frame_rate, &attrib_length); + + fps = (float)frame_rate; + if (frame_rate == 0) + { + if (AvgTimePerFrame == 0) + { + fps = 15; // default value + } + else + { + fps = 10000000.0f / (float)AvgTimePerFrame; + + int ifps = (int)(fps * 100); + if (ifps == 2997 || ifps == 2996 || ifps == 2998) + fps = (30.0f * 1000.0f) / 1001.0f; + else if (ifps == 2397 || ifps == 2396 || ifps == 2398) + fps = (24.0f * 1000.0f) / 1001.0f; + else if (ifps == 2400) + fps = 24.0f; + else if (ifps == 3000) + fps = 30.0f; + } + } +} + +void imFileFormatWMV::SetOutputProps() +{ + DWORD output_number; + Reader->GetOutputNumberForStream(stream_number, &output_number); + + DWORD format_count; + Reader->GetOutputFormatCount(output_number, &format_count); + + for(DWORD f = 0; f < format_count; f++) + { + IWMOutputMediaProps* Props; + Reader->GetOutputFormat(output_number, f, &Props); + + DWORD pcbType; + Props->GetMediaType(NULL, &pcbType); + WM_MEDIA_TYPE* mt = (WM_MEDIA_TYPE*)malloc(pcbType); + Props->GetMediaType(mt, &pcbType); + + if (mt->subtype == WMMEDIASUBTYPE_RGB24 || + mt->subtype == WMMEDIASUBTYPE_RGB8) + { + Reader->SetOutputProps(output_number, Props); + Props->Release(); + free(mt); + return; + } + + Props->Release(); + free(mt); + } +} + +int imFileFormatWMV::SetInputProps() +{ + DWORD input_count; + Writer->GetInputCount(&input_count); + + GUID guidInputType; + IWMInputMediaProps* Props = NULL; + + input_number = (DWORD)-1; + for(DWORD i = 0; i < input_count; i++) + { + Writer->GetInputProps(i, &Props); + + Props->GetType(&guidInputType); + + if(guidInputType == WMMEDIATYPE_Video) + { + input_number = i; + break; + } + + Props->Release(); + } + + if (input_number == (DWORD)-1) + return 0; + + DWORD cbVideoInfo = sizeof(WMVIDEOINFOHEADER) - sizeof(BITMAPINFOHEADER) + this->BitmapInfoSize; + WMVIDEOINFOHEADER* pVideoInfo = (WMVIDEOINFOHEADER*)new BYTE[cbVideoInfo]; + + pVideoInfo->rcSource.left = 0; + pVideoInfo->rcSource.top = 0; + pVideoInfo->rcSource.bottom = this->bmiHeader->biHeight; + pVideoInfo->rcSource.right = this->bmiHeader->biWidth; + pVideoInfo->rcTarget = pVideoInfo->rcSource; + pVideoInfo->dwBitRate = (DWORD)(this->BitmapDataSize * fps); + pVideoInfo->dwBitErrorRate = 0; + pVideoInfo->AvgTimePerFrame = (LONGLONG)(10000000.0f / fps); + + CopyMemory(&(pVideoInfo->bmiHeader), this->bmiHeader, BitmapInfoSize); + + WM_MEDIA_TYPE mt; + mt.majortype = WMMEDIATYPE_Video; + mt.bFixedSizeSamples = TRUE; + mt.bTemporalCompression = FALSE; + mt.lSampleSize = BitmapDataSize; + mt.formattype = WMFORMAT_VideoInfo; + mt.pUnk = NULL; + mt.cbFormat = cbVideoInfo; + mt.pbFormat = (BYTE*)pVideoInfo; + + switch (this->bmiHeader->biBitCount) + { + case 32: + mt.subtype = WMMEDIASUBTYPE_RGB32; + break; + case 24: + mt.subtype = WMMEDIASUBTYPE_RGB24; + break; + case 8: + mt.subtype = WMMEDIASUBTYPE_RGB8; + break; + } + + Props->SetMediaType(&mt); + + HRESULT hr = Writer->SetInputProps(input_number, Props); + Props->Release(); + free(pVideoInfo); + + if (FAILED(hr)) + return 0; + + return 1; +} + +int imFileFormatWMV::SetProfile() +{ + HRESULT hr; + + IWMProfileManager* ProfileManager = NULL; + WMCreateProfileManager(&ProfileManager); + + IWMProfile* Profile = NULL; + hr = ProfileManager->CreateEmptyProfile(WMT_VER_9_0, &Profile); + if (FAILED(hr)) + { + ProfileManager->Release(); + return 0; + } + + if (imStrEqual(this->compression, "NONE")) + { + hr = iAddUncompressedVideoStream(Profile, + this->bmiHeader, + this->BitmapInfoSize, this->BitmapDataSize, this->fps); + } + else + { + DWORD dwBitRate = 2400*1000; + const void* attrib_data = AttribTable()->Get("DataRate"); + if (attrib_data) + dwBitRate = (*(int*)attrib_data) * 1000; + + DWORD dwQuality = 50; + attrib_data = AttribTable()->Get("WMFQuality"); + if (attrib_data) + dwQuality = *(int*)attrib_data; + + DWORD dwSecPerKey = 5000; + attrib_data = AttribTable()->Get("MaxKeyFrameTime"); + if (attrib_data) + dwSecPerKey = *(int*)attrib_data; + + BOOL fIsVBR = FALSE; // CBR is the default + attrib_data = AttribTable()->Get("VBR"); + if (attrib_data) + fIsVBR = *(int*)attrib_data; + + GUID subtype = iWMFCompFindSubType(this->compression); + if (subtype == WMMEDIASUBTYPE_Base) + { + Profile->Release(); + ProfileManager->Release(); + return 0; + } + + hr = iAddCompressedVideoStream(ProfileManager, Profile, subtype, + this->bmiHeader, this->fps, + fIsVBR, dwBitRate, dwQuality, dwSecPerKey); + } + + hr = Writer->SetProfile(Profile); + Profile->Release(); + ProfileManager->Release(); + + if (FAILED(hr)) + return 0; + + return 1; +} + +int imFileFormatWMV::ReadImageInfo(int index) +{ + if (this->seekable && this->current_frame != index) + { + HRESULT hr = Reader->SetRangeByFrame(stream_number, index, 0); + this->current_frame = index; + + if (hr == NS_E_INVALID_REQUEST) + { + QWORD start_time = (QWORD)(index * (10000000.0f / fps)); + hr = Reader->SetRange(start_time, 0); + } + + if (hr != S_OK) + return IM_ERR_ACCESS; + } + + if (this->bmiHeader != NULL) + return IM_ERR_NONE; + + imAttribTable* attrib_table = AttribTable(); + + /* must clear the attribute list, because it can have multiple images and + has many attributes that may exists only for specific images. */ + attrib_table->RemoveAll(); + imFileSetBaseAttributes(this); + + if (MediaType->formattype == WMFORMAT_VideoInfo) + { + WMVIDEOINFOHEADER* info_header = (WMVIDEOINFOHEADER*)MediaType->pbFormat; + bmiHeader = &info_header->bmiHeader; + + if (info_header->dwBitRate) + { + int data_rate = info_header->dwBitRate/1000; + attrib_table->Set("DataRate", IM_INT, 1, &data_rate); + } + } + else if (MediaType->formattype == WMFORMAT_MPEG2Video) + { + WMVIDEOINFOHEADER2* info_header = (WMVIDEOINFOHEADER2*)MediaType->pbFormat; + bmiHeader = &info_header->bmiHeader; + + if (info_header->dwBitRate) + { + int data_rate = info_header->dwBitRate/1000; + attrib_table->Set("DataRate", IM_INT, 1, &data_rate); + } + + if (info_header->dwInterlaceFlags) + { + int int_value = 1; + attrib_table->Set("Interlaced", IM_INT, 1, &int_value); + + if (info_header->dwInterlaceFlags & AMINTERLACE_1FieldPerSample) + int_value = 1; + else + int_value = 2; + + attrib_table->Set("FieldsPerSample", IM_INT, 1, &int_value); + + if (info_header->dwInterlaceFlags & AMINTERLACE_Field1First) + int_value = 1; + else + int_value = 2; + + attrib_table->Set("FirstField", IM_INT, 1, &int_value); + + // OBS: The top field in PAL is field 1, and the top field in NTSC is field 2 + } + + if (info_header->dwPictAspectRatioX) + attrib_table->Set("XAspectRatio", IM_INT, 1, &info_header->dwPictAspectRatioX); + if (info_header->dwPictAspectRatioY) + attrib_table->Set("YAspectRatio", IM_INT, 1, &info_header->dwPictAspectRatioY); + } + else + return IM_ERR_DATA; + + attrib_table->Set("FPS", IM_FLOAT, 1, &fps); + + int top_down = 0; + if (bmiHeader->biHeight < 0) + top_down = 1; + + this->width = bmiHeader->biWidth; + this->height = top_down? -bmiHeader->biHeight: bmiHeader->biHeight; + + int bpp = bmiHeader->biBitCount; + + this->file_data_type = IM_BYTE; + + if (bpp > 8) + { + this->file_color_mode = IM_RGB; + this->file_color_mode |= IM_PACKED; + } + else + { + this->palette_count = 1 << bpp; + this->file_color_mode = IM_MAP; + } + + if (bpp < 8) + this->convert_bpp = bpp; + + if (bpp == 32) + this->file_color_mode |= IM_ALPHA; + + if (top_down) + this->file_color_mode |= IM_TOPDOWN; + + if (bpp <= 8) + { + /* updates the palette_count based on the number of colors used */ + if (bmiHeader->biClrUsed != 0 && + (int)bmiHeader->biClrUsed < this->palette_count) + this->palette_count = bmiHeader->biClrUsed; + + ReadPalette((unsigned char*)(bmiHeader + 1)); + } + + this->line_buffer_extra = 4; // room enough for padding + + iReadAttrib(attrib_table); + + return IM_ERR_NONE; +} + +int imFileFormatWMV::WriteImageInfo() +{ + if (this->bmiHeader) + { + if (this->bmiHeader->biWidth != width || this->bmiHeader->biHeight != height || + imColorModeSpace(file_color_mode) != imColorModeSpace(user_color_mode)) + return IM_ERR_DATA; + + return IM_ERR_NONE; // parameters can be set only once + } + + // force bottom up orientation + this->file_data_type = IM_BYTE; + this->file_color_mode = imColorModeSpace(this->user_color_mode); + + int bpp; + if (this->file_color_mode == IM_RGB) + { + this->file_color_mode |= IM_PACKED; + bpp = 24; + + if (imColorModeHasAlpha(this->user_color_mode)) + { + this->file_color_mode |= IM_ALPHA; + bpp = 32; + + this->rmask = 0x00FF0000; + this->roff = 16; + + this->gmask = 0x0000FF00; + this->goff = 8; + + this->bmask = 0x000000FF; + this->boff = 0; + } + } + else + bpp = 8; + + this->line_buffer_extra = 4; // room enough for padding + + imAttribTable* attrib_table = AttribTable(); + + const void* attrib_data = attrib_table->Get("FPS"); + if (attrib_data) + fps = *(float*)attrib_data; + else + fps = 15; + + this->BitmapDataSize = this->height * imFileLineSizeAligned(this->width, bpp, 4); + + DWORD biClrUsed = bpp > 8? 0: this->palette_count; + this->BitmapInfoSize = sizeof(BITMAPINFOHEADER) + biClrUsed * sizeof(RGBQUAD); + + this->bmiHeader = (BITMAPINFOHEADER*)malloc(this->BitmapInfoSize); + this->bmiHeader->biSize = sizeof(BITMAPINFOHEADER); + this->bmiHeader->biWidth = this->width; + this->bmiHeader->biHeight = this->height; + this->bmiHeader->biPlanes = 1; + this->bmiHeader->biBitCount = (WORD)bpp; + this->bmiHeader->biCompression = BI_RGB; + this->bmiHeader->biSizeImage = this->BitmapDataSize; + this->bmiHeader->biXPelsPerMeter = 0; + this->bmiHeader->biYPelsPerMeter = 0; + this->bmiHeader->biClrUsed = biClrUsed; + this->bmiHeader->biClrImportant = 0; + + if (this->bmiHeader->biBitCount <= 8) + WritePalette((unsigned char*)(this->bmiHeader + 1)); + + if (!SetProfile()) + return IM_ERR_COMPRESS; + + if (!SetInputProps()) + return IM_ERR_ACCESS; + + HRESULT hr = Writer->SetOutputFilename(wfile_name); + if(FAILED(hr)) + return IM_ERR_ACCESS; + + iWriteAttrib(attrib_table); + + hr = Writer->BeginWriting(); + if(FAILED(hr)) + return IM_ERR_ACCESS; + + return IM_ERR_NONE; +} + +void imFileFormatWMV::ReadPalette(unsigned char* bmp_colors) +{ + /* convert the color map to the IM format */ + for (int c = 0; c < this->palette_count; c++) + { + int i = c * 4; + this->palette[c] = imColorEncode(bmp_colors[i + 2], + bmp_colors[i + 1], + bmp_colors[i]); + } +} + +void imFileFormatWMV::WritePalette(unsigned char* bmp_colors) +{ + /* convert the color map to the IM format */ + for (int c = 0; c < this->palette_count; c++) + { + int i = c * 4; + imColorDecode(&bmp_colors[i + 2], &bmp_colors[i + 1], &bmp_colors[i], this->palette[c]); + bmp_colors[i + 3] = 0; + } +} + +void imFileFormatWMV::InitMasks(imDib* dib) +{ + if (dib->bmih->biCompression == BI_BITFIELDS) + { + unsigned int Mask; + unsigned int *PalMask = (unsigned int*)dib->bmic; + + this->roff = 0; + this->rmask = Mask = PalMask[0]; + while (!(Mask & 0x01) && (Mask != 0)) + {Mask >>= 1; this->roff++;} + + this->goff = 0; + this->gmask = Mask = PalMask[1]; + while (!(Mask & 0x01) && (Mask != 0)) + {Mask >>= 1; this->goff++;} + + this->boff = 0; + this->bmask = Mask = PalMask[2]; + while (!(Mask & 0x01) && (Mask != 0)) + {Mask >>= 1; this->boff++;} + } + else + { + if (dib->bmih->biBitCount == 16) + { + this->rmask = 0x7C00; + this->roff = 10; + + this->gmask = 0x03E0; + this->goff = 5; + + this->bmask = 0x001F; + this->boff = 0; + } + else + { + this->rmask = 0x00FF0000; + this->roff = 16; + + this->gmask = 0x0000FF00; + this->goff = 8; + + this->bmask = 0x000000FF; + this->boff = 0; + } + } +} + +void imFileFormatWMV::FixRGB(int bpp) +{ + int x; + + switch (bpp) + { + case 16: + { + /* inverts the WORD values if not intel */ + if (imBinCPUByteOrder() == IM_BIGENDIAN) + imBinSwapBytes2(this->line_buffer, this->width); + + imushort* word_data = (imushort*)this->line_buffer; + imbyte* byte_data = (imbyte*)this->line_buffer; + + // from end to start + for (x = this->width-1; x >= 0; x--) + { + imushort word_value = word_data[x]; + int c = x*3; + byte_data[c] = (imbyte)((((rmask & word_value) >> roff) * 255) / (rmask >> roff)); + byte_data[c+1] = (imbyte)((((gmask & word_value) >> goff) * 255) / (gmask >> goff)); + byte_data[c+2] = (imbyte)((((bmask & word_value) >> boff) * 255) / (bmask >> boff)); + } + } + break; + case 32: + { + unsigned int* dword_data = (unsigned int*)this->line_buffer; + imbyte* byte_data = (imbyte*)this->line_buffer; + + for (x = 0; x < this->width; x++) + { + unsigned int dword_value = dword_data[x]; + int c = x*3; + byte_data[c] = (imbyte)((rmask & dword_value) >> roff); + byte_data[c+1] = (imbyte)((gmask & dword_value) >> goff); + byte_data[c+2] = (imbyte)((bmask & dword_value) >> boff); + byte_data[c+3] = (imbyte)((0xFF000000 & dword_value) >> 24); + } + } + break; + default: // 24 + { + imbyte* byte_data = (imbyte*)this->line_buffer; + for (x = 0; x < this->width; x++) + { + int c = x*3; + imbyte temp = byte_data[c]; // swap R and B + byte_data[c] = byte_data[c+2]; + byte_data[c+2] = temp; + } + } + break; + } +} + +int imFileFormatWMV::ReadImageData(void* data) +{ + imCounterTotal(this->counter, this->height, "Reading WMV Frame..."); + + INSSBuffer* pSample = NULL; + + { + QWORD cnsSampleTime = 0; // All will be ignored + QWORD cnsDuration = 0; + DWORD dwFlags = 0; + WORD wStreamNum = 0; + DWORD dwOutputNum = 0; + HRESULT hr; + + hr = Reader->GetNextSample(stream_number, &pSample, &cnsSampleTime, + &cnsDuration, &dwFlags, + &dwOutputNum, &wStreamNum); + + if (FAILED(hr)) + return IM_ERR_ACCESS; + } + + imbyte* dib_bits = NULL; + pSample->GetBuffer(&dib_bits); + if (!dib_bits) + { + pSample->Release(); + return IM_ERR_MEM; + } + + imDib* dib = imDibCreateReference((imbyte*)this->bmiHeader, dib_bits); + + if (dib->bmih->biBitCount == 16 || dib->bmih->biBitCount == 32) + InitMasks(dib); + else if (dib->bmih->biBitCount <= 8) + { + this->palette_count = dib->palette_count; + ReadPalette((unsigned char*)dib->bmic); + } + + for (int row = 0; row < this->height; row++) + { + CopyMemory(this->line_buffer, dib_bits, dib->line_size); + dib_bits += dib->line_size; + + if (dib->bmih->biBitCount > 8) + FixRGB(dib->bmih->biBitCount); + + imFileLineBufferRead(this, data, row, 0); + + if (!imCounterInc(this->counter)) + { + imDibDestroy(dib); + dib = NULL; + pSample->Release(); + return IM_ERR_COUNTER; + } + } + + imDibDestroy(dib); + pSample->Release(); + this->current_frame++; + + return IM_ERR_NONE; +} + +int imFileFormatWMV::WriteImageData(void* data) +{ + imCounterTotal(this->counter, this->height, "Writing WMV Frame..."); + + INSSBuffer* pSample = NULL; + Writer->AllocateSample(BitmapDataSize, &pSample); + + imbyte* dib_bits = NULL; + if (pSample) pSample->GetBuffer(&dib_bits); + if (!dib_bits || !pSample) + { + if (pSample) pSample->Release(); + return IM_ERR_MEM; + } + + imDib* dib = imDibCreateReference((imbyte*)this->bmiHeader, dib_bits); + if (dib->bmih->biBitCount <= 8) + WritePalette((unsigned char*)dib->bmic); + + for (int row = 0; row < this->height; row++) + { + imFileLineBufferWrite(this, data, row, 0); + + if (dib->bmih->biBitCount > 8) + FixRGB(dib->bmih->biBitCount); + + CopyMemory(dib_bits, this->line_buffer, dib->line_size); + dib_bits += dib->line_size; + + if (!imCounterInc(this->counter)) + return IM_ERR_COUNTER; + } + + QWORD VideoTime = (QWORD)(this->image_count * (10000000.0f / fps)); + + HRESULT hr = Writer->WriteSample(input_number, + VideoTime, + 0, + pSample); + if (hr != 0) + return IM_ERR_ACCESS; + + imDibDestroy(dib); + pSample->Release(); + this->image_count++; + + return IM_ERR_NONE; +} + +int imFormatWMV::CanWrite(const char* compression, int color_mode, int data_type) const +{ + (void)compression; + + int color_space = imColorModeSpace(color_mode); + + if (color_space == IM_YCBCR || color_space == IM_LAB || + color_space == IM_LUV || color_space == IM_XYZ || + color_space == IM_CMYK) + return IM_ERR_DATA; + + if (data_type != IM_BYTE) + return IM_ERR_DATA; + + return IM_ERR_NONE; +} diff --git a/im/src/im_image.cpp b/im/src/im_image.cpp new file mode 100755 index 0000000..1fb993d --- /dev/null +++ b/im/src/im_image.cpp @@ -0,0 +1,695 @@ +/** \file + * \brief Image Manipulation + * + * See Copyright Notice in im_lib.h + * $Id: im_image.cpp,v 1.4 2009/08/13 22:34:25 scuri Exp $ + */ + +#include +#include +#include +#include + +#include "im.h" +#include "im_image.h" +#include "im_util.h" +#include "im_attrib.h" +#include "im_file.h" + + +int imImageCheckFormat(int color_mode, int data_type) +{ + if ((imColorModeSpace(color_mode) == IM_MAP || imColorModeSpace(color_mode) == IM_BINARY) && + (data_type != IM_BYTE)) + return 0; + + return 1; +} + +int imImagePixelOffset(int is_packed, int width, int height, int depth, int col, int row, int plane) +{ + if (is_packed) + return row*width*depth + col*depth + plane; + else + return plane*width*height + row*width + col; +} + +int imImageDataSize(int width, int height, int color_mode, int data_type) +{ + return width * height * imColorModeDepth(color_mode) * imDataTypeSize(data_type); +} + +int imImageLineCount(int width, int color_mode) +{ + if (imColorModeIsPacked(color_mode)) + return width*imColorModeDepth(color_mode); + else + return width; +} + +int imImageLineSize(int width, int color_mode, int data_type) +{ + return imImageLineCount(width, color_mode) * imDataTypeSize(data_type); +} + +static void iImageInit(imImage* image, int width, int height, int color_space, int data_type, int has_alpha) +{ + assert(width>0); + assert(height>0); + assert(color_space >= IM_RGB && color_space <= IM_XYZ); + assert(data_type >= IM_BYTE && data_type <= IM_CFLOAT); + + image->width = width; + image->height = height; + image->color_space = color_space; + image->data_type = data_type; + image->has_alpha = has_alpha; + + image->depth = imColorModeDepth(color_space); + image->line_size = image->width * imDataTypeSize(data_type); + image->plane_size = image->line_size * image->height; + image->size = image->plane_size * image->depth; + image->count = image->width * image->height; + + int depth = image->depth+1; // add room for an alpha plane pointer, even if does not have alpha now. + + if (image->data) + { + /* if reallocating, preserve the data buffer */ + void* data0 = image->data[0]; + + free(image->data); + image->data = (void**)malloc(depth * sizeof(void*)); + + image->data[0] = data0; + } + else + image->data = (void**)malloc(depth * sizeof(void*)); +} + +imImage* imImageInit(int width, int height, int color_space, int data_type, void* data_buffer, long* palette, int palette_count) +{ + if (!imImageCheckFormat(color_space, data_type)) + return NULL; + + imImage* image = (imImage*)malloc(sizeof(imImage)); + image->data = 0; + + iImageInit(image, width, height, color_space, data_type, 0); + + if (data_buffer) + { + for (int d = 0; d < image->depth; d++) + image->data[d] = (imbyte*)data_buffer + d*image->plane_size; + } + + if (imColorModeDepth(color_space) == 1) + { + image->palette = palette; + image->palette_count = palette_count; + } + else + { + image->palette = NULL; + image->palette_count = 0; + } + + image->attrib_table = new imAttribTable(599); + + return image; +} + +imImage* imImageCreate(int width, int height, int color_space, int data_type) +{ + imImage* image = imImageInit(width, height, color_space, data_type, NULL, NULL, 0); + if (!image) return NULL; + + /* palette is available to BINARY, MAP and GRAY */ + if (imColorModeDepth(color_space) == 1) + { + image->palette = (long*)malloc(256*sizeof(long)); + + if (image->color_space == IM_BINARY) + { + image->palette_count = 2; + image->palette[0] = imColorEncode(0, 0, 0); + image->palette[1] = imColorEncode(255, 255, 255); + } + else + { + image->palette_count = 256; + for (int i = 0; i < 256; i++) + image->palette[i] = imColorEncode((imbyte)i, (imbyte)i, (imbyte)i); + } + } + + /* allocate data buffer */ + image->data[0] = malloc(image->size); + if (!image->data[0]) + { + imImageDestroy(image); + return NULL; + } + + /* initialize data plane pointers */ + for (int d = 1; d < image->depth; d++) + image->data[d] = (imbyte*)(image->data[0]) + d*image->plane_size; + + imImageClear(image); + + return image; +} + +imImage* imImageCreateBased(const imImage* image, int width, int height, int color_space, int data_type) +{ + assert(image); + + if (width <= 0) width = image->width; + if (height <= 0) height = image->height; + if (color_space < 0) color_space = image->color_space; + if (data_type < 0) data_type = image->data_type; + + imImage* new_image = imImageCreate(width, height, color_space, data_type); + imImageCopyAttributes(image, new_image); + + if (image->has_alpha) + imImageAddAlpha(new_image); + + return new_image; +} + +void imImageAddAlpha(imImage* image) +{ + assert(image); + + if (image->has_alpha) + return; + + unsigned char* new_data = (unsigned char*)realloc(image->data[0], image->size+image->plane_size); + if (!new_data) + return; + + image->data[0] = new_data; + for (int d = 1; d < image->depth+1; d++) + image->data[d] = (imbyte*)(image->data[0]) + d*image->plane_size; + + memset(image->data[image->depth], 0, image->plane_size); + + image->has_alpha = IM_ALPHA; +} + +void imImageReshape(imImage* image, int width, int height) +{ + assert(image); + + int old_size = image->size, + old_width = width, + old_height = height; + + iImageInit(image, width, height, image->color_space, image->data_type, image->has_alpha); + + if (old_size < image->size) + { + void* data0 = realloc(image->data[0], image->has_alpha? image->size+image->plane_size: image->size); + if (!data0) // if failed restore the previous size + iImageInit(image, old_width, old_height, image->color_space, image->data_type, image->has_alpha); + else + image->data[0] = data0; + } + + /* initialize data plane pointers */ + int depth = image->has_alpha? image->depth+1: image->depth; + for (int d = 1; d < depth; d++) + image->data[d] = (imbyte*)image->data[0] + d*image->plane_size; +} + +void imImageDestroy(imImage* image) +{ + assert(image); + + imAttribTable* attrib_table = (imAttribTable*)image->attrib_table; + delete attrib_table; + + if (image->data[0]) + free(image->data[0]); + + if (image->palette) + free(image->palette); + + free(image->data); + + // This will help detect invalid image usage after destroy. + memset(image, 0, sizeof(imImage)); + + free(image); +} + +void imImageClear(imImage* image) +{ + assert(image); + + if ((image->color_space == IM_YCBCR || image->color_space == IM_LAB || image->color_space == IM_LUV) && + (image->data_type == IM_BYTE || image->data_type == IM_USHORT)) + { + memset(image->data[0], 0, image->plane_size); + + if (image->data_type == IM_BYTE) + { + imbyte* usdata = (imbyte*)image->data[1]; + for (int i = 0; i < 2*image->count; i++) + *usdata++ = 128; + } + else + { + imushort* usdata = (imushort*)image->data[1]; + for (int i = 0; i < 2*image->count; i++) + *usdata++ = 32768; + } + } + else + memset(image->data[0], 0, image->size); + + if (image->has_alpha) + memset(image->data[image->depth], 0, image->plane_size); +} + +int imImageIsBitmap(const imImage* image) +{ + assert(image); + return imColorModeIsBitmap(image->color_space, image->data_type); +} + +void imImageCopy(const imImage* src_image, imImage* dst_image) +{ + assert(src_image); + assert(dst_image); + + imImageCopyData(src_image, dst_image); + + if (dst_image != src_image) + imImageCopyAttributes(src_image, dst_image); +} + +void imImageCopyData(const imImage* src_image, imImage* dst_image) +{ + assert(src_image); + assert(dst_image); + assert(imImageMatch(src_image, dst_image)); + + if (dst_image != src_image) + { + memcpy(dst_image->data[0], src_image->data[0], (src_image->has_alpha && dst_image->has_alpha)? src_image->size+src_image->plane_size: src_image->size); + } +} + +imImage* imImageDuplicate(const imImage* image) +{ + assert(image); + + imImage* new_image = imImageCreate(image->width, image->height, image->color_space, image->data_type); + if (!new_image) + return NULL; + + if (image->has_alpha) + imImageAddAlpha(new_image); + + imImageCopy(image, new_image); + + return new_image; +} + +imImage* imImageClone(const imImage* image) +{ + assert(image); + + imImage* new_image = imImageCreate(image->width, image->height, image->color_space, image->data_type); + if (!new_image) + return NULL; + + if (image->has_alpha) + imImageAddAlpha(new_image); + + imImageCopyAttributes(image, new_image); + + return new_image; +} + +void imImageSetAttribute(const imImage* image, const char* attrib, int data_type, int count, const void* data) +{ + assert(image); + assert(attrib); + imAttribTable* attrib_table = (imAttribTable*)image->attrib_table; + if (data) + { + if (count == -1 && data_type == IM_BYTE) // Data is zero terminated like a string + count = strlen((char*)data)+1; + + attrib_table->Set(attrib, data_type, count, data); + } + else if (count == 0) + attrib_table->UnSet(attrib); + else + attrib_table->Set(attrib, data_type, count, NULL); +} + +const void* imImageGetAttribute(const imImage* image, const char* attrib, int *data_type, int *count) +{ + assert(image); + assert(attrib); + imAttribTable* attrib_table = (imAttribTable*)image->attrib_table; + return attrib_table->Get(attrib, data_type, count); +} + +static void iAttributeTableCopy(const void* src_attrib_table, void* dst_attrib_table) +{ + const imAttribTable* src_table = (const imAttribTable*)src_attrib_table; + imAttribTable* dst_table = (imAttribTable*)dst_attrib_table; + dst_table->CopyFrom(*src_table); +} + +void imImageCopyAttributes(const imImage* src_image, imImage* dst_image) +{ + assert(src_image); + assert(dst_image); + + if (src_image->palette && dst_image->palette && + src_image->color_space == dst_image->color_space) + { + memcpy(dst_image->palette, src_image->palette, 256*sizeof(long)); + dst_image->palette_count = src_image->palette_count; + } + + iAttributeTableCopy(src_image->attrib_table, dst_image->attrib_table); +} + +static int iAttribCB(void* user_data, int index, const char* name, int data_type, int count, const void* data) +{ + (void)data_type; + (void)data; + (void)count; + char** attrib = (char**)user_data; + attrib[index] = (char*)name; + return 1; +} + +void imImageGetAttributeList(const imImage* image, char** attrib, int *attrib_count) +{ + assert(image); + assert(attrib_count); + + imAttribTable* attrib_table = (imAttribTable*)image->attrib_table; + *attrib_count = attrib_table->Count(); + + if (attrib) attrib_table->ForEach((void*)attrib, iAttribCB); +} + +void imImageSetPalette(imImage* image, long* palette, int palette_count) +{ + assert(image); + + if (image->palette) + { + free(image->palette); + image->palette = palette; + image->palette_count = palette_count; + } +} + +int imImageMatchSize(const imImage* image1, const imImage* image2) +{ + assert(image1); + assert(image2); + + return ((image1->width == image2->width) && + (image1->height == image2->height)); +} + +int imImageMatchColor(const imImage* image1, const imImage* image2) +{ + assert(image1); + assert(image2); + + return (image1->data_type == image2->data_type && + image1->color_space == image2->color_space); +} + +int imImageMatchDataType(const imImage* image1, const imImage* image2) +{ + assert(image1); + assert(image2); + + return (image1->data_type == image2->data_type && + image1->width == image2->width && + image1->height == image2->height); +} + +int imImageMatchColorSpace(const imImage* image1, const imImage* image2) +{ + assert(image1); + assert(image2); + + return (image1->width == image2->width && + image1->height == image2->height && + image1->color_space == image2->color_space); +} + +int imImageMatch(const imImage* image1, const imImage* image2) +{ + assert(image1); + assert(image2); + + return (image1->data_type == image2->data_type && + image1->width == image2->width && + image1->height == image2->height && + image1->color_space == image2->color_space); +} + +void imImageSetBinary(imImage* image) +{ + assert(image); + + if (image->palette) + { + image->color_space = IM_BINARY; + image->palette_count = 2; + image->palette[0] = imColorEncode(0, 0, 0); + image->palette[1] = imColorEncode(255, 255, 255); + } +} + +void imImageMakeBinary(imImage *image) +{ + assert(image); + + imbyte *map = (imbyte*)image->data[0]; + for(int i = 0; i < image->count; i++) + { + if (*map) + *map = 1; + map++; + } +} + +void imImageMakeGray(imImage *image) +{ + assert(image); + + imbyte *map = (imbyte*)image->data[0]; + for(int i = 0; i < image->count; i++) + { + if (*map) + *map = 255; + map++; + } +} + +static void iLoadImageData(imFile* ifile, imImage* image, int *error, int bitmap) +{ + iAttributeTableCopy(ifile->attrib_table, image->attrib_table); + *error = imFileReadImageData(ifile, image->data[0], bitmap, image->has_alpha); + if (image->color_space == IM_MAP) + imFileGetPalette(ifile, image->palette, &image->palette_count); +} + +imImage* imFileLoadImage(imFile* ifile, int index, int *error) +{ + assert(ifile); + + int width, height, color_mode, data_type; + *error = imFileReadImageInfo(ifile, index, &width, &height, &color_mode, &data_type); + if (*error) return NULL; + + imImage* image = imImageCreate(width, height, imColorModeSpace(color_mode), data_type); + if (!image) + { + *error = IM_ERR_MEM; + return NULL; + } + + if (imColorModeHasAlpha(color_mode)) + imImageAddAlpha(image); + + iLoadImageData(ifile, image, error, 0); + + return image; +} + +void imFileLoadImageFrame(imFile* ifile, int index, imImage* image, int *error) +{ + assert(ifile); + + int width, height, color_mode, data_type; + *error = imFileReadImageInfo(ifile, index, &width, &height, &color_mode, &data_type); + if (*error) return; + + // check if we can reuse the data + if (image->width != width || + image->height != height || + image->depth != imColorModeDepth(imColorModeSpace(color_mode)) || + image->has_alpha != imColorModeHasAlpha(color_mode) || + image->data_type != data_type) + { + *error = IM_ERR_DATA; + return; + } + + image->color_space = imColorModeSpace(color_mode); + iLoadImageData(ifile, image, error, 0); +} + +imImage* imFileLoadBitmap(imFile* ifile, int index, int *error) +{ + assert(ifile); + + int width, height, color_mode, data_type; + *error = imFileReadImageInfo(ifile, index, &width, &height, &color_mode, &data_type); + if (*error) return NULL; + + imImage* image = imImageCreate(width, height, imColorModeToBitmap(color_mode), IM_BYTE); + if (!image) + { + *error = IM_ERR_MEM; + return NULL; + } + + if (imColorModeHasAlpha(color_mode)) + imImageAddAlpha(image); + + iLoadImageData(ifile, image, error, 1); + + return image; +} + +void imFileLoadBitmapFrame(imFile* ifile, int index, imImage* image, int *error) +{ + assert(ifile); + + int width, height, color_mode, data_type; + *error = imFileReadImageInfo(ifile, index, &width, &height, &color_mode, &data_type); + if (*error) return; + + // check if we can reuse the data + if (image->width != width || + image->height != height || + image->depth != imColorModeDepth(imColorModeToBitmap(color_mode)) || + image->has_alpha != imColorModeHasAlpha(color_mode) || + image->data_type != IM_BYTE) + { + *error = IM_ERR_DATA; + return; + } + + image->color_space = imColorModeToBitmap(color_mode); + iLoadImageData(ifile, image, error, 1); +} + +imImage* imFileLoadImageRegion(imFile* ifile, int index, int bitmap, int *error, + int xmin, int xmax, int ymin, int ymax, int width, int height) +{ + assert(ifile); + + int color_mode, data_type; + *error = imFileReadImageInfo(ifile, index, NULL, NULL, &color_mode, &data_type); + if (*error) return NULL; + + imImage* image = imImageCreate(width, height, + bitmap? imColorModeToBitmap(color_mode): imColorModeSpace(color_mode), + bitmap? IM_BYTE: data_type); + if (!image) + { + *error = IM_ERR_MEM; + return NULL; + } + + if (imColorModeHasAlpha(color_mode)) + imImageAddAlpha(image); + + imFileSetAttribute(ifile, "ViewXmin", IM_INT, 1, &xmin); + imFileSetAttribute(ifile, "ViewXmax", IM_INT, 1, &xmax); + imFileSetAttribute(ifile, "ViewYmin", IM_INT, 1, &ymin); + imFileSetAttribute(ifile, "ViewYmax", IM_INT, 1, &ymax); + imFileSetAttribute(ifile, "ViewWidth", IM_INT, 1, &width); + imFileSetAttribute(ifile, "ViewHeight", IM_INT, 1, &height); + + iLoadImageData(ifile, image, error, bitmap); + + return image; +} + +int imFileSaveImage(imFile* ifile, const imImage* image) +{ + assert(ifile); + assert(image); + + if (image->color_space == IM_MAP) + imFileSetPalette(ifile, image->palette, image->palette_count); + + iAttributeTableCopy(image->attrib_table, ifile->attrib_table); + + int color_mode = image->color_space; + if (image->has_alpha) + color_mode |= IM_ALPHA; + + int error = imFileWriteImageInfo(ifile, image->width, image->height, color_mode, image->data_type); + if (error) return error; + + return imFileWriteImageData(ifile, image->data[0]); +} + +imImage* imFileImageLoad(const char* file_name, int index, int *error) +{ + imFile* ifile = imFileOpen(file_name, error); + if (!ifile) return NULL; + imImage* image = imFileLoadImage(ifile, index, error); + imFileClose(ifile); + return image; +} + +imImage* imFileImageLoadBitmap(const char* file_name, int index, int *error) +{ + imFile* ifile = imFileOpen(file_name, error); + if (!ifile) return NULL; + imImage* image = imFileLoadBitmap(ifile, index, error); + imFileClose(ifile); + return image; +} + +imImage* imFileImageLoadRegion(const char* file_name, int index, int bitmap, int *error, + int xmin, int xmax, int ymin, int ymax, int width, int height) +{ + imFile* ifile = imFileOpen(file_name, error); + if (!ifile) return NULL; + imImage* image = imFileLoadImageRegion(ifile, index, bitmap, error, xmin, xmax, ymin, ymax, width, height); + imFileClose(ifile); + return image; +} + +int imFileImageSave(const char* file_name, const char* format, const imImage* image) +{ + int error; + imFile* ifile = imFileNew(file_name, format, &error); + if (!ifile) return error; + error = imFileSaveImage(ifile, image); + imFileClose(ifile); + return error; +} diff --git a/im/src/im_lib.cpp b/im/src/im_lib.cpp new file mode 100755 index 0000000..05a71d8 --- /dev/null +++ b/im/src/im_lib.cpp @@ -0,0 +1,38 @@ +/** \file + * \brief Library Management + * + * See Copyright Notice in im_lib.h + * $Id: im_lib.cpp,v 1.5 2009/10/01 14:43:42 scuri Exp $ + */ + +#include +#include + +#include "im_lib.h" + +/* This appears only here to avoid changing the im_lib.h header for bug fixes */ +#define IM_VERSION_FIX "" +#define IM_VERSION_FIX_NUMBER 0 + +static char *iVersion = "TECVERID.str:IM:LIB:" IM_VERSION IM_VERSION_FIX; + +const char iIdent[] = + "$IM: " IM_VERSION IM_VERSION_FIX " " IM_COPYRIGHT " $\n" + "$URL: www.tecgraf.puc-rio.br/im $\n"; + +const char* imVersion(void) +{ + (void)iVersion; + (void)iIdent; + return IM_VERSION IM_VERSION_FIX; +} + +const char* imVersionDate(void) +{ + return IM_VERSION_DATE; +} + +int imVersionNumber(void) +{ + return IM_VERSION_NUMBER+IM_VERSION_FIX_NUMBER; +} diff --git a/im/src/im_lua3.c b/im/src/im_lua3.c new file mode 100755 index 0000000..1c85e59 --- /dev/null +++ b/im/src/im_lua3.c @@ -0,0 +1,1297 @@ +/** \file + * \brief LuaBinding for Lua 3 + * + * See Copyright Notice in im_lib.h + * $Id: im_lua3.c,v 1.1 2008/10/17 06:10:16 scuri Exp $ + */ + +#include +#include +#include + +#include + +#include "im.h" +#include "im_lib.h" + +#include +#include + +#include "imlua.h" + + +/***************************************************************************\ +* Globals. * +\***************************************************************************/ +static int color_tag; +static int imagergb_tag; +static int imagergba_tag; +static int palette_tag; +static int imagemap_tag; +static int channel_tag; + +static channel_t channel_info; + +#define IMLUA_VERSION "IMLua 1.2" +/***************************************************************************\ +* Creation and destruction functions. * +\***************************************************************************/ + +/***************************************************************************\ +* Creates a buffer for a RGB image. * +\***************************************************************************/ +static void imlua_createimagergb(void) +{ + lua_Object width, height; + long int width_i, height_i; + imagergb_t *imagergb_p; + + width = lua_getparam(1); + height = lua_getparam(2); + if (!(lua_isnumber(width) && lua_isnumber(height))) + lua_error("imCreateImageRGB: invalid dimensions parameter!"); + width_i = (long int) lua_getnumber(width); + height_i = (long int) lua_getnumber(height); + if (width_i < 1 || height_i < 1) + lua_error("imCreateImageRGB: image dimensions should be positive integers!"); + + if (lua_getparam(3) != LUA_NOOBJECT) + lua_error("imCreateImageRGB: too many parameters!"); + + imagergb_p = (imagergb_t *) malloc(sizeof(imagergb_t)); + if (!imagergb_p) { + lua_pushnil(); + return; + } + + imagergb_p->width = width_i; + imagergb_p->height = height_i; + imagergb_p->size = width_i*height_i; + imagergb_p->red = (unsigned char *) malloc(imagergb_p->size); + imagergb_p->green = (unsigned char *) malloc(imagergb_p->size); + imagergb_p->blue = (unsigned char *) malloc(imagergb_p->size); + + if (!(imagergb_p->red && imagergb_p->green && imagergb_p->blue)) { + if (imagergb_p->red) free(imagergb_p->red); + if (imagergb_p->green) free(imagergb_p->green); + if (imagergb_p->blue) free(imagergb_p->blue); + free(imagergb_p); + lua_pushnil(); + return; + } + + memset(imagergb_p->red, 255, imagergb_p->size); + memset(imagergb_p->green, 255, imagergb_p->size); + memset(imagergb_p->blue, 255, imagergb_p->size); + + lua_pushusertag((void *) imagergb_p, imagergb_tag); +} + +/***************************************************************************\ +* Frees a previously allocated imagergb. We don't free imagergb_p to avoid * +* problems if the user called killimagergb twice with the same object. The * +* structure will be freed by a userdata "gc" fallback in LUA 3.0. * +\***************************************************************************/ +static void imlua_killimagergb(void) +{ + lua_Object imagergb; + imagergb_t *imagergb_p; + + imagergb = lua_getparam(1); + if (imagergb == LUA_NOOBJECT) + lua_error("imKillImageRGB: imagergb parameter missing!"); + if (lua_isnil(imagergb)) + lua_error("imKillImageRGB: attempt to kill a NIL imagergb!"); + if (lua_tag(imagergb) != imagergb_tag) + lua_error("imKillImageRGB: invalid imagergb parameter!"); + imagergb_p = (imagergb_t *) lua_getuserdata(imagergb); + if (!(imagergb_p->red && imagergb_p->green && imagergb_p->blue)) + lua_error("imKillImageRGB: attempt to kill a killed imagergb!"); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("imKillImageRGB: too many parameters!"); + + free(imagergb_p->red); + free(imagergb_p->green); + free(imagergb_p->blue); + imagergb_p->red = NULL; + imagergb_p->green = NULL; + imagergb_p->blue = NULL; +} + +/***************************************************************************\ +* Creates a palette as a palette_tag usertag lua_Object. A palette can be * +* considered and treated as a color table. * +\***************************************************************************/ +static void imlua_createpalette(void) +{ + lua_Object size; + long int size_i; + palette_t *palette_p; + + size = lua_getparam(1); + if (!(lua_isnumber(size))) + lua_error("imCreatePalette: invalid palette parameter!"); + size_i = (long int) lua_getnumber(size); + if (size_i < 1) + lua_error("imCreatePalette: palette size should be a positive integer!"); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("imCreatePalette: too many parameters!"); + + palette_p = (palette_t *) malloc(sizeof(palette_t)); + if (!palette_p) { + lua_pushnil(); + return; + } + + palette_p->size = size_i; + palette_p->color = (long int *) malloc(palette_p->size * sizeof(long int)); + if (!palette_p->color) { + free(palette_p); + lua_pushnil(); + return; + } + + memset(palette_p->color, 255, palette_p->size * sizeof(long int)); + lua_pushusertag((void *) palette_p, palette_tag); +} + +/***************************************************************************\ +* Frees a previously allocated palette. We don't free palette_p to prevent * +* a problem if the user called killpalette twice with the same object. The * +* structure will be freed by a userdata "gc" fallback in LUA 3.0. * +\***************************************************************************/ +static void imlua_killpalette(void) +{ + lua_Object palette; + palette_t *palette_p; + + palette = lua_getparam(1); + if (palette == LUA_NOOBJECT) + lua_error("imKillPalette: palette parameter missing!"); + if (lua_isnil(palette)) + lua_error("imKillPalette: attempt to kill a NIL palette!"); + if (lua_tag(palette) != palette_tag) + lua_error("imKillPalette: invalid palette parameter!"); + palette_p = (palette_t *) lua_getuserdata(palette); + if (!palette_p->color) + lua_error("imKillPalette: attempt to kill a killed palette!"); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("imKillPalette: too many parameters!"); + + free(palette_p->color); + palette_p->color = NULL; +} + +/***************************************************************************\ +* Creates a imagemap as a imagemap_tag usertag lua_Object. * +\***************************************************************************/ +static void imlua_createimagemap(void) +{ + lua_Object width; + lua_Object height; + + long int width_i; + long int height_i; + imagemap_t *imagemap_p; + + width = lua_getparam(1); + height = lua_getparam(2); + if (!(lua_isnumber(width) && lua_isnumber(height))) + lua_error("imCreateImageMap: invalid dimensions parameter!"); + width_i = (long int) lua_getnumber(width); + height_i = (long int) lua_getnumber(height); + if (width_i < 1 || height_i < 1) + lua_error("imCreateImageMap: imagemap dimensions should be positive integers!"); + + if (lua_getparam(3) != LUA_NOOBJECT) + lua_error("imCreateImageMap: too many parameters!"); + + imagemap_p = (imagemap_t *) malloc(sizeof(imagemap_t)); + if (!imagemap_p) { + lua_pushnil(); + return; + } + + imagemap_p->size = width_i*height_i; + imagemap_p->width = width_i; + imagemap_p->height = height_i; + imagemap_p->index = (unsigned char *) malloc(imagemap_p->size); + if (!imagemap_p->index) { + free(imagemap_p); + lua_pushnil(); + return; + } + + memset(imagemap_p->index, 0, imagemap_p->size); + lua_pushusertag((void *) imagemap_p, imagemap_tag); +} + +/***************************************************************************\ +* Frees a previously allocated imagemap. We don't free imagemap_p to avoid * +* problems if the user called killimagemap twice with the same object. The * +* structure will be freed by a userdata "gc" fallback in LUA 3.0. * +\***************************************************************************/ +static void imlua_killimagemap(void) +{ + lua_Object imagemap; + imagemap_t *imagemap_p; + + imagemap = lua_getparam(1); + if (imagemap == LUA_NOOBJECT) + lua_error("imKillImageMap: imagemap parameter missing!"); + if (lua_isnil(imagemap)) + lua_error("imKillImageMap: attempt to kill a NIL imagemap!"); + if (lua_tag(imagemap) != imagemap_tag) + lua_error("imKillImageMap: invalid imagemap parameter!"); + imagemap_p = (imagemap_t *) lua_getuserdata(imagemap); + if (!imagemap_p->index) + lua_error("imKillImageMap: attempt to kill a killed imagemap!"); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("imKillImageMap: too many parameters!"); + + free(imagemap_p->index); + imagemap_p->index = NULL; +} + +/***************************************************************************\ +* IM API Functions. * +\***************************************************************************/ + +/***************************************************************************\ +* imFileFormat * +\***************************************************************************/ +static void imlua_fileformat(void) +{ + lua_Object file; + + char *file_s; + int format_i; + int compress_i; + + int err; + + file = lua_getparam(1); + if (!lua_isstring(file)) + lua_error("imFileFormat: invalid filename parameter!"); + file_s = (char *) lua_getstring(file); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("imFileFormat: too many parameters!"); + + err = imFileFormat(file_s, &format_i); + + compress_i = (format_i & IM_DEFAULT) ? 1 : 0; + format_i = format_i & 0xFF; + + /* if success, return the format */ + if (err == IM_ERR_NONE) { + lua_pushnumber( format_i); + lua_pushnumber( compress_i); + } + /* if failure, return nil */ + else { + lua_pushnil(); + lua_pushnil(); + } + + lua_pushnumber( err); +} + +/***************************************************************************\ +* imFileFormat * +\***************************************************************************/ +static void imlua_imageinfo(void) +{ + lua_Object file; + + char *file_s; + + int width, height, image_type, pal_size; + int err; + + file = lua_getparam(1); + if (!lua_isstring(file)) + lua_error("imFileFormat: invalid filename parameter!"); + file_s = (char *) lua_getstring(file); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("imFileFormat: too many parameters!"); + + err = imImageInfo(file_s, &width, &height, &image_type, &pal_size); + + /* if success, return the format */ + if (err == IM_ERR_NONE) { + lua_pushnumber( width); + lua_pushnumber( height); + lua_pushnumber( image_type); + lua_pushnumber( pal_size); + } + /* if failure, return nil */ + else { + lua_pushnil(); + lua_pushnil(); + lua_pushnil(); + lua_pushnil(); + } + + lua_pushnumber( err); +} + +/***************************************************************************\ +* imEncodeColor * +\***************************************************************************/ +static void imlua_encodecolor(void) +{ + lua_Object red, green, blue; + float red_f, green_f, blue_f; + unsigned char red_i, green_i, blue_i; + long int color_i; + + red = lua_getparam(1); + green = lua_getparam(2); + blue = lua_getparam(3); + + if (lua_getparam(4) != LUA_NOOBJECT) + lua_error("imEncodeColor: too many parameters!"); + + if (!(lua_isnumber(red) && lua_isnumber(green) && lua_isnumber(blue))) + lua_error("imEncodeColor: invalid color component parameter!"); + + red_f = (float)lua_getnumber(red); + green_f = (float)lua_getnumber(green); + blue_f = (float)lua_getnumber(blue); + + if (red_f < 0 || red_f > 255 || green_f < 0 || + green_f > 255 || blue_f < 0 || blue_f > 255) + lua_error("imEncodeColor: color components values should be in range [0, 255]!"); + + red_i = (unsigned char) (red_f); + green_i = (unsigned char) (green_f); + blue_i = (unsigned char) (blue_f); + + color_i = imEncodeColor(red_i, green_i, blue_i); + lua_pushusertag((void *) color_i, color_tag); +} + +/***************************************************************************\ +* imDecodeColor * +\***************************************************************************/ +static void imlua_decodecolor(void) +{ + lua_Object color; + long int color_i; + unsigned char red_i, green_i, blue_i; + + color = lua_getparam(1); + if (lua_tag(color) != color_tag) + lua_error("imDecodeColor: invalid color parameter!"); + color_i = (long int) lua_getuserdata(color); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("imDecodeColor: too many parameters!"); + + imDecodeColor(&red_i, &green_i, &blue_i, color_i); + + lua_pushnumber( red_i); + lua_pushnumber( green_i); + lua_pushnumber( blue_i); +} + +/***************************************************************************\ +* imLoadRGB * +\***************************************************************************/ +static void imlua_loadrgb(void) +{ + lua_Object file, imagergb; + + imagergb_t *imagergb_p; + char *file_s; + + int err; + + file = lua_getparam(1); + if (!lua_isstring(file)) + lua_error("imLoadRGB: invalid filename parameter!"); + file_s = (char *) lua_getstring(file); + + imagergb = lua_getparam(2); + if (lua_tag(imagergb) != imagergb_tag) + lua_error("imLoadRGB: invalid imagergb parameter!"); + imagergb_p = (imagergb_t *) lua_getuserdata(imagergb); + + if (lua_getparam(3) != LUA_NOOBJECT) + lua_error("imLoadRGB: too many parameters!"); + + err = imLoadRGB(file_s, imagergb_p->red, imagergb_p->green, imagergb_p->blue); + lua_pushnumber( err); +} + +/***************************************************************************\ +* imLoadMap * +\***************************************************************************/ +static void imlua_loadmap(void) +{ + lua_Object file, imagemap, palette; + + imagemap_t *imagemap_p; + palette_t *palette_p; + char *file_s; + + int err; + + file = lua_getparam(1); + if (!lua_isstring(file)) + lua_error("imLoadMap: invalid filename parameter!"); + file_s = (char *) lua_getstring(file); + + imagemap = lua_getparam(2); + if (lua_tag(imagemap) != imagemap_tag) + lua_error("imLoadMap: invalid imagemap parameter!"); + imagemap_p = (imagemap_t *) lua_getuserdata(imagemap); + + palette = lua_getparam(3); + if (lua_tag(palette) != palette_tag) + lua_error("imLoadMap: invalid palette parameter!"); + palette_p = (palette_t *) lua_getuserdata(palette); + + if (lua_getparam(4) != LUA_NOOBJECT) + lua_error("imLoadMap: too many parameters!"); + + err = imLoadMap(file_s, imagemap_p->index, palette_p->color); + lua_pushnumber( err); +} + +/***************************************************************************\ +* imSaveRGB * +\***************************************************************************/ +static void imlua_savergb(void) +{ + lua_Object file, imagergb, format, compress; + + imagergb_t *imagergb_p; + char *file_s; + int format_i; + int compress_i; + + int err; + + imagergb = lua_getparam(1); + if (lua_tag(imagergb) != imagergb_tag) + lua_error("imSaveRGB: invalid imagergb parameter!"); + imagergb_p = (imagergb_t *) lua_getuserdata(imagergb); + + format = lua_getparam(2); + if (!lua_isnumber(format)) + lua_error("imSaveRGB: invalid format parameter!"); + format_i = (int) lua_getnumber(format); + + compress = lua_getparam(3); + if (!lua_isnumber(compress)) + lua_error("imSaveRGB: invalid compression parameter!"); + compress_i = (int) lua_getnumber(compress); + + file = lua_getparam(4); + if (!lua_isstring(file)) + lua_error("imSaveRGB: invalid filename parameter!"); + file_s = (char *) lua_getstring(file); + + if (lua_getparam(5) != LUA_NOOBJECT) + lua_error("imSaveRGB: too many parameters!"); + + err = imSaveRGB(imagergb_p->width, imagergb_p->height, format_i | (compress_i << 8), + imagergb_p->red, imagergb_p->green, imagergb_p->blue, file_s); + lua_pushnumber( err); +} + +/***************************************************************************\ +* imSaveMap * +\***************************************************************************/ +static void imlua_savemap(void) +{ + lua_Object file, imagemap, palette, format, compress; + + imagemap_t *imagemap_p; + palette_t *palette_p; + char *file_s; + int format_i; + int compress_i; + + int err; + + imagemap = lua_getparam(1); + if (lua_tag(imagemap) != imagemap_tag) + lua_error("imSaveMap: invalid imagemap parameter!"); + imagemap_p = (imagemap_t *) lua_getuserdata(imagemap); + + palette = lua_getparam(2); + if (lua_tag(palette) != palette_tag) + lua_error("imLoadMap: invalid palette parameter!"); + palette_p = (palette_t *) lua_getuserdata(palette); + + format = lua_getparam(3); + if (!lua_isnumber(format)) + lua_error("imSaveMap: invalid format parameter!"); + format_i = (int) lua_getnumber(format); + + compress = lua_getparam(4); + if (!lua_isnumber(compress)) + lua_error("imSaveMap: invalid compression parameter!"); + compress_i = (int) lua_getnumber(compress); + + file = lua_getparam(5); + if (!lua_isstring(file)) + lua_error("imSaveMap: invalid filename parameter!"); + file_s = (char *) lua_getstring(file); + + if (lua_getparam(6) != LUA_NOOBJECT) + lua_error("imSaveMap: too many parameters!"); + + err = imSaveMap(imagemap_p->width, imagemap_p->height, format_i | (compress_i << 8), + imagemap_p->index, palette_p->size, palette_p->color, file_s); + lua_pushnumber( err); +} + +/***************************************************************************\ +* imRGB2Map * +\***************************************************************************/ +static void imlua_rgb2map(void) +{ + lua_Object imagergb, imagemap, palette; + + imagemap_t *imagemap_p; + palette_t *palette_p; + imagergb_t *imagergb_p; + + imagergb = lua_getparam(1); + if (lua_tag(imagergb) != imagergb_tag) + lua_error("imRGB2Map: invalid imagergb parameter!"); + imagergb_p = (imagergb_t *) lua_getuserdata(imagergb); + + imagemap = lua_getparam(2); + if (lua_tag(imagemap) != imagemap_tag) + lua_error("imRGB2Map: invalid imagemap parameter!"); + imagemap_p = (imagemap_t *) lua_getuserdata(imagemap); + + palette = lua_getparam(3); + if (lua_tag(palette) != palette_tag) + lua_error("imRGB2Map: invalid palette parameter!"); + palette_p = (palette_t *) lua_getuserdata(palette); + + if (lua_getparam(4) != LUA_NOOBJECT) + lua_error("imRGB2Map: too many parameters!"); + + if (imagergb_p->size != imagemap_p->size) + lua_error("imRGB2Map: images have incompatible dimensions!"); + + imRGB2Map(imagergb_p->width, imagergb_p->height, imagergb_p->red, + imagergb_p->green, imagergb_p->blue, imagemap_p->index, palette_p->size, + palette_p->color); +} + +/***************************************************************************\ +* imMap2RGB * +\***************************************************************************/ +static void imlua_map2rgb(void) +{ + lua_Object imagergb, imagemap, palette; + + imagemap_t *imagemap_p; + palette_t *palette_p; + imagergb_t *imagergb_p; + + imagemap = lua_getparam(1); + if (lua_tag(imagemap) != imagemap_tag) + lua_error("imMap2RGB: invalid imagemap parameter!"); + imagemap_p = (imagemap_t *) lua_getuserdata(imagemap); + + palette = lua_getparam(2); + if (lua_tag(palette) != palette_tag) + lua_error("imMap2RGB: invalid palette parameter!"); + palette_p = (palette_t *) lua_getuserdata(palette); + + imagergb = lua_getparam(3); + if (lua_tag(imagergb) != imagergb_tag) + lua_error("imMap2RGB: invalid imagergb parameter!"); + imagergb_p = (imagergb_t *) lua_getuserdata(imagergb); + + if (lua_getparam(4) != LUA_NOOBJECT) + lua_error("imMap2RGB: too many parameters!"); + + if (imagergb_p->size != imagemap_p->size) + lua_error("imMap2RGB: images have incompatible dimensions!"); + + imMap2RGB(imagemap_p->width, imagemap_p->height, imagemap_p->index, palette_p->size, + palette_p->color, imagergb_p->red, imagergb_p->green, imagergb_p->blue); +} + +/***************************************************************************\ +* imMap2Gray * +\***************************************************************************/ +static void imlua_map2gray(void) +{ + lua_Object imagemap, palette, graymap, grays; + + imagemap_t *imagemap_p; + palette_t *palette_p; + imagemap_t *graymap_p; + palette_t *grays_p; + + imagemap = lua_getparam(1); + if (lua_tag(imagemap) != imagemap_tag) + lua_error("imMap2Gray: invalid imagemap parameter!"); + imagemap_p = (imagemap_t *) lua_getuserdata(imagemap); + + palette = lua_getparam(2); + if (lua_tag(palette) != palette_tag) + lua_error("imMap2Gray: invalid palette parameter!"); + palette_p = (palette_t *) lua_getuserdata(palette); + + graymap = lua_getparam(3); + if (lua_tag(graymap) != imagemap_tag) + lua_error("imMap2Gray: invalid graymap parameter!"); + graymap_p = (imagemap_t *) lua_getuserdata(graymap); + + grays = lua_getparam(4); + if (lua_tag(grays) != palette_tag) + lua_error("imMap2Gray: invalid grays parameter!"); + grays_p = (palette_t *) lua_getuserdata(grays); + + if (lua_getparam(5) != LUA_NOOBJECT) + lua_error("imMap2Gray: too many parameters!"); + + if (imagemap_p->size != graymap_p->size) + lua_error("imMap2Gray: images have incompatible dimensions!"); + + if (grays_p->size < 256) + lua_error("imMap2Gray: grays palette should be of size 256!"); + + imMap2Gray(imagemap_p->width, imagemap_p->height, imagemap_p->index, + palette_p->size, palette_p->color, graymap_p->index, grays_p->color); +} + +/***************************************************************************\ +* imRGB2Gray * +\***************************************************************************/ +static void imlua_rgb2gray(void) +{ + lua_Object imagergb, graymap, grays; + + imagergb_t *imagergb_p; + imagemap_t *graymap_p; + palette_t *grays_p; + + imagergb = lua_getparam(1); + if (lua_tag(imagergb) != imagergb_tag) + lua_error("imRGB2Gray: invalid imagergb parameter!"); + imagergb_p = (imagergb_t *) lua_getuserdata(imagergb); + + graymap = lua_getparam(2); + if (lua_tag(graymap) != imagemap_tag) + lua_error("imRGB2Gray: invalid graymap parameter!"); + graymap_p = (imagemap_t *) lua_getuserdata(graymap); + + grays = lua_getparam(3); + if (lua_tag(grays) != palette_tag) + lua_error("imRGB2Gray: invalid grays parameter!"); + grays_p = (palette_t *) lua_getuserdata(grays); + + if (lua_getparam(4) != LUA_NOOBJECT) + lua_error("imRGB2Gray: too many parameters!"); + + if (imagergb_p->size != graymap_p->size) + lua_error("imRGB2Gray: images have incompatible dimensions!"); + + if (grays_p->size < 256) + lua_error("imRGB2Gray: grays palette should be of size 256!"); + + imRGB2Gray(imagergb_p->width, imagergb_p->height, imagergb_p->red, + imagergb_p->green, imagergb_p->blue, graymap_p->index, grays_p->color); +} + +/***************************************************************************\ +* imStretch. * +\***************************************************************************/ +static void imlua_stretch(void) +{ + lua_Object src, dst; + + imagemap_t *srcmap_p; + imagemap_t *dstmap_p; + imagergb_t *srcrgb_p; + imagergb_t *dstrgb_p; + + src = lua_getparam(1); + dst = lua_getparam(2); + if (lua_getparam(3) != LUA_NOOBJECT) + lua_error("imStretch: too many parameters!"); + + if ((lua_tag(src) == imagergb_tag) && (lua_tag(dst) == imagergb_tag)) { + srcrgb_p = (imagergb_t *) lua_getuserdata(src); + dstrgb_p = (imagergb_t *) lua_getuserdata(dst); + imStretch(srcrgb_p->width, srcrgb_p->height, srcrgb_p->red, + dstrgb_p->width, dstrgb_p->height, dstrgb_p->red); + imStretch(srcrgb_p->width, srcrgb_p->height, srcrgb_p->green, + dstrgb_p->width, dstrgb_p->height, dstrgb_p->green); + imStretch(srcrgb_p->width, srcrgb_p->height, srcrgb_p->blue, + dstrgb_p->width, dstrgb_p->height, dstrgb_p->blue); + } + else if ((lua_tag(src) == imagemap_tag) && (lua_tag(dst) == imagemap_tag)) { + srcmap_p = (imagemap_t *) lua_getuserdata(src); + dstmap_p = (imagemap_t *) lua_getuserdata(dst); + imStretch(srcmap_p->width, srcmap_p->height, srcmap_p->index, + dstmap_p->width, dstmap_p->height, dstmap_p->index); + } + else { + lua_error("imStretch: inconsistent parameters!"); + } +} + +/***************************************************************************\ +* imResize. * +\***************************************************************************/ +static void imlua_resize(void) +{ + lua_Object src, dst; + + imagergb_t *srcrgb_p; + imagergb_t *dstrgb_p; + + src = lua_getparam(1); + dst = lua_getparam(2); + if (lua_getparam(3) != LUA_NOOBJECT) + lua_error("imResize: too many parameters!"); + + if ((lua_tag(src) == imagergb_tag) && (lua_tag(dst) == imagergb_tag)) { + srcrgb_p = (imagergb_t *) lua_getuserdata(src); + dstrgb_p = (imagergb_t *) lua_getuserdata(dst); + imStretch(srcrgb_p->width, srcrgb_p->height, srcrgb_p->red, + dstrgb_p->width, dstrgb_p->height, dstrgb_p->red); + imStretch(srcrgb_p->width, srcrgb_p->height, srcrgb_p->green, + dstrgb_p->width, dstrgb_p->height, dstrgb_p->green); + imStretch(srcrgb_p->width, srcrgb_p->height, srcrgb_p->blue, + dstrgb_p->width, dstrgb_p->height, dstrgb_p->blue); + } + else { + lua_error("imResize: parameters must be of type imagergb_tag!"); + } +} + +/***************************************************************************\ +* imVersion. * +\***************************************************************************/ +static void imlua_version(void) +{ + if (lua_getparam(1) != LUA_NOOBJECT) + lua_error("imVersion: too many parameters!"); + + lua_pushstring(imVersion()); +} + +/***************************************************************************\ +* Fallback implementation. * +\***************************************************************************/ + +/***************************************************************************\ +* imagemap "settable" fallback. * +\***************************************************************************/ +static void imagemapsettable_fb(void) +{ + lua_Object imagemap, index, value; + + imagemap_t *imagemap_p; + long int index_i; + long int value_i; + + imagemap = lua_getparam(1); + index = lua_getparam(2); + value = lua_getparam(3); + + imagemap_p = (imagemap_t *) lua_getuserdata(imagemap); + if (!imagemap_p) { + lua_error("imagemap_tag \"settable\": invalid imagemap_tag object!"); + } + + if (!lua_isnumber(index)) { + lua_error("imagemap_tag \"settable\": index should be a number!"); + } + + if (!lua_isnumber(value)) { + lua_error("imagemap_tag \"settable\": value should be a number!"); + } + + value_i = (long int) lua_getnumber(value); + if ((value_i < 0 || value_i > 255)) + lua_error("imagemap_tag \"settable\": value should be in range [0, 255]!"); + + index_i = (long int) lua_getnumber(index); + if (index_i < 0 || index_i >= imagemap_p->size) + lua_error("imagemap_tag \"settable\": index is out of bounds!"); + + imagemap_p->index[index_i] = (unsigned char) value_i; +} + +/***************************************************************************\ +* palette "settable" fallback. * +\***************************************************************************/ +static void palettesettable_fb(void) +{ + lua_Object palette, index, color; + + palette_t *palette_p; + long int index_i; + long int color_i; + + palette = lua_getparam(1); + index = lua_getparam(2); + color = lua_getparam(3); + + palette_p = (palette_t *) lua_getuserdata(palette); + if (!palette_p) { + lua_error("palette_tag \"settable\": invalid palette_tag object!"); + } + + if (!lua_isnumber(index)) { + lua_error("palette_tag \"settable\": index should be a number!"); + } + + if (lua_tag(color) != color_tag) + lua_error("palette_tag \"settable\": value should be of type color_tag!"); + + color_i = (long int) lua_getuserdata(color); + + index_i = (long int) lua_getnumber(index); + if (index_i < 0 || index_i >= palette_p->size) + lua_error("palette_tag \"settable\": index is out of bounds!"); + + palette_p->color[index_i] = color_i; +} + +/***************************************************************************\ +* channel "settable" fallback. This fallback is called when a LUA line like * +* "imagergb.r[y*w + x] = c" is executed. The imagergb "gettable" fallback * +* fills and returns a channel structure with info about the buffer. This * +* structure is consulted and the value is assigned where it should. * +\***************************************************************************/ +static void channelsettable_fb(void) +{ + lua_Object channel, index, value; + + channel_t *channel_p; + long int index_i; + long int value_i; + + channel = lua_getparam(1); + index = lua_getparam(2); + value = lua_getparam(3); + + channel_p = (channel_t *) lua_getuserdata(channel); + if (!channel_p) { + lua_error("channel_tag \"settable\": invalid channel_tag object!"); + } + + if (!lua_isnumber(index)) { + lua_error("channel_tag \"settable\": index should be a number!"); + } + index_i = (long int) lua_getnumber(index); + if (index_i < 0 || index_i >= channel_p->size) { + lua_error("channel_tag \"settable\": index is out of bounds!"); + } + + if (!lua_isnumber(value)) { + lua_error("channel_tag \"settable\": value should be a number!"); + } + value_i = (long int) lua_getnumber(value); + if ((value_i < 0 || value_i > 255)) { + lua_error("channel_tag \"settable\": value should be in range [0, 255]!"); + } + + channel_p->value[index_i] = (unsigned char) value_i; +} + +/***************************************************************************\ +* imagemap "gettable" fallback. * +\***************************************************************************/ +static void imagemapgettable_fb(void) +{ + lua_Object imagemap, index; + + imagemap_t *imagemap_p; + long int index_i; + + imagemap = lua_getparam(1); + index = lua_getparam(2); + + imagemap_p = (imagemap_t *) lua_getuserdata(imagemap); + if (!imagemap_p) + lua_error("imagemap_tag \"gettable\": invalid imagemap_tag object!"); + + if (!lua_isnumber(index)) { + lua_error("imagemap_tag \"gettable\": index should be a number!"); + } + + index_i = (long int) lua_getnumber(index); + if (index_i < 0 || index_i >= imagemap_p->size) + lua_error("imagemap_tag \"gettable\": index is out of bounds!"); + + lua_pushnumber( imagemap_p->index[index_i]); +} + +/***************************************************************************\ +* palette "gettable" fallback. * +\***************************************************************************/ +static void palettegettable_fb(void) +{ + lua_Object palette, index; + + palette_t *palette_p; + long int index_i; + + palette = lua_getparam(1); + index = lua_getparam(2); + + palette_p = (palette_t *) lua_getuserdata(palette); + if (!palette_p) + lua_error("palette_tag \"gettable\": invalid palette_tag object!"); + + if (!lua_isnumber(index)) { + lua_error("palette_tag \"gettable\": index should be a number!"); + } + + index_i = (long int) lua_getnumber(index); + if (index_i < 0 || index_i >= palette_p->size) + lua_error("palette_tag \"gettable\": index is out of bounds!"); + + lua_pushusertag((void *) palette_p->color[index_i], color_tag); +} + +/***************************************************************************\ +* channel "gettable" fallback. This fallback is called when a LUA line like * +* "c = imagergb.r[y*w + x]" is executed. The imagergb "gettable" fallback * +* fills and returns a channel structure with info about the buffer. This * +* structure is consulted and the appropriate value is returned. * +\***************************************************************************/ +static void channelgettable_fb(void) +{ + lua_Object channel, index; + + channel_t *channel_p; + long int index_i; + + channel = lua_getparam(1); + index = lua_getparam(2); + + channel_p = (channel_t *) lua_getuserdata(channel); + if (!channel_p) { + lua_error("channel_tag \"gettable\": invalid channel_tag object!"); + } + + if (!lua_isnumber(index)) { + lua_error("channel_tag \"gettable\": index should be a number!"); + } + index_i = (long int) lua_getnumber(index); + if (index_i < 0 || index_i >= channel_p->size) { + lua_error("channel_tag \"gettable\": index is out of bounds!"); + } + + lua_pushnumber( channel_p->value[index_i]); +} + +/***************************************************************************\ +* imagergb "gettable" fallback. This fallback is called when a LUA line * +* like "c = imagergb.r[y*w + x]" or "imagergb.r[y*w + x] = c" is executed. * +* The channel_info global is filled and its address is returned with a * +* channel_tag usertag lua_Object. The following "gettable" or "settable" * +* then assigns or returns the appropriate value. * +\***************************************************************************/ +static void imagergbgettable_fb(void) +{ + lua_Object imagergb, index; + + char *index_s; + imagergb_t *imagergb_p; + + imagergb = lua_getparam(1); + index = lua_getparam(2); + + imagergb_p = (imagergb_t *) lua_getuserdata(imagergb); + if (!imagergb_p) + lua_error("imagergb_tag \"gettable\": invalid imagergb_tag object!"); + + if (!lua_isstring(index)) { + lua_error("imagergb_tag \"gettable\": index should be a channel name!"); + } + index_s = (char *) lua_getstring(index); + + channel_info.size = imagergb_p->size; + + if (*index_s == 'r' || *index_s == 'R') { + channel_info.value = imagergb_p->red; + } + else if (*index_s == 'g' || *index_s == 'G') { + channel_info.value = imagergb_p->green; + } + else if (*index_s == 'b' || *index_s == 'B') { + channel_info.value = imagergb_p->blue; + } + else { + lua_error("imagergb_tag \"gettable\": index is an invalid channel name!"); + } + + lua_pushusertag((void *) &channel_info, channel_tag); +} + +/***************************************************************************\ +* imagergba "gettable" fallback. This fallback is called when a LUA line * +* like "c = imagergba.r[y*w + x]" or "imagergba.r[y*w + x] = c" is executed.* +* The channel_info global is filled and its address is returned with a * +* channel_tag usertag lua_Object. The following "gettable" or "settable" * +* then assigns or returns the appropriate value. * +\***************************************************************************/ +static void imagergbagettable_fb(void) +{ + lua_Object imagergba, index; + + char *index_s; + imagergba_t *imagergba_p; + + imagergba = lua_getparam(1); + index = lua_getparam(2); + + imagergba_p = (imagergba_t *) lua_getuserdata(imagergba); + if (!imagergba_p) + lua_error("imagergba_tag \"gettable\": invalid imagergba_tag object!"); + + if (!lua_isstring(index)) { + lua_error("imagergba_tag \"gettable\": index should be a channel name!"); + } + index_s = (char *) lua_getstring(index); + + channel_info.size = imagergba_p->size; + + if (*index_s == 'r' || *index_s == 'R') { + channel_info.value = imagergba_p->red; + } + else if (*index_s == 'g' || *index_s == 'G') { + channel_info.value = imagergba_p->green; + } + else if (*index_s == 'b' || *index_s == 'B') { + channel_info.value = imagergba_p->blue; + } + else if (*index_s == 'a' || *index_s == 'A') { + channel_info.value = imagergba_p->alpha; + } + else { + lua_error("imagergba_tag \"gettable\": index is an invalid channel name!"); + } + + lua_pushusertag((void *) &channel_info, channel_tag); +} + +/***************************************************************************\ +* palette "gc" fallback. * +\***************************************************************************/ +static void palettegc_fb(void) +{ + lua_Object palette; + + palette_t *palette_p; + + palette = lua_getparam(1); + palette_p = (palette_t *) lua_getuserdata(palette); + if (!palette_p) + lua_error("palette_tag \"gc\": invalid palette_tag object!"); + + /* if the palette has not been killed, kill it */ + if (palette_p->color) free(palette_p->color); + + /* free the palette_t structure */ + free(palette_p); +} + +/***************************************************************************\ +* imagergb "gc" fallback. * +\***************************************************************************/ +static void imagergbgc_fb(void) +{ + lua_Object imagergb; + + imagergb_t *imagergb_p; + + imagergb = lua_getparam(1); + imagergb_p = (imagergb_t *) lua_getuserdata(imagergb); + if (!imagergb_p) + lua_error("imagergb_tag \"gc\": invalid imagergb_tag object!"); + + /* if the imagergb has not been killed, kill it */ + if (imagergb_p->red) free(imagergb_p->red); + if (imagergb_p->green) free(imagergb_p->green); + if (imagergb_p->blue) free(imagergb_p->blue); + + /* free the imagergb_t structure */ + free(imagergb_p); +} + +/***************************************************************************\ +* imagergba "gc" fallback. * +\***************************************************************************/ +static void imagergbagc_fb(void) +{ + lua_Object imagergba; + + imagergba_t *imagergba_p; + + imagergba = lua_getparam(1); + imagergba_p = (imagergba_t *) lua_getuserdata(imagergba); + if (!imagergba_p) + lua_error("imagergba_tag \"gc\": invalid imagergba_tag object!"); + + /* if the imagergba has not been killed, kill it */ + if (imagergba_p->red) free(imagergba_p->red); + if (imagergba_p->green) free(imagergba_p->green); + if (imagergba_p->blue) free(imagergba_p->blue); + if (imagergba_p->alpha) free(imagergba_p->alpha); + + /* free the imagergba_t structure */ + free(imagergba_p); +} + +/***************************************************************************\ +* imagemap "gc" fallback. * +\***************************************************************************/ +static void imagemapgc_fb(void) +{ + lua_Object imagemap; + + imagemap_t *imagemap_p; + + imagemap = lua_getparam(1); + imagemap_p = (imagemap_t *) lua_getuserdata(imagemap); + if (!imagemap_p) + lua_error("imagemap_tag \"gc\": invalid imagemap_tag object!"); + + /* if the imagemap has not been killed, kill it */ + if (imagemap_p->index) free(imagemap_p->index); + + /* free the imagemap_t structure */ + free(imagemap_p); +} + +/***************************************************************************\ +* Initialization code. * +\***************************************************************************/ + +/***************************************************************************\ +* Initializes IMLua. * +\***************************************************************************/ +void imlua_open(void) +{ + lua_Object cdlua_tag; + + /* check if CD has been initialized */ + cdlua_tag = lua_getglobal("CDLUA_INSTALLED"); + + /* get CD defined tags, let CD deal with the user tag objects */ + if ((cdlua_tag != LUA_NOOBJECT) && (!lua_isnil(cdlua_tag))) { + cdlua_tag = lua_getglobal("CDLUA_COLOR_TAG"); + color_tag = (int) lua_getnumber(cdlua_tag); + cdlua_tag = lua_getglobal("CDLUA_IMAGERGB_TAG"); + imagergb_tag = (int) lua_getnumber(cdlua_tag); + cdlua_tag = lua_getglobal("CDLUA_IMAGERGBA_TAG"); + imagergba_tag = (int) lua_getnumber(cdlua_tag); + cdlua_tag = lua_getglobal("CDLUA_PALETTE_TAG"); + palette_tag = (int) lua_getnumber(cdlua_tag); + cdlua_tag = lua_getglobal("CDLUA_IMAGEMAP_TAG"); + imagemap_tag = (int) lua_getnumber(cdlua_tag); + cdlua_tag = lua_getglobal("CDLUA_CHANNEL_TAG"); + channel_tag = (int) lua_getnumber(cdlua_tag); + } + /* define IM own tags and fallbacks */ + else { + color_tag = lua_newtag(); + imagergb_tag = lua_newtag(); + imagergba_tag = lua_newtag(); + imagemap_tag = lua_newtag(); + palette_tag = lua_newtag(); + channel_tag = lua_newtag(); + + /* associate the fallbacks */ + lua_pushcfunction(palettesettable_fb); lua_settagmethod(palette_tag, "settable"); + lua_pushcfunction(channelsettable_fb); lua_settagmethod(channel_tag, "settable"); + lua_pushcfunction(imagemapsettable_fb); lua_settagmethod(imagemap_tag, "settable"); + + lua_pushcfunction(imagergbgettable_fb); lua_settagmethod(imagergb_tag, "gettable"); + lua_pushcfunction(imagergbagettable_fb); lua_settagmethod(imagergba_tag, "gettable"); + lua_pushcfunction(palettegettable_fb); lua_settagmethod(palette_tag, "gettable"); + lua_pushcfunction(imagemapgettable_fb); lua_settagmethod(imagemap_tag, "gettable"); + lua_pushcfunction(channelgettable_fb); lua_settagmethod(channel_tag, "gettable"); + + lua_pushcfunction(imagergbgc_fb); lua_settagmethod(imagergb_tag, "gc"); + lua_pushcfunction(imagergbagc_fb); lua_settagmethod(imagergba_tag, "gc"); + lua_pushcfunction(palettegc_fb); lua_settagmethod(palette_tag, "gc"); + lua_pushcfunction(imagemapgc_fb); lua_settagmethod(imagemap_tag, "gc"); + } + + /* register used tags in global context for other libraries use */ + lua_pushnumber(1.0f); lua_setglobal("IMLUA_INSTALLED"); + lua_pushnumber( color_tag); lua_setglobal("IMLUA_COLOR_TAG"); + lua_pushnumber( imagergb_tag); lua_setglobal("IMLUA_IMAGERGB_TAG"); + lua_pushnumber( imagergba_tag); lua_setglobal("IMLUA_IMAGERGBA_TAG"); + lua_pushnumber( imagemap_tag); lua_setglobal("IMLUA_IMAGEMAP_TAG"); + lua_pushnumber( palette_tag); lua_setglobal("IMLUA_PALETTE_TAG"); + lua_pushnumber( channel_tag); lua_setglobal("IMLUA_CHANNEL_TAG"); + + /* registered IM functions */ + lua_register("imDecodeColor", imlua_decodecolor); + lua_register("imEncodeColor", imlua_encodecolor); + lua_register("imLoadRGB", imlua_loadrgb); + lua_register("imLoadMap", imlua_loadmap); + lua_register("imSaveRGB", imlua_savergb); + lua_register("imSaveMap", imlua_savemap); + lua_register("imFileFormat", imlua_fileformat); + lua_register("imImageInfo", imlua_imageinfo); + lua_register("imRGB2Map", imlua_rgb2map); + lua_register("imMap2RGB", imlua_map2rgb); + lua_register("imRGB2Gray", imlua_rgb2gray); + lua_register("imMap2Gray", imlua_map2gray); + lua_register("imVersion", imlua_version); + lua_register("imResize", imlua_resize); + lua_register("imStretch", imlua_stretch); + + /* creation and destruction functions */ + lua_register("imCreateImageRGB", imlua_createimagergb); + lua_register("imCreateImageMap", imlua_createimagemap); + lua_register("imCreatePalette", imlua_createpalette); + lua_register("imKillImageRGB", imlua_killimagergb); + lua_register("imKillImageMap", imlua_killimagemap); + lua_register("imKillPalette", imlua_killpalette); + + /* im constants */ + lua_pushnumber( IM_BMP); lua_setglobal("IM_BMP"); + lua_pushnumber( IM_PCX); lua_setglobal("IM_PCX"); + lua_pushnumber( IM_GIF); lua_setglobal("IM_GIF"); + lua_pushnumber( IM_TIF); lua_setglobal("IM_TIF"); + lua_pushnumber( IM_RAS); lua_setglobal("IM_RAS"); + lua_pushnumber( IM_SGI); lua_setglobal("IM_SGI"); + lua_pushnumber( IM_JPG); lua_setglobal("IM_JPG"); + lua_pushnumber( IM_LED); lua_setglobal("IM_LED"); + lua_pushnumber( IM_TGA); lua_setglobal("IM_TGA"); + + lua_pushnumber( 0); lua_setglobal("IM_NONE"); + lua_pushnumber( 1); lua_setglobal("IM_DEFAULT"); + lua_pushnumber( 2); lua_setglobal("IM_COMPRESSED"); + + lua_pushnumber( IM_RGB); lua_setglobal("IM_RGB"); + lua_pushnumber( IM_MAP); lua_setglobal("IM_MAP"); + + lua_pushnumber( IM_ERR_NONE); lua_setglobal("IM_ERR_NONE"); + lua_pushnumber( IM_ERR_OPEN); lua_setglobal("IM_ERR_OPEN"); + lua_pushnumber( IM_ERR_READ); lua_setglobal("IM_ERR_READ"); + lua_pushnumber( IM_ERR_WRITE); lua_setglobal("IM_ERR_WRITE"); + lua_pushnumber( IM_ERR_FORMAT); lua_setglobal("IM_ERR_FORMAT"); + lua_pushnumber( IM_ERR_TYPE); lua_setglobal("IM_ERR_TYPE"); + lua_pushnumber( IM_ERR_COMP); lua_setglobal("IM_ERR_COMP"); +} diff --git a/im/src/im_palette.cpp b/im/src/im_palette.cpp new file mode 100755 index 0000000..0e6f967 --- /dev/null +++ b/im/src/im_palette.cpp @@ -0,0 +1,551 @@ +/** \file + * \brief Palette Generators + * Creates several standard palettes + * + * See Copyright Notice in im_lib.h + * $Id: im_palette.cpp,v 1.1 2008/10/17 06:10:16 scuri Exp $ + */ + +#include "im.h" +#include "im_util.h" +#include "im_palette.h" +#include "im_colorhsi.h" + +#include +#include +#include +#include + +static inline int iSqr(int x) +{ + return x*x; +} + +static inline int iAbs(int x) +{ + return x < 0? -x: x; +} + +int imPaletteFindNearest(const long* palette, int palette_count, long color) +{ + assert(palette); + assert(palette_count); + + int lSqrDiff, lBestDiff = (unsigned int)-1; + int pIndex = -1; + + imbyte red1, green1, blue1; + imColorDecode(&red1, &green1, &blue1, color); + + for (int lIndex = 0; lIndex < palette_count; lIndex++, palette++) + { + if (color == *palette) + return lIndex; + + imbyte red2, green2, blue2; + imColorDecode(&red2, &green2, &blue2, *palette); + + lSqrDiff = iSqr(red1 - red2) + + iSqr(green1 - green2) + + iSqr(blue1 - blue2); + + if (lSqrDiff < lBestDiff) + { + lBestDiff = lSqrDiff; + pIndex = lIndex; + } + } + + return pIndex; +} + +int imPaletteFindColor(const long* palette, int palette_count, long color, unsigned char tol) +{ + assert(palette); + assert(palette_count); + + /* Divides in two section for faster results when Tolerance is 0.*/ + if (tol == 0) + { + for (int lIndex = 0; lIndex < palette_count; lIndex++, palette++) + { + if (color == *palette) + return lIndex; + } + } + else + { + imbyte red1, green1, blue1; + imColorDecode(&red1, &green1, &blue1, color); + + for (int lIndex = 0; lIndex < palette_count; lIndex++, palette++) + { + imbyte red2, green2, blue2; + imColorDecode(&red2, &green2, &blue2, *palette); + + if (iAbs(red1 - red2) < tol && + iAbs(green1 - green2) < tol && + iAbs(blue1 - blue2) < tol) + { + return lIndex; + } + } + } + + return -1; +} + +long* imPaletteGray(void) +{ + long* palette = (long*)malloc(sizeof(long)*256); + long* ct = palette; + + for (int lIndex = 0; lIndex < 256; lIndex++) + { + /* From (0, 0, 0) to (255, 255, 255)*/ + /* From Black to White */ + *(ct++) = imColorEncode((imbyte)lIndex, (imbyte)lIndex, (imbyte)lIndex); + } + + return palette; +} + +long* imPaletteRed(void) +{ + long* palette = (long*)malloc(sizeof(long)*256); + long* ct = palette; + + for (int lIndex = 0; lIndex < 256; lIndex++) + { + /* From (0, 0, 0) to (255, 0, 0) */ + /* From Black to Red */ + *(ct++) = imColorEncode((imbyte)lIndex, 0, 0); + } + + return palette; +} + +long* imPaletteGreen(void) +{ + long* palette = (long*)malloc(sizeof(long)*256); + long* ct = palette; + + for (int lIndex = 0; lIndex < 256; lIndex++) + { + /* From (0, 0, 0) to (0, 255, 0)*/ + /* From Black to Green */ + *(ct++) = imColorEncode(0, (imbyte)lIndex, 0); + } + + return palette; +} + +long* imPaletteBlue(void) +{ + long* palette = (long*)malloc(sizeof(long)*256); + long* ct = palette; + + for (int lIndex = 0; lIndex < 256; lIndex++) + { + /* From (0, 0, 0) to (0, 0, 255)*/ + /* From Black to Blue */ + *(ct++) = imColorEncode(0, 0, (imbyte)lIndex); + } + + return palette; +} + +long* imPaletteYellow(void) +{ + long* palette = (long*)malloc(sizeof(long)*256); + long* ct = palette; + + for (int lIndex = 0; lIndex < 256; lIndex++) + { + /* From (0, 0, 0) to (255, 255, 0)*/ + /* From Black to Yellow */ + *(ct++) = imColorEncode((imbyte)lIndex, (imbyte)lIndex, 0); + } + + return palette; +} + +long* imPaletteMagenta(void) +{ + long* palette = (long*)malloc(sizeof(long)*256); + long* ct = palette; + + for (int lIndex = 0; lIndex < 256; lIndex++) + { + /* From (0, 0, 0) to (255, 0, 255)*/ + /* From Black to Magenta */ + *(ct++) = imColorEncode((imbyte)lIndex, 0, (imbyte)lIndex); + } + + return palette; +} + +long* imPaletteCian(void) +{ + long* palette = (long*)malloc(sizeof(long)*256); + long* ct = palette; + + for (int lIndex = 0; lIndex < 256; lIndex++) + { + /* From (0, 0, 0) to (0, 255, 255)*/ + /* From Black to Cian */ + *(ct++) = imColorEncode(0, (imbyte)lIndex, (imbyte)lIndex); + } + + return palette; +} + +long* imPaletteHues(void) +{ + long* palette = (long*)malloc(sizeof(long)*256); + long* ct = palette; + int i; + float tone, step1 = 255.0f/41.0f, step2 = 255.0f/42.0f; + + /* 1+42+1+41+1+42+1+41+1+42+1+41+1 = 256 */ + + /* red */ + *(ct++) = imColorEncode((imbyte)255, 0, 0); + + for (tone = step2, i = 0; i < 42; i++, tone += step2) + { + /* From (255, 0, 0) to (255, 255, 0) */ + /* From Red to Yellow */ + *(ct++) = imColorEncode((imbyte)255, (imbyte)tone, 0); + } + + /* yellow */ + *(ct++) = imColorEncode((imbyte)255, (imbyte)255, 0); + + for (tone = step1, i = 0; i < 41; i++, tone += step1) + { + /* From (255, 255, 0) to (0, 255, 0) */ + /* From Yellow to Green */ + *(ct++) = imColorEncode((imbyte)(255.0f-tone), (imbyte)255, 0); + } + + /* green */ + *(ct++) = imColorEncode(0, (imbyte)255, 0);; + + for (tone = step2, i = 0; i < 42; i++, tone += step2) + { + /* From (0, 255, 0) to (0, 255, 255) */ + /* From Green to Cian */ + *(ct++) = imColorEncode(0, (imbyte)255, (imbyte)tone); + } + + /* cian */ + *(ct++) = imColorEncode(0, (imbyte)255, (imbyte)255); + + for (tone = step1, i = 0; i < 41; i++, tone += step1) + { + /* From (0, 255, 255) to (0, 0, 255) */ + /* From Cian to Blue */ + *(ct++) = imColorEncode(0, (imbyte)(255.0f-tone), (imbyte)255); + } + + /* blue */ + *(ct++) = imColorEncode(0, 0, (imbyte)255); + + for (tone = step2, i = 0; i < 42; i++, tone += step2) + { + /* From (0, 0, 255) to (255, 0, 255) */ + /* From Blue to Magenta */ + *(ct++) = imColorEncode((imbyte)tone, 0, (imbyte)255); + } + + /* magenta */ + *(ct++) = imColorEncode((imbyte)255, 0, (imbyte)255); + + for (tone = step1, i = 0; i < 41; i++, tone += step1) + { + /* From (255, 0, 255) to (255, 0, 0) */ + /* From Magenta to Red */ + *(ct++) = imColorEncode((imbyte)255, 0, (imbyte)(255.0f-tone)); + } + + /* black */ + *(ct++) = imColorEncode(0, 0, 0);; + + return palette; +} + +long* imPaletteRainbow(void) +{ + long* palette = (long*)malloc(sizeof(long)*256); + long* ct = palette; + int hue; + unsigned char r, g, b; + float h, s, i, factor, H; + + s = 1.0f; + factor = 360.0f / 256.0f; + + for (hue = 0; hue < 256; hue++) + { + h = hue * factor; + h = 300-h; + if (h < 0) h += 360; + H = h/57.2957795131f; + + i = imColorHSI_ImaxS(H, cos(H), sin(H)); + + imColorHSI2RGBbyte(h, s, i, &r, &g, &b); + + *(ct++) = imColorEncode(r, g, b);; + } + + return palette; +} + +long* imPaletteBlueIce(void) +{ + long* palette = (long*)malloc(sizeof(long)*256); + long* ct = palette; + + for (int lIndex = 0; lIndex < 256; lIndex++) + { + /* From (0, 0, 255) to (255, 255, 255)*/ + /* From Blue to White */ + *(ct++) = imColorEncode((imbyte)lIndex, (imbyte)lIndex, 255); + } + + return palette; +} + +long* imPaletteHotIron(void) +{ + long* palette = (long*)malloc(sizeof(long)*256); + long* ct = palette; + int lIndex, lSubIndex; + + for (lIndex = 0, lSubIndex = 0; lSubIndex < 128; lSubIndex++, lIndex += 2) + { + /* From (0, 0, 0) to (254, 0, 0) */ + /* From Black to ~Red */ + *(ct++) = imColorEncode((imbyte)lIndex, 0, 0); + } + + for (lIndex = 0, lSubIndex = 0; lSubIndex < 64; lSubIndex++, lIndex += 2) + { + /* From (255, 0, 0) to (255, 126, 0) */ + /* From Red to ~Orange */ + *(ct++) = imColorEncode(255, (imbyte)lIndex, 0); + } + + for (lIndex = 0, lSubIndex = 0; lSubIndex < 63; lSubIndex++, lIndex += 2) + { + /* From (255, 128, 0) to (255, 252, 252)*/ + /* From Orange to ~White */ + imbyte red = 255; + imbyte green = (imbyte)(128 + lIndex); + imbyte blue = (imbyte)(lIndex * 2 + 4); + + *(ct++) = imColorEncode(red, green, blue); + } + + *(ct++) = imColorEncode(255, 255, 255); + + return palette; +} + +long* imPaletteBlackBody(void) +{ + long* palette = (long*)malloc(sizeof(long)*256); + long* ct = palette; + int lIndex, lSubIndex; + + for (lIndex = 0, lSubIndex = 0; lSubIndex < 85; lSubIndex++, lIndex += 3) + { + /* From (0, 0, 0) to (252, 0, 0) */ + /* From Black to ~Red */ + *(ct++) = imColorEncode((imbyte)lIndex, 0, 0); + } + + for (lIndex = 0, lSubIndex = 0; lSubIndex < 85; lSubIndex++, lIndex += 3) + { + /* From (255, 0, 0) to (255, 252, 0)*/ + /* From Red to ~Yellow */ + *(ct++) = imColorEncode(255, (imbyte)lIndex, 0); + } + + for (lIndex = 0, lSubIndex = 0; lSubIndex < 86; lSubIndex++, lIndex += 3) + { + /* From (255, 255, 0) to (255, 255, 255)*/ + /* From Yellow to White */ + *(ct++) = imColorEncode(255, 255, (imbyte)lIndex); + } + + return palette; +} + +long* imPaletteHighContrast(void) +{ + long* palette = (long*)malloc(sizeof(long)*256); + long* ct = palette; + int lIndex; + + static struct{unsigned char r, g, b;} HighContrastColors[65] = { + { 0,0,0 }, + + { 255,0,0 }, { 128,0,0 }, { 64,0,0 }, { 192,0,0 }, + { 0,255,0 }, { 0,128,0 }, { 0,64,0 }, { 0,192,0 }, + { 0,0,255 }, { 0,0,128 }, { 0,0,64 }, { 0,0,192 }, + { 255,255,0 }, { 128,128,0 }, { 64,64,0 }, { 192,192,0 }, + { 255,0,255 }, { 128,0,128 }, { 64,0,64 }, { 192,0,192 }, + { 0,255,255 }, { 0,128,128 }, { 0,64,64 }, { 0,192,192 }, + { 255,255,255 }, { 128,128,128 }, { 64,64,64 }, { 192,192,192 }, + + { 255,128,128 }, { 64,255,255 }, { 192,255,255 }, + { 128,255,128 }, { 255,64,255 }, { 255,192,255 }, + { 128,128,255 }, { 255,255,64 }, { 255,255,192 }, + { 255,255,128 }, { 64,64,255 }, { 192,192,255 }, + { 255,128,255 }, { 64,255,64 }, { 192,255,192 }, + { 128,255,255 }, { 255,64,64 }, { 255,192,192 }, + + { 128,64,64 }, { 128,192,192 }, + { 64,128,64 }, { 192,128,192 }, + { 64,64,128 }, { 192,192,128 }, + { 128,128,64 }, { 128,128,192 }, + { 128,64,128 }, { 128,192,128 }, + { 64,128,128 }, { 192,128,128 }, + + { 192,64,64 }, + { 64,192,64 }, + { 64,64,192 }, + { 192,192,64 }, + { 192,64,192 }, + { 64,192,192 }, + }; + + for (lIndex = 0; lIndex < 65; lIndex++) + { + *(ct++) = imColorEncode(HighContrastColors[lIndex].r, + HighContrastColors[lIndex].g, + HighContrastColors[lIndex].b); + } + + for (; lIndex < 256; lIndex++) + { + *(ct++) = imColorEncode((imbyte)lIndex, (imbyte)lIndex, (imbyte)lIndex); + } + + return palette; +} + +/* 256 divided in 6 steps results in these steps.*/ +static int iSixStepsTable[6] = {0, 51, 102, 153, 204, 255}; + +long* imPaletteUniform(void) +{ + long* palette = (long*)malloc(sizeof(long)*256); + long* ct = palette; + + for (int lRedIndex = 0; lRedIndex < 6; lRedIndex++) + for (int lGreenIndex = 0; lGreenIndex < 6; lGreenIndex++) + for (int lBlueIndex = 0; lBlueIndex < 6; lBlueIndex++) + { + imbyte red = (imbyte)iSixStepsTable[lRedIndex]; + imbyte green = (imbyte)iSixStepsTable[lGreenIndex]; + imbyte blue = (imbyte)iSixStepsTable[lBlueIndex]; + + *(ct++) = imColorEncode(red, green, blue); + } + + /* We initialize only 216 colors (6x6x6), rest 40 colors.*/ + /* Fill them with a gray scale palette.*/ + for (int lIndex = 6; lIndex < 246; lIndex += 6) + { + *(ct++) = imColorEncode((imbyte)lIndex, (imbyte)lIndex, (imbyte)lIndex); + } + + return palette; +} + +/* X divided by 51. Convert to 216 color space. */ +static int iDividedBy51Table[256] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5 +}; + +/* X multiplied by 36. Shift to red position.*/ +static int iTimes36Table[6] = {0, 36, 72, 108, 144, 180}; + +/* X multiplied by 36. Shift to green position.*/ +static int iTimes6Table[6] = {0, 6, 12, 18, 24, 30}; + +int imPaletteUniformIndex(long color) +{ + imbyte red, green, blue; + imColorDecode(&red, &green, &blue, color); + return iTimes36Table[iDividedBy51Table[red]] + iTimes6Table[iDividedBy51Table[green]] + iDividedBy51Table[blue]; +} + +/* Remainder of X divided by 51. Used to position in the halftone*/ +static int iModulo51Table[256] = +{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, + 42, 43, 44, 45, 46, 47, 48, 49, 50, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 0, 1, 2, 3, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 0 +}; + +/* Dither matrices for 8 bit to 2.6 bit halftones.*/ +static int iHalftone8x8Table[64] = +{ + 0, 38, 9, 47, 2, 40, 11, 50, + 25, 12, 35, 22, 27, 15, 37, 24, + 6, 44, 3, 41, 8, 47, 5, 43, + 31, 19, 28, 15, 34, 21, 31, 18, + 1, 39, 11, 49, 0, 39, 10, 48, + 27, 14, 36, 23, 26, 13, 35, 23, + 7, 46, 4, 43, 7, 45, 3, 42, + 33, 20, 30, 17, 32, 19, 29, 16 +}; + +int imPaletteUniformIndexHalftoned(long color, int x, int y) +{ + int lHalf = iHalftone8x8Table[(x % 8) * 8 + y % 8]; + + imbyte red, green, blue; + imColorDecode(&red, &green, &blue, color); + + /* Now, look up each value in the halftone matrix using an 8x8 ordered dither.*/ + int lRed = iDividedBy51Table[red] + (iModulo51Table[red] > lHalf? 1: 0); + int lGreen = iDividedBy51Table[green] + (iModulo51Table[green] > lHalf? 1: 0); + int lBlue = iDividedBy51Table[blue] + (iModulo51Table[blue] > lHalf? 1: 0); + + return iTimes36Table[lRed] + iTimes6Table[lGreen] + lBlue; +} diff --git a/im/src/im_process.def b/im/src/im_process.def new file mode 100755 index 0000000..07bba47 --- /dev/null +++ b/im/src/im_process.def @@ -0,0 +1,165 @@ +EXPORTS + imCalcRMSError + imCalcSNR + imProcessAutoCovariance + imProcessBinMorphClose + imProcessBinMorphConvolve + imProcessBinMorphDilate + imProcessBinMorphErode + imProcessBinMorphOpen + imProcessBinMorphOutline + imProcessCompassConvolve + imProcessConvolve + imProcessConvolveRep + imProcessConvolveSep + imProcessDiffOfGaussianConvolve + imProcessGaussianConvolve + imProcessGrayMorphClose + imProcessGrayMorphConvolve + imProcessGrayMorphDilate + imProcessGrayMorphErode + imProcessGrayMorphGradient + imProcessGrayMorphOpen + imProcessGrayMorphTopHat + imProcessGrayMorphWell + imProcessHoughLines + imProcessHoughLinesDraw + imProcessLapOfGaussianConvolve + imProcessLocalMaxThreshold + imProcessMeanConvolve + imProcessMedianConvolve + imProcessMinMaxThreshold + imProcessOtsuThreshold + imProcessPercentThreshold + imProcessRadial + imProcessRangeContrastThreshold + imProcessRangeConvolve + imProcessRankClosestConvolve + imProcessRankMaxConvolve + imProcessRankMinConvolve + imProcessReduce + imProcessRenderAddGaussianNoise + imProcessRenderAddSpeckleNoise + imProcessRenderAddUniformNoise + imProcessRenderBox + imProcessRenderCondOp + imProcessRenderCone + imProcessRenderConstant + imProcessRenderCosine + imProcessRenderGaussian + imProcessRenderLapOfGaussian + imProcessRenderOp + imProcessRenderRamp + imProcessRenderRandomNoise + imProcessRenderSinc + imProcessRenderTent + imProcessRenderWheel + imProcessResize + imProcessRotate + imProcessSobelConvolve + imProcessUniformErrThreshold + imCalcCountColors + imCalcGrayHistogram + imCalcHistogram + imCalcHistogramStatistics + imCalcHistoImageStatistics + imCalcImageStatistics + imProcessPixelate + imProcessArithmeticConstOp + imProcessArithmeticOp + imProcessBinMorphThin + imProcessBitMask + imProcessBitPlane + imProcessBitwiseOp + imProcessBlendConst + imProcessBlend + imProcessCalcRotateSize + imProcessDifusionErrThreshold + imProcessDirectConv + imProcessEqualizeHistogram + imProcessExpandHistogram + imProcessFlip + imProcessHysteresisThresEstimate + imProcessHysteresisThreshold + imProcessLocalMaxThresEstimate + imProcessMergeComplex + imProcessMergeComponents + imProcessMergeHSI + imProcessMirror + imProcessMultipleMean + imProcessMultipleStdDev + imProcessQuantizeGrayUniform + imProcessQuantizeRGBUniform + imProcessReduceBy4 + imProcessRotate180 + imProcessRotate90 + imProcessSplitComplex + imProcessSplitComponents + imProcessSplitHSI + imProcessSplitYChroma + imProcessThreshold + imProcessThresholdByDiff + imProcessToneGamut + imProcessUnArithmeticOp + imProcessUnNormalize + imProcessZeroCrossing + imProcessRotateKernel + imProcessAddMargins + imProcessReplaceColor + imProcessPosterize + imProcessNegative + imProcessCanny + imProcessMultiplyConj + imProcessNormalizeComponents + imGaussianStdDev2KernelSize + imProcessBitwiseNot + imProcessDistanceTransform + imAnalyzeFindRegions + imAnalyzeMeasureArea + imAnalyzeMeasureCentroid + imAnalyzeMeasurePrincipalAxis + imAnalyzeMeasureHoles + imProcessPerimeterLine + imAnalyzeMeasurePerimeter + imProcessRemoveByArea + imProcessFillHoles + imAnalyzeMeasurePerimArea + imProcessSliceThreshold + imProcessRenderGrid + imProcessRenderChessboard + imProcessInsert + imProcessCrop + imProcessRegionalMaximum + imCalcUShortHistogram + imProcessSwirl + imProcessPrewittConvolve + imProcessSplineEdgeConvolve + imProcessConvolveDual + imKernelSobel + imKernelPrewitt + imKernelKirsh + imKernelLaplacian4 + imKernelLaplacian8 + imKernelLaplacian5x5 + imKernelLaplacian7x7 + imKernelGradian3x3 + imKernelGradian7x7 + imKernelSculpt + imKernelMean3x3 + imKernelMean5x5 + imKernelCircularMean5x5 + imKernelMean7x7 + imKernelCircularMean7x7 + imKernelGaussian3x3 + imKernelGaussian5x5 + imKernelBarlett5x5 + imKernelTopHat5x5 + imKernelTopHat7x7 + imKernelEnhance + imGaussianKernelSize2StdDev + imProcessRotateRef + imProcessInterlaceSplit + imProcessBarlettConvolve + imProcessUnsharp + imProcessSharp + imProcessSharpKernel diff --git a/im/src/im_process.dep b/im/src/im_process.dep new file mode 100644 index 0000000..83b76c9 --- /dev/null +++ b/im/src/im_process.dep @@ -0,0 +1,84 @@ +$(OBJDIR)/im_arithmetic_bin.o: process/im_arithmetic_bin.cpp ../include/im.h \ + ../include/old_im.h ../include/im_util.h ../include/im_math.h \ + ../include/im_util.h ../include/im_complex.h ../include/im_math.h \ + ../include/im_counter.h ../include/im_process_pon.h \ + ../include/im_image.h ../include/im_math_op.h ../include/im_complex.h +$(OBJDIR)/im_morphology_gray.o: process/im_morphology_gray.cpp ../include/im.h \ + ../include/old_im.h ../include/im_util.h ../include/im_counter.h \ + ../include/im_convert.h ../include/im_image.h \ + ../include/im_process_loc.h ../include/im_process_pon.h +$(OBJDIR)/im_quantize.o: process/im_quantize.cpp ../include/im.h \ + ../include/old_im.h ../include/im_util.h ../include/im_palette.h \ + ../include/im_math.h ../include/im_util.h ../include/im_process_pon.h \ + ../include/im_image.h +$(OBJDIR)/im_arithmetic_un.o: process/im_arithmetic_un.cpp ../include/im.h \ + ../include/old_im.h ../include/im_util.h ../include/im_math.h \ + ../include/im_util.h ../include/im_complex.h ../include/im_math.h \ + ../include/im_process_pon.h ../include/im_image.h \ + ../include/im_math_op.h ../include/im_complex.h +$(OBJDIR)/im_geometric.o: process/im_geometric.cpp ../include/im.h \ + ../include/old_im.h ../include/im_util.h ../include/im_counter.h \ + ../include/im_process_loc.h ../include/im_image.h \ + ../include/im_math_op.h ../include/im_complex.h ../include/im_math.h \ + ../include/im_util.h +$(OBJDIR)/im_render.o: process/im_render.cpp ../include/im.h ../include/old_im.h \ + ../include/im_util.h ../include/im_counter.h ../include/im_math.h \ + ../include/im_util.h ../include/im_process_pon.h ../include/im_image.h +$(OBJDIR)/im_color.o: process/im_color.cpp ../include/im.h ../include/old_im.h \ + ../include/im_util.h ../include/im_colorhsi.h ../include/im_palette.h \ + ../include/im_process_pon.h ../include/im_image.h +$(OBJDIR)/im_histogram.o: process/im_histogram.cpp ../include/im.h \ + ../include/old_im.h ../include/im_util.h ../include/im_math.h \ + ../include/im_util.h ../include/im_process_pon.h ../include/im_image.h \ + ../include/im_process_ana.h +$(OBJDIR)/im_resize.o: process/im_resize.cpp ../include/im.h ../include/old_im.h \ + ../include/im_util.h ../include/im_math.h ../include/im_util.h \ + ../include/im_complex.h ../include/im_math.h ../include/im_counter.h \ + ../include/im_process_loc.h ../include/im_image.h +$(OBJDIR)/im_convolve.o: process/im_convolve.cpp ../include/im.h \ + ../include/old_im.h ../include/im_util.h ../include/im_counter.h \ + ../include/im_complex.h ../include/im_math.h ../include/im_util.h \ + ../include/im_math_op.h ../include/im_complex.h ../include/im_image.h \ + ../include/im_kernel.h ../include/im_process_loc.h \ + ../include/im_image.h ../include/im_process_pon.h +$(OBJDIR)/im_houghline.o: process/im_houghline.cpp ../include/im.h \ + ../include/old_im.h ../include/im_util.h ../include/im_complex.h \ + ../include/im_math.h ../include/im_util.h ../include/im_convert.h \ + ../include/im_image.h ../include/im_counter.h \ + ../include/im_process_glo.h +$(OBJDIR)/im_statistics.o: process/im_statistics.cpp ../include/im.h \ + ../include/old_im.h ../include/im_util.h ../include/im_math_op.h \ + ../include/im_complex.h ../include/im_math.h ../include/im_util.h \ + ../include/im_process_ana.h ../include/im_image.h +$(OBJDIR)/im_convolve_rank.o: process/im_convolve_rank.cpp ../include/im.h \ + ../include/old_im.h ../include/im_util.h ../include/im_counter.h \ + ../include/im_math.h ../include/im_util.h ../include/im_process_loc.h \ + ../include/im_image.h +$(OBJDIR)/im_logic.o: process/im_logic.cpp ../include/im.h ../include/old_im.h \ + ../include/im_util.h ../include/im_process_pon.h ../include/im_image.h +$(OBJDIR)/im_threshold.o: process/im_threshold.cpp ../include/im.h \ + ../include/old_im.h ../include/im_util.h ../include/im_process_pon.h \ + ../include/im_image.h ../include/im_process_ana.h +$(OBJDIR)/im_effects.o: process/im_effects.cpp ../include/im.h ../include/old_im.h \ + ../include/im_util.h ../include/im_math.h ../include/im_util.h \ + ../include/im_complex.h ../include/im_math.h \ + ../include/im_process_pon.h ../include/im_image.h \ + ../include/im_math_op.h ../include/im_complex.h +$(OBJDIR)/im_morphology_bin.o: process/im_morphology_bin.cpp ../include/im.h \ + ../include/old_im.h ../include/im_util.h ../include/im_counter.h \ + ../include/im_process_loc.h ../include/im_image.h \ + ../include/im_process_pon.h +$(OBJDIR)/im_tonegamut.o: process/im_tonegamut.cpp ../include/im.h \ + ../include/old_im.h ../include/im_util.h ../include/im_math.h \ + ../include/im_util.h ../include/im_process_pon.h ../include/im_image.h +$(OBJDIR)/im_canny.o: process/im_canny.cpp ../include/im.h ../include/old_im.h \ + ../include/im_process_loc.h ../include/im_image.h +$(OBJDIR)/im_distance.o: process/im_distance.cpp ../include/im.h \ + ../include/old_im.h ../include/im_util.h ../include/im_process_glo.h \ + ../include/im_image.h +$(OBJDIR)/im_analyze.o: process/im_analyze.cpp ../include/im.h ../include/old_im.h \ + ../include/im_util.h ../include/im_math.h ../include/im_util.h \ + ../include/im_process_ana.h ../include/im_image.h \ + ../include/im_process_pon.h +$(OBJDIR)/im_kernel.o: process/im_kernel.cpp ../include/im.h ../include/old_im.h \ + ../include/im_util.h ../include/im_image.h ../include/im_kernel.h diff --git a/im/src/im_process.mak b/im/src/im_process.mak new file mode 100755 index 0000000..064be76 --- /dev/null +++ b/im/src/im_process.mak @@ -0,0 +1,36 @@ +PROJNAME = im +LIBNAME = im_process +OPT = YES + +SRC = \ + im_arithmetic_bin.cpp im_morphology_gray.cpp im_quantize.cpp \ + im_arithmetic_un.cpp im_geometric.cpp im_render.cpp \ + im_color.cpp im_histogram.cpp im_resize.cpp \ + im_convolve.cpp im_houghline.cpp im_statistics.cpp \ + im_convolve_rank.cpp im_logic.cpp im_threshold.cpp \ + im_effects.cpp im_morphology_bin.cpp im_tonegamut.cpp \ + im_canny.cpp im_distance.cpp im_analyze.cpp \ + im_kernel.cpp +SRC := $(addprefix process/, $(SRC)) + +USE_IM = Yes +IM = .. + +ifneq ($(findstring Win, $(TEC_SYSNAME)), ) + ifneq ($(findstring ow, $(TEC_UNAME)), ) + DEFINES += IM_DEFMATHFLOAT + endif + ifneq ($(findstring bc, $(TEC_UNAME)), ) + DEFINES += IM_DEFMATHFLOAT + endif +else + ifneq ($(findstring AIX, $(TEC_UNAME)), ) + DEFINES += IM_DEFMATHFLOAT + endif + ifneq ($(findstring SunOS, $(TEC_UNAME)), ) + DEFINES += IM_DEFMATHFLOAT + endif + ifneq ($(findstring HP-UX, $(TEC_UNAME)), ) + DEFINES += IM_DEFMATHFLOAT + endif +endif diff --git a/im/src/im_rgb2map.cpp b/im/src/im_rgb2map.cpp new file mode 100755 index 0000000..465743a --- /dev/null +++ b/im/src/im_rgb2map.cpp @@ -0,0 +1,964 @@ +/** \file + * \brief RGB to Map Conversion + * + * Most part of this code is based on jquant2.c from version 5 + * of the IJG JPEG software, + * copyright (C) 1991-1994, Thomas G. Lane. + * Some other parts are from XV software + * copyright John Bradley. + * This file doen not follows the IM library nomenclature convention. + * + * See Copyright Notice in im_lib.h + * $Id: im_rgb2map.cpp,v 1.1 2008/10/17 06:10:16 scuri Exp $ + */ + + +#include +#include +#include + +#include "im.h" +#include "im_util.h" +#include "im_convert.h" +#include "im_counter.h" + + +/* RANGE forces a to be in the range b..c (inclusive) */ +#define RANGE(a,b,c) { if (a < b) a = b; if (a > c) a = c; } + +static void xvbcopy(const imbyte* src, imbyte* dst, int len) +{ + /* determine if the regions overlap + * + * 3 cases: src=dst, srcdst + * + * if src=dst, they overlap completely, but nothing needs to be moved + * if srcdst then they overlap + * if src>dst and srcdst) { /* do a backward copy */ + src = src + len - 1; + dst = dst + len - 1; + for ( ; len>0; len--, src--, dst--) *dst = *src; + } + + else { /* they either overlap (src>dst) or they don't overlap */ + /* do a forward copy */ + for ( ; len>0; len--, src++, dst++) *dst = *src; + } +} + +/****************************/ +static int quick_map(imbyte *red, imbyte *green, imbyte *blue, int w, int h, imbyte *map, + imbyte *rmap, imbyte *gmap, imbyte *bmap, int maxcol) +{ +/* scans picture until it finds more than 'maxcol' different colors. If it +finds more than 'maxcol' colors, it returns '0'. If it DOESN'T, it does +the 24-to-8 conversion by simply sticking the colors it found into +a colormap, and changing instances of a color in pic24 into colormap + indicies (in pic8) */ + + unsigned long colors[256],col; + int i, nc, low, high, mid, count; + imbyte *pred, *pgreen, *pblue, *pix; + + if (maxcol>256) maxcol = 256; + + /* put the first color in the table by hand */ + nc = 0; mid = 0; + + count = w*h; + for (i=count,pred=red,pgreen=green,pblue=blue; i; i--) + { + col = (((unsigned long) *pred++) << 16); + col += (((unsigned long) *pgreen++) << 8); + col += *pblue++; + + /* binary search the 'colors' array to see if it's in there */ + low = 0; high = nc-1; + while (low <= high) + { + mid = (low+high)/2; + if (col < colors[mid]) high = mid - 1; + else if (col > colors[mid]) low = mid + 1; + else break; + } + + if (high < low) + { /* didn't find color in list, add it. */ + if (nc>=maxcol) + return 0; + + xvbcopy((const imbyte*)&colors[low], (imbyte*)&colors[low+1], (nc - low) * sizeof(unsigned long)); + colors[low] = col; + nc++; + } + } + + /* run through the data a second time, this time mapping pixel values in + pic24 into colormap offsets into 'colors' */ + + for (i=count,pred=red,pgreen=green,pblue=blue, pix=map; i; i--,pix++) + { + col = (((unsigned long) *pred++) << 16); + col += (((unsigned long) *pgreen++) << 8); + col += *pblue++; + + /* binary search the 'colors' array. It *IS* in there */ + low = 0; high = nc-1; + while (low <= high) + { + mid = (low+high)/2; + if (col < colors[mid]) high = mid - 1; + else if (col > colors[mid]) low = mid + 1; + else break; + } + + if (high < low) + return 0; + + *pix = (imbyte)mid; + } + + /* and load up the 'desired colormap' */ + for (i=0; i>16); + gmap[i] = (unsigned char)((colors[i]>>8) & 0xff); + bmap[i] = (unsigned char)( colors[i] & 0xff); + } + + return nc; +} + +#define MAXNUMCOLORS 256 /* maximum size of colormap */ + +#define C0_SCALE 2 /* scale R distances by this much */ +#define C1_SCALE 3 /* scale G distances by this much */ +#define C2_SCALE 1 /* and B by this much */ + +#define HIST_C0_BITS 5 /* bits of precision in R histogram */ +#define HIST_C1_BITS 6 /* bits of precision in G histogram */ +#define HIST_C2_BITS 5 /* bits of precision in B histogram */ + +/* Number of elements along histogram axes. */ +#define HIST_C0_ELEMS (1< 0) + { + /* get pixel value and index into the histogram */ + histp = & histogram[*red >> C0_SHIFT] [*green >> C1_SHIFT] [*blue >> C2_SHIFT]; + + /* increment, check for overflow and undo increment if so. */ + if (++(*histp) <= 0) + (*histp)--; + + red++; + green++; + blue++; + } +} + + +static boxptr find_biggest_color_pop (boxptr boxlist, int numboxes) +{ + register boxptr boxp; + register int i; + register long maxc = 0; + boxptr which = NULL; + + for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { + if (boxp->colorcount > maxc && boxp->volume > 0) { + which = boxp; + maxc = boxp->colorcount; + } + } + return which; +} + +static boxptr find_biggest_volume (boxptr boxlist, int numboxes) +{ + register boxptr boxp; + register int i; + register int maxv = 0; + boxptr which = NULL; + + for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { + if (boxp->volume > maxv) { + which = boxp; + maxv = boxp->volume; + } + } + return which; +} + + +static void update_box (boxptr boxp) +{ + hist2d * histogram = sl_histogram; + histptr histp; + int c0,c1,c2; + int c0min,c0max,c1min,c1max,c2min,c2max; + int dist0,dist1,dist2; + long ccount; + + c0min = boxp->c0min; c0max = boxp->c0max; + c1min = boxp->c1min; c1max = boxp->c1max; + c2min = boxp->c2min; c2max = boxp->c2max; + + if (c0max > c0min) + for (c0 = c0min; c0 <= c0max; c0++) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c0min = c0min = c0; + goto have_c0min; + } + } +have_c0min: + if (c0max > c0min) + for (c0 = c0max; c0 >= c0min; c0--) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c0max = c0max = c0; + goto have_c0max; + } + } +have_c0max: + if (c1max > c1min) + for (c1 = c1min; c1 <= c1max; c1++) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c1min = c1min = c1; + goto have_c1min; + } + } +have_c1min: + if (c1max > c1min) + for (c1 = c1max; c1 >= c1min; c1--) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c1max = c1max = c1; + goto have_c1max; + } + } +have_c1max: + if (c2max > c2min) + for (c2 = c2min; c2 <= c2max; c2++) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1min][c2]; + for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) + if (*histp != 0) { + boxp->c2min = c2min = c2; + goto have_c2min; + } + } +have_c2min: + if (c2max > c2min) + for (c2 = c2max; c2 >= c2min; c2--) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1min][c2]; + for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) + if (*histp != 0) { + boxp->c2max = c2max = c2; + goto have_c2max; + } + } +have_c2max: + + dist0 = ((c0max - c0min) << C0_SHIFT) * C0_SCALE; + dist1 = ((c1max - c1min) << C1_SHIFT) * C1_SCALE; + dist2 = ((c2max - c2min) << C2_SHIFT) * C2_SCALE; + boxp->volume = dist0*dist0 + dist1*dist1 + dist2*dist2; + + ccount = 0; + for (c0 = c0min; c0 <= c0max; c0++) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++, histp++) + if (*histp != 0) { + ccount++; + } + } + boxp->colorcount = ccount; +} + + +static int median_cut (boxptr boxlist, int numboxes, int desired_colors) +{ + int n,lb; + int c0,c1,c2,cmax; + register boxptr b1,b2; + + while (numboxes < desired_colors) { + /* Select box to split. + * Current algorithm: by population for first half, then by volume. + */ + if (numboxes*2 <= desired_colors) { + b1 = find_biggest_color_pop(boxlist, numboxes); + } else { + b1 = find_biggest_volume(boxlist, numboxes); + } + if (b1 == NULL) /* no splittable boxes left! */ + break; + b2 = &boxlist[numboxes]; /* where new box will go */ + /* Copy the color bounds to the new box. */ + b2->c0max = b1->c0max; b2->c1max = b1->c1max; b2->c2max = b1->c2max; + b2->c0min = b1->c0min; b2->c1min = b1->c1min; b2->c2min = b1->c2min; + /* Choose which axis to split the box on. + */ + c0 = ((b1->c0max - b1->c0min) << C0_SHIFT) * C0_SCALE; + c1 = ((b1->c1max - b1->c1min) << C1_SHIFT) * C1_SCALE; + c2 = ((b1->c2max - b1->c2min) << C2_SHIFT) * C2_SCALE; + cmax = c1; n = 1; + if (c0 > cmax) { cmax = c0; n = 0; } + if (c2 > cmax) { n = 2; } + switch (n) { + case 0: + lb = (b1->c0max + b1->c0min) / 2; + b1->c0max = lb; + b2->c0min = lb+1; + break; + case 1: + lb = (b1->c1max + b1->c1min) / 2; + b1->c1max = lb; + b2->c1min = lb+1; + break; + case 2: + lb = (b1->c2max + b1->c2min) / 2; + b1->c2max = lb; + b2->c2min = lb+1; + break; + } + /* Update stats for boxes */ + update_box(b1); + update_box(b2); + numboxes++; + } + return numboxes; +} + +static void compute_color (boxptr boxp, int icolor) +{ + /* Current algorithm: mean weighted by pixels (not colors) */ + /* Note it is important to get the rounding correct! */ + hist2d * histogram = sl_histogram; + histptr histp; + int c0,c1,c2; + int c0min,c0max,c1min,c1max,c2min,c2max; + long count; + long total = 0; + long c0total = 0; + long c1total = 0; + long c2total = 0; + + c0min = boxp->c0min; c0max = boxp->c0max; + c1min = boxp->c1min; c1max = boxp->c1max; + c2min = boxp->c2min; c2max = boxp->c2max; + + for (c0 = c0min; c0 <= c0max; c0++) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) { + if ((count = *histp++) != 0) { + total += count; + c0total += ((c0 << C0_SHIFT) + ((1<>1)) * count; + c1total += ((c1 << C1_SHIFT) + ((1<>1)) * count; + c2total += ((c2 << C2_SHIFT) + ((1<>1)) * count; + } + } + } + + sl_colormap[0][icolor] = (imbyte) ((c0total + (total>>1)) / total); + sl_colormap[1][icolor] = (imbyte) ((c1total + (total>>1)) / total); + sl_colormap[2][icolor] = (imbyte) ((c2total + (total>>1)) / total); +} + + +static void slow_select_colors (int descolors) +/* Master routine for color selection */ +{ + box boxlist[MAXNUMCOLORS]; + int numboxes; + int i; + + /* Initialize one box containing whole space */ + numboxes = 1; + boxlist[0].c0min = 0; + boxlist[0].c0max = 255 >> C0_SHIFT; + boxlist[0].c1min = 0; + boxlist[0].c1max = 255 >> C1_SHIFT; + boxlist[0].c2min = 0; + boxlist[0].c2max = 255 >> C2_SHIFT; + /* Shrink it to actually-used volume and set its statistics */ + update_box(& boxlist[0]); + /* Perform median-cut to produce final box list */ + numboxes = median_cut(boxlist, numboxes, descolors); + /* Compute the representative color for each box, fill colormap */ + for (i = 0; i < numboxes; i++) + compute_color(& boxlist[i], i); + sl_num_colors = numboxes; +} + + +/* log2(histogram cells in update box) for each axis; this can be adjusted */ +#define BOX_C0_LOG (HIST_C0_BITS-3) +#define BOX_C1_LOG (HIST_C1_BITS-3) +#define BOX_C2_LOG (HIST_C2_BITS-3) + +#define BOX_C0_ELEMS (1<> 1; + maxc1 = minc1 + ((1 << BOX_C1_SHIFT) - (1 << C1_SHIFT)); + centerc1 = (minc1 + maxc1) >> 1; + maxc2 = minc2 + ((1 << BOX_C2_SHIFT) - (1 << C2_SHIFT)); + centerc2 = (minc2 + maxc2) >> 1; + + minmaxdist = 0x7FFFFFFFL; + + for (i = 0; i < numcolors; i++) { + /* We compute the squared-c0-distance term, then add in the other two. */ + x = sl_colormap[0][i]; + if (x < minc0) { + tdist = (x - minc0) * C0_SCALE; + min_dist = tdist*tdist; + tdist = (x - maxc0) * C0_SCALE; + max_dist = tdist*tdist; + } else if (x > maxc0) { + tdist = (x - maxc0) * C0_SCALE; + min_dist = tdist*tdist; + tdist = (x - minc0) * C0_SCALE; + max_dist = tdist*tdist; + } else { + /* within cell range so no contribution to min_dist */ + min_dist = 0; + if (x <= centerc0) { + tdist = (x - maxc0) * C0_SCALE; + max_dist = tdist*tdist; + } else { + tdist = (x - minc0) * C0_SCALE; + max_dist = tdist*tdist; + } + } + + x = sl_colormap[1][i]; + if (x < minc1) { + tdist = (x - minc1) * C1_SCALE; + min_dist += tdist*tdist; + tdist = (x - maxc1) * C1_SCALE; + max_dist += tdist*tdist; + } else if (x > maxc1) { + tdist = (x - maxc1) * C1_SCALE; + min_dist += tdist*tdist; + tdist = (x - minc1) * C1_SCALE; + max_dist += tdist*tdist; + } else { + /* within cell range so no contribution to min_dist */ + if (x <= centerc1) { + tdist = (x - maxc1) * C1_SCALE; + max_dist += tdist*tdist; + } else { + tdist = (x - minc1) * C1_SCALE; + max_dist += tdist*tdist; + } + } + + x = sl_colormap[2][i]; + if (x < minc2) { + tdist = (x - minc2) * C2_SCALE; + min_dist += tdist*tdist; + tdist = (x - maxc2) * C2_SCALE; + max_dist += tdist*tdist; + } else if (x > maxc2) { + tdist = (x - maxc2) * C2_SCALE; + min_dist += tdist*tdist; + tdist = (x - minc2) * C2_SCALE; + max_dist += tdist*tdist; + } else { + /* within cell range so no contribution to min_dist */ + if (x <= centerc2) { + tdist = (x - maxc2) * C2_SCALE; + max_dist += tdist*tdist; + } else { + tdist = (x - minc2) * C2_SCALE; + max_dist += tdist*tdist; + } + } + + mindist[i] = min_dist; /* save away the results */ + if (max_dist < minmaxdist) + minmaxdist = max_dist; + } + + ncolors = 0; + for (i = 0; i < numcolors; i++) { + if (mindist[i] <= minmaxdist) + colorlist[ncolors++] = (imbyte) i; + } + return ncolors; +} + + +static void find_best_colors (int minc0, int minc1, int minc2, int numcolors, + imbyte* colorlist, imbyte* bestcolor) +{ + int ic0, ic1, ic2; + int i, icolor; + register int * bptr; /* pointer into bestdist[] array */ + imbyte * cptr; /* pointer into bestcolor[] array */ + int dist0, dist1; /* initial distance values */ + register int dist2; /* current distance in inner loop */ + int xx0, xx1; /* distance increments */ + register int xx2; + int inc0, inc1, inc2; /* initial values for increments */ + /* This array holds the distance to the nearest-so-far color for each cell */ + int bestdist[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; + + /* Initialize best-distance for each cell of the update box */ + bptr = bestdist; + for (i = BOX_C0_ELEMS*BOX_C1_ELEMS*BOX_C2_ELEMS-1; i >= 0; i--) + *bptr++ = 0x7FFFFFFFL; + + /* Nominal steps between cell centers ("x" in Thomas article) */ +#define STEP_C0 ((1 << C0_SHIFT) * C0_SCALE) +#define STEP_C1 ((1 << C1_SHIFT) * C1_SCALE) +#define STEP_C2 ((1 << C2_SHIFT) * C2_SCALE) + + for (i = 0; i < numcolors; i++) { + icolor = colorlist[i]; + /* Compute (square of) distance from minc0/c1/c2 to this color */ + inc0 = (minc0 - (int) sl_colormap[0][icolor]) * C0_SCALE; + dist0 = inc0*inc0; + inc1 = (minc1 - (int) sl_colormap[1][icolor]) * C1_SCALE; + dist0 += inc1*inc1; + inc2 = (minc2 - (int) sl_colormap[2][icolor]) * C2_SCALE; + dist0 += inc2*inc2; + /* Form the initial difference increments */ + inc0 = inc0 * (2 * STEP_C0) + STEP_C0 * STEP_C0; + inc1 = inc1 * (2 * STEP_C1) + STEP_C1 * STEP_C1; + inc2 = inc2 * (2 * STEP_C2) + STEP_C2 * STEP_C2; + /* Now loop over all cells in box, updating distance per Thomas method */ + bptr = bestdist; + cptr = bestcolor; + xx0 = inc0; + for (ic0 = BOX_C0_ELEMS-1; ic0 >= 0; ic0--) { + dist1 = dist0; + xx1 = inc1; + for (ic1 = BOX_C1_ELEMS-1; ic1 >= 0; ic1--) { + dist2 = dist1; + xx2 = inc2; + for (ic2 = BOX_C2_ELEMS-1; ic2 >= 0; ic2--) { + if (dist2 < *bptr) { + *bptr = dist2; + *cptr = (imbyte) icolor; + } + dist2 += xx2; + xx2 += 2 * STEP_C2 * STEP_C2; + bptr++; + cptr++; + } + dist1 += xx1; + xx1 += 2 * STEP_C1 * STEP_C1; + } + dist0 += xx0; + xx0 += 2 * STEP_C0 * STEP_C0; + } + } +} + + +static void fill_inverse_cmap (int c0, int c1, int c2) +{ + hist2d * histogram = sl_histogram; + int minc0, minc1, minc2; /* lower left corner of update box */ + int ic0, ic1, ic2; + register imbyte * cptr; /* pointer into bestcolor[] array */ + register histptr cachep; /* pointer into main cache array */ + /* This array lists the candidate colormap indexes. */ + imbyte colorlist[MAXNUMCOLORS]; + int numcolors; /* number of candidate colors */ + /* This array holds the actually closest colormap index for each cell. */ + imbyte bestcolor[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; + + /* Convert cell coordinates to update box ID */ + c0 >>= BOX_C0_LOG; + c1 >>= BOX_C1_LOG; + c2 >>= BOX_C2_LOG; + + minc0 = (c0 << BOX_C0_SHIFT) + ((1 << C0_SHIFT) >> 1); + minc1 = (c1 << BOX_C1_SHIFT) + ((1 << C1_SHIFT) >> 1); + minc2 = (c2 << BOX_C2_SHIFT) + ((1 << C2_SHIFT) >> 1); + + numcolors = find_nearby_colors(minc0, minc1, minc2, colorlist); + + /* Determine the actually nearest colors. */ + find_best_colors(minc0, minc1, minc2, numcolors, colorlist, bestcolor); + + /* Save the best color numbers (plus 1) in the main cache array */ + c0 <<= BOX_C0_LOG; /* convert ID back to base cell indexes */ + c1 <<= BOX_C1_LOG; + c2 <<= BOX_C2_LOG; + cptr = bestcolor; + for (ic0 = 0; ic0 < BOX_C0_ELEMS; ic0++) { + for (ic1 = 0; ic1 < BOX_C1_ELEMS; ic1++) { + cachep = & histogram[c0+ic0][c1+ic1][c2]; + for (ic2 = 0; ic2 < BOX_C2_ELEMS; ic2++) { + *cachep++ = (histcell) (*cptr++ + 1); + } + } + } +} + + +static void slow_map_pixels (imbyte *red, imbyte *green, imbyte *blue, int width, int height, imbyte *map) +{ + register LOCFSERROR cur0, cur1, cur2; /* current error or pixel value */ + LOCFSERROR belowerr0, belowerr1, belowerr2; /* error for pixel below cur */ + LOCFSERROR bpreverr0, bpreverr1, bpreverr2; /* error for below/prev col */ + register FSERRPTR errorptr; /* => fserrors[] at column before current */ + imbyte *inRptr, *inGptr, *inBptr; /* => current input pixel */ + imbyte* outptr; /* => current output pixel */ + histptr cachep; + int dir; /* +1 or -1 depending on direction */ + int dir3; /* 3*dir, for advancing errorptr */ + int row, col, offset; + int *error_limit = sl_error_limiter; + imbyte* colormap0 = sl_colormap[0]; + imbyte* colormap1 = sl_colormap[1]; + imbyte* colormap2 = sl_colormap[2]; + hist2d * histogram = sl_histogram; + + for (row = 0; row < height; row++) + { + offset = row * width; + + inRptr = & red[offset]; + inGptr = & green[offset]; + inBptr = & blue[offset]; + outptr = & map[offset]; + + if (sl_on_odd_row) + { + /* work right to left in this row */ + offset = width-1; + + inRptr += offset; /* so point to rightmost pixel */ + inGptr += offset; /* so point to rightmost pixel */ + inBptr += offset; /* so point to rightmost pixel */ + + outptr += offset; + + dir = -1; + dir3 = -3; + errorptr = sl_fserrors + (width+1)*3; /* => entry after last column */ + sl_on_odd_row = 0; /* flip for next time */ + } + else + { + /* work left to right in this row */ + dir = 1; + dir3 = 3; + errorptr = sl_fserrors; /* => entry before first real column */ + sl_on_odd_row = 1; /* flip for next time */ + } + + /* Preset error values: no error propagated to first pixel from left */ + cur0 = cur1 = cur2 = 0; + /* and no error propagated to row below yet */ + belowerr0 = belowerr1 = belowerr2 = 0; + bpreverr0 = bpreverr1 = bpreverr2 = 0; + + for (col = width; col > 0; col--) + { + cur0 = (cur0 + errorptr[dir3+0] + 8) >> 4; + cur1 = (cur1 + errorptr[dir3+1] + 8) >> 4; + cur2 = (cur2 + errorptr[dir3+2] + 8) >> 4; + + cur0 = error_limit[cur0]; + cur1 = error_limit[cur1]; + cur2 = error_limit[cur2]; + + cur0 += inRptr[0]; + cur1 += inGptr[0]; + cur2 += inBptr[0]; + + RANGE(cur0, 0, 255); + RANGE(cur1, 0, 255); + RANGE(cur2, 0, 255); + + /* Index into the cache with adjusted pixel value */ + cachep = & histogram[cur0>>C0_SHIFT][cur1>>C1_SHIFT][cur2>>C2_SHIFT]; + + /* If we have not seen this color before, find nearest colormap */ + /* entry and update the cache */ + if (*cachep == 0) + fill_inverse_cmap(cur0>>C0_SHIFT, cur1>>C1_SHIFT, cur2>>C2_SHIFT); + + /* Now emit the colormap index for this cell */ + { + register int pixcode = *cachep - 1; + *outptr = (imbyte) pixcode; + /* Compute representation error for this pixel */ + cur0 -= (int) colormap0[pixcode]; + cur1 -= (int) colormap1[pixcode]; + cur2 -= (int) colormap2[pixcode]; + } + + /* Compute error fractions to be propagated to adjacent pixels. + * Add these into the running sums, and simultaneously shift the + * next-line error sums left by 1 column. */ + { + register LOCFSERROR bnexterr, delta; + bnexterr = cur0; /* Process component 0 */ + delta = cur0 * 2; + cur0 += delta; /* form error * 3 */ + errorptr[0] = (FSERROR) (bpreverr0 + cur0); + cur0 += delta; /* form error * 5 */ + bpreverr0 = belowerr0 + cur0; + belowerr0 = bnexterr; + cur0 += delta; /* form error * 7 */ + bnexterr = cur1; /* Process component 1 */ + delta = cur1 * 2; + cur1 += delta; /* form error * 3 */ + errorptr[1] = (FSERROR) (bpreverr1 + cur1); + cur1 += delta; /* form error * 5 */ + bpreverr1 = belowerr1 + cur1; + belowerr1 = bnexterr; + cur1 += delta; /* form error * 7 */ + bnexterr = cur2; /* Process component 2 */ + delta = cur2 * 2; + cur2 += delta; /* form error * 3 */ + errorptr[2] = (FSERROR) (bpreverr2 + cur2); + cur2 += delta; /* form error * 5 */ + bpreverr2 = belowerr2 + cur2; + belowerr2 = bnexterr; + cur2 += delta; /* form error * 7 */ + } + + /* At this point curN contains the 7/16 error value to be propagated + * to the next pixel on the current line, and all the errors for the + * next line have been shifted over. We are therefore ready to move on. + */ + inRptr += dir; /* Advance pixel pointers to next column */ + inGptr += dir; /* Advance pixel pointers to next column */ + inBptr += dir; /* Advance pixel pointers to next column */ + outptr += dir; + errorptr += dir3; /* advance errorptr to current column */ + } + + /* Post-loop cleanup: we must unload the final error values into the + * final fserrors[] entry. Note we need not unload belowerrN because + * it is for the dummy column before or after the actual array. + */ + errorptr[0] = (FSERROR) bpreverr0; /* unload prev errs into array */ + errorptr[1] = (FSERROR) bpreverr1; + errorptr[2] = (FSERROR) bpreverr2; + } +} + + +/* Allocate and fill in the error_limiter table */ +static void init_error_limit (void) +{ + int * table; + int in, out, STEPSIZE; + + table = (int *) malloc((size_t) ((255*2+1) * sizeof(int))); + if (! table) return; + + table += 255; /* so can index -255 .. +255 */ + sl_error_limiter = table; + + STEPSIZE = ((255+1)/16); + + /* Map errors 1:1 up to +- 255/16 */ + out = 0; + for (in = 0; in < STEPSIZE; in++, out++) + { + table[in] = out; + table[-in] = -out; + } + + /* Map errors 1:2 up to +- 3*255/16 */ + for (; in < STEPSIZE*3; in++, out += (in&1) ? 0 : 1) + { + table[in] = out; + table[-in] = -out; + } + + /* Clamp the rest to final out value (which is (255+1)/8) */ + for (; in <= 255; in++) + { + table[in] = out; + table[-in] = -out; + } +} + +int imConvertRGB2Map(int width, int height, unsigned char *red, unsigned char *green, unsigned char *blue, unsigned char *map, long *palette, int *palette_count) +{ + int i, err, new_palette_count; + imbyte rm[256], gm[256], bm[256]; + + if (*palette_count <= 0 || *palette_count > 256) + *palette_count = 256; + + new_palette_count = quick_map(red, green, blue, width, height, map, rm, gm, bm, *palette_count); + if (new_palette_count) + { + for (i=0; i < new_palette_count; i++) + *palette++ = imColorEncode(rm[i], gm[i], bm[i]); + + *palette_count = new_palette_count; + return IM_ERR_NONE; + } + + err = slow_quant(red, green, blue, width, height, map, rm, gm, bm, *palette_count); + if (err) + return IM_ERR_MEM; + + for (i=0; i < *palette_count; i++) + *palette++ = imColorEncode(rm[i], gm[i], bm[i]); + + return IM_ERR_NONE; +} + diff --git a/im/src/im_str.cpp b/im/src/im_str.cpp new file mode 100755 index 0000000..f50dcf1 --- /dev/null +++ b/im/src/im_str.cpp @@ -0,0 +1,67 @@ +/** \file + * \brief String Utilities + * + * See Copyright Notice in im_lib.h + * $Id: im_str.cpp,v 1.1 2008/10/17 06:10:16 scuri Exp $ + */ + + +#include +#include +#include + +#include "im_util.h" + +int imStrEqual(const char* str1, const char* str2) +{ + assert(str1); + assert(str2); + + /* While both strings are equal and not 0 */ + while (*str1 == *str2 && *str1) + { + str1++; + str2++; + } + + /* Is last char not equal ? */ + if (*str1 != *str2) + return 0; + + return 1; +} + +int imStrNLen(const char* str, int max_len) +{ + assert(str); + + const char* start_str = str; + + while(max_len && *str) + { + max_len--; + str++; + } + + return str - start_str; +} + +int imStrCheck(const void* data, int count) +{ + const char* str = (char*)data; + + if (str[count-1] == 0) + return 1; + + while(count && *str) + { + count--; + str++; + } + + if (count > 0) + return 1; + + return 0; +} + diff --git a/im/src/im_sysfile_unix.cpp b/im/src/im_sysfile_unix.cpp new file mode 100755 index 0000000..2065bb6 --- /dev/null +++ b/im/src/im_sysfile_unix.cpp @@ -0,0 +1,211 @@ +/** \file + * \brief System Dependent Binary File Access (UNIX) + * + * See Copyright Notice in im_lib.h + * $Id: im_sysfile_unix.cpp,v 1.1 2008/10/17 06:10:16 scuri Exp $ + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "im_util.h" +#include "im_binfile.h" + + +class imBinSystemFile: public imBinFileBase +{ +protected: + int FileHandle, + Error; + + unsigned long ReadBuf(void* pValues, unsigned long pSize); + unsigned long WriteBuf(void* pValues, unsigned long pSize); + +public: + virtual void Open(const char* pFileName); + virtual void New(const char* pFileName); + virtual void Close(); + + unsigned long FileSize(); + int HasError() const; + void SeekTo(unsigned long pOffset); + void SeekOffset(long pOffset); + void SeekFrom(long pOffset); + unsigned long Tell() const; + int EndOfFile() const; +}; + +imBinFileBase* iBinSystemFileNewFunc() +{ + return new imBinSystemFile(); +} + +void imBinSystemFile::Open(const char* pFileName) +{ + int mode = O_RDONLY; +#ifdef O_BINARY + mode |= O_BINARY; +#endif + this->FileHandle = open(pFileName, mode, 0); + if (this->FileHandle < 0) + this->Error = errno; + else + this->Error = 0; + InitByteOrder(imBinCPUByteOrder()); + this->IsNew = 0; +} + +void imBinSystemFile::New(const char* pFileName) +{ + int mode = O_WRONLY | O_CREAT | O_TRUNC; +#ifdef O_BINARY + mode |= O_BINARY; +#endif + this->FileHandle = open(pFileName, mode, 0666); // User/Group/Other can read and write + if (this->FileHandle < 0) + this->Error = errno; + else + this->Error = 0; + InitByteOrder(imBinCPUByteOrder()); + this->IsNew = 1; +} + +void imBinSystemFile::Close() +{ + assert(this->FileHandle > -1); + int ret = close(this->FileHandle); + if (ret < 0) + this->Error = errno; + else + this->Error = 0; +} + +int imBinSystemFile::HasError() const +{ + if (this->FileHandle < 0 || this->Error) return 1; + return 0; +} + +unsigned long imBinSystemFile::ReadBuf(void* pValues, unsigned long pSize) +{ + assert(this->FileHandle > -1); + int ret = read(this->FileHandle, pValues, (size_t)pSize); + if (ret < 0) + this->Error = errno; + else + this->Error = 0; + return ret < 0? 0: ret; +} + +unsigned long imBinSystemFile::WriteBuf(void* pValues, unsigned long pSize) +{ + assert(this->FileHandle > -1); + int ret = write(this->FileHandle, pValues, (size_t)pSize); + if (ret < 0) + this->Error = errno; + else + this->Error = 0; + return ret < 0? 0: ret; +} + +void imBinSystemFile::SeekTo(unsigned long pOffset) +{ + assert(this->FileHandle > -1); + int ret = lseek(this->FileHandle, pOffset, SEEK_SET); + if (ret < 0) + this->Error = errno; + else + this->Error = 0; +} + +void imBinSystemFile::SeekOffset(long pOffset) +{ + assert(this->FileHandle > -1); + int ret = lseek(this->FileHandle, pOffset, SEEK_CUR); + if (ret < 0) + this->Error = errno; + else + this->Error = 0; +} + +void imBinSystemFile::SeekFrom(long pOffset) +{ + assert(this->FileHandle > -1); + int ret = lseek(this->FileHandle, pOffset, SEEK_END); + if (ret < 0) + this->Error = errno; + else + this->Error = 0; +} + +unsigned long imBinSystemFile::Tell() const +{ + assert(this->FileHandle > -1); + long offset = lseek(this->FileHandle, 0L, SEEK_CUR); + return offset < 0? 0: offset; +} + +unsigned long imBinSystemFile::FileSize() +{ + assert(this->FileHandle > -1); + long lCurrentPosition = lseek(this->FileHandle, 0L, SEEK_CUR); + long lSize = lseek(this->FileHandle, 0L, SEEK_END); + lseek(this->FileHandle, lCurrentPosition, SEEK_SET); + return lSize < 0? 0: lSize; +} + +int imBinSystemFile::EndOfFile() const +{ + assert(this->FileHandle > -1); + long lCurrentPosition = lseek(this->FileHandle, 0L, SEEK_CUR); + long lSize = lseek(this->FileHandle, 0L, SEEK_END); + lseek(this->FileHandle, lCurrentPosition, SEEK_SET); + return lCurrentPosition == lSize? 1: 0; +} + + + +class imBinSystemFileHandle: public imBinSystemFile +{ +public: + virtual void Open(const char* pFileName); + virtual void New(const char* pFileName); + virtual void Close(); +}; + +imBinFileBase* iBinSystemFileHandleNewFunc() +{ + return new imBinSystemFileHandle(); +} + +void imBinSystemFileHandle::Open(const char* pFileName) +{ + // the file was successfully opened already by the client + + int *s = (int*)pFileName; + this->FileHandle = s[0]; + InitByteOrder(imBinCPUByteOrder()); + this->IsNew = 0; + this->Error = 0; +} + +void imBinSystemFileHandle::New(const char* pFileName) +{ + // the file was successfully opened already the client + + int *s = (int*)pFileName; + this->FileHandle = s[0]; + InitByteOrder(imBinCPUByteOrder()); + this->IsNew = 1; + this->Error = 0; +} + +void imBinSystemFileHandle::Close() +{ + // does nothing, the client must close the file +} diff --git a/im/src/im_sysfile_win32.cpp b/im/src/im_sysfile_win32.cpp new file mode 100755 index 0000000..1daf85b --- /dev/null +++ b/im/src/im_sysfile_win32.cpp @@ -0,0 +1,207 @@ +/** \file + * \brief System Dependent Binary File Access. + * + * See Copyright Notice in im_lib.h + * $Id: im_sysfile_win32.cpp,v 1.2 2009/10/01 16:12:24 scuri Exp $ + */ + +#include + +#include +#include +#include +#include + +#include "im_util.h" +#include "im_binfile.h" + +/* not defined in VC6 */ +#ifndef INVALID_SET_FILE_POINTER +#define INVALID_SET_FILE_POINTER ((DWORD)-1) +#endif + +class imBinSystemFile: public imBinFileBase +{ +protected: + HANDLE FileHandle; + int Error; + + unsigned long ReadBuf(void* pValues, unsigned long pSize); + unsigned long WriteBuf(void* pValues, unsigned long pSize); + +public: + virtual void Open(const char* pFileName); + virtual void New(const char* pFileName); + virtual void Close(); + + unsigned long FileSize(); + int HasError() const; + void SeekTo(unsigned long pOffset); + void SeekOffset(long pOffset); + void SeekFrom(long pOffset); + unsigned long Tell() const; + int EndOfFile() const; +}; + +imBinFileBase* iBinSystemFileNewFunc() +{ + return new imBinSystemFile(); +} + +void imBinSystemFile::Open(const char* pFileName) +{ + this->FileHandle = CreateFile(pFileName, GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + this->Error = (this->FileHandle == INVALID_HANDLE_VALUE)? 1: 0; + SetLastError(NO_ERROR); + InitByteOrder(imBinCPUByteOrder()); + this->IsNew = 0; +} + +void imBinSystemFile::New(const char* pFileName) +{ + this->FileHandle = CreateFile(pFileName, GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + this->Error = (this->FileHandle == INVALID_HANDLE_VALUE)? 1: 0; + SetLastError(NO_ERROR); + InitByteOrder(imBinCPUByteOrder()); + this->IsNew = 1; +} + +void imBinSystemFile::Close() +{ + if (this->FileHandle != INVALID_HANDLE_VALUE) + CloseHandle(this->FileHandle); + + this->FileHandle = INVALID_HANDLE_VALUE; + this->Error = 1; +} + +unsigned long imBinSystemFile::FileSize() +{ + assert(this->FileHandle != INVALID_HANDLE_VALUE); + this->Error = 0; + DWORD Size = GetFileSize(this->FileHandle, NULL); + if (Size == INVALID_FILE_SIZE) + this->Error = 1; + return Size; +} + +unsigned long imBinSystemFile::ReadBuf(void* pValues, unsigned long pSize) +{ + assert(this->FileHandle != INVALID_HANDLE_VALUE); + this->Error = 0; + DWORD dwSize = 0; + ReadFile(this->FileHandle, pValues, pSize, &dwSize, NULL); + if (dwSize != pSize) + this->Error = 1; + return dwSize; +} + +unsigned long imBinSystemFile::WriteBuf(void* pValues, unsigned long pSize) +{ + assert(this->FileHandle != INVALID_HANDLE_VALUE); + this->Error = 0; + DWORD dwSize = 0; + WriteFile(this->FileHandle, pValues, pSize, &dwSize, NULL); + if (dwSize != pSize) + this->Error = 1; + return dwSize; +} + +int imBinSystemFile::HasError() const +{ + return this->Error; +} + +void imBinSystemFile::SeekTo(unsigned long pOffset) +{ + assert(this->FileHandle != INVALID_HANDLE_VALUE); + this->Error = 0; + DWORD ret = SetFilePointer(this->FileHandle, pOffset, NULL, FILE_BEGIN); + if (ret == INVALID_SET_FILE_POINTER) + this->Error = 1; +} + +void imBinSystemFile::SeekOffset(long pOffset) +{ + assert(this->FileHandle != INVALID_HANDLE_VALUE); + this->Error = 0; + DWORD ret = SetFilePointer(this->FileHandle, pOffset, NULL, FILE_CURRENT); + if (ret == INVALID_SET_FILE_POINTER) + this->Error = 1; +} + +void imBinSystemFile::SeekFrom(long pOffset) +{ + assert(this->FileHandle != INVALID_HANDLE_VALUE); + this->Error = 0; + DWORD ret = SetFilePointer(this->FileHandle, pOffset, NULL, FILE_END); + if (ret == INVALID_SET_FILE_POINTER) + this->Error = 1; +} + +unsigned long imBinSystemFile::Tell() const +{ + assert(this->FileHandle != INVALID_HANDLE_VALUE); + return SetFilePointer(this->FileHandle, 0, NULL, FILE_CURRENT); +} + +int imBinSystemFile::EndOfFile() const +{ + assert(this->FileHandle != INVALID_HANDLE_VALUE); + DWORD cur_pos = SetFilePointer(this->FileHandle, 0, NULL, FILE_CURRENT); + DWORD end_pos = SetFilePointer(this->FileHandle, 0, NULL, FILE_END); + SetFilePointer(this->FileHandle, cur_pos, NULL, FILE_CURRENT); + return (cur_pos == end_pos)? 1: 0; +} + + + +class imBinSystemFileHandle: public imBinSystemFile +{ +public: + virtual void Open(const char* pFileName); + virtual void New(const char* pFileName); + virtual void Close(); +}; + +imBinFileBase* iBinSystemFileHandleNewFunc() +{ + return new imBinSystemFileHandle(); +} + +void imBinSystemFileHandle::Open(const char* pFileName) +{ + // the file was successfully opened already the client + + HANDLE file_handle = (HANDLE)pFileName; + this->FileHandle = file_handle; + InitByteOrder(imBinCPUByteOrder()); + this->IsNew = 0; + this->Error = 0; +} + +void imBinSystemFileHandle::New(const char* pFileName) +{ + // the file was successfully opened already the client + + HANDLE file_handle = (HANDLE)pFileName; + this->FileHandle = file_handle; + InitByteOrder(imBinCPUByteOrder()); + this->IsNew = 1; + this->Error = 0; +} + +void imBinSystemFileHandle::Close() +{ + // does nothing, the client must close the file +} diff --git a/im/src/im_wmv.def b/im/src/im_wmv.def new file mode 100755 index 0000000..1e017f3 --- /dev/null +++ b/im/src/im_wmv.def @@ -0,0 +1,2 @@ +EXPORTS + imFormatRegisterWMV \ No newline at end of file diff --git a/im/src/im_wmv.mak b/im/src/im_wmv.mak new file mode 100755 index 0000000..fef3c40 --- /dev/null +++ b/im/src/im_wmv.mak @@ -0,0 +1,23 @@ +PROJNAME = im +LIBNAME = im_wmv +OPT = YES + +SRC = im_format_wmv.cpp + +ifneq ($(findstring _64, $(TEC_UNAME)), ) + WMFSDK = d:/lng/wmfsdk95 + INCLUDES = $(WMFSDK)/include +else +# WMFSDK = d:/lng/wmfsdk11 +# EXTRAINCS = $(WMFSDK)/include + WMFSDK = d:/lng/wmfsdk9 + INCLUDES = $(WMFSDK)/include +endif + +DEFINES = _CRT_NON_CONFORMING_SWPRINTFS + +LDIR = $(WMFSDK)/lib +LIBS = wmvcore + +USE_IM = Yes +IM = .. diff --git a/im/src/imlua3.def b/im/src/imlua3.def new file mode 100755 index 0000000..d27384d --- /dev/null +++ b/im/src/imlua3.def @@ -0,0 +1,2 @@ +EXPORTS + imlua_open \ No newline at end of file diff --git a/im/src/imlua3.mak b/im/src/imlua3.mak new file mode 100755 index 0000000..aac7b00 --- /dev/null +++ b/im/src/imlua3.mak @@ -0,0 +1,12 @@ +PROJNAME = im +LIBNAME = imlua3 +OPT = YES + +SRC = im_lua3.c + +USE_LUA = Yes +#Do NOT use USE_CD because we use no CD functions, only headers are used. +INCLUDES = $(CD)/include + +USE_IM = Yes +IM = .. diff --git a/im/src/imlua5.mak b/im/src/imlua5.mak new file mode 100755 index 0000000..554b701 --- /dev/null +++ b/im/src/imlua5.mak @@ -0,0 +1,18 @@ +PROJNAME = im +LIBNAME = imlua51 + +OPT = YES + +LOHDIR = lua5/loh +SRC = lua5/imlua.c lua5/imlua_aux.c lua5/imlua_convert.c lua5/imlua_file.c lua5/imlua_image.c lua5/imlua_palette.c lua5/imlua_util.c +DEF_FILE = lua5/imlua.def + +SRCLUA = lua5/im_image.lua lua5/im_convert.lua +SRCLUADIR = lua5 + +INCLUDES = lua5 + +USE_IM = YES +USE_LUA51 = YES +NO_LUALINK = Yes +IM = .. diff --git a/im/src/imlua51.dep b/im/src/imlua51.dep new file mode 100644 index 0000000..ff88e68 --- /dev/null +++ b/im/src/imlua51.dep @@ -0,0 +1,38 @@ +$(OBJDIR)/imlua.o: lua5/imlua.c ../include/im.h ../include/old_im.h \ + ../include/im_lib.h ../include/im_image.h ../include/im_convert.h \ + ../include/im_image.h ../../lua5.1/include/lua.h \ + ../../lua5.1/include/luaconf.h ../../lua5.1/include/lauxlib.h \ + ../../lua5.1/include/lua.h ../include/imlua.h lua5/imlua_aux.h \ + lua5/imlua_image.h lua5/imlua_palette.h +$(OBJDIR)/imlua_aux.o: lua5/imlua_aux.c ../include/im.h ../include/old_im.h \ + ../include/im_image.h ../include/im_util.h ../../lua5.1/include/lua.h \ + ../../lua5.1/include/luaconf.h ../../lua5.1/include/lauxlib.h \ + ../../lua5.1/include/lua.h ../include/imlua.h lua5/imlua_aux.h \ + lua5/imlua_image.h +$(OBJDIR)/imlua_convert.o: lua5/imlua_convert.c ../include/im.h ../include/old_im.h \ + ../include/im_image.h ../include/im_convert.h ../include/im_image.h \ + ../../lua5.1/include/lua.h ../../lua5.1/include/luaconf.h \ + ../../lua5.1/include/lauxlib.h ../../lua5.1/include/lua.h \ + ../include/imlua.h lua5/imlua_image.h lua5/imlua_aux.h \ + lua5/loh/im_convert_be64.loh +$(OBJDIR)/imlua_file.o: lua5/imlua_file.c ../include/im.h ../include/old_im.h \ + ../include/im_raw.h ../include/im_image.h ../include/im_util.h \ + ../../lua5.1/include/lua.h ../../lua5.1/include/luaconf.h \ + ../../lua5.1/include/lauxlib.h ../../lua5.1/include/lua.h \ + ../include/imlua.h lua5/imlua_aux.h lua5/imlua_image.h \ + lua5/imlua_palette.h +$(OBJDIR)/imlua_image.o: lua5/imlua_image.c ../include/im.h ../include/old_im.h \ + ../include/im_image.h ../include/im_util.h ../include/im_convert.h \ + ../include/im_image.h ../../lua5.1/include/lua.h \ + ../../lua5.1/include/luaconf.h ../../lua5.1/include/lauxlib.h \ + ../../lua5.1/include/lua.h ../include/imlua.h lua5/imlua_image.h \ + lua5/imlua_palette.h lua5/imlua_aux.h lua5/loh/im_image_be64.loh +$(OBJDIR)/imlua_palette.o: lua5/imlua_palette.c ../include/im.h ../include/old_im.h \ + ../include/im_image.h ../include/im_util.h ../include/im_palette.h \ + ../../lua5.1/include/lua.h ../../lua5.1/include/luaconf.h \ + ../../lua5.1/include/lauxlib.h ../../lua5.1/include/lua.h \ + ../include/imlua.h lua5/imlua_aux.h lua5/imlua_palette.h +$(OBJDIR)/imlua_util.o: lua5/imlua_util.c ../include/im.h ../include/old_im.h \ + ../include/im_util.h ../include/im_image.h ../../lua5.1/include/lua.h \ + ../../lua5.1/include/luaconf.h ../../lua5.1/include/lauxlib.h \ + ../../lua5.1/include/lua.h ../include/imlua.h lua5/imlua_aux.h diff --git a/im/src/imlua_capture5.mak b/im/src/imlua_capture5.mak new file mode 100755 index 0000000..a4fe97c --- /dev/null +++ b/im/src/imlua_capture5.mak @@ -0,0 +1,18 @@ +PROJNAME = im +LIBNAME = imlua_capture51 +DEF_FILE = imlua_capture.def + +OPT = YES + +SRCDIR = lua5 + +SRC = imlua_capture.c + +LIBS = im_capture + +INCLUDES = lua5 + +USE_IMLUA = Yes +USE_LUA51 = Yes +NO_LUALINK = Yes +IM = .. diff --git a/im/src/imlua_process5.mak b/im/src/imlua_process5.mak new file mode 100755 index 0000000..85415c4 --- /dev/null +++ b/im/src/imlua_process5.mak @@ -0,0 +1,19 @@ +PROJNAME = im +LIBNAME = imlua_process51 + +OPT = YES + +LOHDIR = lua5/loh +SRC = lua5/imlua_process.c lua5/imlua_kernel.c +DEF_FILE = lua5/imlua_process.def + +SRCLUA = lua5/im_process.lua +SRCLUADIR = lua5 + +LIBS = im_process +INCLUDES = lua5 + +USE_IMLUA = YES +USE_LUA51 = YES +NO_LUALINK = Yes +IM = .. diff --git a/im/src/imlua_process51.dep b/im/src/imlua_process51.dep new file mode 100644 index 0000000..5f98a3b --- /dev/null +++ b/im/src/imlua_process51.dep @@ -0,0 +1,17 @@ +$(OBJDIR)/imlua_process.o: lua5/imlua_process.c ../include/im.h ../include/old_im.h \ + ../include/im_image.h ../include/im_process.h \ + ../include/im_process_pon.h ../include/im_image.h \ + ../include/im_process_loc.h ../include/im_process_glo.h \ + ../include/im_process_ana.h ../include/im_util.h \ + ../../lua5.1/include/lua.h ../../lua5.1/include/luaconf.h \ + ../../lua5.1/include/lauxlib.h ../../lua5.1/include/lua.h \ + ../include/imlua.h lua5/imlua_aux.h lua5/imlua_image.h \ + lua5/loh/im_process_be64.loh +$(OBJDIR)/imlua_kernel.o: lua5/imlua_kernel.c ../include/im.h ../include/old_im.h \ + ../include/im_image.h ../include/im_process.h \ + ../include/im_process_pon.h ../include/im_image.h \ + ../include/im_process_loc.h ../include/im_process_glo.h \ + ../include/im_process_ana.h ../include/im_util.h ../include/im_kernel.h \ + ../../lua5.1/include/lua.h ../../lua5.1/include/luaconf.h \ + ../../lua5.1/include/lauxlib.h ../../lua5.1/include/lua.h \ + ../include/imlua.h lua5/imlua_aux.h lua5/imlua_image.h diff --git a/im/src/imlua_wmv.mak b/im/src/imlua_wmv.mak new file mode 100755 index 0000000..f487075 --- /dev/null +++ b/im/src/imlua_wmv.mak @@ -0,0 +1,17 @@ +PROJNAME = im +LIBNAME = imlua_wmv51 +DEF_FILE = imlua_wmv.def + +OPT = YES + +SRCDIR = lua5 + +SRC = imlua_wmv.c + +LIBS = im_wmv + +INCLUDES = lua5 + +USE_IMLUA = Yes +USE_LUA51 = Yes +IM = .. diff --git a/im/src/jas_binfile.c b/im/src/jas_binfile.c new file mode 100755 index 0000000..487a2d3 --- /dev/null +++ b/im/src/jas_binfile.c @@ -0,0 +1,97 @@ +/** \file + * \brief libJasper I/O + * I/O uses imBinFile instead of libJasper original handlers. + * + * See Copyright Notice in im_lib.h + * $Id: jas_binfile.c,v 1.1 2008/10/17 06:10:16 scuri Exp $ + */ + +#include + +#include "jasper/jas_types.h" +#include "jasper/jas_stream.h" +#include "jasper/jas_malloc.h" +#include "jasper/jas_math.h" + +#include "im_binfile.h" + +/* These were static in jas_stream.c */ +jas_stream_t *jas_stream_create(void); +void jas_stream_initbuf(jas_stream_t *stream, int bufmode, char *buf, int bufsize); + +static int file_read(jas_stream_obj_t *obj, char *buf, int cnt) +{ + imBinFile* file_bin = (imBinFile*)obj; + return imBinFileRead(file_bin, buf, cnt, 1); +} + +static int file_write(jas_stream_obj_t *obj, char *buf, int cnt) +{ + imBinFile* file_bin = (imBinFile*)obj; + return imBinFileWrite(file_bin, buf, cnt, 1); +} + +static long file_seek(jas_stream_obj_t *obj, long offset, int origin) +{ + imBinFile* file_bin = (imBinFile*)obj; + switch (origin) + { + case SEEK_SET: + imBinFileSeekTo(file_bin, offset); + break; + case SEEK_CUR: + imBinFileSeekOffset(file_bin, offset); + break; + case SEEK_END: + imBinFileSeekFrom(file_bin, offset); + break; + } + + return imBinFileError(file_bin); +} + +static int file_close(jas_stream_obj_t *obj) +{ + imBinFile* file_bin = (imBinFile*)obj; + imBinFileClose(file_bin); + return 0; +} + +static jas_stream_ops_t jas_stream_fileops = { + file_read, + file_write, + file_seek, + file_close +}; + +jas_stream_t *jas_binfile_open(const char *file_name, int is_new) +{ + void* handle; + jas_stream_t *stream; + + if (is_new) + handle = (void*)imBinFileNew(file_name); + else + handle = (void*)imBinFileOpen(file_name); + + if (!handle) + return 0; + + /* Allocate a stream object. */ + stream = jas_stream_create(); + + if (is_new) + stream->openmode_ = JAS_STREAM_WRITE | JAS_STREAM_CREATE | JAS_STREAM_BINARY; + else + stream->openmode_ = JAS_STREAM_READ | JAS_STREAM_BINARY; + + /* Select the operations for a file stream object. */ + stream->ops_ = &jas_stream_fileops; + + stream->obj_ = handle; + + /* By default, use full buffering for this type of stream. */ + jas_stream_initbuf(stream, JAS_STREAM_FULLBUF, 0, 0); + + return stream; +} diff --git a/im/src/lua5/im_convert.lua b/im/src/lua5/im_convert.lua new file mode 100755 index 0000000..231bdb5 --- /dev/null +++ b/im/src/lua5/im_convert.lua @@ -0,0 +1,18 @@ + +function im.ConvertDataTypeNew(src_image, data_type, cpx2real, gamma, abssolute, cast_mode) + local dst_image = im.ImageCreateBased(src_image, nil, nil, nil, data_type) + return im.ConvertDataType(src_image, dst_image, cpx2real, gamma, abssolute, cast_mode), dst_image +end + +function im.ConvertColorSpaceNew(src_image, color_space, has_alpha) + local dst_image = im.ImageCreateBased(src_image, nil, nil, color_space) + if (has_alpha) then dst_image:AddAlpha() end + return im.ConvertColorSpace(src_image, dst_image), dst_image +end + +function im.ConvertToBitmapNew(src_image, color_space, has_alpha, cpx2real, gamma, abssolute, cast_mode) + if (not color_space) then color_space = im.ColorModeToBitmap(src_image:ColorSpace()) end + local dst_image = im.ImageCreateBased(src_image, nil, nil, color_space) + if (has_alpha) then dst_image:AddAlpha() end + return im.ConvertToBitmap(src_image, dst_image, cpx2real, gamma, abssolute, cast_mode), dst_image +end diff --git a/im/src/lua5/im_fftw.lua b/im/src/lua5/im_fftw.lua new file mode 100755 index 0000000..7bae53e --- /dev/null +++ b/im/src/lua5/im_fftw.lua @@ -0,0 +1,57 @@ + +------------------------------------------------------------------------------- +-- Creates a new function, with the name suffixed by "New". This new function +-- creates a new image, based on a source image, and calls the previous function +-- with this new image. +-- We assume here that the functions returns only one parameter or none. + +local function OneSourceOneDest (funcname, width, height, color_space, data_type) + local func = im[funcname] + assert(func) -- see if function is really defined + + -- define function with "New" suffix + im[funcname.."New"] = function (src_image, ...) + -- create destination image + local dst_image = im.ImageCreateBased(src_image, width, height, color_space, data_type) + + -- call previous method, repassing all parameters + local ret = func(src_image, dst_image, unpack(arg)) + if (ret) then + return ret, dst_image + else + return dst_image + end + end +end + +------------------------------------------------------------------------------- +-- This function is similar to OneSourceOneDest, but it receives two source +-- images. + +local function TwoSourcesOneDest (funcname, width, height, color_space, data_type) + local func = im[funcname] + + -- see if function is really defined + assert(func, string.format("undefined function `%s'", funcname)) + + -- define function with "New" suffix + im[funcname.."New"] = function (src_image1, src_image2, ...) + -- create destination image + local dst_image = im.ImageCreateBased(src_image1, width, height, color_space, data_type) + + -- call previous method, repassing all parameters + local ret = func(src_image1, src_image2, dst_image, unpack(arg)) + if (ret) then + return ret, dst_image + else + return dst_image + end + end +end + +------------------------------------------------------------------------------- + +TwoSourcesOneDest("ProcessCrossCorrelation") +OneSourceOneDest("ProcessAutoCorrelation", nil, nil, nil, im.CFLOAT) +OneSourceOneDest("ProcessFFT") +OneSourceOneDest("ProcessIFFT") diff --git a/im/src/lua5/im_image.lua b/im/src/lua5/im_image.lua new file mode 100755 index 0000000..5eb9fd4 --- /dev/null +++ b/im/src/lua5/im_image.lua @@ -0,0 +1,24 @@ +-- If all parameteres, besides the image, are nil, this is equivalent to image:Clone. +-- If any parameter is not nil, then the value is used instead of the one from the source image. +-- If a parameter is a function, then the function is called, passing the source +-- image as parameter, to obtain the substituion value. + +function im.ImageCreateBased(image, width, height, color_space, data_type) + -- default values are those of the source image + width = width or image:Width() + height = height or image:Height() + color_space = color_space or image:ColorSpace() + data_type = data_type or image:DataType() + + -- callback to calculate parameters based on source image + if type(width) == "function" then width = width(image) end + if type(height) == "function" then height = height(image) end + if type(color_space) == "function" then color_space = color_space(image) end + if type(data_type) == "function" then data_type = data_type(image) end + + -- create a new image + local new_image = im.ImageCreate(width, height, color_space, data_type) + image:CopyAttributes(new_image) + if (image:HasAlpha()) then new_image:AddAlpha() end + return new_image +end diff --git a/im/src/lua5/im_process.lua b/im/src/lua5/im_process.lua new file mode 100755 index 0000000..d74c6b1 --- /dev/null +++ b/im/src/lua5/im_process.lua @@ -0,0 +1,329 @@ + +------------------------------------------------------------------------------- +-- Creates a new function, with the name suffixed by "New". This new function +-- creates a new image, based on a source image, and calls the previous function +-- with this new image. +-- We assume here that the functions returns only one parameter or none. + +local function OneSourceOneDest (funcname, width, height, color_space, data_type) + local func = im[funcname] + assert(func) -- see if function is really defined + + -- define function with "New" suffix + im[funcname.."New"] = function (src_image, ...) + -- create destination image + local dst_image = im.ImageCreateBased(src_image, width, height, color_space, data_type) + + -- call previous method, repassing all parameters + local ret = func(src_image, dst_image, unpack(arg)) + if (ret) then + return ret, dst_image + else + return dst_image + end + end +end + +------------------------------------------------------------------------------- +-- This function is similar to OneSourceOneDest, but it receives two source +-- images. + +local function TwoSourcesOneDest (funcname, width, height, color_space, data_type) + local func = im[funcname] + + -- see if function is really defined + assert(func, string.format("undefined function `%s'", funcname)) + + -- define function with "New" suffix + im[funcname.."New"] = function (src_image1, src_image2, ...) + -- create destination image + local dst_image = im.ImageCreateBased(src_image1, width, height, color_space, data_type) + + -- call previous method, repassing all parameters + local ret = func(src_image1, src_image2, dst_image, unpack(arg)) + if (ret) then + return ret, dst_image + else + return dst_image + end + end +end + +------------------------------------------------------------------------------- +-- This function is similar to OneSourceOneDest, but it receives three source +-- images. + +local function ThreeSourcesOneDest (funcname, width, height, color_space, data_type) + local func = im[funcname] + assert(func) -- see if function is really defined + + -- define function with "New" suffix + im[funcname.."New"] = function (src_image1, src_image2, src_image3, ...) + -- create destination image + local dst_image = im.ImageCreateBased(src_image1, width, height, color_space, data_type) + + -- call previous method, repassing all parameters + local ret = func(src_image1, src_image2, src_image3, dst_image, unpack(arg)) + if (ret) then + return ret, dst_image + else + return dst_image + end + end +end + +------------------------------------------------------------------------------- +-- This function is similar to OneSourceOneDest, but it creates two destiny +-- images. + +local function OneSourceTwoDests (funcname, width, height, color_space, data_type) + local func = im[funcname] + assert(func) -- see if function is really defined + + -- define function with "New" suffix + im[funcname.."New"] = function (src_image, ...) + -- create destination image + local dst_image1 = im.ImageCreateBased(src_image, width, height, color_space, data_type) + local dst_image2 = im.ImageCreateBased(src_image, width, height, color_space, data_type) + + -- call previous method, repassing all parameters + local ret = func(src_image, dst_image1, dst_image2, unpack(arg)) + if (ret) then + return ret, dst_image1, dst_image2 + else + return dst_image1, dst_image2 + end + end +end + +------------------------------------------------------------------------------- +-- This function is similar to OneSourceOneDest, but it creates three destiny +-- images. + +local function OneSourceThreeDests (funcname, width, height, color_space, data_type) + local func = im[funcname] + assert(func) -- see if function is really defined + + -- define function with "New" suffix + im[funcname.."New"] = function (src_image, ...) + -- create destination image + local dst_image1 = im.ImageCreateBased(src_image, width, height, color_space, data_type) + local dst_image2 = im.ImageCreateBased(src_image, width, height, color_space, data_type) + local dst_image3 = im.ImageCreateBased(src_image, width, height, color_space, data_type) + + -- call previous method, repassing all parameters + local ret = func(src_image, dst_image1, dst_image2, dst_image3, unpack(arg)) + if (ret) then + return ret, dst_image1, dst_image2, dst_image3 + else + return dst_image1, dst_image2, dst_image3 + end + end +end + +------------------------------------------------------------------------------- + +local function hough_height(image) + local function sqr(x) return x*x end + local rmax = math.sqrt(sqr(image:Width()) + sqr(image:Height())) / 2 + return 2*rmax+1 +end + +OneSourceOneDest("AnalyzeFindRegions", nil, nil, nil, im.USHORT) +OneSourceOneDest("ProcessPerimeterLine") +OneSourceOneDest("ProcessRemoveByArea") +OneSourceOneDest("ProcessFillHoles") +OneSourceOneDest("ProcessHoughLines", 180, hough_height, im.GRAY, im.INT) +OneSourceOneDest("ProcessHoughLinesDraw") +OneSourceOneDest("ProcessDistanceTransform", nil, nil, nil, im.FLOAT) +OneSourceOneDest("ProcessRegionalMaximum", nil, nil, im.BINARY, nil) + +function im.ProcessReduceNew (src_image, width, height) + local dst_image = im.ImageCreateBased(src_image, width, height) + return im.ProcessReduce(src_image, dst_image), dst_image +end + +function im.ProcessResizeNew (src_image, width, height) + local dst_image = im.ImageCreateBased(src_image, width, height) + return im.ProcessResize(src_image, dst_image), dst_image +end + +OneSourceOneDest("ProcessReduceBy4", function (image) return image:Width() / 2 end, + function (image) return image:Height() / 2 end) + +function im.ProcessCropNew (src_image, xmin, xmax, ymin, ymax) + local width = xmax - xmin + 1 + local height = ymax - ymin + 1 + local dst_image = im.ImageCreateBased(src_image, width, height) + im.ProcessCrop(src_image, dst_image, xmin, ymin) + return dst_image +end + +TwoSourcesOneDest("ProcessInsert") + +function im.ProcessAddMarginsNew (src_image, xmin, xmax, ymin, ymax) + local width = xmax - xmin + 1 + local height = ymax - ymin + 1 + local dst_image = im.ImageCreateBased(src_image, width, height) + im.ProcessAddMargins(src_image, dst_image, xmin, ymin) + return dst_image +end + +function im.ProcessRotateNew (src_image, cos0, sin0, order) + local width, height = im.ProcessCalcRotateSize(src_image:Width(), src_image:Height(), cos0, sin0) + local dst_image = im.ImageCreateBased(src_image, width, height) + return im.ProcessRotate(src_image, dst_image, cos0, sin0, order), dst_image +end + +OneSourceOneDest("ProcessRotateRef") +OneSourceOneDest("ProcessRotate90", function (image) return image:Height() end, function (image) return image:Width() end) +OneSourceOneDest("ProcessRotate180") +OneSourceOneDest("ProcessMirror") +OneSourceOneDest("ProcessFlip") +OneSourceOneDest("ProcessRadial") +OneSourceOneDest("ProcessGrayMorphConvolve") +OneSourceOneDest("ProcessGrayMorphErode") +OneSourceOneDest("ProcessGrayMorphDilate") +OneSourceOneDest("ProcessGrayMorphOpen") +OneSourceOneDest("ProcessGrayMorphClose") +OneSourceOneDest("ProcessGrayMorphTopHat") +OneSourceOneDest("ProcessGrayMorphWell") +OneSourceOneDest("ProcessGrayMorphGradient") +OneSourceOneDest("ProcessBinMorphConvolve") +OneSourceOneDest("ProcessBinMorphErode") +OneSourceOneDest("ProcessBinMorphDilate") +OneSourceOneDest("ProcessBinMorphOpen") +OneSourceOneDest("ProcessBinMorphClose") +OneSourceOneDest("ProcessBinMorphOutline") +OneSourceOneDest("ProcessBinMorphThin") +OneSourceOneDest("ProcessMedianConvolve") +OneSourceOneDest("ProcessRangeConvolve") +OneSourceOneDest("ProcessRankClosestConvolve") +OneSourceOneDest("ProcessRankMaxConvolve") +OneSourceOneDest("ProcessRankMinConvolve") +OneSourceOneDest("ProcessConvolve") +OneSourceOneDest("ProcessConvolveSep") +OneSourceOneDest("ProcessConvolveRep") +OneSourceOneDest("ProcessConvolveDual") +OneSourceOneDest("ProcessCompassConvolve") +OneSourceOneDest("ProcessMeanConvolve") +OneSourceOneDest("ProcessGaussianConvolve") +OneSourceOneDest("ProcessBarlettConvolve") +OneSourceTwoDests("ProcessInterlaceSplit", nil, function (image) if (image:Height()) then return image:Height() else return image:Height()/2 end end) + +function im.ProcessInterlaceSplitNew(src_image) + -- create destination image + local dst_height1 = src_image:Height()/2 + if math.mod(src_image:Height(), 2) then + dst_height1 = dst_height1 + 1 + end + + local dst_image1 = im.ImageCreateBased(src_image, nil, dst_height1) + local dst_image2 = im.ImageCreateBased(src_image, nil, src_image:Height()/2) + + -- call method, repassing all parameters + im.ProcessInterlaceSplit(src_image, dst_image1, dst_image2) + return dst_image1, dst_image2 +end + +local function int_datatype (image) + local data_type = image:DataType() + if data_type == im.BYTE or data_type == im.USHORT then + data_type = im.INT + end + return data_type +end + +OneSourceOneDest("ProcessDiffOfGaussianConvolve", nil, nil, nil, int_datatype) +OneSourceOneDest("ProcessLapOfGaussianConvolve", nil, nil, nil, int_datatype) +OneSourceOneDest("ProcessSobelConvolve") +OneSourceOneDest("ProcessSplineEdgeConvolve") +OneSourceOneDest("ProcessPrewittConvolve") +OneSourceOneDest("ProcessZeroCrossing") +OneSourceOneDest("ProcessCanny") +OneSourceOneDest("ProcessUnArithmeticOp") +TwoSourcesOneDest("ProcessArithmeticOp") +OneSourceOneDest("ProcessUnsharp") +OneSourceOneDest("ProcessSharp") +TwoSourcesOneDest("ProcessSharpKernel") + +function im.ProcessArithmeticConstOpNew (src_image, src_const, op) + local dst_image = im.ImageCreateBased(src_image) + im.ProcessArithmeticConstOp(src_image, src_const, dst_image, op) + return dst_image +end + +TwoSourcesOneDest("ProcessBlendConst") +ThreeSourcesOneDest("ProcessBlend") +OneSourceTwoDests("ProcessSplitComplex") +TwoSourcesOneDest("ProcessMergeComplex", nil, nil, nil, im.CFLOAT) + +function im.ProcessMultipleMeanNew (src_image_list, dst_image) + local dst_image = im.ImageCreateBased(src_image_list[1]) + im.ProcessMultipleMean(src_image_list, dst_image) + return dst_image +end + +function im.ProcessMultipleStdDevNew (src_image_list, mean_image) + local dst_image = im.ImageCreateBased(src_image_list[1]) + im.ProcessMultipleStdDev(src_image_list, mean_image, dst_image) + return dst_image +end + +TwoSourcesOneDest("ProcessAutoCovariance") +OneSourceOneDest("ProcessMultiplyConj") +OneSourceOneDest("ProcessQuantizeRGBUniform", nil, nil, im.MAP, nil) +OneSourceOneDest("ProcessQuantizeGrayUniform") +OneSourceOneDest("ProcessExpandHistogram") +OneSourceOneDest("ProcessEqualizeHistogram") + +function im.ProcessSplitYChromaNew (src_image) + local y_image = im.ImageCreateBased(src_image, nil, nil, im.GRAY, im.BYTE) + local chroma_image = im.ImageCreateBased(src_image, nil, nil, im.RGB, im.BYTE) + im.ProcessSplitYChroma(src_image, y_image, chroma_image) + return y_image, chroma_image +end + +OneSourceThreeDests("ProcessSplitHSI", nil, nil, im.GRAY, im.FLOAT) +ThreeSourcesOneDest("ProcessMergeHSI", nil, nil, im.RGB, im.BYTE) + +function im.ProcessSplitComponentsNew (src_image) + local depth = src_image:Depth() + local dst_images = {} + for i = 1, depth do + table.insert(dst_images, im.ImageCreateBased(src_image, nil, nil, im.GRAY)) + end + im.ProcessSplitComponents(src_image, dst_images) + return unpack(dst_images) +end + +function im.ProcessMergeComponentsNew (src_image_list) + local dst_image = im.ImageCreateBased(src_image_list[1], nil, nil, im.RGB) + im.ProcessMergeComponents(src_image_list, dst_image) + return dst_image +end + +OneSourceOneDest("ProcessNormalizeComponents", nil, nil, nil, im.FLOAT) +OneSourceOneDest("ProcessReplaceColor") +TwoSourcesOneDest("ProcessBitwiseOp") +OneSourceOneDest("ProcessBitwiseNot") +OneSourceOneDest("ProcessBitMask") +OneSourceOneDest("ProcessBitPlane") +OneSourceOneDest("ProcessToneGamut") +OneSourceOneDest("ProcessUnNormalize", nil, nil, nil, im.BYTE) +OneSourceOneDest("ProcessDirectConv", nil, nil, nil, im.BYTE) +OneSourceOneDest("ProcessNegative") +OneSourceOneDest("ProcessRangeContrastThreshold", nil, nil, im.BINARY, nil) +OneSourceOneDest("ProcessLocalMaxThreshold", nil, nil, im.BINARY, nil) +OneSourceOneDest("ProcessThreshold", nil, nil, im.BINARY, nil) +TwoSourcesOneDest("ProcessThresholdByDiff") +OneSourceOneDest("ProcessHysteresisThreshold", nil, nil, im.BINARY, nil) +OneSourceOneDest("ProcessUniformErrThreshold", nil, nil, im.BINARY, nil) +OneSourceOneDest("ProcessDifusionErrThreshold") +OneSourceOneDest("ProcessPercentThreshold") +OneSourceOneDest("ProcessOtsuThreshold") +OneSourceOneDest("ProcessMinMaxThreshold", nil, nil, im.BINARY, nil) +OneSourceOneDest("ProcessSliceThreshold", nil, nil, im.BINARY, nil) +OneSourceOneDest("ProcessPixelate") +OneSourceOneDest("ProcessPosterize") + diff --git a/im/src/lua5/imlua.c b/im/src/lua5/imlua.c new file mode 100755 index 0000000..7e5c328 --- /dev/null +++ b/im/src/lua5/imlua.c @@ -0,0 +1,252 @@ +/** \file + * \brief IM Lua 5 Binding + * + * See Copyright Notice in im_lib.h + * $Id: imlua.c,v 1.2 2008/12/11 19:02:49 scuri Exp $ + */ + +#include +#include +#include + +#include "im.h" +#include "im_lib.h" +#include "im_image.h" +#include "im_convert.h" + +#include +#include + +#include "imlua.h" +#include "imlua_aux.h" +#include "imlua_image.h" +#include "imlua_palette.h" + +/*****************************************************************************\ + im.Version() +\*****************************************************************************/ +static int imluaVersion (lua_State *L) +{ + lua_pushstring(L, imVersion()); + return 1; +} + +/*****************************************************************************\ + im.VersionDate() +\*****************************************************************************/ +static int imluaVersionDate (lua_State *L) +{ + lua_pushstring(L, imVersionDate()); + return 1; +} + +/*****************************************************************************\ + im.VersionNumber() +\*****************************************************************************/ +static int imluaVersionNumber (lua_State *L) +{ + lua_pushnumber(L, imVersionNumber()); + return 1; +} + +/*****************************************************************************\ + im.FormatList() +\*****************************************************************************/ +static int imluaFormatList (lua_State *L) +{ + int i, format_count; + char *format_list[50]; + + imFormatList(format_list, &format_count); + + lua_newtable(L); + for (i = 0; i < format_count; i++) + { + lua_pushstring(L, format_list[i]); + lua_settable(L, -2); + } + + return 1; +} + +/*****************************************************************************\ + im.FormatInfo(format) +\*****************************************************************************/ +static int imluaFormatInfo (lua_State *L) +{ + char desc[50]; + char ext[50]; + int can_sequence; + int error; + + error = imFormatInfo(luaL_checkstring(L, 1), desc, ext, &can_sequence); + + imlua_pusherror(L, error); + if (error) + return 1; + + lua_pushstring(L, desc); + lua_pushstring(L, ext); + lua_pushboolean(L, can_sequence); + + return 4; +} + +/*****************************************************************************\ + im.FormatCompressions(format) +\*****************************************************************************/ +static int imluaFormatCompressions (lua_State *L) +{ + int i, comp_count; + int error; + char *comp[50]; + + int color_mode = luaL_optint(L, 2, -1); + int data_type = luaL_optint(L, 3, -1); + + error = imFormatCompressions(luaL_checkstring(L, 1), comp, &comp_count, color_mode, data_type); + + imlua_pusherror(L, error); + if (error) + return 1; + + lua_newtable(L); + for (i = 0; i < comp_count; i++) + { + lua_pushstring(L, comp[i]); + lua_settable(L, -2); + } + + return 2; +} + +/*****************************************************************************\ + im.FormatCanWriteImage(format, compression, color_mode, data_type) +\*****************************************************************************/ +static int imluaFormatCanWriteImage (lua_State *L) +{ + const char *format = luaL_checkstring(L, 1); + const char *compression = luaL_checkstring(L, 2); + int color_mode = luaL_checkint(L, 3); + int data_type = luaL_checkint(L, 4); + + lua_pushboolean(L, imFormatCanWriteImage(format, compression, color_mode, data_type)); + return 1; +} + +/*****************************************************************************\ + Constants +\*****************************************************************************/ +static const imlua_constant im_constants[] = { + + { "BYTE", IM_BYTE, NULL }, + { "USHORT", IM_USHORT, NULL }, + { "INT", IM_INT, NULL }, + { "FLOAT", IM_FLOAT, NULL }, + { "CFLOAT", IM_CFLOAT, NULL }, + + { "RGB", IM_RGB, NULL }, + { "MAP", IM_MAP, NULL }, + { "GRAY", IM_GRAY, NULL }, + { "BINARY", IM_BINARY, NULL }, + { "CMYK", IM_CMYK, NULL }, + { "YCBCR", IM_YCBCR, NULL }, + { "LAB", IM_LAB, NULL }, + { "LUV", IM_LUV, NULL }, + { "XYZ", IM_XYZ, NULL }, + + { "ALPHA", IM_ALPHA, NULL }, + { "PACKED", IM_PACKED, NULL }, + { "TOPDOWN", IM_TOPDOWN, NULL }, + + { "ERR_NONE", IM_ERR_NONE, NULL }, + { "ERR_OPEN", IM_ERR_OPEN, NULL }, + { "ERR_ACCESS", IM_ERR_ACCESS, NULL }, + { "ERR_FORMAT", IM_ERR_FORMAT, NULL }, + { "ERR_DATA", IM_ERR_DATA, NULL }, + { "ERR_COMPRESS", IM_ERR_COMPRESS, NULL }, + { "ERR_MEM", IM_ERR_MEM, NULL }, + { "ERR_COUNTER", IM_ERR_COUNTER, NULL }, + + { "CPX_REAL", IM_CPX_REAL, NULL }, + { "CPX_IMAG", IM_CPX_IMAG, NULL }, + { "CPX_MAG", IM_CPX_MAG, NULL }, + { "CPX_PHASE", IM_CPX_PHASE, NULL }, + + { "GAMMA_LINEAR", IM_GAMMA_LINEAR, NULL }, + { "GAMMA_LOGLITE", IM_GAMMA_LOGLITE, NULL }, + { "GAMMA_LOGHEAVY", IM_GAMMA_LOGHEAVY, NULL }, + { "GAMMA_EXPLITE", IM_GAMMA_EXPLITE, NULL }, + { "GAMMA_EXPHEAVY", IM_GAMMA_EXPHEAVY, NULL }, + + { "CAST_MINMAX", IM_CAST_MINMAX, NULL }, + { "CAST_FIXED", IM_CAST_FIXED, NULL }, + { "CAST_DIRECT", IM_CAST_DIRECT, NULL }, + + { "_AUTHOR", 0, IM_AUTHOR }, + { "_COPYRIGHT", 0, IM_COPYRIGHT }, + { "_VERSION_DATE", 0, IM_VERSION_DATE }, + { "_DESCRIPTION", 0, IM_DESCRIPTION }, + { "_NAME", 0, IM_NAME }, + + { NULL, -1, NULL }, +}; + +void imlua_regconstants (lua_State *L, const imlua_constant *imconst) +{ + const imlua_constant *l = imconst; + for (; l->name; l++) + { + lua_pushstring(L, l->name); + if (l->str_value) + lua_pushstring(L, l->str_value); + else + lua_pushnumber(L, l->value); + lua_settable(L, -3); + } + + lua_pushstring(L, "_VERSION"); + lua_pushstring(L, imVersion()); + lua_settable(L, -3); + + lua_pushstring(L, "_VERSION_NUMBER"); + lua_pushnumber(L, imVersionNumber()); + lua_settable(L, -3); +} + +static const luaL_reg im_lib[] = { + {"Version", imluaVersion}, + {"VersionDate", imluaVersionDate}, + {"VersionNumber", imluaVersionNumber}, + + {"FormatList", imluaFormatList}, + {"FormatInfo", imluaFormatInfo}, + {"FormatCompressions", imluaFormatCompressions}, + {"FormatCanWriteImage", imluaFormatCanWriteImage}, + + {NULL, NULL} +}; + +int imlua_open (lua_State *L) +{ + luaL_register(L, "im", im_lib); /* leave "im" table at the top of the stack */ + imlua_regconstants(L, im_constants); + + imlua_open_file(L); + imlua_open_image(L); + imlua_open_convert(L); + imlua_open_util(L); + imlua_open_palette(L); + + return 1; +} + +int luaopen_imlua(lua_State *L) +{ + return imlua_open(L); +} + +int luaopen_imlua51(lua_State *L) +{ + return imlua_open(L); +} diff --git a/im/src/lua5/imlua.def b/im/src/lua5/imlua.def new file mode 100755 index 0000000..259c822 --- /dev/null +++ b/im/src/lua5/imlua.def @@ -0,0 +1,24 @@ +EXPORTS + luaopen_imlua + luaopen_imlua51 + imlua_open + imlua_checkimage + imlua_newarrayulong + imlua_newarrayint + imlua_newarrayfloat + imlua_checkdatatype + imlua_checkcolorspace + imlua_toarrayint + imlua_toarrayfloat + imlua_toarrayulong + imlua_getn + imlua_checktype + imlua_checkmask + imlua_regconstants + imlua_pushimage + imlua_matchcolor + imlua_matchsize + imlua_matchdatatype + imlua_matchcolorspace + imlua_match + \ No newline at end of file diff --git a/im/src/lua5/imlua_aux.c b/im/src/lua5/imlua_aux.c new file mode 100755 index 0000000..e472dca --- /dev/null +++ b/im/src/lua5/imlua_aux.c @@ -0,0 +1,256 @@ +/** \file + * \brief IM Lua 5 Binding + * + * See Copyright Notice in im_lib.h + * $Id: imlua_aux.c,v 1.2 2009/08/04 21:35:26 scuri Exp $ + */ + +#include +#include +#include + +#include "im.h" +#include "im_image.h" +#include "im_util.h" + +#include +#include + +#include "imlua.h" +#include "imlua_aux.h" +#include "imlua_image.h" + + +/*****************************************************************************\ +\*****************************************************************************/ +int imlua_getn (lua_State *L, int index) +{ + int n; + lua_pushstring(L, "table"); + lua_gettable(L, LUA_GLOBALSINDEX); + lua_pushstring(L, "getn"); + lua_gettable(L, -2); + lua_pushvalue(L, index); + lua_call(L, 1, 1); + n = luaL_checkint(L, -1); + lua_pop(L, 2); + return n; +} + +/*****************************************************************************\ + Creates an int array. +\*****************************************************************************/ +int imlua_newarrayint (lua_State *L, int *value, int count, int start) +{ + int i; + lua_newtable(L); + for (i = 0; i < count; i++) + { + lua_pushnumber(L, value[i]); + lua_rawseti(L, -2, i+start); + } + return 1; +} + +/*****************************************************************************\ + Creates an unsigned long array. +\*****************************************************************************/ +int imlua_newarrayulong (lua_State *L, unsigned long *value, int count, int start) +{ + int i; + lua_newtable(L); + for (i = 0; i < count; i++) + { + lua_pushnumber(L, value[i]); + lua_rawseti(L, -2, i+start); + } + return 1; +} + +/*****************************************************************************\ + Creates a float array. +\*****************************************************************************/ +int imlua_newarrayfloat (lua_State *L, float *value, int count, int start) +{ + int i; + lua_newtable(L); + for (i = 0; i < count; i++) + { + lua_pushnumber(L, value[i]); + lua_rawseti(L, -2, i+start); + } + return 1; +} + +/*****************************************************************************\ + Retrieve an int array. +\*****************************************************************************/ +int *imlua_toarrayint (lua_State *L, int index, int *count, int start) +{ + int i, n; + int *value = NULL; + + if (lua_istable(L, index)) + { + n = imlua_getn(L, index); + if (start == 0) n++; + if (count) *count = n; + + value = (int*) malloc (sizeof(int) * n); + for (i = 0; i < n; i++) + { + lua_rawgeti(L, index, i+start); + value[i] = luaL_checkint(L, -1); + lua_pop(L, 1); + } + } + return value; +} + +/*****************************************************************************\ + Retrieve an ulong array. +\*****************************************************************************/ +unsigned long *imlua_toarrayulong (lua_State *L, int index, int *count, int start) +{ + int i, n; + unsigned long *value = NULL; + + if (lua_istable(L, index)) + { + n = imlua_getn(L, index); + if (start == 0) n++; + if (count) *count = n; + + value = (unsigned long*) malloc (sizeof(unsigned long) * n); + for (i = 0; i < n; i++) + { + lua_rawgeti(L, index, i+start); + value[i] = luaL_checkint(L, -1); + lua_pop(L, 1); + } + } + return value; +} + +/*****************************************************************************\ + Retrieve a float array. +\*****************************************************************************/ +float *imlua_toarrayfloat (lua_State *L, int index, int *count, int start) +{ + int i, n; + float *value = NULL; + + if (lua_istable(L, index)) + { + n = imlua_getn(L, index); + if (start == 0) n++; + if (count) *count = n; + + value = (float*) malloc (sizeof(float) * n); + for (i = 0; i < n; i++) + { + lua_rawgeti(L, index, i+start); + value[i] = (float) luaL_checknumber(L, -1); + lua_pop(L, 1); + } + } + return value; +} + + +/*****************************************************************************\ + Creates a bit mask based on a string formatted as "11000110". +\*****************************************************************************/ +unsigned char imlua_checkmask (lua_State *L, int index) +{ + int i; + unsigned char mask = 0; + const char *str = luaL_checkstring(L, index); + if (strlen(str) != 8) + luaL_argerror(L, index, "invalid mask, must have 8 elements"); + + for (i = 0; i < 8; i++) + { + char c = str[i]; + if (c != '0' && c != '1') + luaL_argerror(L, index, "invalid mask, must have 0s or 1s only"); + + mask |= (c - '0') << (7 - i); + } + + return mask; +} + +/*****************************************************************************\ + Checks data_type and color_space of an image. If it doesn't match throw a lua error. +\*****************************************************************************/ +void imlua_checktype (lua_State *L, int index, imImage *image, int color_space, int data_type) +{ + if (image->data_type != data_type) + { + char msg[100] = "image data type must be "; + strcat(msg, imDataTypeName(data_type)); + luaL_argerror(L, index, msg); + } + + if (image->color_space != color_space) + { + char msg[100] = "image color space must be "; + strcat(msg, imColorModeSpaceName(color_space)); + luaL_argerror(L, index, msg); + } +} + +/*****************************************************************************\ + Checks color_space of an image. If it doesn't match throw a lua error. +\*****************************************************************************/ +void imlua_checkcolorspace (lua_State *L, int index, imImage *image, int color_space) +{ + if (image->color_space != color_space) + { + char msg[100] = "image color space must be "; + strcat(msg, imColorModeSpaceName(color_space)); + luaL_argerror(L, index, msg); + } +} + +/*****************************************************************************\ + Checks a data_type of an image. If it doesn't match throw a lua error. +\*****************************************************************************/ +void imlua_checkdatatype (lua_State *L, int index, imImage *image, int data_type) +{ + if (image->data_type != data_type) + { + char msg[100] = "image data type must be "; + strcat(msg, imDataTypeName(data_type)); + luaL_argerror(L, index, msg); + } +} + +/*****************************************************************************\ + Checks if the size of the two images are equal. If it doesn't match throw a lua error. +\*****************************************************************************/ +void imlua_matchsize(lua_State *L, imImage *image1, imImage *image2) +{ + imlua_matchcheck(L, imImageMatchSize(image1, image2), "images must have the same size"); +} + +void imlua_matchcolor(lua_State *L, imImage *image1, imImage *image2) +{ + imlua_matchcheck(L, imImageMatchColor(image1, image2), "images must have the same data type and color space"); +} + +void imlua_matchdatatype(lua_State *L, imImage *image1, imImage *image2) +{ + imlua_matchcheck(L, imImageMatchDataType(image1, image2), "images must have the same size and data type"); +} + +void imlua_matchcolorspace(lua_State *L, imImage *image1, imImage *image2) +{ + imlua_matchcheck(L, imImageMatchColorSpace(image1, image2), "images must have the same size and color space"); +} + +void imlua_match(lua_State *L, imImage *image1, imImage *image2) +{ + imlua_matchcheck(L, imImageMatch(image1, image2), "images must have the same size, data type and color space"); +} diff --git a/im/src/lua5/imlua_aux.h b/im/src/lua5/imlua_aux.h new file mode 100755 index 0000000..2dc4466 --- /dev/null +++ b/im/src/lua5/imlua_aux.h @@ -0,0 +1,82 @@ +/** \file + * \brief IM Lua 5 Binding + * + * See Copyright Notice in im_lib.h + * $Id: imlua_aux.h,v 1.1 2008/10/17 06:16:32 scuri Exp $ + */ + +#ifndef __IMLUA_AUX_H +#define __IMLUA_AUX_H + +#if defined(__cplusplus) +extern "C" { +#endif + + +/********************************/ +/* exported from "imlua_aux.c". */ +/********************************/ + +/* get table size */ + +int imlua_getn(lua_State *L, int index); + +/* array */ + +int imlua_newarrayint(lua_State *L, int *value, int count, int start); +int imlua_newarrayulong(lua_State *L, unsigned long *value, int count, int start); +int imlua_newarrayfloat(lua_State *L, float *value, int count, int start); + +int *imlua_toarrayint(lua_State *L, int index, int *count, int start); +unsigned long *imlua_toarrayulong (lua_State *L, int index, int *count, int start); +float *imlua_toarrayfloat(lua_State *L, int index, int *count, int start); + +/* other parameter checking */ + +unsigned char imlua_checkmask(lua_State *L, int index); + +void imlua_checktype(lua_State *L, int index, imImage *image, int color_space, int data_type); +void imlua_checkdatatype(lua_State *L, int index, imImage *image, int data_type); +void imlua_checkcolorspace(lua_State *L, int index, imImage *image, int color_space); + +void imlua_matchsize(lua_State *L, imImage *image1, imImage *image2); +void imlua_matchcolor(lua_State *L, imImage *image1, imImage *image2); +void imlua_matchdatatype(lua_State *L, imImage *image1, imImage *image2); +void imlua_matchcolorspace(lua_State *L, imImage *image1, imImage *image2); +void imlua_match(lua_State *L, imImage *image1, imImage *image2); + +/* used only when comparing two images */ +#define imlua_matchcheck(L, cond, extramsg) if (!(cond)) \ + luaL_error(L, extramsg) + +#define imlua_pusherror(L, _e) ((_e == IM_ERR_NONE)? lua_pushnil(L): lua_pushnumber(L, _e)) + + +/********************************/ +/* exported from "imlua.c". */ +/********************************/ + +/* constant registration. */ + +typedef struct _imlua_constant { + const char *name; + lua_Number value; + const char *str_value; +} imlua_constant; + +void imlua_regconstants(lua_State *L, const imlua_constant *imconst); + + +/********************************/ +/* private module open */ +/********************************/ + +void imlua_open_convert(lua_State *L); /* imlua_convert.c */ +void imlua_open_util(lua_State *L); /* imlua_util.c */ +void imlua_open_file(lua_State *L); /* imlua_file.c */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/im/src/lua5/imlua_avi.c b/im/src/lua5/imlua_avi.c new file mode 100755 index 0000000..f2cd7f4 --- /dev/null +++ b/im/src/lua5/imlua_avi.c @@ -0,0 +1,44 @@ +/** \file + * \brief AVI format Lua 5 Binding + * + * See Copyright Notice in cd.h + */ + +#include +#include + +#include "im_format_avi.h" + +#include +#include + + +static int imlua_FormatRegisterAVI(lua_State *L) +{ + (void)L; + imFormatRegisterAVI(); + return 0; +} + +static const struct luaL_reg imlib[] = { + {"FormatRegisterAVI", imlua_FormatRegisterAVI}, + {NULL, NULL}, +}; + + +static int imlua_avi_open (lua_State *L) +{ + imFormatRegisterAVI(); + luaL_register(L, "im", imlib); /* leave "im" table at the top of the stack */ + return 1; +} + +int luaopen_imlua_avi(lua_State* L) +{ + return imlua_avi_open(L); +} + +int luaopen_imlua_avi51(lua_State* L) +{ + return imlua_avi_open(L); +} diff --git a/im/src/lua5/imlua_avi.def b/im/src/lua5/imlua_avi.def new file mode 100755 index 0000000..3086a0d --- /dev/null +++ b/im/src/lua5/imlua_avi.def @@ -0,0 +1,4 @@ +EXPORTS + luaopen_imlua_avi + luaopen_imlua_avi51 + \ No newline at end of file diff --git a/im/src/lua5/imlua_capture.c b/im/src/lua5/imlua_capture.c new file mode 100755 index 0000000..59ec0fb --- /dev/null +++ b/im/src/lua5/imlua_capture.c @@ -0,0 +1,443 @@ +/** \file + * \brief IM Lua 5 Binding + * + * See Copyright Notice in im_lib.h + * $Id: imlua_capture.c,v 1.2 2009/08/12 04:09:17 scuri Exp $ + */ + +#include +#include + +#include "im.h" +#include "im_image.h" +#include "im_capture.h" + +#include +#include + +#include "imlua.h" +#include "imlua_aux.h" +#include "imlua_image.h" + + + +static imVideoCapture** imlua_rawcheckvideocapture (lua_State *L, int param) +{ + return (imVideoCapture**)luaL_checkudata(L, param, "imVideoCapture"); +} + +static imVideoCapture* imlua_checkvideocapture (lua_State *L, int param) +{ + imVideoCapture** vc_p = imlua_rawcheckvideocapture(L, param); + + if (!(*vc_p)) + luaL_argerror(L, param, "destroyed imVideoCapture"); + + return *vc_p; +} + +static void imlua_pushvideocapture(lua_State *L, imVideoCapture* vc) +{ + if (!vc) + lua_pushnil(L); + else + { + imVideoCapture** vc_p = (imVideoCapture**) lua_newuserdata(L, sizeof(imVideoCapture*)); + *vc_p = vc; + luaL_getmetatable(L, "imVideoCapture"); + lua_setmetatable(L, -2); + } +} + +/*****************************************************************************\ + im.VideoCaptureDeviceCount() +\*****************************************************************************/ +static int imluaVideoCaptureDeviceCount (lua_State *L) +{ + lua_pushnumber(L, imVideoCaptureDeviceCount()); + return 1; +} + +/*****************************************************************************\ + im.VideoCaptureDeviceDesc(device) +\*****************************************************************************/ +static int imluaVideoCaptureDeviceDesc (lua_State *L) +{ + lua_pushstring(L, imVideoCaptureDeviceDesc(luaL_checkint(L, 1))); + return 1; +} + +/*****************************************************************************\ + im.VideoCaptureDeviceDesc(device) +\*****************************************************************************/ +static int imluaVideoCaptureReloadDevices (lua_State *L) +{ + lua_pushnumber(L, imVideoCaptureReloadDevices()); + return 1; +} + +/*****************************************************************************\ + im.VideoCaptureCreate() +\*****************************************************************************/ +static int imluaVideoCaptureCreate (lua_State *L) +{ + imlua_pushvideocapture(L, imVideoCaptureCreate()); + return 1; +} + +/*****************************************************************************\ + vc:Connect([device]) +\*****************************************************************************/ +static int imluaVideoCaptureConnect (lua_State *L) +{ + imVideoCapture *vc = imlua_checkvideocapture(L, 1); + int device = luaL_optint(L, 2, -1); + if (device == -1) + lua_pushnumber(L, imVideoCaptureConnect(vc, device)); + else + lua_pushboolean(L, imVideoCaptureConnect(vc, device)); + return 1; +} + +/*****************************************************************************\ + vc:Disconnect() +\*****************************************************************************/ +static int imluaVideoCaptureDisconnect (lua_State *L) +{ + imVideoCaptureDisconnect(imlua_checkvideocapture(L, 1)); + return 0; +} + +/*****************************************************************************\ + vc:DialogCount() +\*****************************************************************************/ +static int imluaVideoCaptureDialogCount (lua_State *L) +{ + lua_pushnumber(L, imVideoCaptureDialogCount(imlua_checkvideocapture(L, 1))); + return 1; +} + +/*****************************************************************************\ + vc:ShowDialog() +\*****************************************************************************/ +static int imluaVideoCaptureShowDialog (lua_State *L) +{ + imVideoCapture *vc = imlua_checkvideocapture(L, 1); + int dialog = luaL_checkint(L, 2); + void *parent = lua_touserdata(L, 3); + + lua_pushboolean(L, imVideoCaptureShowDialog(vc, dialog, parent)); + return 1; +} + +/*****************************************************************************\ + vc:DialogDesc() +\*****************************************************************************/ +static int imluaVideoCaptureDialogDesc (lua_State *L) +{ + imVideoCapture *vc = imlua_checkvideocapture(L, 1); + int dialog = luaL_checkint(L, 2); + + lua_pushstring(L, imVideoCaptureDialogDesc(vc, dialog)); + return 1; +} + +/*****************************************************************************\ + vc:FormatCount() +\*****************************************************************************/ +static int imluaVideoCaptureFormatCount (lua_State *L) +{ + lua_pushnumber(L, imVideoCaptureFormatCount(imlua_checkvideocapture(L, 1))); + return 1; +} + +/*****************************************************************************\ + vc:GetFormat() +\*****************************************************************************/ +static int imluaVideoCaptureGetFormat (lua_State *L) +{ + imVideoCapture *vc = imlua_checkvideocapture(L, 1); + int format = luaL_checkint(L, 2); + int width, height; + char desc[10]; + + lua_pushboolean(L, imVideoCaptureGetFormat(vc, format, &width, &height, desc)); + lua_pushnumber(L, width); + lua_pushnumber(L, height); + lua_pushstring(L, desc); + + return 4; +} + +/*****************************************************************************\ + vc:GetImageSize() +\*****************************************************************************/ +static int imluaVideoCaptureGetImageSize (lua_State *L) +{ + imVideoCapture *vc = imlua_checkvideocapture(L, 1); + int width, height; + + imVideoCaptureGetImageSize(vc, &width, &height); + lua_pushnumber(L, width); + lua_pushnumber(L, height); + + return 2; +} + +/*****************************************************************************\ + vc:SetImageSize() +\*****************************************************************************/ +static int imluaVideoCaptureSetImageSize (lua_State *L) +{ + imVideoCapture *vc = imlua_checkvideocapture(L, 1); + int width = luaL_checkint(L, 2); + int height = luaL_checkint(L, 3); + + lua_pushboolean(L, imVideoCaptureSetImageSize(vc, width, height)); + + return 1; +} + +/*****************************************************************************\ + vc:SetInOut() +\*****************************************************************************/ +static int imluaVideoCaptureSetInOut(lua_State *L) +{ + imVideoCapture *vc = imlua_checkvideocapture(L, 1); + int input = luaL_checkint(L, 2); + int output = luaL_checkint(L, 3); + int cross = luaL_checkint(L, 4); + + lua_pushboolean(L, imVideoCaptureSetInOut(vc, input, output, cross)); + + return 1; +} + +/*****************************************************************************\ + vc:SetFormat() +\*****************************************************************************/ +static int imluaVideoCaptureSetFormat (lua_State *L) +{ + imVideoCapture *vc = imlua_checkvideocapture(L, 1); + int format = luaL_optint(L, 2, -1); + if (format == -1) + lua_pushnumber(L, imVideoCaptureSetFormat(vc, format)); + else + lua_pushboolean(L, imVideoCaptureSetFormat(vc, format)); + return 1; +} + +/*****************************************************************************\ + vc:ResetAttribute(attrib, fauto) +\*****************************************************************************/ +static int imluaVideoCaptureResetAttribute (lua_State *L) +{ + imVideoCapture *vc = imlua_checkvideocapture(L, 1); + const char *attrib = luaL_checkstring(L, 2); + int fauto = lua_toboolean(L, 3); + + lua_pushboolean(L, imVideoCaptureResetAttribute(vc, attrib, fauto)); + return 1; +} + +/*****************************************************************************\ + vc:SetAttribute(attrib, percent) +\*****************************************************************************/ +static int imluaVideoCaptureSetAttribute (lua_State *L) +{ + imVideoCapture *vc = imlua_checkvideocapture(L, 1); + const char *attrib = luaL_checkstring(L, 2); + float percent = (float) luaL_checknumber(L, 3); + + lua_pushboolean(L, imVideoCaptureSetAttribute(vc, attrib, percent)); + return 1; +} + +/*****************************************************************************\ + vc:GetAttribute(attrib) +\*****************************************************************************/ +static int imluaVideoCaptureGetAttribute (lua_State *L) +{ + imVideoCapture *vc = imlua_checkvideocapture(L, 1); + const char *attrib = luaL_checkstring(L, 2); + float percent; + + lua_pushboolean(L, imVideoCaptureGetAttribute(vc, attrib, &percent)); + lua_pushnumber(L, percent); + return 2; +} + +/*****************************************************************************\ + vc:GetAttributeList() +\*****************************************************************************/ +static int imluaVideoCaptureGetAttributeList (lua_State *L) +{ + imVideoCapture *vc = imlua_checkvideocapture(L, 1); + int num_attrib; + const char **attribs; + int i; + + attribs = imVideoCaptureGetAttributeList(vc, &num_attrib); + lua_newtable(L); + for (i = 0; i < num_attrib; i++) + { + lua_pushstring(L, attribs[i]); + lua_rawseti(L, -2, i + 1); + } + + return 1; +} + +/*****************************************************************************\ + vc:Frame(image) +\*****************************************************************************/ +static int imluaVideoCaptureFrame (lua_State *L) +{ + imVideoCapture *vc = imlua_checkvideocapture(L, 1); + imImage *image = imlua_checkimage(L, 2); + int timeout = luaL_checkint(L, 3); + + if (!(image->color_space == IM_RGB || image->color_space == IM_GRAY)) + luaL_argerror(L, 2, "image must be of RGB or Gray color spaces"); + imlua_checkdatatype(L, 2, image, IM_BYTE); + + lua_pushboolean(L, imVideoCaptureFrame(vc, image->data[0], image->color_space, timeout)); + + return 1; +} + +/*****************************************************************************\ + vc:OneFrame(image) +\*****************************************************************************/ +static int imluaVideoCaptureOneFrame (lua_State *L) +{ + imVideoCapture *vc = imlua_checkvideocapture(L, 1); + imImage *image = imlua_checkimage(L, 2); + + if (!(image->color_space == IM_RGB || image->color_space == IM_GRAY)) + luaL_argerror(L, 2, "image must be of RGB or Gray color spaces"); + imlua_checkdatatype(L, 2, image, IM_BYTE); + + lua_pushboolean(L, imVideoCaptureOneFrame(vc, image->data[0], image->color_space)); + + return 1; +} + +/*****************************************************************************\ + vc:Live(image) +\*****************************************************************************/ +static int imluaVideoCaptureLive (lua_State *L) +{ + imVideoCapture *vc = imlua_checkvideocapture(L, 1); + int live = luaL_optint(L, 2, -1); + if (live == -1) + lua_pushnumber(L, imVideoCaptureLive(vc, live)); + else + lua_pushboolean(L, imVideoCaptureLive(vc, live)); + + return 1; +} + +/*****************************************************************************\ + vc:Destroy() +\*****************************************************************************/ +static int imluaVideoCaptureDestroy (lua_State *L) +{ + imVideoCapture **vc_p = imlua_rawcheckvideocapture(L, 1); + if (!(*vc_p)) + luaL_argerror(L, 1, "destroyed imVideoCapture"); + + imVideoCaptureDestroy(*vc_p); + *vc_p = NULL; /* mark as destroyed */ + + return 0; +} + +/*****************************************************************************\ + gc +\*****************************************************************************/ +static int imluaVideoCapture_gc (lua_State *L) +{ + imVideoCapture **vc_p = (imVideoCapture **)lua_touserdata(L, 1); + if (*vc_p) + { + imVideoCaptureDestroy(*vc_p); + *vc_p = NULL; /* mark as destroyed */ + } + return 0; +} + +/*****************************************************************************\ + tostring +\*****************************************************************************/ +static int imluaVideoCapture_tostring (lua_State *L) +{ + imVideoCapture **vc_p = (imVideoCapture **)lua_touserdata(L, 1); + lua_pushfstring(L, "imVideoCapture (%p)%s", vc_p, (*vc_p)? "": "-destroyed"); + return 1; +} + +static const luaL_reg imcapture_lib[] = { + {"VideoCaptureDeviceCount", imluaVideoCaptureDeviceCount}, + {"VideoCaptureDeviceDesc", imluaVideoCaptureDeviceDesc}, + {"VideoCaptureReloadDevices", imluaVideoCaptureReloadDevices}, + {"VideoCaptureCreate", imluaVideoCaptureCreate}, + {"VideoCaptureDestroy", imluaVideoCaptureDestroy}, + {NULL, NULL} +}; + +static const luaL_reg imcapture_metalib[] = { + {"Destroy", imluaVideoCaptureDestroy}, + {"Connect", imluaVideoCaptureConnect}, + {"Disconnect", imluaVideoCaptureDisconnect}, + {"DialogCount", imluaVideoCaptureDialogCount}, + {"ShowDialog", imluaVideoCaptureShowDialog}, + {"DialogDesc", imluaVideoCaptureDialogDesc}, + {"FormatCount", imluaVideoCaptureFormatCount}, + {"GetFormat", imluaVideoCaptureGetFormat}, + {"SetFormat", imluaVideoCaptureSetFormat}, + {"GetImageSize", imluaVideoCaptureGetImageSize}, + {"SetImageSize", imluaVideoCaptureSetImageSize}, + {"SetInOut", imluaVideoCaptureSetInOut}, + {"ResetAttribute", imluaVideoCaptureResetAttribute}, + {"GetAttribute", imluaVideoCaptureGetAttribute}, + {"SetAttribute", imluaVideoCaptureSetAttribute}, + {"GetAttributeList", imluaVideoCaptureGetAttributeList}, + {"OneFrame", imluaVideoCaptureOneFrame}, + {"Frame", imluaVideoCaptureFrame}, + {"Live", imluaVideoCaptureLive}, + + {"__gc", imluaVideoCapture_gc}, + {"__tostring", imluaVideoCapture_tostring}, + + {NULL, NULL} +}; + +static void createmeta (lua_State *L) +{ + /* Object Oriented Access */ + luaL_newmetatable(L, "imVideoCapture"); /* create new metatable for imVideoCapture handle */ + lua_pushliteral(L, "__index"); + lua_pushvalue(L, -2); /* push metatable */ + lua_rawset(L, -3); /* metatable.__index = metatable */ + luaL_register(L, NULL, imcapture_metalib); /* register methods */ + lua_pop(L, 1); /* removes the metatable from the top of the stack */ +} + +int imlua_open_capture(lua_State *L) +{ + createmeta(L); + luaL_register(L, "im", imcapture_lib); /* leave "im" table at the top of the stack */ + return 1; +} + +int luaopen_imlua_capture(lua_State *L) +{ + return imlua_open_capture(L); +} + +int luaopen_imlua_capture51(lua_State *L) +{ + return imlua_open_capture(L); +} + diff --git a/im/src/lua5/imlua_capture.def b/im/src/lua5/imlua_capture.def new file mode 100755 index 0000000..1b279cf --- /dev/null +++ b/im/src/lua5/imlua_capture.def @@ -0,0 +1,5 @@ +EXPORTS + imlua_open_capture + luaopen_imlua_capture + luaopen_imlua_capture51 + \ No newline at end of file diff --git a/im/src/lua5/imlua_convert.c b/im/src/lua5/imlua_convert.c new file mode 100755 index 0000000..c2c56d9 --- /dev/null +++ b/im/src/lua5/imlua_convert.c @@ -0,0 +1,96 @@ +/** \file + * \brief IM Lua 5 Binding + * + * See Copyright Notice in im_lib.h + * $Id: imlua_convert.c,v 1.3 2009/08/18 02:23:33 scuri Exp $ + */ + +#include "im.h" +#include "im_image.h" +#include "im_convert.h" + +#include +#include + +#include "imlua.h" +#include "imlua_image.h" +#include "imlua_aux.h" + +/*****************************************************************************\ + im.ConvertDataType(src_image, dst_image, cpx2real, gamma, abssolute, cast_mode) +\*****************************************************************************/ +static int imluaConvertDataType (lua_State *L) +{ + imImage* src_image = imlua_checkimage(L, 1); + imImage* dst_image = imlua_checkimage(L, 2); + int cpx2real = luaL_checkint(L, 3); + float gamma = (float) luaL_checknumber(L, 4); + int abssolute = lua_toboolean(L, 5); + int cast_mode = luaL_checkint(L, 6); + + imlua_matchcolorspace(L, src_image, dst_image); + imlua_pusherror(L, imConvertDataType(src_image, dst_image, cpx2real, gamma, abssolute, cast_mode)); + return 1; +} + +/*****************************************************************************\ + im.ConvertColorSpace(src_image, dst_image) +\*****************************************************************************/ +static int imluaConvertColorSpace (lua_State *L) +{ + imImage* src_image = imlua_checkimage(L, 1); + imImage* dst_image = imlua_checkimage(L, 2); + + imlua_matchdatatype(L, src_image, dst_image); + imlua_pusherror(L, imConvertColorSpace(src_image, dst_image)); + return 1; +} + +/*****************************************************************************\ + im.ConvertToBitmap(src_image, dst_image, cpx2real, gamma, abssolute, cast_mode) +\*****************************************************************************/ +static int imluaConvertToBitmap (lua_State *L) +{ + imImage* src_image = imlua_checkimage(L, 1); + imImage* dst_image = imlua_checkimage(L, 2); + int cpx2real = luaL_checkint(L, 3); + float gamma = (float) luaL_checknumber(L, 4); + int abssolute = lua_toboolean(L, 5); + int cast_mode = luaL_checkint(L, 6); + + imlua_matchsize(L, src_image, dst_image); + imlua_matchcheck(L, imImageIsBitmap(dst_image), "image must be a bitmap"); + + imlua_pusherror(L, imConvertToBitmap(src_image, dst_image, cpx2real, gamma, abssolute, cast_mode)); + return 1; +} + +static const luaL_reg imconvert_lib[] = { + {"ConvertDataType", imluaConvertDataType}, + {"ConvertColorSpace", imluaConvertColorSpace}, + {"ConvertToBitmap", imluaConvertToBitmap}, + {NULL, NULL} +}; + +void imlua_open_convert (lua_State *L) +{ + /* "im" table is at the top of the stack */ + luaL_register(L, NULL, imconvert_lib); +#ifdef TEC_BIGENDIAN +#ifdef TEC_64 +#include "loh/im_convert_be64.loh" +#else +#include "loh/im_convert_be32.loh" +#endif +#else +#ifdef TEC_64 +#ifdef WIN64 +#include "loh/im_convert_le64w.loh" +#else +#include "loh/im_convert_le64.loh" +#endif +#else +#include "loh/im_convert.loh" +#endif +#endif +} diff --git a/im/src/lua5/imlua_fftw.c b/im/src/lua5/imlua_fftw.c new file mode 100755 index 0000000..c8ad3df --- /dev/null +++ b/im/src/lua5/imlua_fftw.c @@ -0,0 +1,162 @@ +/** \file + * \brief IM Lua 5 Binding + * + * See Copyright Notice in im_lib.h + * $Id: imlua_fftw.c,v 1.2 2008/11/26 17:25:51 scuri Exp $ + */ + +#include + +#include "im.h" +#include "im_image.h" +#include "im_process.h" +#include "im_util.h" + +#include +#include + +#include "imlua.h" +#include "imlua_aux.h" +#include "imlua_image.h" + + +/*****************************************************************************\ + Domain Transform Operations +\*****************************************************************************/ + +/*****************************************************************************\ + im.ProcessFFT(src_image, dst_image) +\*****************************************************************************/ +static int imluaProcessFFT (lua_State *L) +{ + imImage* src_image = imlua_checkimage(L, 1); + imImage* dst_image = imlua_checkimage(L, 2); + + imlua_matchsize(L, src_image, dst_image); + imlua_checkdatatype(L, 2, dst_image, IM_CFLOAT); + + imProcessFFT(src_image, dst_image); + return 0; +} + +/*****************************************************************************\ + im.ProcessIFFT(src_image, dst_image) +\*****************************************************************************/ +static int imluaProcessIFFT (lua_State *L) +{ + imImage* src_image = imlua_checkimage(L, 1); + imImage* dst_image = imlua_checkimage(L, 2); + + imlua_matchsize(L, src_image, dst_image); + imlua_checkdatatype(L, 1, src_image, IM_CFLOAT); + imlua_checkdatatype(L, 2, dst_image, IM_CFLOAT); + + imProcessIFFT(src_image, dst_image); + return 0; +} + +/*****************************************************************************\ + im.ProcessFFTRaw(src_image, inverse, center, normalize) +\*****************************************************************************/ +static int imluaProcessFFTraw (lua_State *L) +{ + imImage* src_image = imlua_checkimage(L, 1); + int inverse = luaL_checkint(L, 2); + int center = luaL_checkint(L, 3); + int normalize = luaL_checkint(L, 4); + + imlua_checkdatatype(L, 1, src_image, IM_CFLOAT); + + imProcessFFTraw(src_image, inverse, center, normalize); + return 0; +} + +/*****************************************************************************\ + im.ProcessSwapQuadrants(src_image, inverse, center, normalize) +\*****************************************************************************/ +static int imluaProcessSwapQuadrants (lua_State *L) +{ + imImage* src_image = imlua_checkimage(L, 1); + int center2origin = luaL_checkint(L, 2); + + imlua_checkdatatype(L, 1, src_image, IM_CFLOAT); + + imProcessSwapQuadrants(src_image, center2origin); + return 0; +} + +/*****************************************************************************\ + im.ProcessCrossCorrelation(image1, image2, dst_image) +\*****************************************************************************/ +static int imluaProcessCrossCorrelation (lua_State *L) +{ + imImage* image1 = imlua_checkimage(L, 1); + imImage* image2 = imlua_checkimage(L, 2); + imImage* dst_image = imlua_checkimage(L, 3); + + imlua_matchsize(L, image1, dst_image); + imlua_matchsize(L, image2, dst_image); + imlua_checkdatatype(L, 3, dst_image, IM_CFLOAT); + + imProcessCrossCorrelation(image1, image2, dst_image); + return 0; +} + +/*****************************************************************************\ + im.ProcessAutoCorrelation(src_image, dst_image) +\*****************************************************************************/ +static int imluaProcessAutoCorrelation (lua_State *L) +{ + imImage* src_image = imlua_checkimage(L, 1); + imImage* dst_image = imlua_checkimage(L, 2); + + imlua_matchsize(L, src_image, dst_image); + imlua_checkdatatype(L, 2, dst_image, IM_CFLOAT); + + imProcessAutoCorrelation(src_image, dst_image); + return 0; +} + +static const luaL_reg imfftw_lib[] = { + {"ProcessFFT", imluaProcessFFT}, + {"ProcessIFFT", imluaProcessIFFT}, + {"ProcessFFTraw", imluaProcessFFTraw}, + {"ProcessSwapQuadrants", imluaProcessSwapQuadrants}, + {"ProcessCrossCorrelation", imluaProcessCrossCorrelation}, + {"ProcessAutoCorrelation", imluaProcessAutoCorrelation}, + + {NULL, NULL} +}; + +int imlua_open_fftw (lua_State *L) +{ + luaL_register(L, "im", imfftw_lib); /* leave "im" table at the top of the stack */ +#ifdef TEC_BIGENDIAN +#ifdef TEC_64 +#include "loh/im_fftw_be64.loh" +#else +#include "loh/im_fftw_be32.loh" +#endif +#else +#ifdef TEC_64 +#ifdef WIN64 +#include "loh/im_fftw_le64w.loh" +#else +#include "loh/im_fftw_le64.loh" +#endif +#else +#include "loh/im_fftw.loh" +#endif +#endif + return 1; +} + +int luaopen_imlua_fftw(lua_State *L) +{ + return imlua_open_fftw(L); +} + +int luaopen_imlua_fftw51(lua_State *L) +{ + return imlua_open_fftw(L); +} diff --git a/im/src/lua5/imlua_fftw.def b/im/src/lua5/imlua_fftw.def new file mode 100755 index 0000000..216c967 --- /dev/null +++ b/im/src/lua5/imlua_fftw.def @@ -0,0 +1,4 @@ +EXPORTS + imlua_open_fftw + luaopen_imlua_fftw + luaopen_imlua_fftw51 \ No newline at end of file diff --git a/im/src/lua5/imlua_file.c b/im/src/lua5/imlua_file.c new file mode 100755 index 0000000..066dd76 --- /dev/null +++ b/im/src/lua5/imlua_file.c @@ -0,0 +1,661 @@ +/** \file + * \brief IM Lua 5 Binding + * + * See Copyright Notice in im_lib.h + * $Id: imlua_file.c,v 1.2 2009/08/04 21:35:26 scuri Exp $ + */ + +#include +#include +#include + +#include "im.h" +#include "im_raw.h" +#include "im_image.h" +#include "im_util.h" + +#include +#include + +#include "imlua.h" +#include "imlua_aux.h" +#include "imlua_image.h" +#include "imlua_palette.h" + + + +static imFile** imlua_rawcheckfile(lua_State *L, int param) +{ + return (imFile**)luaL_checkudata(L, param, "imFile"); +} + +static imFile* imlua_checkfile (lua_State *L, int param) +{ + imFile** ifile_p = imlua_rawcheckfile(L, param); + + if (!(*ifile_p)) + luaL_argerror(L, param, "closed imFile"); + + return *ifile_p; +} + +static int imlua_pushifileerror(lua_State *L, imFile* ifile, int error) +{ + if (error) + { + lua_pushnil(L); + imlua_pusherror(L, error); + return 2; + } + else + { + imFile** ifile_p = (imFile**) lua_newuserdata(L, sizeof(imFile*)); + *ifile_p = ifile; + luaL_getmetatable(L, "imFile"); + lua_setmetatable(L, -2); + return 1; + } +} + + +/*****************************************************************************\ + im.FileOpen(filename) +\*****************************************************************************/ +static int imluaFileOpen (lua_State *L) +{ + const char *filename = luaL_checkstring(L, 1); + int error; + imFile *ifile = imFileOpen(filename, &error); + return imlua_pushifileerror(L, ifile, error); +} + +/*****************************************************************************\ + im.FileOpenAs(filename) +\*****************************************************************************/ +static int imluaFileOpenAs (lua_State *L) +{ + const char *filename = luaL_checkstring(L, 1); + const char *format = luaL_checkstring(L, 2); + int error; + imFile *ifile = imFileOpenAs(filename, format, &error); + return imlua_pushifileerror(L, ifile, error); +} + +/*****************************************************************************\ + im.FileOpenRaw(filename) +\*****************************************************************************/ +static int imluaFileOpenRaw (lua_State *L) +{ + const char *filename = luaL_checkstring(L, 1); + int error; + imFile *ifile = imFileOpenRaw(filename, &error); + return imlua_pushifileerror(L, ifile, error); +} + +/*****************************************************************************\ + im.FileNew(filename, format) +\*****************************************************************************/ +static int imluaFileNew (lua_State *L) +{ + const char *filename = luaL_checkstring(L, 1); + const char *format = luaL_checkstring(L, 2); + int error; + + imFile *ifile = imFileNew(filename, format, &error); + return imlua_pushifileerror(L, ifile, error); +} + +/*****************************************************************************\ + im.FileNewRaw(filename) +\*****************************************************************************/ +static int imluaFileNewRaw (lua_State *L) +{ + const char *filename = luaL_checkstring(L, 1); + int error; + imFile *ifile = imFileNewRaw(filename, &error); + return imlua_pushifileerror(L, ifile, error); +} + +/*****************************************************************************\ + file:Handle() +\*****************************************************************************/ +static int imluaFileHandle (lua_State *L) +{ + lua_pushlightuserdata(L, imFileHandle(imlua_checkfile(L, 1), luaL_checkint(L, 2))); + return 1; +} + +/*****************************************************************************\ + file:LoadImage() +\*****************************************************************************/ +static int imluaFileLoadImage (lua_State *L) +{ + imFile *ifile = imlua_checkfile(L, 1); + int index = luaL_optint(L, 2, 0); + int error; + imImage *image = imFileLoadImage(ifile, index, &error); + return imlua_pushimageerror(L, image, error); +} + +/*****************************************************************************\ + file:LoadImageFrame() +\*****************************************************************************/ +static int imluaFileLoadImageFrame (lua_State *L) +{ + imFile *ifile = imlua_checkfile(L, 1); + int index = luaL_checkint(L, 2); + imImage *image = imlua_checkimage(L, 3); + int error; + + imFileLoadImageFrame(ifile, index, image, &error); + imlua_pusherror(L, error); + + return 1; +} + +/*****************************************************************************\ + file:LoadImageRegion() +\*****************************************************************************/ +static int imluaFileLoadImageRegion (lua_State *L) +{ + imFile *ifile = imlua_checkfile(L, 1); + int index = luaL_checkint(L, 2); + int bitmap = luaL_checkint(L, 3); + int xmin = luaL_checkint(L, 4); + int xmax = luaL_checkint(L, 5); + int ymin = luaL_checkint(L, 6); + int ymax = luaL_checkint(L, 7); + int width = luaL_checkint(L, 8); + int height = luaL_checkint(L, 9); + int error; + imImage *image = imFileLoadImageRegion(ifile, index, bitmap, &error, xmin, xmax, ymin, ymax, width, height); + return imlua_pushimageerror(L, image, error); +} + +/*****************************************************************************\ + file:LoadBitmap() +\*****************************************************************************/ +static int imluaFileLoadBitmap (lua_State *L) +{ + imFile *ifile = imlua_checkfile(L, 1); + int index = luaL_optint(L, 2, 0); + int error; + imImage *image = imFileLoadBitmap(ifile, index, &error); + return imlua_pushimageerror(L, image, error); +} + +/*****************************************************************************\ + file:LoadBitmapFrame() +\*****************************************************************************/ +static int imluaFileLoadBitmapFrame (lua_State *L) +{ + imFile *ifile = imlua_checkfile(L, 1); + int index = luaL_checkint(L, 2); + imImage *image = imlua_checkimage(L, 3); + int error; + + imFileLoadBitmapFrame(ifile, index, image, &error); + imlua_pusherror(L, error); + + return 1; +} + +/*****************************************************************************\ + file:SaveImage() +\*****************************************************************************/ +static int imluaFileSaveImage (lua_State *L) +{ + imFile *ifile = imlua_checkfile(L, 1); + imImage *image = imlua_checkimage(L, 2); + + imlua_pusherror(L, imFileSaveImage(ifile, image)); + return 1; +} + +/*****************************************************************************\ + file:GetInfo() +\*****************************************************************************/ +static int imluaFileGetInfo (lua_State *L) +{ + int image_count; + char format[10]; + char compression[20]; + + imFile *ifile = imlua_checkfile(L, 1); + + imFileGetInfo(ifile, format, compression, &image_count); + + lua_pushstring(L, format); + lua_pushstring(L, compression); + lua_pushnumber(L, image_count); + + return 3; +} + +/*****************************************************************************\ + file:SetInfo() +\*****************************************************************************/ +static int imluaFileSetInfo (lua_State *L) +{ + imFile *ifile = imlua_checkfile(L, 1); + const char *compression = luaL_checkstring(L, 2); + + imFileSetInfo(ifile, compression); + + return 0; +} + +/*****************************************************************************\ + file:SetAttribute(attrib, data_type, data) +\*****************************************************************************/ +static int imluaFileSetAttribute (lua_State *L) +{ + int i, count = 0; + void *data = NULL; + + imFile *ifile = imlua_checkfile(L, 1); + const char *attrib = luaL_checkstring(L, 2); + int data_type = luaL_checkint(L, 3); + + if (!lua_isnil(L, 4)) + { + if (lua_isstring(L, 4) && data_type != IM_BYTE) + luaL_argerror(L, 4, "if value is a string, then data type must be byte"); + else + { + luaL_checktype(L, 4, LUA_TTABLE); + count = imlua_getn(L, 4); + data = malloc(imDataTypeSize(data_type) * count); + } + + switch (data_type) + { + case IM_BYTE: + { + if (lua_isstring(L, 4)) + { + const char* str = lua_tostring(L, 4); + count = strlen(str)+1; + data = malloc(imDataTypeSize(data_type) * count); + memcpy(data, str, count); + } + else + { + imbyte *d = (imbyte*) data; + for (i = 0; i < count; i++) + { + lua_rawgeti(L, 4, i+1); + d[i] = (imbyte) luaL_checkint(L, -1); + lua_pop(L, 1); + } + } + } + break; + + case IM_USHORT: + { + imushort *d = (imushort*) data; + for (i = 0; i < count; i++) + { + lua_rawgeti(L, 4, i+1); + d[i] = (imushort) luaL_checkint(L, -1); + lua_pop(L, 1); + } + } + break; + + case IM_INT: + { + int *d = (int*) data; + for (i = 0; i < count; i++) + { + lua_rawgeti(L, 4, i+1); + d[i] = luaL_checkint(L, -1); + lua_pop(L, 1); + } + } + break; + + case IM_FLOAT: + { + float *d = (float*) data; + for (i = 0; i < count; i++) + { + lua_rawgeti(L, 4, i+1); + d[i] = (float) luaL_checknumber(L, -1); + lua_pop(L, 1); + } + } + break; + + case IM_CFLOAT: + { + float *data_float = (float*) data; + for (i = 0; i < count; i++) + { + int two; + float *value = imlua_toarrayfloat(L, -1, &two, 1); + if (two != 2) + { + free(value); + luaL_argerror(L, 4, "invalid value"); + } + + data_float[i] = value[0]; + data_float[i+1] = value[1]; + free(value); + lua_pop(L, 1); + } + } + break; + } + } + + imFileSetAttribute(ifile, attrib, data_type, count, data); + return 0; +} + +/*****************************************************************************\ + file:GetAttribute(attrib) +\*****************************************************************************/ +static int imluaFileGetAttribute (lua_State *L) +{ + int data_type; + int i, count; + const void *data; + int as_string = 0; + + imFile *ifile = imlua_checkfile(L, 1); + const char *attrib = luaL_checkstring(L, 2); + + data = imFileGetAttribute(ifile, attrib, &data_type, &count); + if (!data) + { + lua_pushnil(L); + return 1; + } + + if (data_type == IM_BYTE && lua_isboolean(L, 3)) + as_string = lua_toboolean(L, 3); + + if (!as_string) + lua_newtable(L); + + switch (data_type) + { + case IM_BYTE: + { + if (as_string) + { + lua_pushstring(L, (const char*)data); + } + else + { + imbyte *data_byte = (imbyte*) data; + for (i = 0; i < count; i++, data_byte++) + { + lua_pushnumber(L, *data_byte); + lua_rawseti(L, -2, i+1); + } + } + } + break; + + case IM_USHORT: + { + imushort *data_ushort = (imushort*) data; + for (i = 0; i < count; i++, data_ushort += 2) + { + lua_pushnumber(L, *data_ushort); + lua_rawseti(L, -2, i+1); + } + } + break; + + case IM_INT: + { + int *data_int = (int*) data; + for (i = 0; i < count; i++, data_int++) + { + lua_pushnumber(L, *data_int); + lua_rawseti(L, -2, i+1); + } + } + break; + + case IM_FLOAT: + { + float *data_float = (float*) data; + for (i = 0; i < count; i++, data_float++) + { + lua_pushnumber(L, *data_float); + lua_rawseti(L, -2, i+1); + } + } + break; + + case IM_CFLOAT: + { + float *data_float = (float*) data; + for (i = 0; i < count; i++, data_float += 2) + { + imlua_newarrayfloat(L, data_float, 2, 1); + lua_rawseti(L, -2, i+1); + } + } + break; + } + + lua_pushnumber(L, data_type); + + return 2; +} + +/*****************************************************************************\ + file:GetAttributeList() +\*****************************************************************************/ +static int imluaFileGetAttributeList (lua_State *L) +{ + int i, attrib_count; + char **attrib; + + imFile* ifile = imlua_checkfile(L, 1); + + imFileGetAttributeList(ifile, NULL, &attrib_count); + + attrib = (char**) malloc(attrib_count * sizeof(char*)); + + imFileGetAttributeList(ifile, attrib, &attrib_count); + + lua_newtable(L); + for (i = 0; i < attrib_count; i++) + { + lua_pushstring(L, attrib[i]); + lua_rawseti(L, -2, i+1); + } + + return 1; +} + +/*****************************************************************************\ + file:GetPalette() +\*****************************************************************************/ +static int imluaFileGetPalette (lua_State *L) +{ + imFile *ifile = imlua_checkfile(L, 1); + long* color = malloc(sizeof(long) * 256); + int count; + imFileGetPalette(ifile, color, &count); + imlua_pushpalette(L, color, count); + return 1; +} + +/*****************************************************************************\ + file:SetPalette(pal) +\*****************************************************************************/ +static int imluaFileSetPalette (lua_State *L) +{ + imFile *ifile = imlua_checkfile(L, 1); + imluaPalette *pal = imlua_checkpalette(L, 2); + imFileSetPalette(ifile, pal->color, pal->count); + return 0; +} + +/*****************************************************************************\ + file:ReadImageInfo() +\*****************************************************************************/ +static int imluaFileReadImageInfo (lua_State *L) +{ + int width, height; + int file_color_mode, file_data_type; + int error; + + imFile *ifile = imlua_checkfile(L, 1); + int index = luaL_optint(L, 2, 0); + + error = imFileReadImageInfo(ifile, index, &width, &height, &file_color_mode, &file_data_type); + + imlua_pusherror(L, error); + if (error) + return 1; + + lua_pushnumber(L, width); + lua_pushnumber(L, height); + lua_pushnumber(L, file_color_mode); + lua_pushnumber(L, file_data_type); + return 5; +} + +/*****************************************************************************\ + file:WriteImageInfo(width, height, user_color_mode, user_data_type) +\*****************************************************************************/ +static int imluaFileWriteImageInfo (lua_State *L) +{ + imFile *ifile = imlua_checkfile(L, 1); + int width = luaL_checkint(L, 2); + int height = luaL_checkint(L, 3); + int user_color_mode = luaL_checkint(L, 4); + int user_data_type = luaL_checkint(L, 5); + + imlua_pusherror(L, imFileWriteImageInfo(ifile, width, height, user_color_mode, user_data_type)); + return 1; +} + +/*****************************************************************************\ + file:ReadImageData(data) +\*****************************************************************************/ +static int imluaFileReadImageData (lua_State *L) +{ + imFile *ifile = imlua_checkfile(L, 1); + void* data = lua_touserdata(L, 2); + int convert2bitmap = lua_toboolean(L, 3); + int color_mode_flags = luaL_checkint(L, 4); + imlua_pusherror(L, imFileReadImageData(ifile, data, convert2bitmap, color_mode_flags)); + return 1; +} + +/*****************************************************************************\ + file:WriteImageData(data) +\*****************************************************************************/ +static int imluaFileWriteImageData (lua_State *L) +{ + imFile *ifile = imlua_checkfile(L, 1); + void* data = lua_touserdata(L, 2); + imlua_pusherror(L, imFileWriteImageData(ifile, data)); + return 1; +} + +/*****************************************************************************\ + file:Close() +\*****************************************************************************/ +static int imluaFileClose (lua_State *L) +{ + imFile** ifile_p = imlua_rawcheckfile(L, 1); + if (!(*ifile_p)) + luaL_argerror(L, 1, "closed imFile"); + + imFileClose(*ifile_p); + *ifile_p = NULL; /* mark as closed */ + return 0; +} + +/*****************************************************************************\ + gc +\*****************************************************************************/ +static int imluaFile_gc (lua_State *L) +{ + imFile **ifile_p = (imFile **)lua_touserdata(L, 1); + if (ifile_p && *ifile_p) + { + imFileClose(*ifile_p); + *ifile_p = NULL; /* mark as closed */ + } + return 0; +} + +/*****************************************************************************\ + tostring +\*****************************************************************************/ +static int imluaFile_tostring (lua_State *L) +{ + imFile **ifile_p = (imFile **)lua_touserdata(L, 1); + lua_pushfstring(L, "imFile(%p)%s", ifile_p, (*ifile_p)? "": "-closed"); + return 1; +} + +/*****************************************************************************\ +\*****************************************************************************/ +static const luaL_reg imfile_lib[] = { + {"FileOpen", imluaFileOpen}, + {"FileOpenAs", imluaFileOpenAs}, + {"FileOpenRaw", imluaFileOpenRaw}, + {"FileNew", imluaFileNew}, + {"FileNewRaw", imluaFileNewRaw}, + {"FileClose", imluaFileClose}, + {NULL, NULL} +}; + +static const luaL_reg imfile_metalib[] = { + {"Handle", imluaFileHandle}, + {"Close", imluaFileClose}, + {"LoadImage", imluaFileLoadImage}, + {"LoadImageFrame", imluaFileLoadImageFrame}, + {"LoadImageRegion", imluaFileLoadImageRegion}, + {"LoadBitmap", imluaFileLoadBitmap}, + {"LoadBitmapFrame", imluaFileLoadBitmapFrame}, + {"SaveImage", imluaFileSaveImage}, + {"GetInfo", imluaFileGetInfo}, + {"SetInfo", imluaFileSetInfo}, + {"SetAttribute", imluaFileSetAttribute}, + {"GetAttribute", imluaFileGetAttribute}, + {"GetAttributeList", imluaFileGetAttributeList}, + {"GetPalette", imluaFileGetPalette}, + {"SetPalette", imluaFileSetPalette}, + {"ReadImageInfo", imluaFileReadImageInfo}, + {"WriteImageInfo", imluaFileWriteImageInfo}, + {"ReadImageData", imluaFileReadImageData}, + {"WriteImageData", imluaFileWriteImageData}, + + {"__gc", imluaFile_gc}, + {"__tostring", imluaFile_tostring}, + + {NULL, NULL} +}; + +static void createmeta (lua_State *L) +{ + /* Object Oriented Access */ + luaL_newmetatable(L, "imFile"); /* create new metatable for imFile handles */ + lua_pushliteral(L, "__index"); + lua_pushvalue(L, -2); /* push metatable */ + lua_rawset(L, -3); /* metatable.__index = metatable */ + luaL_register(L, NULL, imfile_metalib); /* register methods */ + lua_pop(L, 1); /* removes the metatable from the top of the stack */ +} + +void imlua_open_file (lua_State *L) +{ + /* "im" table is at the top of the stack */ + createmeta(L); + luaL_register(L, NULL, imfile_lib); +} diff --git a/im/src/lua5/imlua_image.c b/im/src/lua5/imlua_image.c new file mode 100755 index 0000000..40b1e9c --- /dev/null +++ b/im/src/lua5/imlua_image.c @@ -0,0 +1,1083 @@ +/** \file + * \brief IM Lua 5 Binding + * + * See Copyright Notice in im_lib.h + * $Id: imlua_image.c,v 1.5 2009/09/25 18:40:31 scuri Exp $ + */ + +#include +#include +#include + +#include "im.h" +#include "im_image.h" +#include "im_util.h" +#include "im_convert.h" + +#include +#include + +#include "imlua.h" +#include "imlua_image.h" +#include "imlua_palette.h" +#include "imlua_aux.h" + + +static imImage** imlua_rawcheckimage(lua_State *L, int param) +{ + return (imImage**) luaL_checkudata(L, param, "imImage"); +} + +imImage* imlua_checkimage(lua_State *L, int param) +{ + imImage** image_p = imlua_rawcheckimage(L, param); + + if (!(*image_p)) + luaL_argerror(L, param, "destroyed imImage"); + + return *image_p; +} + +int imlua_pushimageerror(lua_State *L, imImage* image, int error) +{ + if (error) + { + lua_pushnil(L); + imlua_pusherror(L, error); + return 2; + } + else + { + imlua_pushimage(L, image); + return 1; + } +} + +void imlua_pushimage(lua_State *L, imImage* image) +{ + if (!image) + lua_pushnil(L); + else + { + imImage **image_p = (imImage**) lua_newuserdata(L, sizeof(imImage*)); + *image_p = image; + luaL_getmetatable(L, "imImage"); + lua_setmetatable(L, -2); + } +} + +/*****************************************************************************\ + image channel, for indexing +\*****************************************************************************/ +static imluaImageChannel *imlua_newimagechannel (lua_State *L, imImage *image, int channel) +{ + imluaImageChannel* imagechannel = (imluaImageChannel*) lua_newuserdata(L, sizeof(imluaImageChannel)); + imagechannel->image = image; + imagechannel->channel = channel; + luaL_getmetatable(L, "imImageChannel"); + lua_setmetatable(L, -2); + return imagechannel; +} + +static imluaImageChannel* imlua_checkimagechannel (lua_State *L, int param) +{ + return (imluaImageChannel*) luaL_checkudata(L, param, "imImageChannel"); +} + +/*****************************************************************************\ + image row, for indexing +\*****************************************************************************/ +static imluaImageRow *imlua_newimagerow (lua_State *L, imImage *image, int channel, int row) +{ + imluaImageRow* imagerow = (imluaImageRow*) lua_newuserdata(L, sizeof(imluaImageRow)); + imagerow->image = image; + imagerow->channel = channel; + imagerow->row = row; + luaL_getmetatable(L, "imImageChannelRow"); + lua_setmetatable(L, -2); + return imagerow; +} + +static imluaImageRow* imlua_checkimagerow (lua_State *L, int param) +{ + return (imluaImageRow*) luaL_checkudata(L, param, "imImageChannelRow"); +} + +/*****************************************************************************\ + im.ImageCreate(width, height, color_space, data_type) +\*****************************************************************************/ +static int imluaImageCreate (lua_State *L) +{ + int width = luaL_checkint(L, 1); + int height = luaL_checkint(L, 2); + int color_space = luaL_checkint(L, 3); + int data_type = luaL_checkint(L, 4); + + imImage *image = imImageCreate(width, height, color_space, data_type); + imlua_pushimage(L, image); + return 1; +} + +/*****************************************************************************\ + image:AddAlpha() +\*****************************************************************************/ +static int imluaImageAddAlpha (lua_State *L) +{ + imImageAddAlpha(imlua_checkimage(L, 1)); + return 0; +} + +/*****************************************************************************\ + image:Reshape() +\*****************************************************************************/ +static int imluaImageReshape (lua_State *L) +{ + imImage* im = imlua_checkimage(L, 1); + int width = luaL_checkint(L, 2); + int height = luaL_checkint(L, 3); + + imImageReshape(im, width, height); + return 0; +} + +/*****************************************************************************\ + image:Copy() +\*****************************************************************************/ +static int imluaImageCopy (lua_State *L) +{ + imImage* src_image = imlua_checkimage(L, 1); + imImage* dst_image = imlua_checkimage(L, 2); + + imlua_match(L, src_image, dst_image); + imImageCopy(src_image, dst_image); + return 0; +} + +/*****************************************************************************\ + image:CopyData() +\*****************************************************************************/ +static int imluaImageCopyData (lua_State *L) +{ + imImage* src_image = imlua_checkimage(L, 1); + imImage* dst_image = imlua_checkimage(L, 2); + + imlua_match(L, src_image, dst_image); + imImageCopyData(src_image, dst_image); + return 0; +} + +/*****************************************************************************\ + image:Duplicate() +\*****************************************************************************/ +static int imluaImageDuplicate (lua_State *L) +{ + imImage* image = imlua_checkimage(L, 1); + imImage *new_image = imImageDuplicate(image); + imlua_pushimage(L, new_image); + return 1; +} + +/*****************************************************************************\ + image:Clone() +\*****************************************************************************/ +static int imluaImageClone (lua_State *L) +{ + imImage* image = imlua_checkimage(L, 1); + imImage *new_image = imImageClone(image); + imlua_pushimage(L, new_image); + return 1; +} + +/*****************************************************************************\ + image:SetAttribute(attrib, data_type, count, data) +\*****************************************************************************/ +static int imluaImageSetAttribute (lua_State *L) +{ + int i, count = 0; + void *data = NULL; + + imImage* image = imlua_checkimage(L, 1); + const char *attrib = luaL_checkstring(L, 2); + int data_type = luaL_checkint(L, 3); + + if (!lua_isnil(L, 4)) + { + if (lua_isstring(L, 4) && data_type != IM_BYTE) + luaL_argerror(L, 4, "if value is string, then data type must be byte"); + else + { + luaL_checktype(L, 4, LUA_TTABLE); + count = imlua_getn(L, 4); + data = malloc(imDataTypeSize(data_type) * count); + } + + switch (data_type) + { + case IM_BYTE: + { + if (lua_isstring(L, 4)) + { + const char* str = lua_tostring(L, 4); + count = strlen(str)+1; + data = malloc(imDataTypeSize(data_type) * count); + memcpy(data, str, count); + } + else + { + imbyte *data_byte = (imbyte*) data; + for (i = 0; i < count; i++) + { + lua_rawgeti(L, 4, i+1); + data_byte[i] = (imbyte)luaL_checkint(L, -1); + lua_pop(L, 1); + } + } + } + break; + + case IM_USHORT: + { + imushort *data_ushort = (imushort*) data; + for (i = 0; i < count; i++) + { + lua_rawgeti(L, 4, i+1); + data_ushort[i] = (imushort)luaL_checkint(L, -1); + lua_pop(L, 1); + } + } + break; + + case IM_INT: + { + int *data_int = (int*) data; + for (i = 0; i < count; i++) + { + lua_rawgeti(L, 4, i+1); + data_int[i] = luaL_checkint(L, -1); + lua_pop(L, 1); + } + } + break; + + case IM_FLOAT: + { + float *data_float = (float*) data; + for (i = 0; i < count; i++) + { + lua_rawgeti(L, 4, i+1); + data_float[i] = (float) luaL_checknumber(L, -1); + lua_pop(L, 1); + } + } + break; + + case IM_CFLOAT: + { + float *data_float = (float*) data; + for (i = 0; i < count; i++) + { + int two; + float *value = imlua_toarrayfloat(L, -1, &two, 1); + if (two != 2) + { + free(value); + luaL_argerror(L, 4, "invalid value"); + } + + data_float[i] = value[0]; + data_float[i+1] = value[1]; + free(value); + lua_pop(L, 1); + } + } + break; + } + } + + imImageSetAttribute(image, attrib, data_type, count, data); + return 0; +} + +/*****************************************************************************\ + image:GetAttribute(attrib) +\*****************************************************************************/ +static int imluaImageGetAttribute (lua_State *L) +{ + int data_type; + int i, count; + const void *data; + int as_string = 0; + + imImage* image = imlua_checkimage(L, 1); + const char *attrib = luaL_checkstring(L, 2); + + data = imImageGetAttribute(image, attrib, &data_type, &count); + if (!data) + { + lua_pushnil(L); + return 1; + } + + if (data_type == IM_BYTE && lua_isboolean(L, 3)) + as_string = lua_toboolean(L, 3); + + if (!as_string) + lua_newtable(L); + + switch (data_type) + { + case IM_BYTE: + { + if (as_string) + { + lua_pushstring(L, (const char*)data); + } + else + { + imbyte *data_byte = (imbyte*) data; + for (i = 0; i < count; i++, data_byte++) + { + lua_pushnumber(L, *data_byte); + lua_rawseti(L, -2, i+1); + } + } + } + break; + + case IM_USHORT: + { + imushort *data_ushort = (imushort*) data; + for (i = 0; i < count; i++, data_ushort += 2) + { + lua_pushnumber(L, *data_ushort); + lua_rawseti(L, -2, i+1); + } + } + break; + + case IM_INT: + { + int *data_int = (int*) data; + for (i = 0; i < count; i++, data_int++) + { + lua_pushnumber(L, *data_int); + lua_rawseti(L, -2, i+1); + } + } + break; + + case IM_FLOAT: + { + float *data_float = (float*) data; + for (i = 0; i < count; i++, data_float++) + { + lua_pushnumber(L, *data_float); + lua_rawseti(L, -2, i+1); + } + } + break; + + case IM_CFLOAT: + { + float *data_float = (float*) data; + for (i = 0; i < count; i++, data_float += 2) + { + imlua_newarrayfloat(L, data_float, 2, 1); + lua_rawseti(L, -2, i+1); + } + } + break; + } + + lua_pushnumber(L, data_type); + + return 2; +} + +/*****************************************************************************\ + image:GetAttributeList() +\*****************************************************************************/ +static int imluaImageGetAttributeList (lua_State *L) +{ + int i, attrib_count; + char **attrib; + + imImage* image = imlua_checkimage(L, 1); + + imImageGetAttributeList(image, NULL, &attrib_count); + + attrib = (char**) malloc(attrib_count * sizeof(char*)); + + imImageGetAttributeList(image, attrib, &attrib_count); + + lua_newtable(L); + for (i = 0; i < attrib_count; i++) + { + lua_pushstring(L, attrib[i]); + lua_rawseti(L, -2, i+1); + } + + return 1; +} + +/*****************************************************************************\ + image:Clear() +\*****************************************************************************/ +static int imluaImageClear (lua_State *L) +{ + imImageClear(imlua_checkimage(L, 1)); + return 0; +} + +/*****************************************************************************\ + image:isBitmap() +\*****************************************************************************/ +static int imluaImageIsBitmap (lua_State *L) +{ + lua_pushboolean(L, imImageIsBitmap(imlua_checkimage(L, 1))); + return 1; +} + + +/*****************************************************************************\ + image:GetOpenGLData() +\*****************************************************************************/ +static int imluaImageGetOpenGLData (lua_State *L) +{ + int format; + imbyte* gldata; + imImage *image = imlua_checkimage(L, 1); + + gldata = imImageGetOpenGLData(image, &format); + if (!gldata) + { + lua_pushnil(L); + return 1; + } + + lua_pushlightuserdata(L, gldata); + lua_pushinteger(L, format); + return 2; +} + +/*****************************************************************************\ + image:GetPalette() +\*****************************************************************************/ +static int imluaImageGetPalette (lua_State *L) +{ + imImage *image = imlua_checkimage(L, 1); + long* color = malloc(sizeof(long) * 256); + memcpy(color, image->palette, sizeof(long) * 256); + imlua_pushpalette(L, color, 256); + return 1; +} + +/*****************************************************************************\ + image:SetPalette +\*****************************************************************************/ +static int imluaImageSetPalette (lua_State *L) +{ + imImage *image = imlua_checkimage(L, 1); + imluaPalette *pal = imlua_checkpalette(L, 2); + long* palette = (long*)malloc(sizeof(long)*256); + memcpy(palette, pal->color, pal->count*sizeof(long)); + imImageSetPalette(image, palette, pal->count); + return 0; +} + +/*****************************************************************************\ + image:CopyAttributes(dst_image) +\*****************************************************************************/ +static int imluaImageCopyAttributes (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + + imImageCopyAttributes(src_image, dst_image); + return 0; +} + +/*****************************************************************************\ + image:MatchSize(image2) +\*****************************************************************************/ +static int imluaImageMatchSize (lua_State *L) +{ + imImage *image1 = imlua_checkimage(L, 1); + imImage *image2 = imlua_checkimage(L, 2); + + lua_pushboolean(L, imImageMatchSize(image1, image2)); + return 1; +} + +/*****************************************************************************\ + image:MatchColor(image2) +\*****************************************************************************/ +static int imluaImageMatchColor (lua_State *L) +{ + imImage *image1 = imlua_checkimage(L, 1); + imImage *image2 = imlua_checkimage(L, 2); + + lua_pushboolean(L, imImageMatchColor(image1, image2)); + return 1; +} + +/*****************************************************************************\ + image:MatchDataType(image2) +\*****************************************************************************/ +static int imluaImageMatchDataType (lua_State *L) +{ + imImage *image1 = imlua_checkimage(L, 1); + imImage *image2 = imlua_checkimage(L, 2); + + lua_pushboolean(L, imImageMatchDataType(image1, image2)); + return 1; +} + +/*****************************************************************************\ + image:MatchColorSpace(image2) +\*****************************************************************************/ +static int imluaImageMatchColorSpace (lua_State *L) +{ + imImage *image1 = imlua_checkimage(L, 1); + imImage *image2 = imlua_checkimage(L, 2); + + lua_pushboolean(L, imImageMatchColorSpace(image1, image2)); + return 1; +} + +/*****************************************************************************\ + image:Match(image2) +\*****************************************************************************/ +static int imluaImageMatch (lua_State *L) +{ + imImage *image1 = imlua_checkimage(L, 1); + imImage *image2 = imlua_checkimage(L, 2); + + lua_pushboolean(L, imImageMatch(image1, image2)); + return 1; +} + +/*****************************************************************************\ + image:SetBinary() +\*****************************************************************************/ +static int imluaImageSetBinary (lua_State *L) +{ + imImageSetBinary(imlua_checkimage(L, 1)); + return 0; +} + +/*****************************************************************************\ + image:MakeBinary() +\*****************************************************************************/ +static int imluaImageMakeBinary (lua_State *L) +{ + imImageMakeBinary(imlua_checkimage(L, 1)); + return 0; +} + +/*****************************************************************************\ + image:MakeGray() +\*****************************************************************************/ +static int imluaImageMakeGray (lua_State *L) +{ + imImageMakeGray(imlua_checkimage(L, 1)); + return 0; +} + +/*****************************************************************************\ + image:Width() +\*****************************************************************************/ +static int imluaImageWidth(lua_State *L) +{ + imImage *im = imlua_checkimage(L, 1); + lua_pushnumber(L, im->width); + return 1; +} + +/*****************************************************************************\ + image:Height() +\*****************************************************************************/ +static int imluaImageHeight(lua_State *L) +{ + imImage *im = imlua_checkimage(L, 1); + lua_pushnumber(L, im->height); + return 1; +} + +/*****************************************************************************\ + image:Depth() +\*****************************************************************************/ +static int imluaImageDepth(lua_State *L) +{ + imImage *im = imlua_checkimage(L, 1); + lua_pushnumber(L, im->depth); + return 1; +} + +/*****************************************************************************\ + image:DataType() +\*****************************************************************************/ +static int imluaImageDataType(lua_State *L) +{ + imImage *im = imlua_checkimage(L, 1); + lua_pushnumber(L, im->data_type); + return 1; +} + +/*****************************************************************************\ + image:ColorSpace() +\*****************************************************************************/ +static int imluaImageColorSpace(lua_State *L) +{ + imImage *im = imlua_checkimage(L, 1); + lua_pushnumber(L, im->color_space); + return 1; +} + +/*****************************************************************************\ + image:HasAlpha() +\*****************************************************************************/ +static int imluaImageHasAlpha(lua_State *L) +{ + imImage *im = imlua_checkimage(L, 1); + lua_pushnumber(L, im->has_alpha); + return 1; +} + +/*****************************************************************************\ + im.FileImageLoad(filename, [index]) +\*****************************************************************************/ +static int imluaFileImageLoad (lua_State *L) +{ + const char *filename = luaL_checkstring(L, 1); + int index = luaL_optint(L, 2, 0); + int error; + imImage *image = imFileImageLoad(filename, index, &error); + return imlua_pushimageerror(L, image, error); +} + +/*****************************************************************************\ + im.FileImageLoadRegion(filename, [index]) +\*****************************************************************************/ +static int imluaFileImageLoadRegion (lua_State *L) +{ + const char *filename = luaL_checkstring(L, 1); + int index = luaL_checkint(L, 2); + int bitmap = luaL_checkint(L, 3); + int xmin = luaL_checkint(L, 4); + int xmax = luaL_checkint(L, 5); + int ymin = luaL_checkint(L, 6); + int ymax = luaL_checkint(L, 7); + int width = luaL_checkint(L, 8); + int height = luaL_checkint(L, 9); + int error; + imImage *image = imFileImageLoadRegion(filename, index, bitmap, &error, xmin, xmax, ymin, ymax, width, height); + return imlua_pushimageerror(L, image, error); +} + +/*****************************************************************************\ + im.FileImageLoadBitmap(filename, [index]) +\*****************************************************************************/ +static int imluaFileImageLoadBitmap (lua_State *L) +{ + const char *filename = luaL_checkstring(L, 1); + int index = luaL_optint(L, 2, 0); + int error; + imImage *image = imFileImageLoadBitmap(filename, index, &error); + return imlua_pushimageerror(L, image, error); +} + +/*****************************************************************************\ + im.FileImageSave(filename, format, image) +\*****************************************************************************/ +static int imluaFileImageSave (lua_State *L) +{ + const char *file_name = luaL_checkstring(L, 1); + const char *format = luaL_checkstring(L, 2); + imImage *image = imlua_checkimage(L, 3); + + imlua_pusherror(L, imFileImageSave(file_name, format, image)); + return 1; +} + +/*****************************************************************************\ + image:Save(filename, format) +\*****************************************************************************/ +static int imluaImageSave (lua_State *L) +{ + imImage *image = imlua_checkimage(L, 1); + const char *file_name = luaL_checkstring(L, 2); + const char *format = luaL_checkstring(L, 3); + + imlua_pusherror(L, imFileImageSave(file_name, format, image)); + return 1; +} + +/*****************************************************************************\ + image:Destroy() +\*****************************************************************************/ +static int imluaImageDestroy (lua_State *L) +{ + imImage** image_p = imlua_rawcheckimage(L, 1); + if (!(*image_p)) + luaL_argerror(L, 1, "destroyed imImage"); + + imImageDestroy(*image_p); + *image_p = NULL; /* mark as destroyed */ + return 0; +} + +/*****************************************************************************\ + gc +\*****************************************************************************/ +static int imluaImage_gc (lua_State *L) +{ + imImage** image_p = imlua_rawcheckimage(L, 1); + if (*image_p) + { + imImageDestroy(*image_p); + *image_p = NULL; /* mark as destroyed */ + } + + return 0; +} + +/*****************************************************************************\ + image tostring +\*****************************************************************************/ +static int imluaImage_tostring (lua_State *L) +{ + imImage** image_p = (imImage**)lua_touserdata(L, 1); + if (*image_p) + { + imImage *image = *image_p; + lua_pushfstring(L, "imImage(%p) [width=%d,height=%d,color_space=%s,data_type=%s,depth=%d]", + image_p, + image->width, + image->height, + imColorModeSpaceName(image->color_space), + imDataTypeName(image->data_type), + image->depth + ); + } + else + { + lua_pushfstring(L, "imImage(%p)-destroyed", image_p); + } + + return 1; +} + +/*****************************************************************************\ + imagechannel tostring +\*****************************************************************************/ +static int imluaImageChannel_tostring (lua_State *L) +{ + imluaImageChannel *imagechannel = imlua_checkimagechannel(L, 1); + lua_pushfstring(L, "imImageChannel(%p) [channel=%d]", + imagechannel, + imagechannel->channel + ); + return 1; +} + +/*****************************************************************************\ + imagerow tostring +\*****************************************************************************/ +static int imluaImageRow_tostring (lua_State *L) +{ + char buff[32]; + imluaImageRow *imagerow = imlua_checkimagerow(L, 1); + + sprintf(buff, "%p", lua_touserdata(L, 1)); + lua_pushfstring(L, "imImageRow(%s) [channel=%d,row=%d]", + buff, + imagerow->channel, + imagerow->row + ); + return 1; +} + +/*****************************************************************************\ + image row indexing +\*****************************************************************************/ +static int imluaImageRow_index (lua_State *L) +{ + int index; + imluaImageRow *imagerow = imlua_checkimagerow(L, 1); + imImage *image = imagerow->image; + int channel = imagerow->channel; + int row = imagerow->row; + int column = luaL_checkint(L, 2); + + if (column < 0 || column >= imagerow->image->width) + luaL_argerror(L, 2, "invalid column, out of bounds"); + + index = channel * image->width * image->height + row * image->width + column; + + switch (image->data_type) + { + case IM_BYTE: + { + imbyte *bdata = (imbyte*) image->data[0]; + lua_pushnumber(L, (lua_Number) bdata[index]); + } + break; + + case IM_USHORT: + { + imushort *udata = (imushort*) image->data[0]; + lua_pushnumber(L, (lua_Number) udata[index]); + } + break; + + case IM_INT: + { + int *idata = (int*) image->data[0]; + lua_pushnumber(L, (lua_Number) idata[index]); + } + break; + + case IM_FLOAT: + { + float *fdata = (float*) image->data[0]; + lua_pushnumber(L, (lua_Number) fdata[index]); + } + break; + + case IM_CFLOAT: + { + float *cdata = (float*) image->data[0]; + imlua_newarrayfloat(L, cdata + (2*index), 2, 1); + } + break; + } + + return 1; +} + +/*****************************************************************************\ + image row new index +\*****************************************************************************/ +static int imluaImageRow_newindex (lua_State *L) +{ + int index; + imluaImageRow *imagerow = imlua_checkimagerow(L, 1); + imImage *image = imagerow->image; + int channel = imagerow->channel; + int row = imagerow->row; + int column = luaL_checkint(L, 2); + + if (column < 0 || column >= imagerow->image->width) + luaL_argerror(L, 2, "invalid column, out of bounds"); + + index = channel * image->width * image->height + row * image->width + column; + + switch (image->data_type) + { + case IM_BYTE: + { + lua_Number value = luaL_checknumber(L, 3); + imbyte *bdata = (imbyte*) image->data[0]; + bdata[index] = (imbyte) value; + } + break; + + case IM_USHORT: + { + lua_Number value = luaL_checknumber(L, 3); + imushort *udata = (imushort*) image->data[0]; + udata[index] = (imushort) value; + } + break; + + case IM_INT: + { + lua_Number value = luaL_checknumber(L, 3); + int *idata = (int*) image->data[0]; + idata[index] = (int) value; + } + break; + + case IM_FLOAT: + { + lua_Number value = luaL_checknumber(L, 3); + float *fdata = (float*) image->data[0]; + fdata[index] = (float) value; + } + break; + + case IM_CFLOAT: + { + int count; + float *cdata = (float*) image->data[0]; + float *value = imlua_toarrayfloat(L, 3, &count, 1); + if (count != 2) + { + free(value); + luaL_argerror(L, 3, "invalid value"); + } + + cdata[2*index] = value[0]; + cdata[2*index+1] = value[1]; + free(value); + } + break; + } + + return 0; +} + +/*****************************************************************************\ + image channel indexing +\*****************************************************************************/ +static int imluaImageChannel_index (lua_State *L) +{ + imluaImageChannel *imagechannel = imlua_checkimagechannel(L, 1); + int row = luaL_checkint(L, 2); + + if (row < 0 || row >= imagechannel->image->height) + luaL_argerror(L, 2, "invalid row, out of bounds"); + + imlua_newimagerow(L, imagechannel->image, imagechannel->channel, row); + return 1; +} + +/*****************************************************************************\ + image indexing +\*****************************************************************************/ +static int imluaImage_index (lua_State *L) +{ + imImage *image = imlua_checkimage(L, 1); + + if (lua_isnumber(L, 2)) + { + /* handle numeric indexing */ + int channel = luaL_checkint(L, 2); + + /* create channel */ + if (channel < 0 || channel >= image->depth) + luaL_argerror(L, 2, "invalid channel, out of bounds"); + + imlua_newimagechannel(L, image, channel); + } + else if (lua_isstring(L, 2)) + { + /* get raw method */ + lua_getmetatable(L, 1); + lua_pushvalue(L, 2); + lua_rawget(L, -2); + } + else + { + lua_pushnil(L); + } + + return 1; +} + +static const luaL_reg imimage_lib[] = { + {"ImageCreate", imluaImageCreate}, + {"ImageDestroy", imluaImageDestroy}, + {"FileImageLoad", imluaFileImageLoad}, + {"FileImageLoadBitmap", imluaFileImageLoadBitmap}, + {"FileImageLoadRegion", imluaFileImageLoadRegion}, + {"FileImageSave", imluaFileImageSave}, + {NULL, NULL} +}; + +static const luaL_reg imimage_metalib[] = { + {"Destroy", imluaImageDestroy}, + {"AddAlpha", imluaImageAddAlpha}, + {"Reshape", imluaImageReshape}, + {"Copy", imluaImageCopy}, + {"CopyData", imluaImageCopyData}, + {"Duplicate", imluaImageDuplicate}, + {"Clone", imluaImageClone}, + {"SetAttribute", imluaImageSetAttribute}, + {"GetAttribute", imluaImageGetAttribute}, + {"GetAttributeList", imluaImageGetAttributeList}, + {"Clear", imluaImageClear}, + {"IsBitmap", imluaImageIsBitmap}, + {"GetOpenGLData", imluaImageGetOpenGLData}, + {"SetPalette", imluaImageSetPalette}, + {"GetPalette", imluaImageGetPalette}, + {"CopyAttributes", imluaImageCopyAttributes}, + {"MatchSize", imluaImageMatchSize}, + {"MatchColor", imluaImageMatchColor}, + {"MatchDataType", imluaImageMatchDataType}, + {"MatchColorSpace", imluaImageMatchColorSpace}, + {"Match", imluaImageMatch}, + {"SetBinary", imluaImageSetBinary}, + {"MakeBinary", imluaImageMakeBinary}, + {"MakeGray", imluaImageMakeGray}, + {"Width", imluaImageWidth}, + {"Height", imluaImageHeight}, + {"Depth", imluaImageDepth}, + {"DataType", imluaImageDataType}, + {"ColorSpace", imluaImageColorSpace}, + {"HasAlpha", imluaImageHasAlpha}, + {"Save", imluaImageSave}, + + {"__gc", imluaImage_gc}, + {"__tostring", imluaImage_tostring}, + {"__index", imluaImage_index}, + + {NULL, NULL} +}; + +static void createmeta (lua_State *L) +{ + luaL_newmetatable(L, "imImageChannel"); /* create new metatable for imImageChannel handles */ + lua_pushliteral(L, "__index"); + lua_pushcfunction(L, imluaImageChannel_index); + lua_rawset(L, -3); + lua_pushliteral(L, "__tostring"); + lua_pushcfunction(L, imluaImageChannel_tostring); + lua_rawset(L, -3); + lua_pop(L, 1); /* removes the metatable from the top of the stack */ + + luaL_newmetatable(L, "imImageChannelRow"); /* create new metatable for imImageChannelRow handles */ + lua_pushliteral(L, "__index"); + lua_pushcfunction(L, imluaImageRow_index); + lua_rawset(L, -3); + lua_pushliteral(L, "__newindex"); + lua_pushcfunction(L, imluaImageRow_newindex); + lua_rawset(L, -3); + lua_pushliteral(L, "__tostring"); + lua_pushcfunction(L, imluaImageRow_tostring); + lua_rawset(L, -3); + lua_pop(L, 1); /* removes the metatable from the top of the stack */ + + /* Object Oriented Access */ + luaL_newmetatable(L, "imImage"); /* create new metatable for imImage handles */ + lua_pushliteral(L, "__index"); /* dummy code because imluaImage_index will overwrite this behavior */ + lua_pushvalue(L, -2); /* push metatable */ + lua_rawset(L, -3); /* metatable.__index = metatable */ + luaL_register(L, NULL, imimage_metalib); /* register methods */ + lua_pop(L, 1); /* removes the metatable from the top of the stack */ +} + +void imlua_open_image (lua_State *L) +{ + /* "im" table is at the top of the stack */ + createmeta(L); + luaL_register(L, NULL, imimage_lib); +#ifdef TEC_BIGENDIAN +#ifdef TEC_64 +#include "loh/im_image_be64.loh" +#else +#include "loh/im_image_be32.loh" +#endif +#else +#ifdef TEC_64 +#ifdef WIN64 +#include "loh/im_image_le64w.loh" +#else +#include "loh/im_image_le64.loh" +#endif +#else +#include "loh/im_image.loh" +#endif +#endif +} diff --git a/im/src/lua5/imlua_image.h b/im/src/lua5/imlua_image.h new file mode 100755 index 0000000..0a39863 --- /dev/null +++ b/im/src/lua5/imlua_image.h @@ -0,0 +1,38 @@ +/** \file + * \brief IM Lua 5 Binding + * + * See Copyright Notice in im_lib.h + * $Id: imlua_image.h,v 1.1 2008/10/17 06:16:32 scuri Exp $ + */ + +#ifndef __IMLUA_IMAGE_H +#define __IMLUA_IMAGE_H + +#if defined(__cplusplus) +extern "C" { +#endif + + +typedef struct _imluaImageChannel { + imImage *image; + int channel; +} imluaImageChannel; + +typedef struct _imluaImageRow { + imImage *image; + int channel; + int row; +} imluaImageRow; + +void imlua_open_image(lua_State *L); + +int imlua_pushimageerror(lua_State *L, imImage* image, int error); +void imlua_pushimage(lua_State *L, imImage* image); +imImage* imlua_checkimage(lua_State *L, int param); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/im/src/lua5/imlua_jp2.c b/im/src/lua5/imlua_jp2.c new file mode 100755 index 0000000..d69ba7e --- /dev/null +++ b/im/src/lua5/imlua_jp2.c @@ -0,0 +1,44 @@ +/** \file + * \brief jp2 format Lua 5 Binding + * + * See Copyright Notice in cd.h + */ + +#include +#include + +#include "im_format_jp2.h" + +#include +#include + + +static int imlua_FormatRegisterJP2(lua_State *L) +{ + (void)L; + imFormatRegisterJP2(); + return 0; +} + +static const struct luaL_reg imlib[] = { + {"FormatRegisterJP2", imlua_FormatRegisterJP2}, + {NULL, NULL}, +}; + + +static int imlua_jp2_open (lua_State *L) +{ + imFormatRegisterJP2(); + luaL_register(L, "im", imlib); /* leave "im" table at the top of the stack */ + return 1; +} + +int luaopen_imlua_jp2(lua_State* L) +{ + return imlua_jp2_open(L); +} + +int luaopen_imlua_jp251(lua_State* L) +{ + return imlua_jp2_open(L); +} diff --git a/im/src/lua5/imlua_jp2.def b/im/src/lua5/imlua_jp2.def new file mode 100755 index 0000000..29aa05c --- /dev/null +++ b/im/src/lua5/imlua_jp2.def @@ -0,0 +1,4 @@ +EXPORTS + luaopen_imlua_jp2 + luaopen_imlua_jp251 + \ No newline at end of file diff --git a/im/src/lua5/imlua_kernel.c b/im/src/lua5/imlua_kernel.c new file mode 100755 index 0000000..770a989 --- /dev/null +++ b/im/src/lua5/imlua_kernel.c @@ -0,0 +1,182 @@ +/** \file + * \brief IM Lua 5 Binding + * + * See Copyright Notice in im_lib.h + * $Id: imlua_kernel.c,v 1.1 2008/10/17 06:16:32 scuri Exp $ + */ + +#include +#include +#include + +#include "im.h" +#include "im_image.h" +#include "im_process.h" +#include "im_util.h" +#include "im_kernel.h" + +#include +#include + +#include "imlua.h" +#include "imlua_aux.h" +#include "imlua_image.h" + + +static int imluaKernelSobel(lua_State *L) +{ + imlua_pushimage(L, imKernelSobel()); + return 1; +} + +static int imluaKernelPrewitt(lua_State *L) +{ + imlua_pushimage(L, imKernelPrewitt()); + return 1; +} + +static int imluaKernelKirsh(lua_State *L) +{ + imlua_pushimage(L, imKernelKirsh()); + return 1; +} + +static int imluaKernelLaplacian4(lua_State *L) +{ + imlua_pushimage(L, imKernelLaplacian4()); + return 1; +} + +static int imluaKernelLaplacian8(lua_State *L) +{ + imlua_pushimage(L, imKernelLaplacian8()); + return 1; +} + +static int imluaKernelLaplacian5x5(lua_State *L) +{ + imlua_pushimage(L, imKernelLaplacian5x5()); + return 1; +} + +static int imluaKernelLaplacian7x7(lua_State *L) +{ + imlua_pushimage(L, imKernelLaplacian7x7()); + return 1; +} + +static int imluaKernelGradian3x3(lua_State *L) +{ + imlua_pushimage(L, imKernelGradian3x3()); + return 1; +} + +static int imluaKernelGradian7x7(lua_State *L) +{ + imlua_pushimage(L, imKernelGradian7x7()); + return 1; +} + +static int imluaKernelSculpt(lua_State *L) +{ + imlua_pushimage(L, imKernelSculpt()); + return 1; +} + +static int imluaKernelMean3x3(lua_State *L) +{ + imlua_pushimage(L, imKernelMean3x3()); + return 1; +} + +static int imluaKernelMean5x5(lua_State *L) +{ + imlua_pushimage(L, imKernelMean5x5()); + return 1; +} + +static int imluaKernelCircularMean5x5(lua_State *L) +{ + imlua_pushimage(L, imKernelCircularMean5x5()); + return 1; +} + +static int imluaKernelMean7x7(lua_State *L) +{ + imlua_pushimage(L, imKernelMean7x7()); + return 1; +} + +static int imluaKernelCircularMean7x7(lua_State *L) +{ + imlua_pushimage(L, imKernelCircularMean7x7()); + return 1; +} + +static int imluaKernelGaussian3x3(lua_State *L) +{ + imlua_pushimage(L, imKernelGaussian3x3()); + return 1; +} + +static int imluaKernelGaussian5x5(lua_State *L) +{ + imlua_pushimage(L, imKernelGaussian5x5()); + return 1; +} + +static int imluaKernelBarlett5x5(lua_State *L) +{ + imlua_pushimage(L, imKernelBarlett5x5()); + return 1; +} + +static int imluaKernelTopHat5x5(lua_State *L) +{ + imlua_pushimage(L, imKernelTopHat5x5()); + return 1; +} + +static int imluaKernelTopHat7x7(lua_State *L) +{ + imlua_pushimage(L, imKernelTopHat7x7()); + return 1; +} + +static int imluaKernelEnhance(lua_State *L) +{ + imlua_pushimage(L, imKernelEnhance()); + return 1; +} + + +static const luaL_reg imkernel_lib[] = { + {"KernelSobel", imluaKernelSobel}, + {"KernelPrewitt", imluaKernelPrewitt}, + {"KernelKirsh", imluaKernelKirsh}, + {"KernelLaplacian4", imluaKernelLaplacian4}, + {"KernelLaplacian8", imluaKernelLaplacian8}, + {"KernelLaplacian5x5", imluaKernelLaplacian5x5}, + {"KernelLaplacian7x7", imluaKernelLaplacian7x7}, + {"KernelGradian3x3", imluaKernelGradian3x3}, + {"KernelGradian7x7", imluaKernelGradian7x7}, + {"KernelSculpt", imluaKernelSculpt}, + {"KernelMean3x3", imluaKernelMean3x3}, + {"KernelMean5x5", imluaKernelMean5x5}, + {"KernelCircularMean5x5", imluaKernelCircularMean5x5}, + {"KernelMean7x7", imluaKernelMean7x7}, + {"KernelCircularMean7x7", imluaKernelCircularMean7x7}, + {"KernelGaussian3x3", imluaKernelGaussian3x3}, + {"KernelGaussian5x5", imluaKernelGaussian5x5}, + {"KernelBarlett5x5", imluaKernelBarlett5x5}, + {"KernelTopHat5x5", imluaKernelTopHat5x5}, + {"KernelTopHat7x7", imluaKernelTopHat7x7}, + {"KernelEnhance", imluaKernelEnhance}, + {NULL, NULL} +}; + +void imlua_open_kernel (lua_State *L) +{ + /* "im" table is at the top of the stack */ + luaL_register(L, NULL, imkernel_lib); +} diff --git a/im/src/lua5/imlua_palette.c b/im/src/lua5/imlua_palette.c new file mode 100755 index 0000000..80d23eb --- /dev/null +++ b/im/src/lua5/imlua_palette.c @@ -0,0 +1,399 @@ +/** \file + * \brief IM Lua 5 Binding + * + * See Copyright Notice in im_lib.h + * $Id: imlua_palette.c,v 1.1 2008/10/17 06:16:32 scuri Exp $ + */ + +#include +#include +#include + +#include "im.h" +#include "im_image.h" +#include "im_util.h" +#include "im_palette.h" + +#include +#include + +#include "imlua.h" +#include "imlua_aux.h" +#include "imlua_palette.h" + + +static imluaPalette* imlua_rawcheckpalette(lua_State *L, int param) +{ + void *p = lua_touserdata(L, param); + if (p != NULL) { /* value is a userdata? */ + if (lua_getmetatable(L, param)) { /* does it have a metatable? */ + lua_getfield(L, LUA_REGISTRYINDEX, "imPalette"); /* get correct metatable */ + if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */ + lua_pop(L, 2); /* remove both metatables */ + return (imluaPalette*)p; + } + lua_pop(L, 1); /* remove previous metatable */ + + /* check also for CD palette */ + lua_getfield(L, LUA_REGISTRYINDEX, "cdPalette"); /* get correct metatable */ + if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */ + lua_pop(L, 2); /* remove both metatables */ + return (imluaPalette*)p; + } + } + } + luaL_typerror(L, param, "imPalette"); /* else error */ + return NULL; /* to avoid warnings */ +} + +imluaPalette* imlua_checkpalette (lua_State *L, int param) +{ + imluaPalette* pal = imlua_rawcheckpalette(L, param); + if (!pal->color) + luaL_argerror(L, param, "destroyed imPalette"); + + return pal; +} + +void imlua_pushpalette(lua_State *L, long* color, int count) +{ + imluaPalette *pal = (imluaPalette*) lua_newuserdata(L, sizeof(imluaPalette)); + pal->count = count; + pal->color = color; + luaL_getmetatable(L, "imPalette"); + lua_setmetatable(L, -2); +} + +/***************************************************************************\ +* Creates a palette as a "imPalette" userdata. A palette can be * +* considered and treated as a color table. * +* im.PaletteCreate(count: number) -> (palette: "imPalette") * +\***************************************************************************/ +static int imluaPaletteCreate(lua_State *L) +{ + long* color; + + int count = luaL_optint(L, 1, 256); + if (count < 1 || count > 256) + luaL_argerror(L, 1, "palette count should be a positive integer and less then 256"); + + color = (long*)malloc(256*sizeof(long)); + memset(color, 0, 256*sizeof(long)); + + imlua_pushpalette(L, color, count); + return 1; +} + + +/*****************************************************************************\ + im.PaletteFindNearest +\*****************************************************************************/ +static int imluaPaletteFindNearest (lua_State *L) +{ + imluaPalette *pal = imlua_checkpalette(L, 1); + long color = (long int) lua_touserdata(L, 1); + + lua_pushnumber(L, imPaletteFindNearest(pal->color, pal->count, color)); + return 1; +} + +/*****************************************************************************\ + im.PaletteFindColor +\*****************************************************************************/ +static int imluaPaletteFindColor (lua_State *L) +{ + imluaPalette *pal = imlua_checkpalette(L, 1); + long color = (long) lua_touserdata(L, 2); + unsigned char tol = (unsigned char)luaL_checkint(L, 3); + + lua_pushnumber(L, imPaletteFindColor(pal->color, pal->count, color, tol)); + return 1; +} + +/*****************************************************************************\ + im.PaletteGray +\*****************************************************************************/ +static int imluaPaletteGray (lua_State *L) +{ + imlua_pushpalette(L, imPaletteGray(), 256); + return 1; +} + +/*****************************************************************************\ + im.PaletteRed +\*****************************************************************************/ +static int imluaPaletteRed (lua_State *L) +{ + imlua_pushpalette(L, imPaletteRed(), 256); + return 1; +} + +/*****************************************************************************\ + im.PaletteGreen +\*****************************************************************************/ +static int imluaPaletteGreen (lua_State *L) +{ + imlua_pushpalette(L, imPaletteGreen(), 256); + return 1; +} + +/*****************************************************************************\ + im.PaletteBlue +\*****************************************************************************/ +static int imluaPaletteBlue (lua_State *L) +{ + imlua_pushpalette(L, imPaletteBlue(), 256); + return 1; +} + +/*****************************************************************************\ + im.PaletteYellow +\*****************************************************************************/ +static int imluaPaletteYellow (lua_State *L) +{ + imlua_pushpalette(L, imPaletteYellow(), 256); + return 1; +} + +/*****************************************************************************\ + im.PaletteMagenta +\*****************************************************************************/ +static int imluaPaletteMagenta (lua_State *L) +{ + imlua_pushpalette(L, imPaletteMagenta(), 256); + return 1; +} + +/*****************************************************************************\ + im.PaletteCian +\*****************************************************************************/ +static int imluaPaletteCian (lua_State *L) +{ + imlua_pushpalette(L, imPaletteCian(), 256); + return 1; +} + +/*****************************************************************************\ + im.PaletteRainbow +\*****************************************************************************/ +static int imluaPaletteRainbow (lua_State *L) +{ + imlua_pushpalette(L, imPaletteRainbow(), 256); + return 1; +} + +/*****************************************************************************\ + im.PaletteHues +\*****************************************************************************/ +static int imluaPaletteHues (lua_State *L) +{ + imlua_pushpalette(L, imPaletteHues(), 256); + return 1; +} + +/*****************************************************************************\ + im.PaletteBlueIce +\*****************************************************************************/ +static int imluaPaletteBlueIce (lua_State *L) +{ + imlua_pushpalette(L, imPaletteBlueIce(), 256); + return 1; +} + +/*****************************************************************************\ + im.PaletteHotIron +\*****************************************************************************/ +static int imluaPaletteHotIron (lua_State *L) +{ + imlua_pushpalette(L, imPaletteHotIron(), 256); + return 1; +} + +/*****************************************************************************\ + im.PaletteBlackBody +\*****************************************************************************/ +static int imluaPaletteBlackBody (lua_State *L) +{ + imlua_pushpalette(L, imPaletteBlackBody(), 256); + return 1; +} + +/*****************************************************************************\ + im.PaletteHighContrast +\*****************************************************************************/ +static int imluaPaletteHighContrast (lua_State *L) +{ + imlua_pushpalette(L, imPaletteHighContrast(), 256); + return 1; +} + +/*****************************************************************************\ + im.PaletteUniform +\*****************************************************************************/ +static int imluaPaletteUniform (lua_State *L) +{ + imlua_pushpalette(L, imPaletteUniform(), 256); + return 1; +} + +/*****************************************************************************\ + im.PaletteUniformIndex +\*****************************************************************************/ +static int imluaPaletteUniformIndex (lua_State *L) +{ + lua_pushnumber(L, imPaletteUniformIndex((long int) lua_touserdata(L, 1))); + return 1; +} + +/*****************************************************************************\ + im.PaletteUniformIndexHalftoned +\*****************************************************************************/ +static int imluaPaletteUniformIndexHalftoned (lua_State *L) +{ + long color = (long) lua_touserdata(L, 1); + int x = luaL_checkint(L, 2); + int y = luaL_checkint(L, 3); + + lua_pushnumber(L, imPaletteUniformIndexHalftoned(color, x, y)); + return 1; +} + +/***************************************************************************\ +* Frees a previously allocated palette * +* im.PaletteDestroy(palette: "imPalette") * +\***************************************************************************/ +static int imluaPaletteDestroy (lua_State *L) +{ + imluaPalette *pal = imlua_rawcheckpalette(L, 1); + if (!pal->color) + luaL_argerror(L, 1, "destroyed imPalette"); + + free(pal->color); + pal->color = NULL; /* mark as destroyed */ + pal->count = 0; + + return 0; +} + +/*****************************************************************************\ + gc +\*****************************************************************************/ +static int imluaPalette_gc(lua_State *L) +{ + imluaPalette *pal = (imluaPalette*)lua_touserdata(L, 1); + if (pal && pal->color) + { + free(pal->color); + pal->color = NULL; /* mark as destroyed */ + pal->count = 0; + } + + return 0; +} + +/***************************************************************************\ +* color = palette[i] * +\***************************************************************************/ +static int imluaPalette_index(lua_State *L) +{ + imluaPalette *pal = imlua_checkpalette(L, 1); + int index_i = luaL_checkint(L, 2); + + if (index_i < 0 || index_i >= pal->count) + luaL_argerror(L, 2, "index is out of bounds"); + + lua_pushlightuserdata(L, (void*) pal->color[index_i]); + return 1; +} + +/***************************************************************************\ +* palette[i] = color * +\***************************************************************************/ +static int imluaPalette_newindex(lua_State *L) +{ + long color_i; + imluaPalette *pal = imlua_checkpalette(L, 1); + int index_i = luaL_checkint(L, 2); + + if (index_i < 0 || index_i >= pal->count) + luaL_argerror(L, 2, "index is out of bounds"); + + if (!lua_islightuserdata(L, 3)) + luaL_argerror(L, 3, "color must be a light user data"); + + color_i = (long int) lua_touserdata(L, 3); + + pal->color[index_i] = color_i; + return 0; +} + +/*****************************************************************************\ + len +\*****************************************************************************/ +static int imluaPalette_len(lua_State *L) +{ + imluaPalette *pal = (imluaPalette*)lua_touserdata(L, 1); + lua_pushinteger(L, pal->count); + return 1; +} + +/*****************************************************************************\ + tostring +\*****************************************************************************/ +static int imluaPalette_tostring (lua_State *L) +{ + imluaPalette *pal = (imluaPalette*)lua_touserdata(L, 1); + lua_pushfstring(L, "imPalette(%p)%s", pal, (pal->color)? "": "-destroyed"); + return 1; +} + +static const luaL_reg impalette_lib[] = { + {"PaletteFindNearest", imluaPaletteFindNearest}, + {"PaletteFindColor", imluaPaletteFindColor}, + {"PaletteGray", imluaPaletteGray }, + {"PaletteRed", imluaPaletteRed }, + {"PaletteGreen", imluaPaletteGreen }, + {"PaletteBlue", imluaPaletteBlue }, + {"PaletteYellow", imluaPaletteYellow }, + {"PaletteMagenta", imluaPaletteMagenta }, + {"PaletteCian", imluaPaletteCian }, + {"PaletteRainbow", imluaPaletteRainbow }, + {"PaletteHues", imluaPaletteHues }, + {"PaletteBlueIce", imluaPaletteBlueIce }, + {"PaletteHotIron", imluaPaletteHotIron }, + {"PaletteBlackBody", imluaPaletteBlackBody }, + {"PaletteHighContrast", imluaPaletteHighContrast }, + {"PaletteUniform", imluaPaletteUniform }, + {"PaletteUniformIndex", imluaPaletteUniformIndex }, + {"PaletteUniformIndexHalftoned", imluaPaletteUniformIndexHalftoned }, + + {"PaletteDestroy", imluaPaletteDestroy}, + {"PaletteCreate", imluaPaletteCreate}, + + {NULL, NULL} +}; + +static const luaL_reg impalette_metalib[] = { + {"__gc", imluaPalette_gc}, + {"__tostring", imluaPalette_tostring}, + {"__index", imluaPalette_index}, + {"__newindex", imluaPalette_newindex}, + {"__len", imluaPalette_len}, + + {NULL, NULL} +}; + +static void createmeta (lua_State *L) +{ + /* there is no object orientation for imPalette, only array access */ + luaL_newmetatable(L, "imPalette"); /* create new metatable for imPalette handles */ + luaL_register(L, NULL, impalette_metalib); /* register methods */ + lua_pop(L, 1); /* removes the metatable from the top of the stack */ +} + +void imlua_open_palette (lua_State *L) +{ + /* "im" table is at the top of the stack */ + createmeta(L); + luaL_register(L, NULL, impalette_lib); +} diff --git a/im/src/lua5/imlua_palette.h b/im/src/lua5/imlua_palette.h new file mode 100755 index 0000000..453fd01 --- /dev/null +++ b/im/src/lua5/imlua_palette.h @@ -0,0 +1,32 @@ +/** \file + * \brief IM Lua 5 Binding + * + * See Copyright Notice in im_lib.h + * $Id: imlua_palette.h,v 1.1 2008/10/17 06:16:32 scuri Exp $ + */ + +#ifndef __IMLUA_PALETTE_H +#define __IMLUA_PALETTE_H + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* this is the same declaration used in the CD toolkit for cdPalette in Lua */ +typedef struct _imPalette { + long* color; + int count; +} imluaPalette; + +void imlua_pushpalette(lua_State *L, long* color, int count); +imluaPalette* imlua_checkpalette (lua_State *L, int param); + +void imlua_open_palette(lua_State *L); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/im/src/lua5/imlua_process.c b/im/src/lua5/imlua_process.c new file mode 100755 index 0000000..863c1d6 --- /dev/null +++ b/im/src/lua5/imlua_process.c @@ -0,0 +1,3143 @@ +/** \file + * \brief IM Lua 5 Binding + * + * See Copyright Notice in im_lib.h + * $Id: imlua_process.c,v 1.8 2009/10/01 02:56:58 scuri Exp $ + */ + +#include +#include +#include + +#include "im.h" +#include "im_image.h" +#include "im_process.h" +#include "im_util.h" + +#include +#include + +#include "imlua.h" +#include "imlua_aux.h" +#include "imlua_image.h" + + + +/*****************************************************************************\ + Image Statistics Calculations +\*****************************************************************************/ + +/*****************************************************************************\ + im.CalcRMSError(image1, image2) +\*****************************************************************************/ +static int imluaCalcRMSError (lua_State *L) +{ + imImage* image1 = imlua_checkimage(L, 1); + imImage* image2 = imlua_checkimage(L, 2); + + imlua_match(L, image1, image2); + + lua_pushnumber(L, imCalcRMSError(image1, image2)); + return 1; +} + +/*****************************************************************************\ + im.CalcSNR(src_image, noise_image) +\*****************************************************************************/ +static int imluaCalcSNR (lua_State *L) +{ + imImage* src_image = imlua_checkimage(L, 1); + imImage* noise_image = imlua_checkimage(L, 2); + + imlua_match(L, src_image, noise_image); + + lua_pushnumber(L, imCalcSNR(src_image, noise_image)); + return 1; +} + +/*****************************************************************************\ + im.CalcCountColors(src_image) +\*****************************************************************************/ +static int imluaCalcCountColors (lua_State *L) +{ + imImage* src_image = imlua_checkimage(L, 1); + + imlua_checkdatatype(L, 1, src_image, IM_BYTE); + if (src_image->color_space >= IM_CMYK) + luaL_argerror(L, 1, "color space can be RGB, Gray, Binary or Map only"); + + lua_pushnumber(L, imCalcCountColors(src_image)); + return 1; +} + +/*****************************************************************************\ + im.CalcHistogram(src_image, plane, cumulative) +\*****************************************************************************/ +static int imluaCalcHistogram (lua_State *L) +{ + imImage* src_image = imlua_checkimage(L, 1); + int plane = luaL_checkint(L, 2); + int cumulative = lua_toboolean(L, 3); + + switch (src_image->data_type) + { + case IM_BYTE: + { + unsigned long hist[256]; + imCalcHistogram((imbyte*) src_image->data[plane], src_image->count, hist, cumulative); + imlua_newarrayulong(L, hist, 256, 0); + } + break; + + case IM_USHORT: + { + unsigned long hist[65535]; + imCalcUShortHistogram(src_image->data[plane], src_image->count, hist, cumulative); + imlua_newarrayulong(L, hist, 65535, 0); + } + break; + + default: + luaL_argerror(L, 1, "data_type can be byte or ushort only"); + break; + } + + return 1; +} + +/*****************************************************************************\ + im.CalcGrayHistogram(src_image, cumulative) +\*****************************************************************************/ +static int imluaCalcGrayHistogram (lua_State *L) +{ + unsigned long hist[256]; + imImage* src_image = imlua_checkimage(L, 1); + int cumulative = lua_toboolean(L, 2); + + imlua_checkdatatype(L, 1, src_image, IM_BYTE); + if (src_image->color_space >= IM_CMYK) + luaL_argerror(L, 1, "color space can be RGB, Gray, Binary or Map only"); + + imCalcGrayHistogram(src_image, hist, cumulative); + imlua_newarrayulong(L, hist, 256, 0); + + return 1; +} + +/*****************************************************************************\ + im.CalcImageStatistics(src_image) +\*****************************************************************************/ +static int imluaCalcImageStatistics (lua_State *L) +{ + imStats stats; + imImage *image = imlua_checkimage(L, 1); + + if (image->data_type == IM_CFLOAT) + luaL_argerror(L, 1, "data type can NOT be of type cfloat"); + + imCalcImageStatistics(image, &stats); + + lua_newtable(L); + lua_pushstring(L, "max"); lua_pushnumber(L, stats.max); lua_settable(L, -3); + lua_pushstring(L, "min"); lua_pushnumber(L, stats.min); lua_settable(L, -3); + lua_pushstring(L, "positive"); lua_pushnumber(L, stats.positive); lua_settable(L, -3); + lua_pushstring(L, "negative"); lua_pushnumber(L, stats.negative); lua_settable(L, -3); + lua_pushstring(L, "zeros"); lua_pushnumber(L, stats.zeros); lua_settable(L, -3); + lua_pushstring(L, "mean"); lua_pushnumber(L, stats.mean); lua_settable(L, -3); + lua_pushstring(L, "stddev"); lua_pushnumber(L, stats.stddev); lua_settable(L, -3); + return 1; +} + +/*****************************************************************************\ + im.CalcHistogramStatistics(src_image) +\*****************************************************************************/ +static int imluaCalcHistogramStatistics (lua_State *L) +{ + imStats stats; + imImage *image = imlua_checkimage(L, 1); + + imlua_checkdatatype(L, 1, image, IM_BYTE); + + imCalcHistogramStatistics(image, &stats); + + lua_newtable(L); + lua_pushstring(L, "max"); lua_pushnumber(L, stats.max); lua_settable(L, -3); + lua_pushstring(L, "min"); lua_pushnumber(L, stats.min); lua_settable(L, -3); + lua_pushstring(L, "positive"); lua_pushnumber(L, stats.positive); lua_settable(L, -3); + lua_pushstring(L, "negative"); lua_pushnumber(L, stats.negative); lua_settable(L, -3); + lua_pushstring(L, "zeros"); lua_pushnumber(L, stats.zeros); lua_settable(L, -3); + lua_pushstring(L, "mean"); lua_pushnumber(L, stats.mean); lua_settable(L, -3); + lua_pushstring(L, "stddev"); lua_pushnumber(L, stats.stddev); lua_settable(L, -3); + return 1; +} + +/*****************************************************************************\ + im.CalcHistoImageStatistics +\*****************************************************************************/ +static int imluaCalcHistoImageStatistics (lua_State *L) +{ + int* median; + int* mode; + + imImage *image = imlua_checkimage(L, 1); + + imlua_checkdatatype(L, 1, image, IM_BYTE); + + median = (int*)malloc(sizeof(int)*image->depth); + mode = (int*)malloc(sizeof(int)*image->depth); + + imCalcHistoImageStatistics(image, median, mode); + + imlua_newarrayint (L, median, image->depth, 0); + imlua_newarrayint (L, mode, image->depth, 0); + + free(median); + free(mode); + + return 2; +} + +/*****************************************************************************\ + Image Analysis +\*****************************************************************************/ + +/*****************************************************************************\ + im.AnalyzeFindRegions(src_image, dst_image, connect, touch_border) +\*****************************************************************************/ +static int imluaAnalyzeFindRegions (lua_State *L) +{ + imImage* src_image = imlua_checkimage(L, 1); + imImage* dst_image = imlua_checkimage(L, 2); + int connect = luaL_checkint(L, 3); + int touch_border = lua_toboolean(L, 4); + + imlua_checkcolorspace(L, 1, src_image, IM_BINARY); + imlua_checktype(L, 2, dst_image, IM_GRAY, IM_USHORT); + + luaL_argcheck(L, (connect == 4 || connect == 8), 3, "invalid connect value, must be 4 or 8"); + lua_pushnumber(L, imAnalyzeFindRegions(src_image, dst_image, connect, touch_border)); + return 1; +} + +static int iGetMax(imImage* image) +{ + int max = 0; + int i; + + imushort* data = (imushort*)image->data[0]; + for (i = 0; i < image->count; i++) + { + if (*data > max) + max = *data; + + data++; + } + + return max; +} + +static int imlua_checkregioncount(lua_State *L, int narg, imImage* image) +{ + if (lua_isnoneornil(L, narg)) return iGetMax(image); + else return (int)luaL_checknumber(L, narg); +} + + +/*****************************************************************************\ + im.AnalyzeMeasureArea(image, [count]) +\*****************************************************************************/ +static int imluaAnalyzeMeasureArea (lua_State *L) +{ + int count; + int *area; + + imImage* image = imlua_checkimage(L, 1); + + imlua_checktype(L, 1, image, IM_GRAY, IM_USHORT); + + count = imlua_checkregioncount(L, 2, image); + area = (int*) malloc(sizeof(int) * count); + + imAnalyzeMeasureArea(image, area, count); + + imlua_newarrayint(L, area, count, 0); + free(area); + + return 1; +} + +/*****************************************************************************\ + im.AnalyzeMeasurePerimArea(image) +\*****************************************************************************/ +static int imluaAnalyzeMeasurePerimArea (lua_State *L) +{ + int count; + float *perimarea; + + imImage* image = imlua_checkimage(L, 1); + + imlua_checktype(L, 1, image, IM_GRAY, IM_USHORT); + + count = imlua_checkregioncount(L, 2, image); + perimarea = (float*) malloc(sizeof(float) * count); + + imAnalyzeMeasurePerimArea(image, perimarea); + + imlua_newarrayfloat (L, perimarea, count, 0); + free(perimarea); + + return 1; +} + +/*****************************************************************************\ + im.AnalyzeMeasureCentroid(image, [area], [count]) +\*****************************************************************************/ +static int imluaAnalyzeMeasureCentroid (lua_State *L) +{ + int count; + float *cx, *cy; + int *area; + + imImage* image = imlua_checkimage(L, 1); + + imlua_checktype(L, 1, image, IM_GRAY, IM_USHORT); + + area = imlua_toarrayint(L, 2, &count, 0); + count = imlua_checkregioncount(L, 3, image); + + cx = (float*) malloc (sizeof(float) * count); + cy = (float*) malloc (sizeof(float) * count); + + imAnalyzeMeasureCentroid(image, area, count, cx, cy); + + imlua_newarrayfloat(L, cx, count, 0); + imlua_newarrayfloat(L, cy, count, 0); + + if (area) + free(area); + free(cx); + free(cy); + + return 2; +} + +/*****************************************************************************\ + im.AnalyzeMeasurePrincipalAxis(image, [area], [cx], [cy]) +\*****************************************************************************/ +static int imluaAnalyzeMeasurePrincipalAxis (lua_State *L) +{ + int count; + float *cx, *cy; + int *area; + float *major_slope, *major_length, *minor_slope, *minor_length; + + imImage* image = imlua_checkimage(L, 1); + + imlua_checktype(L, 1, image, IM_GRAY, IM_USHORT); + + area = imlua_toarrayint(L, 2, &count, 0); + cx = imlua_toarrayfloat(L, 3, NULL, 0); + cy = imlua_toarrayfloat(L, 4, NULL, 0); + count = imlua_checkregioncount(L, 5, image); + + major_slope = (float*) malloc (sizeof(float) * count); + major_length = (float*) malloc (sizeof(float) * count); + minor_slope = (float*) malloc (sizeof(float) * count); + minor_length = (float*) malloc (sizeof(float) * count); + + imAnalyzeMeasurePrincipalAxis(image, area, cx, cy, count, major_slope, major_length, minor_slope, minor_length); + + imlua_newarrayfloat(L, major_slope, count, 0); + imlua_newarrayfloat(L, major_length, count, 0); + imlua_newarrayfloat(L, minor_slope, count, 0); + imlua_newarrayfloat(L, minor_length, count, 0); + + if (area) + free(area); + if (cx) + free(cx); + if (cy) + free(cy); + + free(major_slope); + free(major_length); + free(minor_slope); + free(minor_length); + + return 4; +} + +/*****************************************************************************\ + im.AnalyzeMeasureHoles +\*****************************************************************************/ +static int imluaAnalyzeMeasureHoles (lua_State *L) +{ + int holes_count, count; + int connect; + int *area = NULL; + float *perim = NULL; + + imImage* image = imlua_checkimage(L, 1); + + imlua_checktype(L, 1, image, IM_GRAY, IM_USHORT); + + connect = luaL_checkint(L, 2); + count = imlua_checkregioncount(L, 3, image); + + area = (int*) malloc (sizeof(int) * count); + perim = (float*) malloc (sizeof(float) * count); + + imAnalyzeMeasureHoles(image, connect, &holes_count, area, perim); + + lua_pushnumber(L, holes_count); + imlua_newarrayint(L, area, holes_count, 0); + imlua_newarrayfloat(L, perim, holes_count, 0); + + if (area) + free(area); + if (perim) + free(perim); + + return 3; +} + +/*****************************************************************************\ + im.AnalyzeMeasurePerimeter(image, [count]) +\*****************************************************************************/ +static int imluaAnalyzeMeasurePerimeter (lua_State *L) +{ + int count; + float *perim; + + imImage* image = imlua_checkimage(L, 1); + + imlua_checktype(L, 1, image, IM_GRAY, IM_USHORT); + + count = imlua_checkregioncount(L, 2, image); + perim = (float*) malloc(sizeof(float) * count); + + imAnalyzeMeasurePerimeter(image, perim, count); + + imlua_newarrayfloat(L, perim, count, 0); + + free(perim); + + return 1; +} + +/*****************************************************************************\ + im.ProcessPerimeterLine(src_image, dst_image) +\*****************************************************************************/ +static int imluaProcessPerimeterLine (lua_State *L) +{ + imImage* src_image = imlua_checkimage(L, 1); + imImage* dst_image = imlua_checkimage(L, 2); + + luaL_argcheck(L, (src_image->data_type < IM_FLOAT), 1, "image data type can be integer only"); + imlua_match(L, src_image, dst_image); + + imProcessPerimeterLine(src_image, dst_image); + return 0; +} + +/*****************************************************************************\ + im.ProcessRemoveByArea(src_image, dst_image, connect, start_size, end_size, inside) +\*****************************************************************************/ +static int imluaProcessRemoveByArea (lua_State *L) +{ + imImage* src_image = imlua_checkimage(L, 1); + imImage* dst_image = imlua_checkimage(L, 2); + int connect = luaL_checkint(L, 3); + int start_size = luaL_checkint(L, 4); + int end_size = luaL_checkint(L, 5); + int inside = lua_toboolean(L, 6); + + imlua_checkcolorspace(L, 1, src_image, IM_BINARY); + imlua_match(L, src_image, dst_image); + luaL_argcheck(L, (connect == 4 || connect == 8), 3, "invalid connect value, must be 4 or 8"); + + imProcessRemoveByArea(src_image, dst_image, connect, start_size, end_size, inside); + return 0; +} + +/*****************************************************************************\ + im.ProcessFillHoles(src_image, dst_image, connect) +\*****************************************************************************/ +static int imluaProcessFillHoles (lua_State *L) +{ + imImage* src_image = imlua_checkimage(L, 1); + imImage* dst_image = imlua_checkimage(L, 2); + int connect = luaL_checkint(L, 3); + + imlua_checkcolorspace(L, 1, src_image, IM_BINARY); + imlua_match(L, src_image, dst_image); + luaL_argcheck(L, (connect == 4 || connect == 8), 3, "invalid connect value, must be 4 or 8"); + + imProcessFillHoles(src_image, dst_image, connect); + return 0; +} + +static void imlua_checkhoughsize(lua_State *L, imImage* image, imImage* hough_image, int param) +{ +#define IMSQR(_x) (_x*_x) + int hough_rmax; + if (hough_image->width != 180) + luaL_argerror(L, param, "invalid image width"); + + hough_rmax = (int)(sqrt((double)(IMSQR(image->width) + IMSQR(image->height)))/2.0); + if (hough_image->height != 2*hough_rmax+1) + luaL_argerror(L, param, "invalid image height"); +} + +/*****************************************************************************\ + im.ProcessHoughLines(src_image, dst_image) +\*****************************************************************************/ +static int imluaProcessHoughLines (lua_State *L) +{ + imImage* src_image = imlua_checkimage(L, 1); + imImage* dst_image = imlua_checkimage(L, 2); + + imlua_checkcolorspace(L, 1, src_image, IM_BINARY); + imlua_checktype(L, 2, dst_image, IM_GRAY, IM_INT); + imlua_checkhoughsize(L, src_image, dst_image, 2); + + lua_pushboolean(L, imProcessHoughLines(src_image, dst_image)); + return 0; +} + +/*****************************************************************************\ + im.ProcessHoughLinesDraw(src_image, hough_points, dst_image) +\*****************************************************************************/ +static int imluaProcessHoughLinesDraw (lua_State *L) +{ + imImage* src_image = imlua_checkimage(L, 1); + imImage* hough_points = imlua_checkimage(L, 3); + imImage* dst_image = imlua_checkimage(L, 4); + imImage* hough = NULL; + if (lua_isuserdata(L, 2)) + { + hough = imlua_checkimage(L, 2); + imlua_checktype(L, 2, hough, IM_GRAY, IM_INT); + imlua_checkhoughsize(L, src_image, hough, 2); + } + + imlua_checktype(L, 1, src_image, IM_GRAY, IM_BYTE); + imlua_checkcolorspace(L, 3, hough_points, IM_BINARY); + imlua_checkhoughsize(L, src_image, hough_points, 3); + imlua_matchsize(L, src_image, dst_image); + + lua_pushnumber(L, imProcessHoughLinesDraw(src_image, hough, hough_points, dst_image)); + return 0; +} + +/*****************************************************************************\ + im.ProcessDistanceTransform(src_image, dst_image) +\*****************************************************************************/ +static int imluaProcessDistanceTransform (lua_State *L) +{ + imImage* src_image = imlua_checkimage(L, 1); + imImage* dst_image = imlua_checkimage(L, 2); + + imlua_checkcolorspace(L, 1, src_image, IM_BINARY); + imlua_checkdatatype(L, 2, dst_image, IM_FLOAT); + imlua_matchsize(L, src_image, dst_image); + + imProcessDistanceTransform(src_image, dst_image); + return 0; +} + +/*****************************************************************************\ + im.ProcessRegionalMaximum(src_image, dst_image) +\*****************************************************************************/ +static int imluaProcessRegionalMaximum (lua_State *L) +{ + imImage* src_image = imlua_checkimage(L, 1); + imImage* dst_image = imlua_checkimage(L, 2); + + imlua_checktype(L, 1, src_image, IM_GRAY, IM_FLOAT); + imlua_checkcolorspace(L, 2, dst_image, IM_BINARY); + imlua_matchsize(L, src_image, dst_image); + + imProcessRegionalMaximum(src_image, dst_image); + return 0; +} + +/*****************************************************************************\ + Image Resize +\*****************************************************************************/ + +/*****************************************************************************\ + im.ProcessReduce(src_image, dst_image, order) +\*****************************************************************************/ +static int imluaProcessReduce (lua_State *L) +{ + imImage* src_image = imlua_checkimage(L, 1); + imImage* dst_image = imlua_checkimage(L, 2); + int order = luaL_checkint(L, 3); + + imlua_matchcolor(L, src_image, dst_image); + luaL_argcheck(L, (order == 0 || order == 1), 3, "invalid order, must be 0 or 1"); + + lua_pushboolean(L, imProcessReduce(src_image, dst_image, order)); + return 1; +} + +/*****************************************************************************\ + im.ProcessResize(src_image, dst_image, order) +\*****************************************************************************/ +static int imluaProcessResize (lua_State *L) +{ + imImage* src_image = imlua_checkimage(L, 1); + imImage* dst_image = imlua_checkimage(L, 2); + int order = luaL_checkint(L, 3); + + imlua_matchcolor(L, src_image, dst_image); + luaL_argcheck(L, (order == 0 || order == 1 || order == 3), 3, "invalid order, must be 0, 1 or 3"); + + lua_pushboolean(L, imProcessResize(src_image, dst_image, order)); + return 1; +} + +/*****************************************************************************\ + im.ProcessReduceBy4(src_image, dst_image) +\*****************************************************************************/ +static int imluaProcessReduceBy4 (lua_State *L) +{ + imImage* src_image = imlua_checkimage(L, 1); + imImage* dst_image = imlua_checkimage(L, 2); + + imlua_matchcolor(L, src_image, dst_image); + luaL_argcheck(L, + dst_image->width == (src_image->width / 2) && + dst_image->height == (src_image->height / 2), 3, "destiny image size must be source image width/2, height/2"); + + imProcessReduceBy4(src_image, dst_image); + return 0; +} + +/*****************************************************************************\ + im.ProcessCrop(src_image, dst_image, xmin, ymin) +\*****************************************************************************/ +static int imluaProcessCrop (lua_State *L) +{ + imImage* src_image = imlua_checkimage(L, 1); + imImage* dst_image = imlua_checkimage(L, 2); + int xmin = luaL_checkint(L, 3); + int ymin = luaL_checkint(L, 4); + + imlua_matchcolor(L, src_image, dst_image); + luaL_argcheck(L, xmin >= 0 && xmin < src_image->width, 3, "xmin must be >= 0 and < width"); + luaL_argcheck(L, ymin >= 0 && ymin < src_image->height, 4, "ymin must be >= 0 and < height"); + luaL_argcheck(L, dst_image->width <= (src_image->width - xmin), 2, "destiny image size must be smaller than source image width-xmin"); + luaL_argcheck(L, dst_image->height <= (src_image->height - ymin), 2, "destiny image size must be smaller than source image height-ymin"); + + imProcessCrop(src_image, dst_image, xmin, ymin); + return 0; +} + +/*****************************************************************************\ + im.ProcessInsert(src_image, region_image, dst_image, xmin, ymin) +\*****************************************************************************/ +static int imluaProcessInsert (lua_State *L) +{ + imImage* src_image = imlua_checkimage(L, 1); + imImage* region_image = imlua_checkimage(L, 2); + imImage* dst_image = imlua_checkimage(L, 3); + int xmin = luaL_checkint(L, 4); + int ymin = luaL_checkint(L, 5); + + imlua_matchcolor(L, src_image, dst_image); + luaL_argcheck(L, xmin >= 0 && xmin < src_image->width, 3, "xmin must be >= 0 and < width"); + luaL_argcheck(L, ymin >= 0 && ymin < src_image->height, 3, "ymin must be >= 0 and < height"); + + imProcessInsert(src_image, region_image, dst_image, xmin, ymin); + return 0; +} + +/*****************************************************************************\ + im.ProcessAddMargins(src_image, dst_image, xmin, ymin) +\*****************************************************************************/ +static int imluaProcessAddMargins (lua_State *L) +{ + imImage* src_image = imlua_checkimage(L, 1); + imImage* dst_image = imlua_checkimage(L, 2); + int xmin = luaL_checkint(L, 3); + int ymin = luaL_checkint(L, 4); + + imlua_matchcolor(L, src_image, dst_image); + luaL_argcheck(L, dst_image->width > (src_image->width + xmin), 2, "destiny image size must be greatter than source image width+xmin, height+ymin"); + luaL_argcheck(L, dst_image->height > (src_image->height + ymin), 2, "destiny image size must be greatter than source image width+xmin, height+ymin"); + + imProcessAddMargins(src_image, dst_image, xmin, ymin); + return 0; +} + + + +/*****************************************************************************\ + Geometric Operations +\*****************************************************************************/ + +/*****************************************************************************\ + im.ProcessCalcRotateSize +\*****************************************************************************/ +static int imluaProcessCalcRotateSize (lua_State *L) +{ + int new_width, new_height; + + int width = luaL_checkint(L, 1); + int height = luaL_checkint(L, 2); + double cos0 = (double) luaL_checknumber(L, 3); + double sin0 = (double) luaL_checknumber(L, 4); + + imProcessCalcRotateSize(width, height, &new_width, &new_height, cos0, sin0); + lua_pushnumber(L, new_width); + lua_pushnumber(L, new_height); + return 2; +} + +/*****************************************************************************\ + im.ProcessRotate +\*****************************************************************************/ +static int imluaProcessRotate (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + double cos0 = (double) luaL_checknumber(L, 3); + double sin0 = (double) luaL_checknumber(L, 4); + int order = luaL_checkint(L, 5); + + imlua_matchcolor(L, src_image, dst_image); + luaL_argcheck(L, (order == 0 || order == 1 || order == 3), 5, "invalid order, must be 0, 1 or 3"); + + lua_pushboolean(L, imProcessRotate(src_image, dst_image, cos0, sin0, order)); + return 1; +} + +/*****************************************************************************\ + im.ProcessRotateRef +\*****************************************************************************/ +static int imluaProcessRotateRef (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + double cos0 = (double) luaL_checknumber(L, 3); + double sin0 = (double) luaL_checknumber(L, 4); + int x = luaL_checkint(L, 5); + int y = luaL_checkint(L, 6); + int to_origin = lua_toboolean(L, 7); + int order = luaL_checkint(L, 8); + + imlua_matchcolor(L, src_image, dst_image); + luaL_argcheck(L, (order == 0 || order == 1 || order == 3), 5, "invalid order, must be 0, 1, or 3"); + + lua_pushboolean(L, imProcessRotateRef(src_image, dst_image, cos0, sin0, x, y, to_origin, order)); + return 1; +} + +/*****************************************************************************\ + im.ProcessRotate90 +\*****************************************************************************/ +static int imluaProcessRotate90 (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + int dir = lua_toboolean(L, 3); + + imlua_matchcolor(L, src_image, dst_image); + luaL_argcheck(L, dst_image->width == src_image->height && dst_image->height == src_image->width, 2, "destiny width and height must have the source height and width"); + luaL_argcheck(L, (dir == -1 || dir == 1), 3, "invalid dir, can be -1 or 1 only"); + + imProcessRotate90(src_image, dst_image, dir); + return 0; +} + +/*****************************************************************************\ + im.ProcessRotate180 +\*****************************************************************************/ +static int imluaProcessRotate180 (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + + imlua_match(L, src_image, dst_image); + + imProcessRotate180(src_image, dst_image); + return 0; +} + +/*****************************************************************************\ + im.ProcessMirror +\*****************************************************************************/ +static int imluaProcessMirror (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + + imlua_match(L, src_image, dst_image); + + imProcessMirror(src_image, dst_image); + return 0; +} + +/*****************************************************************************\ + im.ProcessFlip +\*****************************************************************************/ +static int imluaProcessFlip (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + + imlua_match(L, src_image, dst_image); + + imProcessFlip(src_image, dst_image); + return 0; +} + +/*****************************************************************************\ + im.ProcessInterlaceSplit +\*****************************************************************************/ +static int imluaProcessInterlaceSplit (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image1 = imlua_checkimage(L, 2); + imImage *dst_image2 = imlua_checkimage(L, 3); + + imlua_matchcolor(L, src_image, dst_image1); + imlua_matchcolor(L, src_image, dst_image2); + luaL_argcheck(L, dst_image1->width == src_image->width && dst_image2->width == src_image->width, 2, "destiny width must be equal to source width"); + + if (src_image->height%2) + { + int dst_height1 = src_image->height/2 + 1; + luaL_argcheck(L, dst_image1->height == dst_height1, 2, "destiny1 height must be equal to source height/2+1 if height odd"); + } + else + luaL_argcheck(L, dst_image1->height == src_image->height/2, 2, "destiny1 height must be equal to source height/2 if height even"); + + luaL_argcheck(L, dst_image2->height == src_image->height/2, 2, "destiny2 height must be equal to source height/2"); + + imProcessInterlaceSplit(src_image, dst_image1, dst_image2); + return 0; +} + +/*****************************************************************************\ + im.ProcessRadial +\*****************************************************************************/ +static int imluaProcessRadial (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + float k1 = (float) luaL_checknumber(L, 3); + int order = luaL_checkint(L, 4); + + imlua_match(L, src_image, dst_image); + luaL_argcheck(L, (order == 0 || order == 1 || order == 3), 4, "invalid order"); + + lua_pushboolean(L, imProcessRadial(src_image, dst_image, k1, order)); + return 1; +} + +/*****************************************************************************\ + im.ProcessSwirl +\*****************************************************************************/ +static int imluaProcessSwirl(lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + float k1 = (float) luaL_checknumber(L, 3); + int order = luaL_checkint(L, 4); + + imlua_match(L, src_image, dst_image); + luaL_argcheck(L, (order == 0 || order == 1 || order == 3), 4, "invalid order, can be 0, 1 or 3"); + + lua_pushboolean(L, imProcessSwirl(src_image, dst_image, k1, order)); + return 1; +} + +static void imlua_checknotcfloat(lua_State *L, imImage *image, int index) +{ + if (image->data_type == IM_CFLOAT) + luaL_argerror(L, index, "image data type can NOT be cfloat"); +} + + +/*****************************************************************************\ + Morphology Operations for Gray Images +\*****************************************************************************/ + +/*****************************************************************************\ + im.ProcessGrayMorphConvolve +\*****************************************************************************/ +static int imluaProcessGrayMorphConvolve (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + imImage *kernel = imlua_checkimage(L, 3); + int ismax = lua_toboolean(L, 4); + + imlua_checknotcfloat(L, src_image, 1); + imlua_match(L, src_image, dst_image); + imlua_checkdatatype(L, 3, kernel, IM_INT); + imlua_matchsize(L, src_image, kernel); + + lua_pushboolean(L, imProcessGrayMorphConvolve(src_image, dst_image, kernel, ismax)); + return 1; +} + +/*****************************************************************************\ + im.ProcessGrayMorphErode +\*****************************************************************************/ +static int imluaProcessGrayMorphErode (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + int kernel_size = luaL_checkint(L, 3); + + imlua_checknotcfloat(L, src_image, 1); + imlua_match(L, src_image, dst_image); + + lua_pushboolean(L, imProcessGrayMorphErode(src_image, dst_image, kernel_size)); + return 1; +} + +/*****************************************************************************\ + im.ProcessGrayMorphDilate +\*****************************************************************************/ +static int imluaProcessGrayMorphDilate (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + int kernel_size = luaL_checkint(L, 3); + + imlua_checknotcfloat(L, src_image, 1); + imlua_match(L, src_image, dst_image); + + lua_pushboolean(L, imProcessGrayMorphDilate(src_image, dst_image, kernel_size)); + return 1; +} + +/*****************************************************************************\ + im.ProcessGrayMorphOpen +\*****************************************************************************/ +static int imluaProcessGrayMorphOpen (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + int kernel_size = luaL_checkint(L, 3); + + imlua_checknotcfloat(L, src_image, 1); + imlua_match(L, src_image, dst_image); + + lua_pushboolean(L, imProcessGrayMorphOpen(src_image, dst_image, kernel_size)); + return 1; +} + +/*****************************************************************************\ + im.ProcessGrayMorphClose +\*****************************************************************************/ +static int imluaProcessGrayMorphClose (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + int kernel_size = luaL_checkint(L, 3); + + imlua_checknotcfloat(L, src_image, 1); + imlua_match(L, src_image, dst_image); + + lua_pushboolean(L, imProcessGrayMorphClose(src_image, dst_image, kernel_size)); + return 1; +} + +/*****************************************************************************\ + im.ProcessGrayMorphTopHat +\*****************************************************************************/ +static int imluaProcessGrayMorphTopHat (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + int kernel_size = luaL_checkint(L, 3); + + imlua_checknotcfloat(L, src_image, 1); + imlua_match(L, src_image, dst_image); + + lua_pushboolean(L, imProcessGrayMorphTopHat(src_image, dst_image, kernel_size)); + return 1; +} + +/*****************************************************************************\ + im.ProcessGrayMorphWell +\*****************************************************************************/ +static int imluaProcessGrayMorphWell (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + int kernel_size = luaL_checkint(L, 3); + + imlua_checknotcfloat(L, src_image, 1); + imlua_match(L, src_image, dst_image); + + lua_pushboolean(L, imProcessGrayMorphWell(src_image, dst_image, kernel_size)); + return 1; +} + +/*****************************************************************************\ + im.ProcessGrayMorphGradient +\*****************************************************************************/ +static int imluaProcessGrayMorphGradient (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + int kernel_size = luaL_checkint(L, 3); + + imlua_checknotcfloat(L, src_image, 1); + imlua_match(L, src_image, dst_image); + + lua_pushboolean(L, imProcessGrayMorphGradient(src_image, dst_image, kernel_size)); + return 1; +} + + + +/*****************************************************************************\ + Morphology Operations for Binary Images +\*****************************************************************************/ + +/*****************************************************************************\ + im.ProcessBinMorphConvolve +\*****************************************************************************/ +static int imluaProcessBinMorphConvolve (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + imImage *kernel = imlua_checkimage(L, 3); + int hit_white = lua_toboolean(L, 4); + int iter = luaL_checkint(L, 5); + + imlua_checkcolorspace(L, 1, src_image, IM_BINARY); + imlua_match(L, src_image, dst_image); + imlua_checkdatatype(L, 3, kernel, IM_INT); + imlua_matchsize(L, src_image, kernel); + + lua_pushboolean(L, imProcessBinMorphConvolve(src_image, dst_image, kernel, hit_white, iter)); + return 1; +} + +/*****************************************************************************\ + im.ProcessBinMorphErode +\*****************************************************************************/ +static int imluaProcessBinMorphErode (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + int kernel_size = luaL_checkint(L, 3); + int iter = luaL_checkint(L, 4); + + imlua_checkcolorspace(L, 1, src_image, IM_BINARY); + imlua_match(L, src_image, dst_image); + + lua_pushboolean(L, imProcessBinMorphErode(src_image, dst_image, kernel_size, iter)); + return 1; +} + +/*****************************************************************************\ + im.ProcessBinMorphDilate +\*****************************************************************************/ +static int imluaProcessBinMorphDilate (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + int kernel_size = luaL_checkint(L, 3); + int iter = luaL_checkint(L, 4); + + imlua_checkcolorspace(L, 1, src_image, IM_BINARY); + imlua_match(L, src_image, dst_image); + + lua_pushboolean(L, imProcessBinMorphDilate(src_image, dst_image, kernel_size, iter)); + return 1; +} + +/*****************************************************************************\ + im.ProcessBinMorphOpen +\*****************************************************************************/ +static int imluaProcessBinMorphOpen (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + int kernel_size = luaL_checkint(L, 3); + int iter = luaL_checkint(L, 4); + + imlua_checkcolorspace(L, 1, src_image, IM_BINARY); + imlua_match(L, src_image, dst_image); + + lua_pushboolean(L, imProcessBinMorphOpen(src_image, dst_image, kernel_size, iter)); + return 1; +} + +/*****************************************************************************\ + im.ProcessBinMorphClose +\*****************************************************************************/ +static int imluaProcessBinMorphClose (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + int kernel_size = luaL_checkint(L, 3); + int iter = luaL_checkint(L, 4); + + imlua_checkcolorspace(L, 1, src_image, IM_BINARY); + imlua_match(L, src_image, dst_image); + + lua_pushboolean(L, imProcessBinMorphClose(src_image, dst_image, kernel_size, iter)); + return 1; +} + +/*****************************************************************************\ + im.ProcessBinMorphOutline +\*****************************************************************************/ +static int imluaProcessBinMorphOutline (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + int kernel_size = luaL_checkint(L, 3); + int iter = luaL_checkint(L, 4); + + imlua_checkcolorspace(L, 1, src_image, IM_BINARY); + imlua_match(L, src_image, dst_image); + + lua_pushboolean(L, imProcessBinMorphOutline(src_image, dst_image, kernel_size, iter)); + return 1; +} + +/*****************************************************************************\ + im.ProcessBinMorphThin +\*****************************************************************************/ +static int imluaProcessBinMorphThin (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + + imlua_checkcolorspace(L, 1, src_image, IM_BINARY); + imlua_match(L, src_image, dst_image); + + imProcessBinMorphThin(src_image, dst_image); + return 0; +} + + + +/*****************************************************************************\ + Rank Convolution Operations +\*****************************************************************************/ + +/*****************************************************************************\ + im.ProcessMedianConvolve +\*****************************************************************************/ +static int imluaProcessMedianConvolve (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + int kernel_size = luaL_checkint(L, 3); + + imlua_checknotcfloat(L, src_image, 1); + imlua_match(L, src_image, dst_image); + + lua_pushboolean(L, imProcessMedianConvolve(src_image, dst_image, kernel_size)); + return 1; +} + +/*****************************************************************************\ + im.ProcessRangeConvolve +\*****************************************************************************/ +static int imluaProcessRangeConvolve (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + int kernel_size = luaL_checkint(L, 3); + + imlua_checknotcfloat(L, src_image, 1); + imlua_match(L, src_image, dst_image); + + lua_pushboolean(L, imProcessRangeConvolve(src_image, dst_image, kernel_size)); + return 1; +} + +/*****************************************************************************\ + im.ProcessRankClosestConvolve +\*****************************************************************************/ +static int imluaProcessRankClosestConvolve (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + int kernel_size = luaL_checkint(L, 3); + + imlua_checknotcfloat(L, src_image, 1); + imlua_match(L, src_image, dst_image); + + lua_pushboolean(L, imProcessRankClosestConvolve(src_image, dst_image, kernel_size)); + return 1; +} + +/*****************************************************************************\ + im.ProcessRankMaxConvolve +\*****************************************************************************/ +static int imluaProcessRankMaxConvolve (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + int kernel_size = luaL_checkint(L, 3); + + imlua_checknotcfloat(L, src_image, 1); + imlua_match(L, src_image, dst_image); + + lua_pushboolean(L, imProcessRankMaxConvolve(src_image, dst_image, kernel_size)); + return 1; +} + +/*****************************************************************************\ + im.ProcessRankMinConvolve +\*****************************************************************************/ +static int imluaProcessRankMinConvolve (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + int kernel_size = luaL_checkint(L, 3); + + imlua_checknotcfloat(L, src_image, 1); + imlua_match(L, src_image, dst_image); + + lua_pushboolean(L, imProcessRankMinConvolve(src_image, dst_image, kernel_size)); + return 1; +} + + +/*****************************************************************************\ + Convolution Operations +\*****************************************************************************/ + +static void imlua_checkkernel(lua_State *L, imImage* kernel, int index) +{ + imlua_checkcolorspace(L, index, kernel, IM_GRAY); + luaL_argcheck(L, kernel->data_type == IM_INT || kernel->data_type == IM_FLOAT, index, "kernel data type can be int or float only"); +} + +/*****************************************************************************\ + im.ProcessConvolve +\*****************************************************************************/ +static int imluaProcessConvolve (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + imImage *kernel = imlua_checkimage(L, 3); + + imlua_match(L, src_image, dst_image); + imlua_checkkernel(L, kernel, 3); + + lua_pushboolean(L, imProcessConvolve(src_image, dst_image, kernel)); + return 1; +} + +/*****************************************************************************\ + im.ProcessConvolveDual +\*****************************************************************************/ +static int imluaProcessConvolveDual (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + imImage *kernel1 = imlua_checkimage(L, 3); + imImage *kernel2 = imlua_checkimage(L, 4); + + imlua_match(L, src_image, dst_image); + imlua_checkkernel(L, kernel1, 3); + imlua_checkkernel(L, kernel2, 4); + + lua_pushboolean(L, imProcessConvolveDual(src_image, dst_image, kernel1, kernel2)); + return 1; +} + +/*****************************************************************************\ + im.ProcessConvolveRep +\*****************************************************************************/ +static int imluaProcessConvolveRep (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + imImage *kernel = imlua_checkimage(L, 3); + int count = luaL_checkint(L, 4); + + imlua_match(L, src_image, dst_image); + imlua_checkkernel(L, kernel, 3); + + lua_pushboolean(L, imProcessConvolveRep(src_image, dst_image, kernel, count)); + return 1; +} + +/*****************************************************************************\ + im.ProcessConvolveSep +\*****************************************************************************/ +static int imluaProcessConvolveSep (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + imImage *kernel = imlua_checkimage(L, 3); + + imlua_match(L, src_image, dst_image); + imlua_checkkernel(L, kernel, 3); + + lua_pushboolean(L, imProcessConvolveSep(src_image, dst_image, kernel)); + return 1; +} + +/*****************************************************************************\ + im.ProcessCompassConvolve +\*****************************************************************************/ +static int imluaProcessCompassConvolve (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + imImage *kernel = imlua_checkimage(L, 3); + + imlua_checknotcfloat(L, src_image, 1); + imlua_match(L, src_image, dst_image); + imlua_checkkernel(L, kernel, 3); + + lua_pushboolean(L, imProcessCompassConvolve(src_image, dst_image, kernel)); + return 1; +} + +/*****************************************************************************\ + im.ProcessRotateKernel +\*****************************************************************************/ +static int imluaProcessRotateKernel (lua_State *L) +{ + imProcessRotateKernel(imlua_checkimage(L, 1)); + return 0; +} + +/*****************************************************************************\ + im.ProcessDiffOfGaussianConvolve +\*****************************************************************************/ +static int imluaProcessDiffOfGaussianConvolve (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + float stddev1 = (float) luaL_checknumber(L, 3); + float stddev2 = (float) luaL_checknumber(L, 4); + + if (src_image->data_type == IM_BYTE || src_image->data_type == IM_USHORT) + { + imlua_matchcolor(L, src_image, dst_image); + imlua_checkdatatype(L, 2, dst_image, IM_INT); + } + else + imlua_match(L, src_image, dst_image); + + lua_pushboolean(L, imProcessDiffOfGaussianConvolve(src_image, dst_image, stddev1, stddev2)); + return 1; +} + +/*****************************************************************************\ + im.ProcessLapOfGaussianConvolve +\*****************************************************************************/ +static int imluaProcessLapOfGaussianConvolve (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + float stddev = (float) luaL_checknumber(L, 3); + + if (src_image->data_type == IM_BYTE || src_image->data_type == IM_USHORT) + { + imlua_matchcolor(L, src_image, dst_image); + imlua_checkdatatype(L, 2, dst_image, IM_INT); + } + else + imlua_match(L, src_image, dst_image); + + lua_pushboolean(L, imProcessLapOfGaussianConvolve(src_image, dst_image, stddev)); + return 1; +} + +/*****************************************************************************\ + im.ProcessMeanConvolve +\*****************************************************************************/ +static int imluaProcessMeanConvolve (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + int kernel_size = luaL_checkint(L, 3); + + imlua_match(L, src_image, dst_image); + + lua_pushboolean(L, imProcessMeanConvolve(src_image, dst_image, kernel_size)); + return 1; +} + +/*****************************************************************************\ + im.ProcessBarlettConvolve +\*****************************************************************************/ +static int imluaProcessBarlettConvolve (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + int kernel_size = luaL_checkint(L, 3); + + imlua_match(L, src_image, dst_image); + + lua_pushboolean(L, imProcessBarlettConvolve(src_image, dst_image, kernel_size)); + return 1; +} + +/*****************************************************************************\ + im.ProcessGaussianConvolve +\*****************************************************************************/ +static int imluaProcessGaussianConvolve (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + float stddev = (float) luaL_checknumber(L, 3); + + imlua_match(L, src_image, dst_image); + + lua_pushboolean(L, imProcessGaussianConvolve(src_image, dst_image, stddev)); + return 1; +} + +/*****************************************************************************\ + im.ProcessPrewittConvolve +\*****************************************************************************/ +static int imluaProcessPrewittConvolve (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + + imlua_match(L, src_image, dst_image); + + lua_pushboolean(L, imProcessPrewittConvolve(src_image, dst_image)); + return 1; +} + +/*****************************************************************************\ + im.ProcessSplineEdgeConvolve +\*****************************************************************************/ +static int imluaProcessSplineEdgeConvolve (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + + imlua_match(L, src_image, dst_image); + + lua_pushboolean(L, imProcessSplineEdgeConvolve(src_image, dst_image)); + return 1; +} + +/*****************************************************************************\ + im.ProcessSobelConvolve +\*****************************************************************************/ +static int imluaProcessSobelConvolve (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + + imlua_match(L, src_image, dst_image); + + lua_pushboolean(L, imProcessSobelConvolve(src_image, dst_image)); + return 1; +} + +/*****************************************************************************\ + im.ProcessZeroCrossing +\*****************************************************************************/ +static int imluaProcessZeroCrossing (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + + luaL_argcheck(L, src_image->data_type == IM_INT || src_image->data_type == IM_FLOAT, 1, "image data type can be int or float only"); + imlua_match(L, src_image, dst_image); + + imProcessZeroCrossing(src_image, dst_image); + return 0; +} + +/*****************************************************************************\ + im.ProcessCanny +\*****************************************************************************/ +static int imluaProcessCanny (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + float stddev = (float) luaL_checknumber(L, 3); + + imlua_checktype(L, 1, src_image, IM_GRAY, IM_BYTE); + imlua_match(L, src_image, dst_image); + + imProcessCanny(src_image, dst_image, stddev); + return 0; +} + +/*****************************************************************************\ + im.ProcessUnsharp +\*****************************************************************************/ +static int imluaProcessUnsharp(lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + float p1 = (float)luaL_checknumber(L, 3); + float p2 = (float)luaL_checknumber(L, 4); + float p3 = (float)luaL_checknumber(L, 5); + + imlua_match(L, src_image, dst_image); + + imProcessUnsharp(src_image, dst_image, p1, p2, p3); + return 0; +} + +/*****************************************************************************\ + im.ProcessSharp +\*****************************************************************************/ +static int imluaProcessSharp(lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + float p1 = (float)luaL_checknumber(L, 3); + float p2 = (float)luaL_checknumber(L, 4); + + imlua_match(L, src_image, dst_image); + + imProcessSharp(src_image, dst_image, p1, p2); + return 0; +} + +/*****************************************************************************\ + im.ProcessSharpKernel +\*****************************************************************************/ +static int imluaProcessSharpKernel(lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *kernel = imlua_checkimage(L, 2); + imImage *dst_image = imlua_checkimage(L, 3); + float p1 = (float)luaL_checknumber(L, 4); + float p2 = (float)luaL_checknumber(L, 5); + + imlua_match(L, src_image, dst_image); + + imProcessSharpKernel(src_image, kernel, dst_image, p1, p2); + return 0; +} + +/*****************************************************************************\ + im.GaussianStdDev2Repetitions +\*****************************************************************************/ +static int imluaGaussianKernelSize2StdDev(lua_State *L) +{ + lua_pushnumber(L, imGaussianKernelSize2StdDev((int)luaL_checknumber(L, 1))); + return 1; +} + +/*****************************************************************************\ + im.GaussianStdDev2KernelSize +\*****************************************************************************/ +static int imluaGaussianStdDev2KernelSize (lua_State *L) +{ + lua_pushnumber(L, imGaussianStdDev2KernelSize((float)luaL_checknumber(L, 1))); + return 1; +} + + + +/*****************************************************************************\ + Arithmetic Operations +\*****************************************************************************/ + +/*****************************************************************************\ + im.ProcessUnArithmeticOp +\*****************************************************************************/ +static int imluaProcessUnArithmeticOp (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + int op = luaL_checkint(L, 3); + + imlua_matchcolorspace(L, src_image, dst_image); + + imProcessUnArithmeticOp(src_image, dst_image, op); + return 0; +} + +/*****************************************************************************\ + im.ProcessArithmeticOp +\*****************************************************************************/ +static int imluaProcessArithmeticOp (lua_State *L) +{ + imImage *src_image1 = imlua_checkimage(L, 1); + imImage *src_image2 = imlua_checkimage(L, 2); + imImage *dst_image = imlua_checkimage(L, 3); + int op = luaL_checkint(L, 4); + + imlua_match(L, src_image1, src_image2); + imlua_matchsize(L, src_image1, dst_image); + imlua_matchsize(L, src_image2, dst_image); + + switch (src_image1->data_type) + { + case IM_BYTE: + luaL_argcheck(L, + dst_image->data_type == IM_BYTE || + dst_image->data_type == IM_USHORT || + dst_image->data_type == IM_INT || + dst_image->data_type == IM_FLOAT, + 2, "source image is byte, destiny image data type can be byte, ushort, int and float only."); + break; + case IM_USHORT: + luaL_argcheck(L, + dst_image->data_type == IM_USHORT || + dst_image->data_type == IM_INT || + dst_image->data_type == IM_FLOAT, + 2, "source image is ushort, destiny image data type can be ushort, int and float only."); + break; + case IM_INT: + luaL_argcheck(L, + dst_image->data_type == IM_INT || + dst_image->data_type == IM_FLOAT, + 2, "source image is int, destiny image data type can be int and float only."); + break; + case IM_FLOAT: + luaL_argcheck(L, + dst_image->data_type == IM_FLOAT, + 2, "source image is float, destiny image data type can be float only."); + break; + case IM_CFLOAT: + luaL_argcheck(L, + dst_image->data_type == IM_CFLOAT, + 2, "source image is cfloat, destiny image data type can be cfloat only."); + break; + } + + imProcessArithmeticOp(src_image1, src_image2, dst_image, op); + return 0; +} + +/*****************************************************************************\ + im.ProcessArithmeticConstOp +\*****************************************************************************/ +static int imluaProcessArithmeticConstOp (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + float src_const = (float) luaL_checknumber(L, 2); + imImage *dst_image = imlua_checkimage(L, 3); + int op = luaL_checkint(L, 4); + + imlua_matchsize(L, src_image, dst_image); + + switch (src_image->data_type) + { + case IM_BYTE: + luaL_argcheck(L, + dst_image->data_type == IM_BYTE || + dst_image->data_type == IM_USHORT || + dst_image->data_type == IM_INT || + dst_image->data_type == IM_FLOAT, + 2, "source image is byte, destiny image data type can be byte, ushort, int and float only."); + break; + case IM_USHORT: + luaL_argcheck(L, + dst_image->data_type == IM_USHORT || + dst_image->data_type == IM_INT || + dst_image->data_type == IM_FLOAT, + 2, "source image is ushort, destiny image data type can be ushort, int and float only."); + break; + case IM_INT: + luaL_argcheck(L, + dst_image->data_type == IM_INT || + dst_image->data_type == IM_FLOAT, + 2, "source image is int, destiny image data type can be int and float only."); + break; + case IM_FLOAT: + luaL_argcheck(L, + dst_image->data_type == IM_FLOAT, + 2, "source image is float, destiny image data type can be float only."); + break; + case IM_CFLOAT: + luaL_argcheck(L, + dst_image->data_type == IM_CFLOAT, + 2, "source image is cfloat, destiny image data type can be cfloat only."); + break; + } + + imProcessArithmeticConstOp(src_image, src_const, dst_image, op); + return 0; +} + +/*****************************************************************************\ + im.ProcessBlendConst +\*****************************************************************************/ +static int imluaProcessBlendConst (lua_State *L) +{ + imImage *src_image1 = imlua_checkimage(L, 1); + imImage *src_image2 = imlua_checkimage(L, 2); + imImage *dst_image = imlua_checkimage(L, 3); + float alpha = (float) luaL_checknumber(L, 4); + + imlua_match(L, src_image1, src_image2); + imlua_match(L, src_image1, dst_image); + + imProcessBlendConst(src_image1, src_image2, dst_image, alpha); + return 0; +} + +/*****************************************************************************\ + im.ProcessBlend +\*****************************************************************************/ +static int imluaProcessBlend (lua_State *L) +{ + imImage *src_image1 = imlua_checkimage(L, 1); + imImage *src_image2 = imlua_checkimage(L, 2); + imImage *alpha_image = imlua_checkimage(L, 3); + imImage *dst_image = imlua_checkimage(L, 4); + + imlua_match(L, src_image1, src_image2); + imlua_match(L, src_image1, dst_image); + imlua_matchdatatype(L, src_image1, alpha_image); + + imProcessBlend(src_image1, src_image2, alpha_image, dst_image); + return 0; +} + +/*****************************************************************************\ + im.ProcessSplitComplex +\*****************************************************************************/ +static int imluaProcessSplitComplex (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image1 = imlua_checkimage(L, 2); + imImage *dst_image2 = imlua_checkimage(L, 3); + int polar = lua_toboolean(L, 4); + + imlua_checkdatatype(L, 1, src_image, IM_CFLOAT); + imlua_checkdatatype(L, 2, dst_image1, IM_FLOAT); + imlua_checkdatatype(L, 3, dst_image2, IM_FLOAT); + imlua_matchcolorspace(L, src_image, dst_image1); + imlua_matchcolorspace(L, src_image, dst_image2); + + imProcessSplitComplex(src_image, dst_image1, dst_image2, polar); + return 0; +} + +/*****************************************************************************\ + im.ProcessMergeComplex +\*****************************************************************************/ +static int imluaProcessMergeComplex (lua_State *L) +{ + imImage *src_image1 = imlua_checkimage(L, 1); + imImage *src_image2 = imlua_checkimage(L, 2); + imImage *dst_image = imlua_checkimage(L, 3); + int polar = lua_toboolean(L, 4); + + imlua_checkdatatype(L, 1, src_image1, IM_FLOAT); + imlua_checkdatatype(L, 2, src_image2, IM_FLOAT); + imlua_checkdatatype(L, 3, dst_image, IM_CFLOAT); + imlua_matchcolorspace(L, src_image1, src_image2); + imlua_matchcolorspace(L, src_image1, dst_image); + + imProcessMergeComplex(src_image1, src_image2, dst_image, polar); + return 0; +} + +/*****************************************************************************\ + im.ProcessMultipleMean +\*****************************************************************************/ +static int imluaProcessMultipleMean (lua_State *L) +{ + int i, src_image_count; + imImage *dst_image; + imImage **src_image_list; + + luaL_checktype(L, 1, LUA_TTABLE); + src_image_count = imlua_getn(L, 1); + + src_image_list = (imImage**)malloc(sizeof(imImage*)*src_image_count); + + for (i = 0; i < src_image_count; i++) + { + lua_rawgeti(L, 1, i+1); + src_image_list[i] = imlua_checkimage(L, -1); + } + + dst_image = imlua_checkimage(L, 2); + + for (i = 0; i < src_image_count; i++) + { + int check = imImageMatchDataType(src_image_list[i], dst_image); + if (!check) free(src_image_list); + imlua_matchcheck(L, check, "images must have the same size and data type"); + } + + imProcessMultipleMean((const imImage**)src_image_list, src_image_count, dst_image); + free(src_image_list); + return 0; +} + +/*****************************************************************************\ + im.ProcessMultipleStdDev +\*****************************************************************************/ +static int imluaProcessMultipleStdDev (lua_State *L) +{ + int i, src_image_count, check; + imImage *dst_image, *mean_image; + imImage **src_image_list; + + if (!lua_istable(L, 1)) + luaL_argerror(L, 1, "must be a table"); + + lua_pushstring(L, "table"); + lua_gettable(L, LUA_GLOBALSINDEX); + lua_pushstring(L, "getn"); + lua_gettable(L, -2); + src_image_count = luaL_checkint(L, -1); + lua_pop(L, 1); + + src_image_list = (imImage**) malloc(src_image_count * sizeof(imImage*)); + + for (i = 0; i < src_image_count; i++) + { + lua_rawgeti(L, 1, i+1); + src_image_list[i] = imlua_checkimage(L, -1); + } + + mean_image = imlua_checkimage(L, 2); + dst_image = imlua_checkimage(L, 3); + + for (i = 0; i < src_image_count; i++) + { + check = imImageMatchDataType(src_image_list[i], dst_image); + if (!check) free(src_image_list); + imlua_matchcheck(L, check, "images must have the same size and data type"); + } + check = imImageMatchDataType(mean_image, dst_image); + if (!check) free(src_image_list); + imlua_matchcheck(L, check, "images must have the same size and data type"); + + imProcessMultipleStdDev((const imImage**)src_image_list, src_image_count, mean_image, dst_image); + free(src_image_list); + return 0; +} + +/*****************************************************************************\ + im.ProcessAutoCovariance +\*****************************************************************************/ +static int imluaProcessAutoCovariance (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *mean_image = imlua_checkimage(L, 2); + imImage *dst_image = imlua_checkimage(L, 3); + + imlua_match(L, src_image, mean_image); + imlua_matchcolorspace(L, src_image, dst_image); + imlua_checkdatatype(L, 3, dst_image, IM_FLOAT); + + lua_pushboolean(L, imProcessAutoCovariance(src_image, mean_image, dst_image)); + return 1; +} + +/*****************************************************************************\ + im.ProcessMultiplyConj +\*****************************************************************************/ +static int imluaProcessMultiplyConj (lua_State *L) +{ + imImage *src_image1 = imlua_checkimage(L, 1); + imImage *src_image2 = imlua_checkimage(L, 2); + imImage *dst_image = imlua_checkimage(L, 3); + + imlua_match(L, src_image1, src_image2); + imlua_match(L, src_image1, dst_image); + + imProcessMultiplyConj(src_image1, src_image2, dst_image); + return 0; +} + + +/*****************************************************************************\ + Additional Image Quantization Operations +\*****************************************************************************/ + +/*****************************************************************************\ + im.ProcessQuantizeRGBUniform +\*****************************************************************************/ +static int imluaProcessQuantizeRGBUniform (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + int dither = lua_toboolean(L, 3); + + imlua_checktype(L, 1, src_image, IM_RGB, IM_BYTE); + imlua_checkcolorspace(L, 2, dst_image, IM_MAP); + imlua_matchsize(L, src_image, dst_image); + + imProcessQuantizeRGBUniform(src_image, dst_image, dither); + return 0; +} + +/*****************************************************************************\ + im.ProcessQuantizeGrayUniform +\*****************************************************************************/ +static int imluaProcessQuantizeGrayUniform (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + int grays = luaL_checkint(L, 3); + + imlua_checktype(L, 1, src_image, IM_GRAY, IM_BYTE); + imlua_checktype(L, 2, dst_image, IM_GRAY, IM_BYTE); + imlua_match(L, src_image, dst_image); + + imProcessQuantizeGrayUniform(src_image, dst_image, grays); + return 0; +} + + +/*****************************************************************************\ + Histogram Based Operations +\*****************************************************************************/ + +/*****************************************************************************\ + im.ProcessExpandHistogram +\*****************************************************************************/ +static int imluaProcessExpandHistogram (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + float percent = (float) luaL_checknumber(L, 3); + + imlua_checkdatatype(L, 1, src_image, IM_BYTE); + imlua_match(L, src_image, dst_image); + luaL_argcheck(L, src_image->color_space == IM_RGB || src_image->color_space == IM_GRAY, 1, "color space can be RGB or Gray only"); + luaL_argcheck(L, dst_image->color_space == IM_RGB || dst_image->color_space == IM_GRAY, 2, "color space can be RGB or Gray only"); + + imProcessExpandHistogram(src_image, dst_image, percent); + return 0; +} + +/*****************************************************************************\ + im.ProcessEqualizeHistogram +\*****************************************************************************/ +static int imluaProcessEqualizeHistogram (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + + imlua_checkdatatype(L, 1, src_image, IM_BYTE); + imlua_match(L, src_image, dst_image); + luaL_argcheck(L, src_image->color_space == IM_RGB || src_image->color_space == IM_GRAY, 1, "color space can be RGB or Gray only"); + luaL_argcheck(L, dst_image->color_space == IM_RGB || dst_image->color_space == IM_GRAY, 2, "color space can be RGB or Gray only"); + + imProcessEqualizeHistogram(src_image, dst_image); + return 0; +} + + + +/*****************************************************************************\ + Color Processing Operations +\*****************************************************************************/ + +/*****************************************************************************\ + im.ProcessSplitYChroma +\*****************************************************************************/ +static int imluaProcessSplitYChroma (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *y_image = imlua_checkimage(L, 2); + imImage *chroma_image = imlua_checkimage(L, 3); + + imlua_checktype(L, 1, src_image, IM_RGB, IM_BYTE); + imlua_checktype(L, 2, y_image, IM_GRAY, IM_BYTE); + imlua_checktype(L, 3, chroma_image, IM_RGB, IM_BYTE); + imlua_matchsize(L, src_image, y_image); + imlua_matchsize(L, src_image, chroma_image); + + imProcessSplitYChroma(src_image, y_image, chroma_image); + return 0; +} + +/*****************************************************************************\ + im.ProcessSplitHSI +\*****************************************************************************/ +static int imluaProcessSplitHSI (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *h_image = imlua_checkimage(L, 2); + imImage *s_image = imlua_checkimage(L, 3); + imImage *i_image = imlua_checkimage(L, 4); + + imlua_checkcolorspace(L, 1, src_image, IM_RGB); + luaL_argcheck(L, src_image->data_type == IM_BYTE || src_image->data_type == IM_FLOAT, 1, "data type can be float or byte only"); + imlua_checktype(L, 2, h_image, IM_GRAY, IM_FLOAT); + imlua_checktype(L, 3, s_image, IM_GRAY, IM_FLOAT); + imlua_checktype(L, 4, i_image, IM_GRAY, IM_FLOAT); + imlua_matchsize(L, src_image, h_image); + imlua_matchsize(L, src_image, s_image); + imlua_matchsize(L, src_image, i_image); + + imProcessSplitHSI(src_image, h_image, s_image, i_image); + return 0; +} + +/*****************************************************************************\ + im.ProcessMergeHSI +\*****************************************************************************/ +static int imluaProcessMergeHSI (lua_State *L) +{ + imImage *h_image = imlua_checkimage(L, 1); + imImage *s_image = imlua_checkimage(L, 2); + imImage *i_image = imlua_checkimage(L, 3); + imImage *dst_image = imlua_checkimage(L, 4); + + imlua_checktype(L, 1, h_image, IM_GRAY, IM_FLOAT); + imlua_checktype(L, 2, s_image, IM_GRAY, IM_FLOAT); + imlua_checktype(L, 3, i_image, IM_GRAY, IM_FLOAT); + imlua_checkcolorspace(L, 4, dst_image, IM_RGB); + luaL_argcheck(L, dst_image->data_type == IM_BYTE || dst_image->data_type == IM_FLOAT, 4, "data type can be float or byte only"); + imlua_matchsize(L, dst_image, h_image); + imlua_matchsize(L, dst_image, s_image); + imlua_matchsize(L, dst_image, i_image); + + imProcessMergeHSI(h_image, s_image, i_image, dst_image); + return 0; +} + +/*****************************************************************************\ + im.ProcessSplitComponents(src_image, { r, g, b} ) +\*****************************************************************************/ +static int imluaProcessSplitComponents (lua_State *L) +{ + int i; + imImage *src_image = imlua_checkimage(L, 1); + imImage **dst_image_list; + + luaL_checktype(L, 2, LUA_TTABLE); + + if (imlua_getn(L, 2) != src_image->depth) + luaL_error(L, "number of destiny images must match the depth of the source image"); + + dst_image_list = (imImage**)malloc(sizeof(imImage*)*src_image->depth); + + for (i = 0; i < src_image->depth; i++) + { + lua_pushnumber(L, i+1); + lua_gettable(L, 2); + dst_image_list[i] = imlua_checkimage(L, -1); + imlua_checkcolorspace(L, 2, dst_image_list[i], IM_GRAY); /* if error here, there will be a memory leak */ + lua_pop(L, 1); + } + + for (i = 0; i < src_image->depth; i++) + { + int check = imImageMatchDataType(src_image, dst_image_list[i]); + if (!check) free(dst_image_list); + imlua_matchcheck(L, check, "images must have the same size and data type"); + } + + imProcessSplitComponents(src_image, dst_image_list); + + free(dst_image_list); + + return 0; +} + +/*****************************************************************************\ + im.ProcessMergeComponents({r, g, b}, rgb) +\*****************************************************************************/ +static int imluaProcessMergeComponents (lua_State *L) +{ + int i; + imImage** src_image_list; + imImage *dst_image; + + luaL_checktype(L, 1, LUA_TTABLE); + dst_image = imlua_checkimage(L, 2); + + if (imlua_getn(L, 1) != dst_image->depth) + luaL_error(L, "number of source images must match the depth of the destination image"); + + src_image_list = (imImage**)malloc(sizeof(imImage*)*dst_image->depth); + + for (i = 0; i < dst_image->depth; i++) + { + lua_pushnumber(L, i+1); + lua_gettable(L, 1); + src_image_list[i] = imlua_checkimage(L, -1); + imlua_checkcolorspace(L, 1, src_image_list[i], IM_GRAY); + lua_pop(L, 1); + } + + for (i = 0; i < dst_image->depth; i++) + { + int check = imImageMatchDataType(src_image_list[i], dst_image); + if (!check) free(src_image_list); + imlua_matchcheck(L, check, "images must have the same size and data type"); + } + + imProcessMergeComponents((const imImage**)src_image_list, dst_image); + + free(src_image_list); + + return 0; +} + +/*****************************************************************************\ + im.ProcessNormalizeComponents +\*****************************************************************************/ +static int imluaProcessNormalizeComponents (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + + imlua_checkdatatype(L, 2, dst_image, IM_FLOAT); + imlua_matchcolorspace(L, src_image, dst_image); + + imProcessNormalizeComponents(src_image, dst_image); + return 0; +} + +/*****************************************************************************\ + im.ProcessReplaceColor +\*****************************************************************************/ +static int imluaProcessReplaceColor (lua_State *L) +{ + int src_count, dst_count; + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + float *src_color = imlua_toarrayfloat(L, 3, &src_count, 1); + float *dst_color = imlua_toarrayfloat(L, 4, &dst_count, 1); + + imlua_checknotcfloat(L, src_image, 1); + imlua_match(L, src_image, dst_image); + luaL_argcheck(L, src_count == src_image->depth, 3, "the colors must have the same number of components of the images"); + luaL_argcheck(L, dst_count == src_image->depth, 4, "the colors must have the same number of components of the images"); + + imProcessReplaceColor(src_image, dst_image, src_color, dst_color); + return 0; +} + + + +/*****************************************************************************\ + Logical Arithmetic Operations +\*****************************************************************************/ + +/*****************************************************************************\ + im.ProcessBitwiseOp +\*****************************************************************************/ +static int imluaProcessBitwiseOp (lua_State *L) +{ + imImage *src_image1 = imlua_checkimage(L, 1); + imImage *src_image2 = imlua_checkimage(L, 2); + imImage *dst_image = imlua_checkimage(L, 3); + int op = luaL_checkint(L, 4); + + luaL_argcheck(L, (src_image1->data_type < IM_FLOAT), 1, "image data type can be integer only"); + imlua_match(L, src_image1, src_image2); + imlua_match(L, src_image1, dst_image); + + imProcessBitwiseOp(src_image1, src_image2, dst_image, op); + return 0; +} + +/*****************************************************************************\ + im.ProcessBitwiseNot +\*****************************************************************************/ +static int imluaProcessBitwiseNot (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + + luaL_argcheck(L, (src_image->data_type < IM_FLOAT), 1, "image data type can be integer only"); + imlua_match(L, src_image, dst_image); + + imProcessBitwiseNot(src_image, dst_image); + return 0; +} + +/*****************************************************************************\ + im.ProcessBitMask(src_image, dst_image, mask, op) +\*****************************************************************************/ +static int imluaProcessBitMask (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + unsigned char mask = imlua_checkmask(L, 3); + int op = luaL_checkint(L, 4); + + imlua_checkdatatype(L, 1, src_image, IM_BYTE); + imlua_match(L, src_image, dst_image); + + imProcessBitMask(src_image, dst_image, mask, op); + return 0; +} + +/*****************************************************************************\ + im.ProcessBitPlane(src_image, dst_image, plane, reset) +\*****************************************************************************/ +static int imluaProcessBitPlane (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + int plane = luaL_checkint(L, 3); + int reset = lua_toboolean(L, 4); + + imlua_checkdatatype(L, 1, src_image, IM_BYTE); + imlua_match(L, src_image, dst_image); + + imProcessBitPlane(src_image, dst_image, plane, reset); + return 0; +} + + + +/*****************************************************************************\ + Synthetic Image Render +\*****************************************************************************/ + +/* NOTE: This breaks on multithread */ +static lua_State *g_renderState = NULL; +int g_paramCount = 0; + +static float imluaRenderFunc (int x, int y, int d, float *param) +{ + lua_State *L = g_renderState; + + luaL_checktype(L, 2, LUA_TFUNCTION); + lua_pushvalue(L, 2); + lua_pushnumber(L, x); + lua_pushnumber(L, y); + lua_pushnumber(L, d); + imlua_newarrayfloat(L, param, g_paramCount, 1); + + lua_call(L, 4, 1); + + return (float) luaL_checknumber(L, -1); +} + +/*****************************************************************************\ + im.ProcessRenderOp(image, function, name, param, plus) +\*****************************************************************************/ +static int imluaProcessRenderOp (lua_State *L) +{ + int count; + + imImage *image = imlua_checkimage(L, 1); + const char *render_name = luaL_checkstring(L, 3); + float *param = imlua_toarrayfloat(L, 4, &count, 1); + int plus = luaL_checkint(L, 5); + + imlua_checknotcfloat(L, image, 1); + + luaL_checktype(L, 2, LUA_TFUNCTION); + + g_renderState = L; + g_paramCount = count; + lua_pushboolean(L, imProcessRenderOp(image, imluaRenderFunc, (char*) render_name, param, plus)); + return 1; +} + +static float imluaRenderCondFunc (int x, int y, int d, int *cond, float *param) +{ + lua_State *L = g_renderState; + + luaL_checktype(L, 2, LUA_TFUNCTION); + lua_pushvalue(L, 2); + lua_pushnumber(L, x); + lua_pushnumber(L, y); + lua_pushnumber(L, d); + imlua_newarrayfloat(L, param, g_paramCount, 1); + + lua_call(L, 4, 2); + + *cond = lua_toboolean(L, -1); + return (float) luaL_checknumber(L, -2); +} + +/*****************************************************************************\ + im.ProcessRenderCondOp(image, function, name, param) +\*****************************************************************************/ +static int imluaProcessRenderCondOp (lua_State *L) +{ + int count; + + imImage *image = imlua_checkimage(L, 1); + const char *render_name = luaL_checkstring(L, 3); + float *param = imlua_toarrayfloat(L, 4, &count, 1); + + imlua_checknotcfloat(L, image, 1); + + luaL_checktype(L, 2, LUA_TFUNCTION); + + g_renderState = L; + g_paramCount = count; + lua_pushboolean(L, imProcessRenderCondOp(image, imluaRenderCondFunc, (char*) render_name, param)); + return 1; +} + +/*****************************************************************************\ + im.ProcessRenderAddSpeckleNoise +\*****************************************************************************/ +static int imluaProcessRenderAddSpeckleNoise (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + float percent = (float) luaL_checknumber(L, 3); + + imlua_checknotcfloat(L, src_image, 1); + imlua_match(L, src_image, dst_image); + + lua_pushboolean(L, imProcessRenderAddSpeckleNoise(src_image, dst_image, percent)); + return 1; +} + +/*****************************************************************************\ + im.ProcessRenderAddGaussianNoise +\*****************************************************************************/ +static int imluaProcessRenderAddGaussianNoise (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + float mean = (float) luaL_checknumber(L, 3); + float stddev = (float) luaL_checknumber(L, 4); + + imlua_checknotcfloat(L, src_image, 1); + imlua_match(L, src_image, dst_image); + + lua_pushboolean(L, imProcessRenderAddGaussianNoise(src_image, dst_image, mean, stddev)); + return 1; +} + +/*****************************************************************************\ + im.ProcessRenderAddUniformNoise +\*****************************************************************************/ +static int imluaProcessRenderAddUniformNoise (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + float mean = (float) luaL_checknumber(L, 3); + float stddev = (float) luaL_checknumber(L, 4); + + imlua_checknotcfloat(L, src_image, 1); + imlua_match(L, src_image, dst_image); + + lua_pushboolean(L, imProcessRenderAddUniformNoise(src_image, dst_image, mean, stddev)); + return 1; +} + +/*****************************************************************************\ + im.ProcessRenderRandomNoise +\*****************************************************************************/ +static int imluaProcessRenderRandomNoise (lua_State *L) +{ + imImage *image = imlua_checkimage(L, 1); + imlua_checknotcfloat(L, image, 1); + lua_pushboolean(L, imProcessRenderRandomNoise(image)); + return 1; +} + +/*****************************************************************************\ + im.ProcessRenderConstant(image, [count]) +\*****************************************************************************/ +static int imluaProcessRenderConstant (lua_State *L) +{ + int i; + float *value = NULL; + + imImage *image = imlua_checkimage(L, 1); + int count = image->depth; + + imlua_checknotcfloat(L, image, 1); + + if (lua_istable(L, 2)) + { + value = (float*) malloc (sizeof(float) * count); + + for (i = 0; i < count; i++) + { + lua_rawgeti(L, 2, i+1); + value[i] = (float) lua_tonumber(L, -1); + lua_pop(L, 1); + } + } + + lua_pushboolean(L, imProcessRenderConstant(image, value)); + + if (value) + free(value); + + return 1; +} + +/*****************************************************************************\ + im.ProcessRenderWheel +\*****************************************************************************/ +static int imluaProcessRenderWheel (lua_State *L) +{ + imImage *image = imlua_checkimage(L, 1); + int int_radius = luaL_checkint(L, 2); + int ext_radius = luaL_checkint(L, 3); + + imlua_checknotcfloat(L, image, 1); + + lua_pushboolean(L, imProcessRenderWheel(image, int_radius, ext_radius)); + return 1; +} + +/*****************************************************************************\ + im.ProcessRenderCone +\*****************************************************************************/ +static int imluaProcessRenderCone (lua_State *L) +{ + imImage *image = imlua_checkimage(L, 1); + int radius = luaL_checkint(L, 2); + + imlua_checknotcfloat(L, image, 1); + + lua_pushboolean(L, imProcessRenderCone(image, radius)); + return 1; +} + +/*****************************************************************************\ + im.ProcessRenderTent +\*****************************************************************************/ +static int imluaProcessRenderTent (lua_State *L) +{ + imImage *image = imlua_checkimage(L, 1); + int width = luaL_checkint(L, 2); + int height = luaL_checkint(L, 3); + + imlua_checknotcfloat(L, image, 1); + + lua_pushboolean(L, imProcessRenderTent(image, width, height)); + return 1; +} + +/*****************************************************************************\ + im.ProcessRenderRamp +\*****************************************************************************/ +static int imluaProcessRenderRamp (lua_State *L) +{ + imImage *image = imlua_checkimage(L, 1); + int start = luaL_checkint(L, 2); + int end = luaL_checkint(L, 3); + int dir = luaL_checkint(L, 4); + + imlua_checknotcfloat(L, image, 1); + + lua_pushboolean(L, imProcessRenderRamp(image, start, end, dir)); + return 1; +} + +/*****************************************************************************\ + im.ProcessRenderBox +\*****************************************************************************/ +static int imluaProcessRenderBox (lua_State *L) +{ + imImage *image = imlua_checkimage(L, 1); + int width = luaL_checkint(L, 2); + int height = luaL_checkint(L, 3); + + imlua_checknotcfloat(L, image, 1); + + lua_pushboolean(L, imProcessRenderBox(image, width, height)); + return 1; +} + +/*****************************************************************************\ + im.ProcessRenderSinc +\*****************************************************************************/ +static int imluaProcessRenderSinc (lua_State *L) +{ + imImage *image = imlua_checkimage(L, 1); + float xperiod = (float) luaL_checknumber(L, 2); + float yperiod = (float) luaL_checknumber(L, 3); + + imlua_checknotcfloat(L, image, 1); + + lua_pushboolean(L, imProcessRenderSinc(image, xperiod, yperiod)); + return 1; +} + +/*****************************************************************************\ + im.ProcessRenderGaussian +\*****************************************************************************/ +static int imluaProcessRenderGaussian (lua_State *L) +{ + imImage *image = imlua_checkimage(L, 1); + float stddev = (float) luaL_checknumber(L, 2); + + imlua_checknotcfloat(L, image, 1); + + lua_pushboolean(L, imProcessRenderGaussian(image, stddev)); + return 1; +} + +/*****************************************************************************\ + im.ProcessRenderLapOfGaussian +\*****************************************************************************/ +static int imluaProcessRenderLapOfGaussian (lua_State *L) +{ + imImage *image = imlua_checkimage(L, 1); + float stddev = (float) luaL_checknumber(L, 2); + + imlua_checknotcfloat(L, image, 1); + + lua_pushboolean(L, imProcessRenderLapOfGaussian(image, stddev)); + return 1; +} + +/*****************************************************************************\ + im.ProcessRenderCosine +\*****************************************************************************/ +static int imluaProcessRenderCosine (lua_State *L) +{ + imImage *image = imlua_checkimage(L, 1); + float xperiod = (float) luaL_checknumber(L, 2); + float yperiod = (float) luaL_checknumber(L, 3); + + imlua_checknotcfloat(L, image, 1); + + lua_pushboolean(L, imProcessRenderCosine(image, xperiod, yperiod)); + return 1; +} + +/*****************************************************************************\ + im.ProcessRenderGrid +\*****************************************************************************/ +static int imluaProcessRenderGrid (lua_State *L) +{ + imImage *image = imlua_checkimage(L, 1); + int x_space = luaL_checkint(L, 2); + int y_space = luaL_checkint(L, 3); + + imlua_checknotcfloat(L, image, 1); + + lua_pushboolean(L, imProcessRenderGrid(image, x_space, y_space)); + return 1; +} + +/*****************************************************************************\ + im.ProcessRenderChessboard +\*****************************************************************************/ +static int imluaProcessRenderChessboard (lua_State *L) +{ + imImage *image = imlua_checkimage(L, 1); + int x_space = luaL_checkint(L, 2); + int y_space = luaL_checkint(L, 3); + + imlua_checknotcfloat(L, image, 1); + + lua_pushboolean(L, imProcessRenderChessboard(image, x_space, y_space)); + return 1; +} + + + +/*****************************************************************************\ + Tone Gamut Operations +\*****************************************************************************/ + +/*****************************************************************************\ + im.ProcessToneGamut +\*****************************************************************************/ +static int imluaProcessToneGamut (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + int op = luaL_checkint(L, 3); + float *param = NULL; + + imlua_checknotcfloat(L, src_image, 1); + imlua_match(L, src_image, dst_image); + + param = imlua_toarrayfloat(L, 4, NULL, 1); + + imProcessToneGamut(src_image, dst_image, op, param); + + if (param) + free(param); + + return 0; +} + +/*****************************************************************************\ + im.ProcessUnNormalize +\*****************************************************************************/ +static int imluaProcessUnNormalize (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + + imlua_checkdatatype(L, 1, src_image, IM_FLOAT); + imlua_checkdatatype(L, 2, dst_image, IM_BYTE); + imlua_matchcolorspace(L, src_image, dst_image); + + imProcessUnNormalize(src_image, dst_image); + return 0; +} + +/*****************************************************************************\ + im.ProcessDirectConv +\*****************************************************************************/ +static int imluaProcessDirectConv (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + + luaL_argcheck(L, + src_image->data_type == IM_USHORT || + src_image->data_type == IM_INT || + src_image->data_type == IM_FLOAT, + 1, "data type can be ushort, int or float only"); + imlua_checkdatatype(L, 2, dst_image, IM_BYTE); + imlua_matchsize(L, src_image, dst_image); + + imProcessDirectConv(src_image, dst_image); + return 0; +} + +/*****************************************************************************\ + im.ProcessNegative +\*****************************************************************************/ +static int imluaProcessNegative (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + + imlua_checknotcfloat(L, src_image, 1); + imlua_match(L, src_image, dst_image); + + imProcessNegative(src_image, dst_image); + return 0; +} + + + +/*****************************************************************************\ + Threshold Operations +\*****************************************************************************/ + +/*****************************************************************************\ + im.ProcessRangeContrastThreshold +\*****************************************************************************/ +static int imluaProcessRangeContrastThreshold (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + int kernel_size = luaL_checkint(L, 3); + int min_range = luaL_checkint(L, 4); + + imlua_checktype(L, 1, src_image, IM_GRAY, IM_BYTE); + luaL_argcheck(L, (src_image->data_type < IM_FLOAT), 1, "image data type can be integer only"); + imlua_checkcolorspace(L, 2, dst_image, IM_BINARY); + imlua_matchsize(L, src_image, dst_image); + + lua_pushboolean(L, imProcessRangeContrastThreshold(src_image, dst_image, kernel_size, min_range)); + return 1; +} + +/*****************************************************************************\ + im.ProcessLocalMaxThreshold +\*****************************************************************************/ +static int imluaProcessLocalMaxThreshold (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + int kernel_size = luaL_checkint(L, 3); + int min_thres = luaL_checkint(L, 4); + + imlua_checktype(L, 1, src_image, IM_GRAY, IM_BYTE); + luaL_argcheck(L, (src_image->data_type < IM_FLOAT), 1, "image data type can be integer only"); + imlua_checkcolorspace(L, 2, dst_image, IM_BINARY); + imlua_matchsize(L, src_image, dst_image); + + lua_pushboolean(L, imProcessLocalMaxThreshold(src_image, dst_image, kernel_size, min_thres)); + return 1; +} + +/*****************************************************************************\ + im.ProcessThreshold +\*****************************************************************************/ +static int imluaProcessThreshold (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + int level = luaL_checkint(L, 3); + int value = luaL_checkint(L, 4); + + imlua_checktype(L, 1, src_image, IM_GRAY, IM_BYTE); + luaL_argcheck(L, (src_image->data_type < IM_FLOAT), 1, "image data type can be integer only"); + + imlua_checkcolorspace(L, 2, dst_image, IM_BINARY); + imlua_matchsize(L, src_image, dst_image); + + imProcessThreshold(src_image, dst_image, level, value); + return 0; +} + +/*****************************************************************************\ + im.ProcessThresholdByDiff +\*****************************************************************************/ +static int imluaProcessThresholdByDiff (lua_State *L) +{ + imImage *src_image1 = imlua_checkimage(L, 1); + imImage *src_image2 = imlua_checkimage(L, 2); + imImage *dst_image = imlua_checkimage(L, 3); + + imlua_checktype(L, 1, src_image1, IM_GRAY, IM_BYTE); + imlua_match(L, src_image1, src_image2); + imlua_checkcolorspace(L, 2, dst_image, IM_BINARY); + imlua_matchsize(L, src_image1, dst_image); + + imProcessThresholdByDiff(src_image1, src_image2, dst_image); + return 0; +} + +/*****************************************************************************\ + im.ProcessHysteresisThreshold +\*****************************************************************************/ +static int imluaProcessHysteresisThreshold (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + int low_thres = luaL_checkint(L, 3); + int high_thres = luaL_checkint(L, 4); + + imlua_checktype(L, 1, src_image, IM_GRAY, IM_BYTE); + imlua_checkcolorspace(L, 2, dst_image, IM_BINARY); + imlua_matchsize(L, src_image, dst_image); + + imProcessHysteresisThreshold(src_image, dst_image, low_thres, high_thres); + return 0; +} + +/*****************************************************************************\ + im.ProcessHysteresisThresEstimate +\*****************************************************************************/ +static int imluaProcessHysteresisThresEstimate (lua_State *L) +{ + int low_thres, high_thres; + + imImage *src_image = imlua_checkimage(L, 1); + + imlua_checktype(L, 1, src_image, IM_GRAY, IM_BYTE); + + imProcessHysteresisThresEstimate(src_image, &low_thres, &high_thres); + lua_pushnumber(L, low_thres); + lua_pushnumber(L, high_thres); + + return 2; +} + +/*****************************************************************************\ + im.ProcessUniformErrThreshold +\*****************************************************************************/ +static int imluaProcessUniformErrThreshold (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + + imlua_checktype(L, 1, src_image, IM_GRAY, IM_BYTE); + imlua_checkcolorspace(L, 2, dst_image, IM_BINARY); + imlua_matchsize(L, src_image, dst_image); + + lua_pushboolean(L, imProcessUniformErrThreshold(src_image, dst_image)); + return 1; +} + +/*****************************************************************************\ + im.ProcessDifusionErrThreshold +\*****************************************************************************/ +static int imluaProcessDifusionErrThreshold (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + int level = luaL_checkint(L, 3); + + imlua_checkdatatype(L, 1, src_image, IM_BYTE); + imlua_checkdatatype(L, 2, dst_image, IM_BYTE); + imlua_matchcheck(L, src_image->depth == dst_image->depth, "images must have the same depth"); + imlua_matchsize(L, src_image, dst_image); + + imProcessDifusionErrThreshold(src_image, dst_image, level); + return 0; +} + +/*****************************************************************************\ + im.ProcessPercentThreshold +\*****************************************************************************/ +static int imluaProcessPercentThreshold (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + float percent = (float) luaL_checknumber(L, 3); + + imlua_checktype(L, 1, src_image, IM_GRAY, IM_BYTE); + imlua_checkcolorspace(L, 2, dst_image, IM_BINARY); + imlua_matchsize(L, src_image, dst_image); + + lua_pushboolean(L, imProcessPercentThreshold(src_image, dst_image, percent)); + return 1; +} + +/*****************************************************************************\ + im.ProcessOtsuThreshold +\*****************************************************************************/ +static int imluaProcessOtsuThreshold (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + + imlua_checktype(L, 1, src_image, IM_GRAY, IM_BYTE); + imlua_checkcolorspace(L, 2, dst_image, IM_BINARY); + imlua_matchsize(L, src_image, dst_image); + + lua_pushnumber(L, imProcessOtsuThreshold(src_image, dst_image)); + return 1; +} + +/*****************************************************************************\ + im.ProcessMinMaxThreshold +\*****************************************************************************/ +static int imluaProcessMinMaxThreshold (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + + imlua_checkcolorspace(L, 1, src_image, IM_GRAY); + luaL_argcheck(L, (src_image->data_type < IM_FLOAT), 1, "image data type can be integer only"); + imlua_checkcolorspace(L, 2, dst_image, IM_BINARY); + imlua_matchsize(L, src_image, dst_image); + + lua_pushboolean(L, imProcessMinMaxThreshold(src_image, dst_image)); + return 1; +} + +/*****************************************************************************\ + im.ProcessLocalMaxThresEstimate +\*****************************************************************************/ +static int imluaProcessLocalMaxThresEstimate (lua_State *L) +{ + int thres; + imImage *image = imlua_checkimage(L, 1); + + imlua_checkdatatype(L, 1, image, IM_BYTE); + + imProcessLocalMaxThresEstimate(image, &thres); + + lua_pushnumber(L, thres); + return 1; +} + +/*****************************************************************************\ + im.ProcessSliceThreshold +\*****************************************************************************/ +static int imluaProcessSliceThreshold (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + + int start_level = luaL_checkint(L, 3); + int end_level = luaL_checkint(L, 4); + + imlua_checkcolorspace(L, 1, src_image, IM_GRAY); + luaL_argcheck(L, (src_image->data_type < IM_FLOAT), 1, "image data type can be integer only"); + imlua_checkcolorspace(L, 2, dst_image, IM_BINARY); + imlua_matchsize(L, src_image, dst_image); + + imProcessSliceThreshold(src_image, dst_image, start_level, end_level); + return 0; +} + + +/*****************************************************************************\ + Special Effects +\*****************************************************************************/ + +/*****************************************************************************\ + im.ProcessPixelate +\*****************************************************************************/ +static int imluaProcessPixelate (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + int box_size = luaL_checkint(L, 3); + + imlua_checkdatatype(L, 1, src_image, IM_BYTE); + imlua_match(L, src_image, dst_image); + + imProcessPixelate(src_image, dst_image, box_size); + return 0; +} + +/*****************************************************************************\ + im.ProcessPosterize +\*****************************************************************************/ +static int imluaProcessPosterize (lua_State *L) +{ + imImage *src_image = imlua_checkimage(L, 1); + imImage *dst_image = imlua_checkimage(L, 2); + int level = luaL_checkint(L, 3); + + imlua_checkdatatype(L, 1, src_image, IM_BYTE); + imlua_match(L, src_image, dst_image); + luaL_argcheck(L, (level >= 1 && level <= 7), 3, "invalid level, must be >=1 and <=7"); + + imProcessPosterize(src_image, dst_image, level); + return 0; +} + + + +static const luaL_reg improcess_lib[] = { + {"CalcRMSError", imluaCalcRMSError}, + {"CalcSNR", imluaCalcSNR}, + {"CalcCountColors", imluaCalcCountColors}, + {"CalcHistogram", imluaCalcHistogram}, + /*{"CalcUShortHistogram", imluaCalcUShortHistogram}, done by imluaCalcHistogram */ + {"CalcGrayHistogram", imluaCalcGrayHistogram}, + {"CalcImageStatistics", imluaCalcImageStatistics}, + {"CalcHistogramStatistics", imluaCalcHistogramStatistics}, + {"CalcHistoImageStatistics", imluaCalcHistoImageStatistics}, + + {"AnalyzeFindRegions", imluaAnalyzeFindRegions}, + {"AnalyzeMeasureArea", imluaAnalyzeMeasureArea}, + {"AnalyzeMeasurePerimArea", imluaAnalyzeMeasurePerimArea}, + {"AnalyzeMeasureCentroid", imluaAnalyzeMeasureCentroid}, + {"AnalyzeMeasurePrincipalAxis", imluaAnalyzeMeasurePrincipalAxis}, + {"AnalyzeMeasurePerimeter", imluaAnalyzeMeasurePerimeter}, + {"AnalyzeMeasureHoles", imluaAnalyzeMeasureHoles}, + + {"ProcessPerimeterLine", imluaProcessPerimeterLine}, + {"ProcessRemoveByArea", imluaProcessRemoveByArea}, + {"ProcessFillHoles", imluaProcessFillHoles}, + + {"ProcessHoughLines", imluaProcessHoughLines}, + {"ProcessHoughLinesDraw", imluaProcessHoughLinesDraw}, + {"ProcessDistanceTransform", imluaProcessDistanceTransform}, + {"ProcessRegionalMaximum", imluaProcessRegionalMaximum}, + + {"ProcessReduce", imluaProcessReduce}, + {"ProcessResize", imluaProcessResize}, + {"ProcessReduceBy4", imluaProcessReduceBy4}, + {"ProcessCrop", imluaProcessCrop}, + {"ProcessAddMargins", imluaProcessAddMargins}, + {"ProcessInsert", imluaProcessInsert}, + + {"ProcessCalcRotateSize", imluaProcessCalcRotateSize}, + {"ProcessRotate", imluaProcessRotate}, + {"ProcessRotateRef", imluaProcessRotateRef}, + {"ProcessRotate90", imluaProcessRotate90}, + {"ProcessRotate180", imluaProcessRotate180}, + {"ProcessMirror", imluaProcessMirror}, + {"ProcessFlip", imluaProcessFlip}, + {"ProcessRadial", imluaProcessRadial}, + {"ProcessSwirl", imluaProcessSwirl}, + {"ProcessInterlaceSplit", imluaProcessInterlaceSplit}, + + {"ProcessGrayMorphConvolve", imluaProcessGrayMorphConvolve}, + {"ProcessGrayMorphErode", imluaProcessGrayMorphErode}, + {"ProcessGrayMorphDilate", imluaProcessGrayMorphDilate}, + {"ProcessGrayMorphOpen", imluaProcessGrayMorphOpen}, + {"ProcessGrayMorphClose", imluaProcessGrayMorphClose}, + {"ProcessGrayMorphTopHat", imluaProcessGrayMorphTopHat}, + {"ProcessGrayMorphWell", imluaProcessGrayMorphWell}, + {"ProcessGrayMorphGradient", imluaProcessGrayMorphGradient}, + + {"ProcessBinMorphConvolve", imluaProcessBinMorphConvolve}, + {"ProcessBinMorphErode", imluaProcessBinMorphErode}, + {"ProcessBinMorphDilate", imluaProcessBinMorphDilate}, + {"ProcessBinMorphOpen", imluaProcessBinMorphOpen}, + {"ProcessBinMorphClose", imluaProcessBinMorphClose}, + {"ProcessBinMorphOutline", imluaProcessBinMorphOutline}, + {"ProcessBinMorphThin", imluaProcessBinMorphThin}, + + {"ProcessMedianConvolve", imluaProcessMedianConvolve}, + {"ProcessRangeConvolve", imluaProcessRangeConvolve}, + {"ProcessRankClosestConvolve", imluaProcessRankClosestConvolve}, + {"ProcessRankMaxConvolve", imluaProcessRankMaxConvolve}, + {"ProcessRankMinConvolve", imluaProcessRankMinConvolve}, + + {"ProcessConvolve", imluaProcessConvolve}, + {"ProcessConvolveDual", imluaProcessConvolveDual}, + {"ProcessConvolveRep", imluaProcessConvolveRep}, + {"ProcessConvolveSep", imluaProcessConvolveSep}, + {"ProcessCompassConvolve", imluaProcessCompassConvolve}, + {"ProcessRotateKernel", imluaProcessRotateKernel}, + {"ProcessDiffOfGaussianConvolve", imluaProcessDiffOfGaussianConvolve}, + {"ProcessLapOfGaussianConvolve", imluaProcessLapOfGaussianConvolve}, + {"ProcessMeanConvolve", imluaProcessMeanConvolve}, + {"ProcessBarlettConvolve", imluaProcessBarlettConvolve}, + {"ProcessGaussianConvolve", imluaProcessGaussianConvolve}, + {"ProcessSobelConvolve", imluaProcessSobelConvolve}, + {"ProcessPrewittConvolve", imluaProcessPrewittConvolve}, + {"ProcessSplineEdgeConvolve", imluaProcessSplineEdgeConvolve}, + {"ProcessZeroCrossing", imluaProcessZeroCrossing}, + {"ProcessCanny", imluaProcessCanny}, + {"ProcessUnsharp", imluaProcessUnsharp}, + {"ProcessSharp", imluaProcessSharp}, + {"ProcessSharpKernel", imluaProcessSharpKernel}, + {"GaussianKernelSize2StdDev", imluaGaussianKernelSize2StdDev}, + {"GaussianStdDev2KernelSize", imluaGaussianStdDev2KernelSize}, + + {"ProcessUnArithmeticOp", imluaProcessUnArithmeticOp}, + {"ProcessArithmeticOp", imluaProcessArithmeticOp}, + {"ProcessArithmeticConstOp", imluaProcessArithmeticConstOp}, + {"ProcessBlendConst", imluaProcessBlendConst}, + {"ProcessBlend", imluaProcessBlend}, + {"ProcessSplitComplex", imluaProcessSplitComplex}, + {"ProcessMergeComplex", imluaProcessMergeComplex}, + {"ProcessMultipleMean", imluaProcessMultipleMean}, + {"ProcessMultipleStdDev", imluaProcessMultipleStdDev}, + {"ProcessAutoCovariance", imluaProcessAutoCovariance}, + {"ProcessMultiplyConj", imluaProcessMultiplyConj}, + + {"ProcessQuantizeRGBUniform", imluaProcessQuantizeRGBUniform}, + {"ProcessQuantizeGrayUniform", imluaProcessQuantizeGrayUniform}, + + {"ProcessExpandHistogram", imluaProcessExpandHistogram}, + {"ProcessEqualizeHistogram", imluaProcessEqualizeHistogram}, + + {"ProcessSplitYChroma", imluaProcessSplitYChroma}, + {"ProcessSplitHSI", imluaProcessSplitHSI}, + {"ProcessMergeHSI", imluaProcessMergeHSI}, + {"ProcessSplitComponents", imluaProcessSplitComponents}, + {"ProcessMergeComponents", imluaProcessMergeComponents}, + {"ProcessNormalizeComponents", imluaProcessNormalizeComponents}, + {"ProcessReplaceColor", imluaProcessReplaceColor}, + + {"ProcessBitwiseOp", imluaProcessBitwiseOp}, + {"ProcessBitwiseNot", imluaProcessBitwiseNot}, + {"ProcessBitMask", imluaProcessBitMask}, + {"ProcessBitPlane", imluaProcessBitPlane}, + + {"ProcessRenderOp", imluaProcessRenderOp}, + {"ProcessRenderCondOp", imluaProcessRenderCondOp}, + {"ProcessRenderAddSpeckleNoise", imluaProcessRenderAddSpeckleNoise}, + {"ProcessRenderAddGaussianNoise", imluaProcessRenderAddGaussianNoise}, + {"ProcessRenderAddUniformNoise", imluaProcessRenderAddUniformNoise}, + {"ProcessRenderRandomNoise", imluaProcessRenderRandomNoise}, + {"ProcessRenderConstant", imluaProcessRenderConstant}, + {"ProcessRenderWheel", imluaProcessRenderWheel}, + {"ProcessRenderCone", imluaProcessRenderCone}, + {"ProcessRenderTent", imluaProcessRenderTent}, + {"ProcessRenderRamp", imluaProcessRenderRamp}, + {"ProcessRenderBox", imluaProcessRenderBox}, + {"ProcessRenderSinc", imluaProcessRenderSinc}, + {"ProcessRenderGaussian", imluaProcessRenderGaussian}, + {"ProcessRenderLapOfGaussian", imluaProcessRenderLapOfGaussian}, + {"ProcessRenderCosine", imluaProcessRenderCosine}, + {"ProcessRenderGrid", imluaProcessRenderGrid}, + {"ProcessRenderChessboard", imluaProcessRenderChessboard}, + + {"ProcessToneGamut", imluaProcessToneGamut}, + {"ProcessUnNormalize", imluaProcessUnNormalize}, + {"ProcessDirectConv", imluaProcessDirectConv}, + {"ProcessNegative", imluaProcessNegative}, + + {"ProcessRangeContrastThreshold", imluaProcessRangeContrastThreshold}, + {"ProcessLocalMaxThreshold", imluaProcessLocalMaxThreshold}, + {"ProcessThreshold", imluaProcessThreshold}, + {"ProcessThresholdByDiff", imluaProcessThresholdByDiff}, + {"ProcessHysteresisThreshold", imluaProcessHysteresisThreshold}, + {"ProcessHysteresisThresEstimate", imluaProcessHysteresisThresEstimate}, + {"ProcessUniformErrThreshold", imluaProcessUniformErrThreshold}, + {"ProcessDifusionErrThreshold", imluaProcessDifusionErrThreshold}, + {"ProcessPercentThreshold", imluaProcessPercentThreshold}, + {"ProcessOtsuThreshold", imluaProcessOtsuThreshold}, + {"ProcessMinMaxThreshold", imluaProcessMinMaxThreshold}, + {"ProcessLocalMaxThresEstimate", imluaProcessLocalMaxThresEstimate}, + {"ProcessSliceThreshold", imluaProcessSliceThreshold}, + + {"ProcessPixelate", imluaProcessPixelate}, + {"ProcessPosterize", imluaProcessPosterize}, + + {NULL, NULL} +}; + +/*****************************************************************************\ + Constants +\*****************************************************************************/ +static const imlua_constant im_process_constants[] = { + + { "UN_EQL", IM_UN_EQL, NULL }, + { "UN_ABS", IM_UN_ABS, NULL }, + { "UN_LESS", IM_UN_LESS, NULL }, + { "UN_INV", IM_UN_INV, NULL }, + { "UN_SQR", IM_UN_SQR, NULL }, + { "UN_SQRT", IM_UN_SQRT, NULL }, + { "UN_LOG", IM_UN_LOG, NULL }, + { "UN_EXP", IM_UN_EXP, NULL }, + { "UN_SIN", IM_UN_SIN, NULL }, + { "UN_COS", IM_UN_COS, NULL }, + { "UN_CONJ", IM_UN_CONJ, NULL }, + { "UN_CPXNORM", IM_UN_CPXNORM, NULL }, + + { "BIN_ADD", IM_BIN_ADD, NULL }, + { "BIN_SUB", IM_BIN_SUB, NULL }, + { "BIN_MUL", IM_BIN_MUL, NULL }, + { "BIN_DIV", IM_BIN_DIV, NULL }, + { "BIN_DIFF", IM_BIN_DIFF, NULL }, + { "BIN_POW", IM_BIN_POW, NULL }, + { "BIN_MIN", IM_BIN_MIN, NULL }, + { "BIN_MAX", IM_BIN_MAX, NULL }, + + { "BIT_AND", IM_BIT_AND, NULL }, + { "BIT_OR", IM_BIT_OR, NULL }, + { "BIT_XOR", IM_BIT_XOR, NULL }, + + { "GAMUT_NORMALIZE", IM_GAMUT_NORMALIZE, NULL }, + { "GAMUT_POW", IM_GAMUT_POW, NULL }, + { "GAMUT_LOG", IM_GAMUT_LOG, NULL }, + { "GAMUT_EXP", IM_GAMUT_EXP, NULL }, + { "GAMUT_INVERT", IM_GAMUT_INVERT, NULL }, + { "GAMUT_ZEROSTART", IM_GAMUT_ZEROSTART, NULL }, + { "GAMUT_SOLARIZE", IM_GAMUT_SOLARIZE, NULL }, + { "GAMUT_SLICE", IM_GAMUT_SLICE, NULL }, + { "GAMUT_EXPAND", IM_GAMUT_EXPAND, NULL }, + { "GAMUT_CROP", IM_GAMUT_CROP, NULL }, + { "GAMUT_BRIGHTCONT", IM_GAMUT_BRIGHTCONT, NULL }, + + { NULL, -1, NULL }, +}; + +/* from imlua_kernel.c */ +void imlua_open_kernel(lua_State *L); + +int imlua_open_process(lua_State *L) +{ + luaL_register(L, "im", improcess_lib); /* leave "im" table at the top of the stack */ + imlua_regconstants(L, im_process_constants); +#ifdef TEC_BIGENDIAN +#ifdef TEC_64 +#include "loh/im_process_be64.loh" +#else +#include "loh/im_process_be32.loh" +#endif +#else +#ifdef TEC_64 +#ifdef WIN64 +#include "loh/im_process_le64w.loh" +#else +#include "loh/im_process_le64.loh" +#endif +#else +#include "loh/im_process.loh" +#endif +#endif + imlua_open_kernel(L); + return 1; +} + +int luaopen_imlua_process(lua_State *L) +{ + return imlua_open_process(L); +} + +int luaopen_imlua_process51(lua_State *L) +{ + return imlua_open_process(L); +} diff --git a/im/src/lua5/imlua_process.def b/im/src/lua5/imlua_process.def new file mode 100755 index 0000000..2b77e77 --- /dev/null +++ b/im/src/lua5/imlua_process.def @@ -0,0 +1,4 @@ +EXPORTS + imlua_open_process + luaopen_imlua_process + luaopen_imlua_process51 \ No newline at end of file diff --git a/im/src/lua5/imlua_util.c b/im/src/lua5/imlua_util.c new file mode 100755 index 0000000..69cfb19 --- /dev/null +++ b/im/src/lua5/imlua_util.c @@ -0,0 +1,279 @@ +/** \file + * \brief IM Lua 5 Binding + * + * See Copyright Notice in im_lib.h + * $Id: imlua_util.c,v 1.1 2008/10/17 06:16:32 scuri Exp $ + */ + +#include "im.h" +#include "im_util.h" +#include "im_image.h" + +#include +#include + +#include "imlua.h" +#include "imlua_aux.h" + +/*****************************************************************************\ + im.ImageDataSize(width, height, color_mode, data_type) +\*****************************************************************************/ +static int imluaImageDataSize (lua_State *L) +{ + int width = luaL_checkint(L, 1); + int height = luaL_checkint(L, 2); + int color_mode = luaL_checkint(L, 3); + int data_type = luaL_checkint(L, 4); + + lua_pushnumber(L, imImageDataSize(width, height, color_mode, data_type)); + return 1; +} + +/*****************************************************************************\ + im.ImageLineSize(width, color_mode, data_type) +\*****************************************************************************/ +static int imluaImageLineSize (lua_State *L) +{ + int width = luaL_checkint(L, 1); + int color_mode = luaL_checkint(L, 2); + int data_type = luaL_checkint(L, 3); + + lua_pushnumber(L, imImageLineSize(width, color_mode, data_type)); + return 1; +} + +/*****************************************************************************\ + im.ImageLineCount(width, color_mode) +\*****************************************************************************/ +static int imluaImageLineCount (lua_State *L) +{ + int width = luaL_checkint(L, 1); + int color_mode = luaL_checkint(L, 2); + + lua_pushnumber(L, imImageLineCount(width, color_mode)); + return 1; +} + +/*****************************************************************************\ + im.ImageCheckFormat(width, color_mode) +\*****************************************************************************/ +static int imluaImageCheckFormat (lua_State *L) +{ + int color_mode = luaL_checkint(L, 1); + int data_type = luaL_checkint(L, 2); + + lua_pushboolean(L, imImageCheckFormat(color_mode, data_type)); + return 1; +} + +/*****************************************************************************\ + im.ColorModeSpaceName(color_mode) +\*****************************************************************************/ +static int imluaColorModeSpaceName (lua_State *L) +{ + lua_pushstring(L, imColorModeSpaceName(luaL_checkint(L, 1))); + return 1; +} + +/*****************************************************************************\ + im.ColorModeDepth(color_mode) +\*****************************************************************************/ +static int imluaColorModeDepth (lua_State *L) +{ + lua_pushnumber(L, imColorModeDepth(luaL_checkint(L, 1))); + return 1; +} + +/*****************************************************************************\ + +\*****************************************************************************/ + +/*****************************************************************************\ + im.ColorModeSpace(color_mode) +\*****************************************************************************/ +static int imluaColorModeSpace (lua_State *L) +{ + lua_pushnumber(L, imColorModeSpace(luaL_checkint(L, 1))); + return 1; +} + +/*****************************************************************************\ + im.ColorModeHasAlpha(color_mode) +\*****************************************************************************/ +static int imluaColorModeMatch (lua_State *L) +{ + lua_pushboolean(L, imColorModeMatch(luaL_checkint(L, 1), luaL_checkint(L, 1))); + return 1; +} + +/*****************************************************************************\ + im.ColorModeHasAlpha(color_mode) +\*****************************************************************************/ +static int imluaColorModeHasAlpha (lua_State *L) +{ + lua_pushboolean(L, imColorModeHasAlpha(luaL_checkint(L, 1))); + return 1; +} + +/*****************************************************************************\ + im.ColorModeIsPacked(color_mode) +\*****************************************************************************/ +static int imluaColorModeIsPacked (lua_State *L) +{ + lua_pushboolean(L, imColorModeIsPacked(luaL_checkint(L, 1))); + return 1; +} + +/*****************************************************************************\ + im.ColorModeIsTopDown(color_mode) +\*****************************************************************************/ +static int imluaColorModeIsTopDown (lua_State *L) +{ + lua_pushboolean(L, imColorModeIsTopDown(luaL_checkint(L, 1))); + return 1; +} + +/*****************************************************************************\ + im.ColorModeToBitmap(color_mode) +\*****************************************************************************/ +static int imluaColorModeToBitmap (lua_State *L) +{ + lua_pushnumber(L, imColorModeToBitmap(luaL_checkint(L, 1))); + return 1; +} + +/*****************************************************************************\ + im.ColorModeIsBitmap +\*****************************************************************************/ +static int imluaColorModeIsBitmap (lua_State *L) +{ + int color_mode = luaL_checkint(L, 1); + int data_type = luaL_checkint(L, 2); + + lua_pushboolean(L, imColorModeIsBitmap(color_mode, data_type)); + return 1; +} + +/*****************************************************************************\ + im.DataTypeSize(data_type) +\*****************************************************************************/ +static int imluaDataTypeSize (lua_State *L) +{ + lua_pushnumber(L, imDataTypeSize(luaL_checkint(L, 1))); + return 1; +} + +/*****************************************************************************\ + im.DataTypeName(data_type) +\*****************************************************************************/ +static int imluaDataTypeName (lua_State *L) +{ + lua_pushstring(L, imDataTypeName(luaL_checkint(L, 1))); + return 1; +} + +/*****************************************************************************\ + im.DataTypeIntMax(data_type) +\*****************************************************************************/ +static int imluaDataTypeIntMax(lua_State *L) +{ + lua_pushnumber(L, imDataTypeIntMax(luaL_checkint(L, 1))); + return 1; +} + +/*****************************************************************************\ + im.DataTypeIntMin(data_type) +\*****************************************************************************/ +static int imluaDataTypeIntMin(lua_State *L) +{ + lua_pushnumber(L, imDataTypeIntMin(luaL_checkint(L, 1))); + return 1; +} + +/***************************************************************************\ +* Creates a color as a light userdata. The color value is * +* placed in the (void *) value. Not beautiful, but works best. * +* im.ColorEncode(r, g, b: number) -> (c: color) * +\***************************************************************************/ +static int imlua_colorencode(lua_State *L) +{ + int red_f, green_f, blue_f; + unsigned char red_i, green_i, blue_i; + long int color_i; + + red_f = luaL_checkint(L, 1); + green_f = luaL_checkint(L, 2); + blue_f = luaL_checkint(L, 3); + + if (red_f < 0 || red_f > 255) + luaL_argerror(L, 1, "color components values should be in range [0, 255]"); + if (green_f < 0 || green_f > 255) + luaL_argerror(L, 2, "color components values should be in range [0, 255]"); + if (blue_f < 0 || blue_f > 255) + luaL_argerror(L, 3, "color components values should be in range [0, 255]"); + + red_i = (unsigned char) (red_f); + green_i = (unsigned char) (green_f); + blue_i = (unsigned char) (blue_f); + + color_i = imColorEncode(red_i, green_i, blue_i); + lua_pushlightuserdata(L, (void *)color_i); + + return 1; +} + +/***************************************************************************\ +* Decodes a color previously created. * +* im.ColorDecode(c: color) -> (r, g, b: number) * +\***************************************************************************/ +static int imlua_colordecode(lua_State *L) +{ + long int color_i; + unsigned char red_i, green_i, blue_i; + + if (!lua_islightuserdata(L, 1)) + luaL_argerror(L, 1, "color must be a light user data"); + + color_i = (long int) lua_touserdata(L,1); + + imColorDecode(&red_i, &green_i, &blue_i, color_i); + lua_pushnumber(L, red_i); + lua_pushnumber(L, green_i); + lua_pushnumber(L, blue_i); + + return 3; +} + +static const luaL_reg imutil_lib[] = { + {"ImageDataSize", imluaImageDataSize}, + {"ImageLineSize", imluaImageLineSize}, + {"ImageLineCount", imluaImageLineCount}, + {"ImageCheckFormat", imluaImageCheckFormat}, + + {"ColorModeSpace", imluaColorModeSpace}, + {"ColorModeSpaceName", imluaColorModeSpaceName}, + {"ColorModeDepth", imluaColorModeDepth}, + + {"ColorModeToBitmap", imluaColorModeToBitmap}, + {"ColorModeIsBitmap", imluaColorModeIsBitmap}, + {"ColorModeMatch", imluaColorModeMatch}, + {"ColorModeHasAlpha", imluaColorModeHasAlpha}, + {"ColorModeIsPacked", imluaColorModeIsPacked}, + {"ColorModeIsTopDown", imluaColorModeIsTopDown}, + + {"DataTypeSize", imluaDataTypeSize}, + {"DataTypeName", imluaDataTypeName}, + {"DataTypeIntMax", imluaDataTypeIntMax}, + {"DataTypeIntMin", imluaDataTypeIntMin}, + + {"ColorEncode", imlua_colorencode}, + {"ColorDecode", imlua_colordecode}, + + {NULL, NULL} +}; + +void imlua_open_util(lua_State *L) +{ + /* "im" table is at the top of the stack */ + luaL_register(L, NULL, imutil_lib); +} diff --git a/im/src/lua5/imlua_wmv.c b/im/src/lua5/imlua_wmv.c new file mode 100755 index 0000000..7f61030 --- /dev/null +++ b/im/src/lua5/imlua_wmv.c @@ -0,0 +1,44 @@ +/** \file + * \brief wmv format Lua 5 Binding + * + * See Copyright Notice in cd.h + */ + +#include +#include + +#include "im_format_wmv.h" + +#include +#include + + +static int imlua_FormatRegisterWMV(lua_State *L) +{ + (void)L; + imFormatRegisterWMV(); + return 0; +} + +static const struct luaL_reg imlib[] = { + {"FormatRegisterWMV", imlua_FormatRegisterWMV}, + {NULL, NULL}, +}; + + +static int imlua_wmv_open (lua_State *L) +{ + imFormatRegisterWMV(); + luaL_register(L, "im", imlib); /* leave "im" table at the top of the stack */ + return 1; +} + +int luaopen_imlua_wmv(lua_State* L) +{ + return imlua_wmv_open(L); +} + +int luaopen_imlua_wmv51(lua_State* L) +{ + return imlua_wmv_open(L); +} diff --git a/im/src/lua5/imlua_wmv.def b/im/src/lua5/imlua_wmv.def new file mode 100755 index 0000000..0c05563 --- /dev/null +++ b/im/src/lua5/imlua_wmv.def @@ -0,0 +1,4 @@ +EXPORTS + luaopen_imlua_wmv + luaopen_imlua_wmv51 + \ No newline at end of file diff --git a/im/src/lua5/loh/im_convert.loh b/im/src/lua5/loh/im_convert.loh new file mode 100644 index 0000000..7d4b03f --- /dev/null +++ b/im/src/lua5/loh/im_convert.loh @@ -0,0 +1,87 @@ +/* code automatically generated by bin2c -- DO NOT EDIT */ +{ +/* #include'ing this file in a C program is equivalent to calling + if (luaL_loadfile(L,"../obj/imlua51/im_convert.lo")==0) lua_call(L, 0, 0); +*/ +/* ../obj/imlua51/im_convert.lo */ +static const unsigned char B1[]={ + 27, 76,117, 97, 81, 0, 1, 4, 4, 4, 8, 0, 21, 0, 0, 0, 64,108,117, 97, + 53, 47,105,109, 95, 99,111,110,118,101,114,116, 46,108,117, 97, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2, 2, 10, 0, 0, 0, 5, 0, 0, 0,100, 0, 0, + 0, 9, 64,128,128, 5, 0, 0, 0,100, 64, 0, 0, 9, 64, 0,129, 5, 0, 0, + 0,100,128, 0, 0, 9, 64,128,129, 30, 0,128, 0, 4, 0, 0, 0, 4, 3, 0, + 0, 0,105,109, 0, 4, 19, 0, 0, 0, 67,111,110,118,101,114,116, 68, 97,116, + 97, 84,121,112,101, 78,101,119, 0, 4, 21, 0, 0, 0, 67,111,110,118,101,114, +116, 67,111,108,111,114, 83,112, 97, 99,101, 78,101,119, 0, 4, 19, 0, 0, 0, + 67,111,110,118,101,114,116, 84,111, 66,105,116,109, 97,112, 78,101,119, 0, 3, + 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 0, 6, 0, 14, 18, + 0, 0, 0,133, 1, 0, 0,134, 65, 64, 3,192, 1, 0, 0, 3, 2, 0, 5,192, + 2,128, 0,156,129, 0, 3,197, 1, 0, 0,198,129,192, 3, 0, 2, 0, 0, 64, + 2, 0, 3,128, 2, 0, 1,192, 2,128, 1, 0, 3, 0, 2, 64, 3,128, 2,220, +129,128, 3, 0, 2, 0, 3,222, 1,128, 1, 30, 0,128, 0, 3, 0, 0, 0, 4, + 3, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, 73,109, 97,103,101, 67,114,101, + 97,116,101, 66, 97,115,101,100, 0, 4, 16, 0, 0, 0, 67,111,110,118,101,114, +116, 68, 97,116, 97, 84,121,112,101, 0, 0, 0, 0, 0, 18, 0, 0, 0, 3, 0, + 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, + 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 7, 0, 0, 0, 10, 0, 0, 0,115,114, + 99, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 17, 0, 0, 0, 10, 0, 0, 0, +100, 97,116, 97, 95,116,121,112,101, 0, 0, 0, 0, 0, 17, 0, 0, 0, 9, 0, + 0, 0, 99,112,120, 50,114,101, 97,108, 0, 0, 0, 0, 0, 17, 0, 0, 0, 6, + 0, 0, 0,103, 97,109,109, 97, 0, 0, 0, 0, 0, 17, 0, 0, 0, 10, 0, 0, + 0, 97, 98,115,115,111,108,117,116,101, 0, 0, 0, 0, 0, 17, 0, 0, 0, 10, + 0, 0, 0, 99, 97,115,116, 95,109,111,100,101, 0, 0, 0, 0, 0, 17, 0, 0, + 0, 10, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 0, 6, 0, 0, 0, 17, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 11, 0, 0, 0, 0, + 3, 0, 8, 18, 0, 0, 0,197, 0, 0, 0,198, 64,192, 1, 0, 1, 0, 0, 67, + 1, 0, 3,192, 1,128, 0,220,128,128, 2,154, 0, 0, 0, 22, 64, 0,128, 11, +129,192, 1, 28, 65, 0, 1, 5, 1, 0, 0, 6,193, 64, 2, 64, 1, 0, 0,128, + 1,128, 1, 28,129,128, 1, 64, 1,128, 1, 30, 1,128, 1, 30, 0,128, 0, 4, + 0, 0, 0, 4, 3, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, 73,109, 97,103, +101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 4, 9, 0, 0, 0, 65,100, +100, 65,108,112,104, 97, 0, 4, 18, 0, 0, 0, 67,111,110,118,101,114,116, 67, +111,108,111,114, 83,112, 97, 99,101, 0, 0, 0, 0, 0, 18, 0, 0, 0, 8, 0, + 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, + 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 10, 0, + 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, + 0, 0, 10, 0, 0, 0, 11, 0, 0, 0, 4, 0, 0, 0, 10, 0, 0, 0,115,114, + 99, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 17, 0, 0, 0, 12, 0, 0, 0, + 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 0, 0, 0, 0, 17, 0, 0, 0, + 10, 0, 0, 0,104, 97,115, 95, 97,108,112,104, 97, 0, 0, 0, 0, 0, 17, 0, + 0, 0, 10, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 0, 6, 0, 0, 0, + 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 18, 0, 0, 0, + 0, 7, 0, 15, 30, 0, 0, 0, 90, 64, 0, 0, 22, 64, 1,128,197, 1, 0, 0, +198, 65,192, 3, 11,130, 64, 0, 28, 2, 0, 1,220,129, 0, 0, 64, 0,128, 3, +197, 1, 0, 0,198,193,192, 3, 0, 2, 0, 0, 67, 2, 0, 5,192, 2,128, 0, +220,129,128, 2,154, 0, 0, 0, 22, 64, 0,128, 11, 2,193, 3, 28, 66, 0, 1, + 5, 2, 0, 0, 6, 66, 65, 4, 64, 2, 0, 0,128, 2,128, 3,192, 2,128, 1, + 0, 3, 0, 2, 64, 3,128, 2,128, 3, 0, 3, 28,130,128, 3, 64, 2,128, 3, + 30, 2,128, 1, 30, 0,128, 0, 6, 0, 0, 0, 4, 3, 0, 0, 0,105,109, 0, + 4, 18, 0, 0, 0, 67,111,108,111,114, 77,111,100,101, 84,111, 66,105,116,109, + 97,112, 0, 4, 11, 0, 0, 0, 67,111,108,111,114, 83,112, 97, 99,101, 0, 4, + 17, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, + 0, 4, 9, 0, 0, 0, 65,100,100, 65,108,112,104, 97, 0, 4, 16, 0, 0, 0, + 67,111,110,118,101,114,116, 84,111, 66,105,116,109, 97,112, 0, 0, 0, 0, 0, + 30, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, + 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 15, 0, 0, 0, + 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, + 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 17, 0, 0, 0, + 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, + 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, + 18, 0, 0, 0, 8, 0, 0, 0, 10, 0, 0, 0,115,114, 99, 95,105,109, 97,103, +101, 0, 0, 0, 0, 0, 29, 0, 0, 0, 12, 0, 0, 0, 99,111,108,111,114, 95, +115,112, 97, 99,101, 0, 0, 0, 0, 0, 29, 0, 0, 0, 10, 0, 0, 0,104, 97, +115, 95, 97,108,112,104, 97, 0, 0, 0, 0, 0, 29, 0, 0, 0, 9, 0, 0, 0, + 99,112,120, 50,114,101, 97,108, 0, 0, 0, 0, 0, 29, 0, 0, 0, 6, 0, 0, + 0,103, 97,109,109, 97, 0, 0, 0, 0, 0, 29, 0, 0, 0, 10, 0, 0, 0, 97, + 98,115,115,111,108,117,116,101, 0, 0, 0, 0, 0, 29, 0, 0, 0, 10, 0, 0, + 0, 99, 97,115,116, 95,109,111,100,101, 0, 0, 0, 0, 0, 29, 0, 0, 0, 10, + 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 0, 14, 0, 0, 0, 29, 0, 0, + 0, 0, 0, 0, 0, 10, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 2, 0, 0, + 0, 7, 0, 0, 0, 11, 0, 0, 0, 7, 0, 0, 0, 13, 0, 0, 0, 18, 0, 0, + 0, 13, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + + if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"../obj/imlua51/im_convert.lo")==0) lua_call(L, 0, 0); +} diff --git a/im/src/lua5/loh/im_convert_be32.loh b/im/src/lua5/loh/im_convert_be32.loh new file mode 100755 index 0000000..eebe1de --- /dev/null +++ b/im/src/lua5/loh/im_convert_be32.loh @@ -0,0 +1,87 @@ +/* code automatically generated by bin2c -- DO NOT EDIT */ +{ +/* #include'ing this file in a C program is equivalent to calling + if (luaL_loadfile(L,"../obj/imlua51/im_convert_be32.lo")==0) lua_call(L, 0, 0); +*/ +/* ../obj/imlua51/im_convert_be32.lo */ +static const unsigned char B1[]={ + 27, 76,117, 97, 81, 0, 0, 4, 4, 4, 8, 0, 0, 0, 0, 21, 64,108,117, 97, + 53, 47,105,109, 95, 99,111,110,118,101,114,116, 46,108,117, 97, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 10, 0, 0, 0, 5, 0, 0, 0, +100,128,128, 64, 9, 0, 0, 0, 5, 0, 0, 64,100,129, 0, 64, 9, 0, 0, 0, + 5, 0, 0,128,100,129,128, 64, 9, 0,128, 0, 30, 0, 0, 0, 4, 4, 0, 0, + 0, 3,105,109, 0, 4, 0, 0, 0, 19, 67,111,110,118,101,114,116, 68, 97,116, + 97, 84,121,112,101, 78,101,119, 0, 4, 0, 0, 0, 21, 67,111,110,118,101,114, +116, 67,111,108,111,114, 83,112, 97, 99,101, 78,101,119, 0, 4, 0, 0, 0, 19, + 67,111,110,118,101,114,116, 84,111, 66,105,116,109, 97,112, 78,101,119, 0, 0, + 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 5, 0, 6, 0, 14, 0, + 0, 0, 18, 0, 0, 1,133, 3, 64, 65,134, 0, 0, 1,192, 5, 0, 2, 3, 0, +128, 2,192, 3, 0,129,156, 0, 0, 1,197, 3,192,129,198, 0, 0, 2, 0, 3, + 0, 2, 64, 1, 0, 2,128, 1,128, 2,192, 2, 0, 3, 0, 2,128, 3, 64, 3, +128,129,220, 3, 0, 2, 0, 1,128, 1,222, 0,128, 0, 30, 0, 0, 0, 3, 4, + 0, 0, 0, 3,105,109, 0, 4, 0, 0, 0, 17, 73,109, 97,103,101, 67,114,101, + 97,116,101, 66, 97,115,101,100, 0, 4, 0, 0, 0, 16, 67,111,110,118,101,114, +116, 68, 97,116, 97, 84,121,112,101, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, + 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, + 0, 3, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, + 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, + 0, 4, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 7, 0, 0, 0, 10,115,114, + 99, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 10, +100, 97,116, 97, 95,116,121,112,101, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, + 0, 9, 99,112,120, 50,114,101, 97,108, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, + 0, 0, 6,103, 97,109,109, 97, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, + 10, 97, 98,115,115,111,108,117,116,101, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, + 0, 0, 10, 99, 97,115,116, 95,109,111,100,101, 0, 0, 0, 0, 0, 0, 0, 0, + 17, 0, 0, 0, 10,100,115,116, 95,105,109, 97,103,101, 0, 0, 0, 0, 6, 0, + 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 11, 0, + 3, 0, 8, 0, 0, 0, 18, 0, 0, 0,197, 1,192, 64,198, 0, 0, 1, 0, 3, + 0, 1, 67, 0,128, 1,192, 2,128,128,220, 0, 0, 0,154,128, 0, 64, 22, 1, +192,129, 11, 1, 0, 65, 28, 0, 0, 1, 5, 2, 64,193, 6, 0, 0, 1, 64, 1, +128, 1,128, 1,128,129, 28, 1,128, 1, 64, 1,128, 1, 30, 0,128, 0, 30, 0, + 0, 0, 4, 4, 0, 0, 0, 3,105,109, 0, 4, 0, 0, 0, 17, 73,109, 97,103, +101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 4, 0, 0, 0, 9, 65,100, +100, 65,108,112,104, 97, 0, 4, 0, 0, 0, 18, 67,111,110,118,101,114,116, 67, +111,108,111,114, 83,112, 97, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, + 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, + 0, 8, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, + 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, + 0, 10, 0, 0, 0, 10, 0, 0, 0, 11, 0, 0, 0, 4, 0, 0, 0, 10,115,114, + 99, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 12, + 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 17, + 0, 0, 0, 10,104, 97,115, 95, 97,108,112,104, 97, 0, 0, 0, 0, 0, 0, 0, + 0, 17, 0, 0, 0, 10,100,115,116, 95,105,109, 97,103,101, 0, 0, 0, 0, 6, + 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 18, + 0, 7, 0, 15, 0, 0, 0, 30, 0, 0, 64, 90,128, 1, 64, 22, 0, 0, 1,197, + 3,192, 65,198, 0, 64,130, 11, 1, 0, 2, 28, 0, 0,129,220, 3,128, 0, 64, + 0, 0, 1,197, 3,192,193,198, 0, 0, 2, 0, 5, 0, 2, 67, 0,128, 2,192, + 2,128,129,220, 0, 0, 0,154,128, 0, 64, 22, 3,193, 2, 11, 1, 0, 66, 28, + 0, 0, 2, 5, 4, 65, 66, 6, 0, 0, 2, 64, 3,128, 2,128, 1,128, 2,192, + 2, 0, 3, 0, 2,128, 3, 64, 3, 0, 3,128, 3,128,130, 28, 3,128, 2, 64, + 1,128, 2, 30, 0,128, 0, 30, 0, 0, 0, 6, 4, 0, 0, 0, 3,105,109, 0, + 4, 0, 0, 0, 18, 67,111,108,111,114, 77,111,100,101, 84,111, 66,105,116,109, + 97,112, 0, 4, 0, 0, 0, 11, 67,111,108,111,114, 83,112, 97, 99,101, 0, 4, + 0, 0, 0, 17, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, + 0, 4, 0, 0, 0, 9, 65,100,100, 65,108,112,104, 97, 0, 4, 0, 0, 0, 16, + 67,111,110,118,101,114,116, 84,111, 66,105,116,109, 97,112, 0, 0, 0, 0, 0, + 0, 0, 0, 30, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, + 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 15, + 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, + 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 17, + 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, + 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, + 0, 0, 0, 18, 0, 0, 0, 8, 0, 0, 0, 10,115,114, 99, 95,105,109, 97,103, +101, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 12, 99,111,108,111,114, 95, +115,112, 97, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 10,104, 97, +115, 95, 97,108,112,104, 97, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 9, + 99,112,120, 50,114,101, 97,108, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, + 6,103, 97,109,109, 97, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 10, 97, + 98,115,115,111,108,117,116,101, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, + 10, 99, 97,115,116, 95,109,111,100,101, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, + 0, 0, 10,100,115,116, 95,105,109, 97,103,101, 0, 0, 0, 0, 14, 0, 0, 0, + 29, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, + 2, 0, 0, 0, 7, 0, 0, 0, 11, 0, 0, 0, 7, 0, 0, 0, 13, 0, 0, 0, + 18, 0, 0, 0, 13, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, +}; + + if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"../obj/imlua51/im_convert_be32.lo")==0) lua_call(L, 0, 0); +} diff --git a/im/src/lua5/loh/im_convert_be64.loh b/im/src/lua5/loh/im_convert_be64.loh new file mode 100644 index 0000000..52c5ec4 --- /dev/null +++ b/im/src/lua5/loh/im_convert_be64.loh @@ -0,0 +1,95 @@ +/* code automatically generated by bin2c -- DO NOT EDIT */ +{ +/* #include'ing this file in a C program is equivalent to calling + if (luaL_loadfile(L,"../obj/imlua51/im_convert_be64.lo")==0) lua_call(L, 0, 0); +*/ +/* ../obj/imlua51/im_convert_be64.lo */ +static const unsigned char B1[]={ + 27, 76,117, 97, 81, 0, 1, 4, 8, 4, 8, 0, 21, 0, 0, 0, 0, 0, 0, 0, + 64,108,117, 97, 53, 47,105,109, 95, 99,111,110,118,101,114,116, 46,108,117, 97, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 10, 0, 0, 0, 5, 0, 0, + 0,100, 0, 0, 0, 9, 64,128,128, 5, 0, 0, 0,100, 64, 0, 0, 9, 64, 0, +129, 5, 0, 0, 0,100,128, 0, 0, 9, 64,128,129, 30, 0,128, 0, 4, 0, 0, + 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 19, 0, 0, 0, 0, 0, + 0, 0, 67,111,110,118,101,114,116, 68, 97,116, 97, 84,121,112,101, 78,101,119, + 0, 4, 21, 0, 0, 0, 0, 0, 0, 0, 67,111,110,118,101,114,116, 67,111,108, +111,114, 83,112, 97, 99,101, 78,101,119, 0, 4, 19, 0, 0, 0, 0, 0, 0, 0, + 67,111,110,118,101,114,116, 84,111, 66,105,116,109, 97,112, 78,101,119, 0, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 0, + 6, 0, 14, 18, 0, 0, 0,133, 1, 0, 0,134, 65, 64, 3,192, 1, 0, 0, 3, + 2, 0, 5,192, 2,128, 0,156,129, 0, 3,197, 1, 0, 0,198,129,192, 3, 0, + 2, 0, 0, 64, 2, 0, 3,128, 2, 0, 1,192, 2,128, 1, 0, 3, 0, 2, 64, + 3,128, 2,220,129,128, 3, 0, 2, 0, 3,222, 1,128, 1, 30, 0,128, 0, 3, + 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, + 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, + 0, 4, 16, 0, 0, 0, 0, 0, 0, 0, 67,111,110,118,101,114,116, 68, 97,116, + 97, 84,121,112,101, 0, 0, 0, 0, 0, 18, 0, 0, 0, 3, 0, 0, 0, 3, 0, + 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, + 0, 0, 5, 0, 0, 0, 7, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,115,114, + 99, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 17, 0, 0, 0, 10, 0, 0, 0, + 0, 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, 0, 0, 0, 0, 0, 17, 0, + 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 99,112,120, 50,114,101, 97,108, 0, 0, + 0, 0, 0, 17, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,103, 97,109,109, 97, + 0, 0, 0, 0, 0, 17, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 97, 98,115, +115,111,108,117,116,101, 0, 0, 0, 0, 0, 17, 0, 0, 0, 10, 0, 0, 0, 0, + 0, 0, 0, 99, 97,115,116, 95,109,111,100,101, 0, 0, 0, 0, 0, 17, 0, 0, + 0, 10, 0, 0, 0, 0, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 0, 6, + 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, + 0, 0, 0, 11, 0, 0, 0, 0, 3, 0, 8, 18, 0, 0, 0,197, 0, 0, 0,198, + 64,192, 1, 0, 1, 0, 0, 67, 1, 0, 3,192, 1,128, 0,220,128,128, 2,154, + 0, 0, 0, 22, 64, 0,128, 11,129,192, 1, 28, 65, 0, 1, 5, 1, 0, 0, 6, +193, 64, 2, 64, 1, 0, 0,128, 1,128, 1, 28,129,128, 1, 64, 1,128, 1, 30, + 1,128, 1, 30, 0,128, 0, 4, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0, +105,109, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, + 97,116,101, 66, 97,115,101,100, 0, 4, 9, 0, 0, 0, 0, 0, 0, 0, 65,100, +100, 65,108,112,104, 97, 0, 4, 18, 0, 0, 0, 0, 0, 0, 0, 67,111,110,118, +101,114,116, 67,111,108,111,114, 83,112, 97, 99,101, 0, 0, 0, 0, 0, 18, 0, + 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, + 0, 0, 8, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, + 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, + 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 11, 0, 0, 0, 4, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, + 17, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 99,111,108,111,114, 95,115,112, + 97, 99,101, 0, 0, 0, 0, 0, 17, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, +104, 97,115, 95, 97,108,112,104, 97, 0, 0, 0, 0, 0, 17, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 0, 6, 0, 0, 0, + 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, + 18, 0, 0, 0, 0, 7, 0, 15, 30, 0, 0, 0, 90, 64, 0, 0, 22, 64, 1,128, +197, 1, 0, 0,198, 65,192, 3, 11,130, 64, 0, 28, 2, 0, 1,220,129, 0, 0, + 64, 0,128, 3,197, 1, 0, 0,198,193,192, 3, 0, 2, 0, 0, 67, 2, 0, 5, +192, 2,128, 0,220,129,128, 2,154, 0, 0, 0, 22, 64, 0,128, 11, 2,193, 3, + 28, 66, 0, 1, 5, 2, 0, 0, 6, 66, 65, 4, 64, 2, 0, 0,128, 2,128, 3, +192, 2,128, 1, 0, 3, 0, 2, 64, 3,128, 2,128, 3, 0, 3, 28,130,128, 3, + 64, 2,128, 3, 30, 2,128, 1, 30, 0,128, 0, 6, 0, 0, 0, 4, 3, 0, 0, + 0, 0, 0, 0, 0,105,109, 0, 4, 18, 0, 0, 0, 0, 0, 0, 0, 67,111,108, +111,114, 77,111,100,101, 84,111, 66,105,116,109, 97,112, 0, 4, 11, 0, 0, 0, + 0, 0, 0, 0, 67,111,108,111,114, 83,112, 97, 99,101, 0, 4, 17, 0, 0, 0, + 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, + 0, 4, 9, 0, 0, 0, 0, 0, 0, 0, 65,100,100, 65,108,112,104, 97, 0, 4, + 16, 0, 0, 0, 0, 0, 0, 0, 67,111,110,118,101,114,116, 84,111, 66,105,116, +109, 97,112, 0, 0, 0, 0, 0, 30, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, + 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, + 14, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, + 15, 0, 0, 0, 15, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, + 16, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, + 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, + 17, 0, 0, 0, 17, 0, 0, 0, 18, 0, 0, 0, 8, 0, 0, 0, 10, 0, 0, 0, + 0, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 29, 0, + 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 99,111,108,111,114, 95,115,112, 97, 99, +101, 0, 0, 0, 0, 0, 29, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,104, 97, +115, 95, 97,108,112,104, 97, 0, 0, 0, 0, 0, 29, 0, 0, 0, 9, 0, 0, 0, + 0, 0, 0, 0, 99,112,120, 50,114,101, 97,108, 0, 0, 0, 0, 0, 29, 0, 0, + 0, 6, 0, 0, 0, 0, 0, 0, 0,103, 97,109,109, 97, 0, 0, 0, 0, 0, 29, + 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 97, 98,115,115,111,108,117,116,101, + 0, 0, 0, 0, 0, 29, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 99, 97,115, +116, 95,109,111,100,101, 0, 0, 0, 0, 0, 29, 0, 0, 0, 10, 0, 0, 0, 0, + 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 0, 14, 0, 0, 0, 29, 0, 0, + 0, 0, 0, 0, 0, 10, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 2, 0, 0, + 0, 7, 0, 0, 0, 11, 0, 0, 0, 7, 0, 0, 0, 13, 0, 0, 0, 18, 0, 0, + 0, 13, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + + if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"../obj/imlua51/im_convert_be64.lo")==0) lua_call(L, 0, 0); +} diff --git a/im/src/lua5/loh/im_convert_le64.loh b/im/src/lua5/loh/im_convert_le64.loh new file mode 100755 index 0000000..e2d2a06 --- /dev/null +++ b/im/src/lua5/loh/im_convert_le64.loh @@ -0,0 +1,95 @@ +/* code automatically generated by bin2c -- DO NOT EDIT */ +{ +/* #include'ing this file in a C program is equivalent to calling + if (luaL_loadfile(L,"../obj/imlua51/im_convert_le64.lo")==0) lua_call(L, 0, 0); +*/ +/* ../obj/imlua51/im_convert_le64.lo */ +static const unsigned char B1[]={ + 27, 76,117, 97, 81, 0, 1, 4, 8, 4, 8, 0, 21, 0, 0, 0, 0, 0, 0, 0, + 64,108,117, 97, 53, 47,105,109, 95, 99,111,110,118,101,114,116, 46,108,117, 97, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 10, 0, 0, 0, 5, 0, 0, + 0,100, 0, 0, 0, 9, 64,128,128, 5, 0, 0, 0,100, 64, 0, 0, 9, 64, 0, +129, 5, 0, 0, 0,100,128, 0, 0, 9, 64,128,129, 30, 0,128, 0, 4, 0, 0, + 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 19, 0, 0, 0, 0, 0, + 0, 0, 67,111,110,118,101,114,116, 68, 97,116, 97, 84,121,112,101, 78,101,119, + 0, 4, 21, 0, 0, 0, 0, 0, 0, 0, 67,111,110,118,101,114,116, 67,111,108, +111,114, 83,112, 97, 99,101, 78,101,119, 0, 4, 19, 0, 0, 0, 0, 0, 0, 0, + 67,111,110,118,101,114,116, 84,111, 66,105,116,109, 97,112, 78,101,119, 0, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 0, + 6, 0, 14, 18, 0, 0, 0,133, 1, 0, 0,134, 65, 64, 3,192, 1, 0, 0, 3, + 2, 0, 5,192, 2,128, 0,156,129, 0, 3,197, 1, 0, 0,198,129,192, 3, 0, + 2, 0, 0, 64, 2, 0, 3,128, 2, 0, 1,192, 2,128, 1, 0, 3, 0, 2, 64, + 3,128, 2,220,129,128, 3, 0, 2, 0, 3,222, 1,128, 1, 30, 0,128, 0, 3, + 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, + 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, + 0, 4, 16, 0, 0, 0, 0, 0, 0, 0, 67,111,110,118,101,114,116, 68, 97,116, + 97, 84,121,112,101, 0, 0, 0, 0, 0, 18, 0, 0, 0, 3, 0, 0, 0, 3, 0, + 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, + 0, 0, 5, 0, 0, 0, 7, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,115,114, + 99, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 17, 0, 0, 0, 10, 0, 0, 0, + 0, 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, 0, 0, 0, 0, 0, 17, 0, + 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 99,112,120, 50,114,101, 97,108, 0, 0, + 0, 0, 0, 17, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,103, 97,109,109, 97, + 0, 0, 0, 0, 0, 17, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 97, 98,115, +115,111,108,117,116,101, 0, 0, 0, 0, 0, 17, 0, 0, 0, 10, 0, 0, 0, 0, + 0, 0, 0, 99, 97,115,116, 95,109,111,100,101, 0, 0, 0, 0, 0, 17, 0, 0, + 0, 10, 0, 0, 0, 0, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 0, 6, + 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, + 0, 0, 0, 11, 0, 0, 0, 0, 3, 0, 8, 18, 0, 0, 0,197, 0, 0, 0,198, + 64,192, 1, 0, 1, 0, 0, 67, 1, 0, 3,192, 1,128, 0,220,128,128, 2,154, + 0, 0, 0, 22, 64, 0,128, 11,129,192, 1, 28, 65, 0, 1, 5, 1, 0, 0, 6, +193, 64, 2, 64, 1, 0, 0,128, 1,128, 1, 28,129,128, 1, 64, 1,128, 1, 30, + 1,128, 1, 30, 0,128, 0, 4, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0, +105,109, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, + 97,116,101, 66, 97,115,101,100, 0, 4, 9, 0, 0, 0, 0, 0, 0, 0, 65,100, +100, 65,108,112,104, 97, 0, 4, 18, 0, 0, 0, 0, 0, 0, 0, 67,111,110,118, +101,114,116, 67,111,108,111,114, 83,112, 97, 99,101, 0, 0, 0, 0, 0, 18, 0, + 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, + 0, 0, 8, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, + 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, + 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 11, 0, 0, 0, 4, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, + 17, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 99,111,108,111,114, 95,115,112, + 97, 99,101, 0, 0, 0, 0, 0, 17, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, +104, 97,115, 95, 97,108,112,104, 97, 0, 0, 0, 0, 0, 17, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 0, 6, 0, 0, 0, + 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, + 18, 0, 0, 0, 0, 7, 0, 15, 30, 0, 0, 0, 90, 64, 0, 0, 22, 64, 1,128, +197, 1, 0, 0,198, 65,192, 3, 11,130, 64, 0, 28, 2, 0, 1,220,129, 0, 0, + 64, 0,128, 3,197, 1, 0, 0,198,193,192, 3, 0, 2, 0, 0, 67, 2, 0, 5, +192, 2,128, 0,220,129,128, 2,154, 0, 0, 0, 22, 64, 0,128, 11, 2,193, 3, + 28, 66, 0, 1, 5, 2, 0, 0, 6, 66, 65, 4, 64, 2, 0, 0,128, 2,128, 3, +192, 2,128, 1, 0, 3, 0, 2, 64, 3,128, 2,128, 3, 0, 3, 28,130,128, 3, + 64, 2,128, 3, 30, 2,128, 1, 30, 0,128, 0, 6, 0, 0, 0, 4, 3, 0, 0, + 0, 0, 0, 0, 0,105,109, 0, 4, 18, 0, 0, 0, 0, 0, 0, 0, 67,111,108, +111,114, 77,111,100,101, 84,111, 66,105,116,109, 97,112, 0, 4, 11, 0, 0, 0, + 0, 0, 0, 0, 67,111,108,111,114, 83,112, 97, 99,101, 0, 4, 17, 0, 0, 0, + 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, + 0, 4, 9, 0, 0, 0, 0, 0, 0, 0, 65,100,100, 65,108,112,104, 97, 0, 4, + 16, 0, 0, 0, 0, 0, 0, 0, 67,111,110,118,101,114,116, 84,111, 66,105,116, +109, 97,112, 0, 0, 0, 0, 0, 30, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, + 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, + 14, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, + 15, 0, 0, 0, 15, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, + 16, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, + 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, + 17, 0, 0, 0, 17, 0, 0, 0, 18, 0, 0, 0, 8, 0, 0, 0, 10, 0, 0, 0, + 0, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 29, 0, + 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 99,111,108,111,114, 95,115,112, 97, 99, +101, 0, 0, 0, 0, 0, 29, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,104, 97, +115, 95, 97,108,112,104, 97, 0, 0, 0, 0, 0, 29, 0, 0, 0, 9, 0, 0, 0, + 0, 0, 0, 0, 99,112,120, 50,114,101, 97,108, 0, 0, 0, 0, 0, 29, 0, 0, + 0, 6, 0, 0, 0, 0, 0, 0, 0,103, 97,109,109, 97, 0, 0, 0, 0, 0, 29, + 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 97, 98,115,115,111,108,117,116,101, + 0, 0, 0, 0, 0, 29, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 99, 97,115, +116, 95,109,111,100,101, 0, 0, 0, 0, 0, 29, 0, 0, 0, 10, 0, 0, 0, 0, + 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 0, 14, 0, 0, 0, 29, 0, 0, + 0, 0, 0, 0, 0, 10, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 2, 0, 0, + 0, 7, 0, 0, 0, 11, 0, 0, 0, 7, 0, 0, 0, 13, 0, 0, 0, 18, 0, 0, + 0, 13, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + + if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"../obj/imlua51/im_convert_le64.lo")==0) lua_call(L, 0, 0); +} diff --git a/im/src/lua5/loh/im_fftw.loh b/im/src/lua5/loh/im_fftw.loh new file mode 100755 index 0000000..9e7c78a --- /dev/null +++ b/im/src/lua5/loh/im_fftw.loh @@ -0,0 +1,110 @@ +/* code automatically generated by bin2c -- DO NOT EDIT */ +{ +/* #include'ing this file in a C program is equivalent to calling + if (luaL_loadfile(L,"../obj/imlua_fftw51/im_fftw.lo")==0) lua_call(L, 0, 0); +*/ +/* ../obj/imlua_fftw51/im_fftw.lo */ +static const unsigned char B1[]={ + 27, 76,117, 97, 81, 0, 1, 4, 4, 4, 8, 0, 18, 0, 0, 0, 64,108,117, 97, + 53, 47,105,109, 95,102,102,116,119, 46,108,117, 97, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 8, 18, 0, 0, 0, 36, 0, 0, 0,100, 64, 0, 0,128, 0, +128, 0,193, 0, 0, 0,156, 64, 0, 1,128, 0, 0, 0,193, 64, 0, 0, 3, 1, + 0, 3,197,129, 0, 0,198,193,192, 3,156, 64, 0, 3,128, 0, 0, 0,193, 0, + 1, 0,156, 64, 0, 1,128, 0, 0, 0,193, 64, 1, 0,156, 64, 0, 1, 30, 0, +128, 0, 6, 0, 0, 0, 4, 24, 0, 0, 0, 80,114,111, 99,101,115,115, 67,114, +111,115,115, 67,111,114,114,101,108, 97,116,105,111,110, 0, 4, 23, 0, 0, 0, + 80,114,111, 99,101,115,115, 65,117,116,111, 67,111,114,114,101,108, 97,116,105, +111,110, 0, 4, 3, 0, 0, 0,105,109, 0, 4, 7, 0, 0, 0, 67, 70, 76, 79, + 65, 84, 0, 4, 11, 0, 0, 0, 80,114,111, 99,101,115,115, 70, 70, 84, 0, 4, + 12, 0, 0, 0, 80,114,111, 99,101,115,115, 73, 70, 70, 84, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 8, 0, 0, 0, 25, 0, 0, 0, 0, 5, 0, 9, 17, 0, 0, 0, + 69, 1, 0, 0, 70, 1,128, 2,133, 65, 0, 0,192, 1,128, 2,156, 65, 0, 1, +133, 1, 0, 0,192, 1, 0, 0, 1,130, 0, 0,213, 1,130, 3, 36, 2, 0, 0, + 0, 0,128, 0, 0, 0, 0, 1, 0, 0,128, 1, 0, 0, 0, 2, 0, 0,128, 2, +137, 1,130, 3, 30, 0,128, 0, 3, 0, 0, 0, 4, 3, 0, 0, 0,105,109, 0, + 4, 7, 0, 0, 0, 97,115,115,101,114,116, 0, 4, 4, 0, 0, 0, 78,101,119, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 24, 0, 0, 0, 5, 1, 7, + 8, 23, 0, 0, 0,133, 0, 0, 0,134, 64, 64, 1,192, 0, 0, 0, 4, 1, 0, + 0, 68, 1,128, 0,132, 1, 0, 1,196, 1,128, 1,156,128, 0, 3,196, 0, 0, + 2, 0, 1, 0, 0, 64, 1, 0, 1,133,129, 0, 0,192, 1,128, 0,156, 1, 0, + 1,220,128, 0, 0,218, 0, 0, 0, 22,192, 0,128, 0, 1,128, 1, 64, 1, 0, + 1, 30, 1,128, 1, 22, 0, 0,128,158, 0, 0, 1, 30, 0,128, 0, 3, 0, 0, + 0, 4, 3, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, 73,109, 97,103,101, 67, +114,101, 97,116,101, 66, 97,115,101,100, 0, 4, 7, 0, 0, 0,117,110,112, 97, + 99,107, 0, 0, 0, 0, 0, 23, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, + 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, + 0, 0, 0, 18, 0, 0, 0, 18, 0, 0, 0, 18, 0, 0, 0, 18, 0, 0, 0, 18, + 0, 0, 0, 18, 0, 0, 0, 18, 0, 0, 0, 19, 0, 0, 0, 19, 0, 0, 0, 20, + 0, 0, 0, 20, 0, 0, 0, 20, 0, 0, 0, 20, 0, 0, 0, 22, 0, 0, 0, 24, + 0, 0, 0, 4, 0, 0, 0, 10, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, + 0, 0, 0, 0, 0, 22, 0, 0, 0, 4, 0, 0, 0, 97,114,103, 0, 0, 0, 0, + 0, 22, 0, 0, 0, 10, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 0, 8, + 0, 0, 0, 22, 0, 0, 0, 4, 0, 0, 0,114,101,116, 0, 15, 0, 0, 0, 22, + 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0,119,105,100,116,104, 0, 7, 0, 0, + 0,104,101,105,103,104,116, 0, 12, 0, 0, 0, 99,111,108,111,114, 95,115,112, + 97, 99,101, 0, 10, 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, 0, 5, 0, + 0, 0,102,117,110, 99, 0, 17, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 10, + 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, + 0, 0, 0, 13, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, + 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 25, 0, 0, 0, 6, + 0, 0, 0, 9, 0, 0, 0,102,117,110, 99,110, 97,109,101, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 6, 0, 0, 0,119,105,100,116,104, 0, 0, 0, 0, 0, 16, 0, + 0, 0, 7, 0, 0, 0,104,101,105,103,104,116, 0, 0, 0, 0, 0, 16, 0, 0, + 0, 12, 0, 0, 0, 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 0, 0, 0, + 0, 16, 0, 0, 0, 10, 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, 0, 0, + 0, 0, 0, 16, 0, 0, 0, 5, 0, 0, 0,102,117,110, 99, 0, 2, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, 50, 0, 0, 0, + 0, 5, 0, 11, 22, 0, 0, 0, 69, 1, 0, 0, 70, 1,128, 2,133, 65, 0, 0, +192, 1,128, 2, 5,130, 0, 0, 6,194, 64, 4, 65, 2, 1, 0,128, 2, 0, 0, + 28, 2,128, 1,156, 65, 0, 0,133, 1, 0, 0,192, 1, 0, 0, 1, 66, 1, 0, +213, 1,130, 3, 36, 2, 0, 0, 0, 0,128, 0, 0, 0, 0, 1, 0, 0,128, 1, + 0, 0, 0, 2, 0, 0,128, 2,137, 1,130, 3, 30, 0,128, 0, 6, 0, 0, 0, + 4, 3, 0, 0, 0,105,109, 0, 4, 7, 0, 0, 0, 97,115,115,101,114,116, 0, + 4, 7, 0, 0, 0,115,116,114,105,110,103, 0, 4, 7, 0, 0, 0,102,111,114, +109, 97,116, 0, 4, 24, 0, 0, 0,117,110,100,101,102,105,110,101,100, 32,102, +117,110, 99,116,105,111,110, 32, 96, 37,115, 39, 0, 4, 4, 0, 0, 0, 78,101, +119, 0, 1, 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, 49, 0, 0, 0, 5, 2, + 7, 10, 24, 0, 0, 0,197, 0, 0, 0,198, 64,192, 1, 0, 1, 0, 0, 68, 1, + 0, 0,132, 1,128, 0,196, 1, 0, 1, 4, 2,128, 1,220,128, 0, 3, 4, 1, + 0, 2, 64, 1, 0, 0,128, 1,128, 0,192, 1,128, 1, 5,130, 0, 0, 64, 2, + 0, 1, 28, 2, 0, 1, 28,129, 0, 0, 26, 1, 0, 0, 22,192, 0,128, 64, 1, + 0, 2,128, 1,128, 1, 94, 1,128, 1, 22, 0, 0,128,222, 0, 0, 1, 30, 0, +128, 0, 3, 0, 0, 0, 4, 3, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, 73, +109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 4, 7, 0, 0, + 0,117,110,112, 97, 99,107, 0, 0, 0, 0, 0, 24, 0, 0, 0, 40, 0, 0, 0, + 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, + 40, 0, 0, 0, 40, 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, + 43, 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, + 44, 0, 0, 0, 44, 0, 0, 0, 45, 0, 0, 0, 45, 0, 0, 0, 45, 0, 0, 0, + 45, 0, 0, 0, 47, 0, 0, 0, 49, 0, 0, 0, 5, 0, 0, 0, 11, 0, 0, 0, +115,114, 99, 95,105,109, 97,103,101, 49, 0, 0, 0, 0, 0, 23, 0, 0, 0, 11, + 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 50, 0, 0, 0, 0, 0, 23, 0, + 0, 0, 4, 0, 0, 0, 97,114,103, 0, 0, 0, 0, 0, 23, 0, 0, 0, 10, 0, + 0, 0,100,115,116, 95,105,109, 97,103,101, 0, 8, 0, 0, 0, 23, 0, 0, 0, + 4, 0, 0, 0,114,101,116, 0, 16, 0, 0, 0, 23, 0, 0, 0, 5, 0, 0, 0, + 6, 0, 0, 0,119,105,100,116,104, 0, 7, 0, 0, 0,104,101,105,103,104,116, + 0, 12, 0, 0, 0, 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 10, 0, 0, + 0,100, 97,116, 97, 95,116,121,112,101, 0, 5, 0, 0, 0,102,117,110, 99, 0, + 22, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, + 35, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, + 35, 0, 0, 0, 38, 0, 0, 0, 38, 0, 0, 0, 38, 0, 0, 0, 38, 0, 0, 0, + 49, 0, 0, 0, 49, 0, 0, 0, 49, 0, 0, 0, 49, 0, 0, 0, 49, 0, 0, 0, + 49, 0, 0, 0, 49, 0, 0, 0, 50, 0, 0, 0, 6, 0, 0, 0, 9, 0, 0, 0, +102,117,110, 99,110, 97,109,101, 0, 0, 0, 0, 0, 21, 0, 0, 0, 6, 0, 0, + 0,119,105,100,116,104, 0, 0, 0, 0, 0, 21, 0, 0, 0, 7, 0, 0, 0,104, +101,105,103,104,116, 0, 0, 0, 0, 0, 21, 0, 0, 0, 12, 0, 0, 0, 99,111, +108,111,114, 95,115,112, 97, 99,101, 0, 0, 0, 0, 0, 21, 0, 0, 0, 10, 0, + 0, 0,100, 97,116, 97, 95,116,121,112,101, 0, 0, 0, 0, 0, 21, 0, 0, 0, + 5, 0, 0, 0,102,117,110, 99, 0, 2, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, + 0, 18, 0, 0, 0, 25, 0, 0, 0, 50, 0, 0, 0, 54, 0, 0, 0, 54, 0, 0, + 0, 54, 0, 0, 0, 55, 0, 0, 0, 55, 0, 0, 0, 55, 0, 0, 0, 55, 0, 0, + 0, 55, 0, 0, 0, 55, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, + 0, 57, 0, 0, 0, 57, 0, 0, 0, 57, 0, 0, 0, 57, 0, 0, 0, 2, 0, 0, + 0, 17, 0, 0, 0, 79,110,101, 83,111,117,114, 99,101, 79,110,101, 68,101,115, +116, 0, 1, 0, 0, 0, 17, 0, 0, 0, 18, 0, 0, 0, 84,119,111, 83,111,117, +114, 99,101,115, 79,110,101, 68,101,115,116, 0, 2, 0, 0, 0, 17, 0, 0, 0, + 0, 0, 0, 0, +}; + + if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"../obj/imlua_fftw51/im_fftw.lo")==0) lua_call(L, 0, 0); +} diff --git a/im/src/lua5/loh/im_fftw_be32.loh b/im/src/lua5/loh/im_fftw_be32.loh new file mode 100755 index 0000000..754d56a --- /dev/null +++ b/im/src/lua5/loh/im_fftw_be32.loh @@ -0,0 +1,110 @@ +/* code automatically generated by bin2c -- DO NOT EDIT */ +{ +/* #include'ing this file in a C program is equivalent to calling + if (luaL_loadfile(L,"../obj/imlua_fftw51/im_fftw_be32.lo")==0) lua_call(L, 0, 0); +*/ +/* ../obj/imlua_fftw51/im_fftw_be32.lo */ +static const unsigned char B1[]={ + 27, 76,117, 97, 81, 0, 0, 4, 4, 4, 8, 0, 0, 0, 0, 18, 64,108,117, 97, + 53, 47,105,109, 95,102,102,116,119, 46,108,117, 97, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 8, 0, 0, 0, 18, 0, 0, 0, 36, 0, 0, 64,100, 0,128, + 0,128, 0, 0, 0,193, 1, 0, 64,156, 0, 0, 0,128, 0, 0, 64,193, 3, 0, + 1, 3, 0, 0,129,197, 3,192,193,198, 3, 0, 64,156, 0, 0, 0,128, 0, 1, + 0,193, 1, 0, 64,156, 0, 0, 0,128, 0, 1, 64,193, 1, 0, 64,156, 0,128, + 0, 30, 0, 0, 0, 6, 4, 0, 0, 0, 24, 80,114,111, 99,101,115,115, 67,114, +111,115,115, 67,111,114,114,101,108, 97,116,105,111,110, 0, 4, 0, 0, 0, 23, + 80,114,111, 99,101,115,115, 65,117,116,111, 67,111,114,114,101,108, 97,116,105, +111,110, 0, 4, 0, 0, 0, 3,105,109, 0, 4, 0, 0, 0, 7, 67, 70, 76, 79, + 65, 84, 0, 4, 0, 0, 0, 11, 80,114,111, 99,101,115,115, 70, 70, 84, 0, 4, + 0, 0, 0, 12, 80,114,111, 99,101,115,115, 73, 70, 70, 84, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 25, 0, 5, 0, 9, 0, 0, 0, 17, + 0, 0, 1, 69, 2,128, 1, 70, 0, 0, 65,133, 2,128, 1,192, 1, 0, 65,156, + 0, 0, 1,133, 0, 0, 1,192, 0, 0,130, 1, 3,130, 1,213, 0, 0, 2, 36, + 0,128, 0, 0, 1, 0, 0, 0, 1,128, 0, 0, 2, 0, 0, 0, 2,128, 0, 0, + 3,130, 1,137, 0,128, 0, 30, 0, 0, 0, 3, 4, 0, 0, 0, 3,105,109, 0, + 4, 0, 0, 0, 7, 97,115,115,101,114,116, 0, 4, 0, 0, 0, 4, 78,101,119, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 24, 5, 1, 7, + 8, 0, 0, 0, 23, 0, 0, 0,133, 1, 64, 64,134, 0, 0, 0,192, 0, 0, 1, + 4, 0,128, 1, 68, 1, 0, 1,132, 1,128, 1,196, 3, 0,128,156, 2, 0, 0, +196, 0, 0, 1, 0, 1, 0, 1, 64, 0, 0,129,133, 0,128, 1,192, 1, 0, 1, +156, 0, 0,128,220, 0, 0, 0,218,128, 0,192, 22, 1,128, 1, 0, 1, 0, 1, + 64, 1,128, 1, 30,128, 0, 0, 22, 1, 0, 0,158, 0,128, 0, 30, 0, 0, 0, + 3, 4, 0, 0, 0, 3,105,109, 0, 4, 0, 0, 0, 17, 73,109, 97,103,101, 67, +114,101, 97,116,101, 66, 97,115,101,100, 0, 4, 0, 0, 0, 7,117,110,112, 97, + 99,107, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 15, 0, 0, 0, 15, 0, + 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, + 0, 0, 15, 0, 0, 0, 18, 0, 0, 0, 18, 0, 0, 0, 18, 0, 0, 0, 18, 0, + 0, 0, 18, 0, 0, 0, 18, 0, 0, 0, 18, 0, 0, 0, 19, 0, 0, 0, 19, 0, + 0, 0, 20, 0, 0, 0, 20, 0, 0, 0, 20, 0, 0, 0, 20, 0, 0, 0, 22, 0, + 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 10,115,114, 99, 95,105,109, 97,103,101, + 0, 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, 4, 97,114,103, 0, 0, 0, 0, + 0, 0, 0, 0, 22, 0, 0, 0, 10,100,115,116, 95,105,109, 97,103,101, 0, 0, + 0, 0, 8, 0, 0, 0, 22, 0, 0, 0, 4,114,101,116, 0, 0, 0, 0, 15, 0, + 0, 0, 22, 0, 0, 0, 5, 0, 0, 0, 6,119,105,100,116,104, 0, 0, 0, 0, + 7,104,101,105,103,104,116, 0, 0, 0, 0, 12, 99,111,108,111,114, 95,115,112, + 97, 99,101, 0, 0, 0, 0, 10,100, 97,116, 97, 95,116,121,112,101, 0, 0, 0, + 0, 5,102,117,110, 99, 0, 0, 0, 0, 17, 0, 0, 0, 9, 0, 0, 0, 9, 0, + 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 13, 0, 0, 0, 13, 0, + 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, + 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 25, 0, + 0, 0, 6, 0, 0, 0, 9,102,117,110, 99,110, 97,109,101, 0, 0, 0, 0, 0, + 0, 0, 0, 16, 0, 0, 0, 6,119,105,100,116,104, 0, 0, 0, 0, 0, 0, 0, + 0, 16, 0, 0, 0, 7,104,101,105,103,104,116, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 12, 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 0, 0, 0, + 0, 0, 0, 0, 16, 0, 0, 0, 10,100, 97,116, 97, 95,116,121,112,101, 0, 0, + 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 5,102,117,110, 99, 0, 0, 0, 0, 2, + 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, 50, + 0, 5, 0, 11, 0, 0, 0, 22, 0, 0, 1, 69, 2,128, 1, 70, 0, 0, 65,133, + 2,128, 1,192, 0, 0,130, 5, 4, 64,194, 6, 0, 1, 2, 65, 0, 0, 2,128, + 1,128, 2, 28, 0, 0, 65,156, 0, 0, 1,133, 0, 0, 1,192, 0, 1, 66, 1, + 3,130, 1,213, 0, 0, 2, 36, 0,128, 0, 0, 1, 0, 0, 0, 1,128, 0, 0, + 2, 0, 0, 0, 2,128, 0, 0, 3,130, 1,137, 0,128, 0, 30, 0, 0, 0, 6, + 4, 0, 0, 0, 3,105,109, 0, 4, 0, 0, 0, 7, 97,115,115,101,114,116, 0, + 4, 0, 0, 0, 7,115,116,114,105,110,103, 0, 4, 0, 0, 0, 7,102,111,114, +109, 97,116, 0, 4, 0, 0, 0, 24,117,110,100,101,102,105,110,101,100, 32,102, +117,110, 99,116,105,111,110, 32, 96, 37,115, 39, 0, 4, 0, 0, 0, 4, 78,101, +119, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, 49, 5, 2, + 7, 10, 0, 0, 0, 24, 0, 0, 0,197, 1,192, 64,198, 0, 0, 1, 0, 0, 0, + 1, 68, 0,128, 1,132, 1, 0, 1,196, 1,128, 2, 4, 3, 0,128,220, 2, 0, + 1, 4, 0, 0, 1, 64, 0,128, 1,128, 1,128, 1,192, 0, 0,130, 5, 1, 0, + 2, 64, 1, 0, 2, 28, 0, 0,129, 28, 0, 0, 1, 26,128, 0,192, 22, 2, 0, + 1, 64, 1,128, 1,128, 1,128, 1, 94,128, 0, 0, 22, 1, 0, 0,222, 0,128, + 0, 30, 0, 0, 0, 3, 4, 0, 0, 0, 3,105,109, 0, 4, 0, 0, 0, 17, 73, +109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 4, 0, 0, 0, + 7,117,110,112, 97, 99,107, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 40, + 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, + 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, 43, + 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, 43, + 0, 0, 0, 44, 0, 0, 0, 44, 0, 0, 0, 45, 0, 0, 0, 45, 0, 0, 0, 45, + 0, 0, 0, 45, 0, 0, 0, 47, 0, 0, 0, 49, 0, 0, 0, 5, 0, 0, 0, 11, +115,114, 99, 95,105,109, 97,103,101, 49, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, + 0, 0, 11,115,114, 99, 95,105,109, 97,103,101, 50, 0, 0, 0, 0, 0, 0, 0, + 0, 23, 0, 0, 0, 4, 97,114,103, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 0, + 0, 10,100,115,116, 95,105,109, 97,103,101, 0, 0, 0, 0, 8, 0, 0, 0, 23, + 0, 0, 0, 4,114,101,116, 0, 0, 0, 0, 16, 0, 0, 0, 23, 0, 0, 0, 5, + 0, 0, 0, 6,119,105,100,116,104, 0, 0, 0, 0, 7,104,101,105,103,104,116, + 0, 0, 0, 0, 12, 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 0, 0, 0, + 10,100, 97,116, 97, 95,116,121,112,101, 0, 0, 0, 0, 5,102,117,110, 99, 0, + 0, 0, 0, 22, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 35, 0, 0, 0, 35, + 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, 35, + 0, 0, 0, 35, 0, 0, 0, 38, 0, 0, 0, 38, 0, 0, 0, 38, 0, 0, 0, 38, + 0, 0, 0, 49, 0, 0, 0, 49, 0, 0, 0, 49, 0, 0, 0, 49, 0, 0, 0, 49, + 0, 0, 0, 49, 0, 0, 0, 49, 0, 0, 0, 50, 0, 0, 0, 6, 0, 0, 0, 9, +102,117,110, 99,110, 97,109,101, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, + 6,119,105,100,116,104, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 7,104, +101,105,103,104,116, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 12, 99,111, +108,111,114, 95,115,112, 97, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, + 0, 10,100, 97,116, 97, 95,116,121,112,101, 0, 0, 0, 0, 0, 0, 0, 0, 21, + 0, 0, 0, 5,102,117,110, 99, 0, 0, 0, 0, 2, 0, 0, 0, 21, 0, 0, 0, + 0, 0, 0, 0, 18, 0, 0, 0, 25, 0, 0, 0, 50, 0, 0, 0, 54, 0, 0, 0, + 54, 0, 0, 0, 54, 0, 0, 0, 55, 0, 0, 0, 55, 0, 0, 0, 55, 0, 0, 0, + 55, 0, 0, 0, 55, 0, 0, 0, 55, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, + 56, 0, 0, 0, 57, 0, 0, 0, 57, 0, 0, 0, 57, 0, 0, 0, 57, 0, 0, 0, + 2, 0, 0, 0, 17, 79,110,101, 83,111,117,114, 99,101, 79,110,101, 68,101,115, +116, 0, 0, 0, 0, 1, 0, 0, 0, 17, 0, 0, 0, 18, 84,119,111, 83,111,117, +114, 99,101,115, 79,110,101, 68,101,115,116, 0, 0, 0, 0, 2, 0, 0, 0, 17, + 0, 0, 0, 0, +}; + + if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"../obj/imlua_fftw51/im_fftw_be32.lo")==0) lua_call(L, 0, 0); +} diff --git a/im/src/lua5/loh/im_fftw_be64.loh b/im/src/lua5/loh/im_fftw_be64.loh new file mode 100644 index 0000000..3b1a6cb --- /dev/null +++ b/im/src/lua5/loh/im_fftw_be64.loh @@ -0,0 +1,122 @@ +/* code automatically generated by bin2c -- DO NOT EDIT */ +{ +/* #include'ing this file in a C program is equivalent to calling + if (luaL_loadfile(L,"../obj/imlua_fftw51/im_fftw_be64.lo")==0) lua_call(L, 0, 0); +*/ +/* ../obj/imlua_fftw51/im_fftw_be64.lo */ +static const unsigned char B1[]={ + 27, 76,117, 97, 81, 0, 1, 4, 8, 4, 8, 0, 18, 0, 0, 0, 0, 0, 0, 0, + 64,108,117, 97, 53, 47,105,109, 95,102,102,116,119, 46,108,117, 97, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2, 8, 18, 0, 0, 0, 36, 0, 0, 0,100, 64, + 0, 0,128, 0,128, 0,193, 0, 0, 0,156, 64, 0, 1,128, 0, 0, 0,193, 64, + 0, 0, 3, 1, 0, 3,197,129, 0, 0,198,193,192, 3,156, 64, 0, 3,128, 0, + 0, 0,193, 0, 1, 0,156, 64, 0, 1,128, 0, 0, 0,193, 64, 1, 0,156, 64, + 0, 1, 30, 0,128, 0, 6, 0, 0, 0, 4, 24, 0, 0, 0, 0, 0, 0, 0, 80, +114,111, 99,101,115,115, 67,114,111,115,115, 67,111,114,114,101,108, 97,116,105, +111,110, 0, 4, 23, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 65, +117,116,111, 67,111,114,114,101,108, 97,116,105,111,110, 0, 4, 3, 0, 0, 0, + 0, 0, 0, 0,105,109, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0, 67, 70, 76, 79, + 65, 84, 0, 4, 11, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 70, + 70, 84, 0, 4, 12, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 73, + 70, 70, 84, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, + 25, 0, 0, 0, 0, 5, 0, 9, 17, 0, 0, 0, 69, 1, 0, 0, 70, 1,128, 2, +133, 65, 0, 0,192, 1,128, 2,156, 65, 0, 1,133, 1, 0, 0,192, 1, 0, 0, + 1,130, 0, 0,213, 1,130, 3, 36, 2, 0, 0, 0, 0,128, 0, 0, 0, 0, 1, + 0, 0,128, 1, 0, 0, 0, 2, 0, 0,128, 2,137, 1,130, 3, 30, 0,128, 0, + 3, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 7, 0, 0, + 0, 0, 0, 0, 0, 97,115,115,101,114,116, 0, 4, 4, 0, 0, 0, 0, 0, 0, + 0, 78,101,119, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, + 0, 24, 0, 0, 0, 5, 1, 7, 8, 23, 0, 0, 0,133, 0, 0, 0,134, 64, 64, + 1,192, 0, 0, 0, 4, 1, 0, 0, 68, 1,128, 0,132, 1, 0, 1,196, 1,128, + 1,156,128, 0, 3,196, 0, 0, 2, 0, 1, 0, 0, 64, 1, 0, 1,133,129, 0, + 0,192, 1,128, 0,156, 1, 0, 1,220,128, 0, 0,218, 0, 0, 0, 22,192, 0, +128, 0, 1,128, 1, 64, 1, 0, 1, 30, 1,128, 1, 22, 0, 0,128,158, 0, 0, + 1, 30, 0,128, 0, 3, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, + 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116, +101, 66, 97,115,101,100, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0,117,110,112, 97, + 99,107, 0, 0, 0, 0, 0, 23, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, + 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, + 0, 0, 0, 18, 0, 0, 0, 18, 0, 0, 0, 18, 0, 0, 0, 18, 0, 0, 0, 18, + 0, 0, 0, 18, 0, 0, 0, 18, 0, 0, 0, 19, 0, 0, 0, 19, 0, 0, 0, 20, + 0, 0, 0, 20, 0, 0, 0, 20, 0, 0, 0, 20, 0, 0, 0, 22, 0, 0, 0, 24, + 0, 0, 0, 4, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,115,114, 99, 95,105, +109, 97,103,101, 0, 0, 0, 0, 0, 22, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, + 0, 97,114,103, 0, 0, 0, 0, 0, 22, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, + 0,100,115,116, 95,105,109, 97,103,101, 0, 8, 0, 0, 0, 22, 0, 0, 0, 4, + 0, 0, 0, 0, 0, 0, 0,114,101,116, 0, 15, 0, 0, 0, 22, 0, 0, 0, 5, + 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119,105,100,116,104, 0, 7, 0, 0, + 0, 0, 0, 0, 0,104,101,105,103,104,116, 0, 12, 0, 0, 0, 0, 0, 0, 0, + 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 10, 0, 0, 0, 0, 0, 0, 0, +100, 97,116, 97, 95,116,121,112,101, 0, 5, 0, 0, 0, 0, 0, 0, 0,102,117, +110, 99, 0, 17, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 10, 0, 0, 0, 10, + 0, 0, 0, 10, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, + 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, + 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 25, 0, 0, 0, 6, 0, 0, 0, 9, + 0, 0, 0, 0, 0, 0, 0,102,117,110, 99,110, 97,109,101, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119,105,100,116,104, 0, 0, 0, + 0, 0, 16, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0,104,101,105,103,104,116, + 0, 0, 0, 0, 0, 16, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 99,111,108, +111,114, 95,115,112, 97, 99,101, 0, 0, 0, 0, 0, 16, 0, 0, 0, 10, 0, 0, + 0, 0, 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, 0, 0, 0, 0, 0, 16, + 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,102,117,110, 99, 0, 2, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, + 50, 0, 0, 0, 0, 5, 0, 11, 22, 0, 0, 0, 69, 1, 0, 0, 70, 1,128, 2, +133, 65, 0, 0,192, 1,128, 2, 5,130, 0, 0, 6,194, 64, 4, 65, 2, 1, 0, +128, 2, 0, 0, 28, 2,128, 1,156, 65, 0, 0,133, 1, 0, 0,192, 1, 0, 0, + 1, 66, 1, 0,213, 1,130, 3, 36, 2, 0, 0, 0, 0,128, 0, 0, 0, 0, 1, + 0, 0,128, 1, 0, 0, 0, 2, 0, 0,128, 2,137, 1,130, 3, 30, 0,128, 0, + 6, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 7, 0, 0, + 0, 0, 0, 0, 0, 97,115,115,101,114,116, 0, 4, 7, 0, 0, 0, 0, 0, 0, + 0,115,116,114,105,110,103, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0,102,111,114, +109, 97,116, 0, 4, 24, 0, 0, 0, 0, 0, 0, 0,117,110,100,101,102,105,110, +101,100, 32,102,117,110, 99,116,105,111,110, 32, 96, 37,115, 39, 0, 4, 4, 0, + 0, 0, 0, 0, 0, 0, 78,101,119, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 38, 0, 0, 0, 49, 0, 0, 0, 5, 2, 7, 10, 24, 0, 0, 0,197, 0, + 0, 0,198, 64,192, 1, 0, 1, 0, 0, 68, 1, 0, 0,132, 1,128, 0,196, 1, + 0, 1, 4, 2,128, 1,220,128, 0, 3, 4, 1, 0, 2, 64, 1, 0, 0,128, 1, +128, 0,192, 1,128, 1, 5,130, 0, 0, 64, 2, 0, 1, 28, 2, 0, 1, 28,129, + 0, 0, 26, 1, 0, 0, 22,192, 0,128, 64, 1, 0, 2,128, 1,128, 1, 94, 1, +128, 1, 22, 0, 0,128,222, 0, 0, 1, 30, 0,128, 0, 3, 0, 0, 0, 4, 3, + 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 73, +109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 4, 7, 0, 0, + 0, 0, 0, 0, 0,117,110,112, 97, 99,107, 0, 0, 0, 0, 0, 24, 0, 0, 0, + 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, + 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, + 43, 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, + 43, 0, 0, 0, 44, 0, 0, 0, 44, 0, 0, 0, 45, 0, 0, 0, 45, 0, 0, 0, + 45, 0, 0, 0, 45, 0, 0, 0, 47, 0, 0, 0, 49, 0, 0, 0, 5, 0, 0, 0, + 11, 0, 0, 0, 0, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 49, 0, 0, + 0, 0, 0, 23, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0,115,114, 99, 95,105, +109, 97,103,101, 50, 0, 0, 0, 0, 0, 23, 0, 0, 0, 4, 0, 0, 0, 0, 0, + 0, 0, 97,114,103, 0, 0, 0, 0, 0, 23, 0, 0, 0, 10, 0, 0, 0, 0, 0, + 0, 0,100,115,116, 95,105,109, 97,103,101, 0, 8, 0, 0, 0, 23, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0,114,101,116, 0, 16, 0, 0, 0, 23, 0, 0, 0, + 5, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119,105,100,116,104, 0, 7, 0, + 0, 0, 0, 0, 0, 0,104,101,105,103,104,116, 0, 12, 0, 0, 0, 0, 0, 0, + 0, 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 10, 0, 0, 0, 0, 0, 0, + 0,100, 97,116, 97, 95,116,121,112,101, 0, 5, 0, 0, 0, 0, 0, 0, 0,102, +117,110, 99, 0, 22, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 35, 0, 0, 0, + 35, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, + 35, 0, 0, 0, 35, 0, 0, 0, 38, 0, 0, 0, 38, 0, 0, 0, 38, 0, 0, 0, + 38, 0, 0, 0, 49, 0, 0, 0, 49, 0, 0, 0, 49, 0, 0, 0, 49, 0, 0, 0, + 49, 0, 0, 0, 49, 0, 0, 0, 49, 0, 0, 0, 50, 0, 0, 0, 6, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0,102,117,110, 99,110, 97,109,101, 0, 0, 0, 0, + 0, 21, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119,105,100,116,104, 0, 0, + 0, 0, 0, 21, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0,104,101,105,103,104, +116, 0, 0, 0, 0, 0, 21, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 99,111, +108,111,114, 95,115,112, 97, 99,101, 0, 0, 0, 0, 0, 21, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,102,117,110, 99, 0, 2, 0, 0, + 0, 21, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 25, 0, 0, 0, 50, 0, 0, + 0, 54, 0, 0, 0, 54, 0, 0, 0, 54, 0, 0, 0, 55, 0, 0, 0, 55, 0, 0, + 0, 55, 0, 0, 0, 55, 0, 0, 0, 55, 0, 0, 0, 55, 0, 0, 0, 56, 0, 0, + 0, 56, 0, 0, 0, 56, 0, 0, 0, 57, 0, 0, 0, 57, 0, 0, 0, 57, 0, 0, + 0, 57, 0, 0, 0, 2, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 79,110,101, + 83,111,117,114, 99,101, 79,110,101, 68,101,115,116, 0, 1, 0, 0, 0, 17, 0, + 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 84,119,111, 83,111,117,114, 99,101,115, + 79,110,101, 68,101,115,116, 0, 2, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, + +}; + + if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"../obj/imlua_fftw51/im_fftw_be64.lo")==0) lua_call(L, 0, 0); +} diff --git a/im/src/lua5/loh/im_fftw_le64.loh b/im/src/lua5/loh/im_fftw_le64.loh new file mode 100755 index 0000000..c5b497a --- /dev/null +++ b/im/src/lua5/loh/im_fftw_le64.loh @@ -0,0 +1,122 @@ +/* code automatically generated by bin2c -- DO NOT EDIT */ +{ +/* #include'ing this file in a C program is equivalent to calling + if (luaL_loadfile(L,"../obj/imlua_fftw51/im_fftw_le64.lo")==0) lua_call(L, 0, 0); +*/ +/* ../obj/imlua_fftw51/im_fftw_le64.lo */ +static const unsigned char B1[]={ + 27, 76,117, 97, 81, 0, 1, 4, 8, 4, 8, 0, 18, 0, 0, 0, 0, 0, 0, 0, + 64,108,117, 97, 53, 47,105,109, 95,102,102,116,119, 46,108,117, 97, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2, 8, 18, 0, 0, 0, 36, 0, 0, 0,100, 64, + 0, 0,128, 0,128, 0,193, 0, 0, 0,156, 64, 0, 1,128, 0, 0, 0,193, 64, + 0, 0, 3, 1, 0, 3,197,129, 0, 0,198,193,192, 3,156, 64, 0, 3,128, 0, + 0, 0,193, 0, 1, 0,156, 64, 0, 1,128, 0, 0, 0,193, 64, 1, 0,156, 64, + 0, 1, 30, 0,128, 0, 6, 0, 0, 0, 4, 24, 0, 0, 0, 0, 0, 0, 0, 80, +114,111, 99,101,115,115, 67,114,111,115,115, 67,111,114,114,101,108, 97,116,105, +111,110, 0, 4, 23, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 65, +117,116,111, 67,111,114,114,101,108, 97,116,105,111,110, 0, 4, 3, 0, 0, 0, + 0, 0, 0, 0,105,109, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0, 67, 70, 76, 79, + 65, 84, 0, 4, 11, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 70, + 70, 84, 0, 4, 12, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 73, + 70, 70, 84, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, + 25, 0, 0, 0, 0, 5, 0, 9, 17, 0, 0, 0, 69, 1, 0, 0, 70, 1,128, 2, +133, 65, 0, 0,192, 1,128, 2,156, 65, 0, 1,133, 1, 0, 0,192, 1, 0, 0, + 1,130, 0, 0,213, 1,130, 3, 36, 2, 0, 0, 0, 0,128, 0, 0, 0, 0, 1, + 0, 0,128, 1, 0, 0, 0, 2, 0, 0,128, 2,137, 1,130, 3, 30, 0,128, 0, + 3, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 7, 0, 0, + 0, 0, 0, 0, 0, 97,115,115,101,114,116, 0, 4, 4, 0, 0, 0, 0, 0, 0, + 0, 78,101,119, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, + 0, 24, 0, 0, 0, 5, 1, 7, 8, 23, 0, 0, 0,133, 0, 0, 0,134, 64, 64, + 1,192, 0, 0, 0, 4, 1, 0, 0, 68, 1,128, 0,132, 1, 0, 1,196, 1,128, + 1,156,128, 0, 3,196, 0, 0, 2, 0, 1, 0, 0, 64, 1, 0, 1,133,129, 0, + 0,192, 1,128, 0,156, 1, 0, 1,220,128, 0, 0,218, 0, 0, 0, 22,192, 0, +128, 0, 1,128, 1, 64, 1, 0, 1, 30, 1,128, 1, 22, 0, 0,128,158, 0, 0, + 1, 30, 0,128, 0, 3, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, + 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116, +101, 66, 97,115,101,100, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0,117,110,112, 97, + 99,107, 0, 0, 0, 0, 0, 23, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, + 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, + 0, 0, 0, 18, 0, 0, 0, 18, 0, 0, 0, 18, 0, 0, 0, 18, 0, 0, 0, 18, + 0, 0, 0, 18, 0, 0, 0, 18, 0, 0, 0, 19, 0, 0, 0, 19, 0, 0, 0, 20, + 0, 0, 0, 20, 0, 0, 0, 20, 0, 0, 0, 20, 0, 0, 0, 22, 0, 0, 0, 24, + 0, 0, 0, 4, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,115,114, 99, 95,105, +109, 97,103,101, 0, 0, 0, 0, 0, 22, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, + 0, 97,114,103, 0, 0, 0, 0, 0, 22, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, + 0,100,115,116, 95,105,109, 97,103,101, 0, 8, 0, 0, 0, 22, 0, 0, 0, 4, + 0, 0, 0, 0, 0, 0, 0,114,101,116, 0, 15, 0, 0, 0, 22, 0, 0, 0, 5, + 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119,105,100,116,104, 0, 7, 0, 0, + 0, 0, 0, 0, 0,104,101,105,103,104,116, 0, 12, 0, 0, 0, 0, 0, 0, 0, + 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 10, 0, 0, 0, 0, 0, 0, 0, +100, 97,116, 97, 95,116,121,112,101, 0, 5, 0, 0, 0, 0, 0, 0, 0,102,117, +110, 99, 0, 17, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 10, 0, 0, 0, 10, + 0, 0, 0, 10, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, + 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, + 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 25, 0, 0, 0, 6, 0, 0, 0, 9, + 0, 0, 0, 0, 0, 0, 0,102,117,110, 99,110, 97,109,101, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119,105,100,116,104, 0, 0, 0, + 0, 0, 16, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0,104,101,105,103,104,116, + 0, 0, 0, 0, 0, 16, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 99,111,108, +111,114, 95,115,112, 97, 99,101, 0, 0, 0, 0, 0, 16, 0, 0, 0, 10, 0, 0, + 0, 0, 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, 0, 0, 0, 0, 0, 16, + 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,102,117,110, 99, 0, 2, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, + 50, 0, 0, 0, 0, 5, 0, 11, 22, 0, 0, 0, 69, 1, 0, 0, 70, 1,128, 2, +133, 65, 0, 0,192, 1,128, 2, 5,130, 0, 0, 6,194, 64, 4, 65, 2, 1, 0, +128, 2, 0, 0, 28, 2,128, 1,156, 65, 0, 0,133, 1, 0, 0,192, 1, 0, 0, + 1, 66, 1, 0,213, 1,130, 3, 36, 2, 0, 0, 0, 0,128, 0, 0, 0, 0, 1, + 0, 0,128, 1, 0, 0, 0, 2, 0, 0,128, 2,137, 1,130, 3, 30, 0,128, 0, + 6, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 7, 0, 0, + 0, 0, 0, 0, 0, 97,115,115,101,114,116, 0, 4, 7, 0, 0, 0, 0, 0, 0, + 0,115,116,114,105,110,103, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0,102,111,114, +109, 97,116, 0, 4, 24, 0, 0, 0, 0, 0, 0, 0,117,110,100,101,102,105,110, +101,100, 32,102,117,110, 99,116,105,111,110, 32, 96, 37,115, 39, 0, 4, 4, 0, + 0, 0, 0, 0, 0, 0, 78,101,119, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 38, 0, 0, 0, 49, 0, 0, 0, 5, 2, 7, 10, 24, 0, 0, 0,197, 0, + 0, 0,198, 64,192, 1, 0, 1, 0, 0, 68, 1, 0, 0,132, 1,128, 0,196, 1, + 0, 1, 4, 2,128, 1,220,128, 0, 3, 4, 1, 0, 2, 64, 1, 0, 0,128, 1, +128, 0,192, 1,128, 1, 5,130, 0, 0, 64, 2, 0, 1, 28, 2, 0, 1, 28,129, + 0, 0, 26, 1, 0, 0, 22,192, 0,128, 64, 1, 0, 2,128, 1,128, 1, 94, 1, +128, 1, 22, 0, 0,128,222, 0, 0, 1, 30, 0,128, 0, 3, 0, 0, 0, 4, 3, + 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 73, +109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 4, 7, 0, 0, + 0, 0, 0, 0, 0,117,110,112, 97, 99,107, 0, 0, 0, 0, 0, 24, 0, 0, 0, + 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, + 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, + 43, 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, + 43, 0, 0, 0, 44, 0, 0, 0, 44, 0, 0, 0, 45, 0, 0, 0, 45, 0, 0, 0, + 45, 0, 0, 0, 45, 0, 0, 0, 47, 0, 0, 0, 49, 0, 0, 0, 5, 0, 0, 0, + 11, 0, 0, 0, 0, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 49, 0, 0, + 0, 0, 0, 23, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0,115,114, 99, 95,105, +109, 97,103,101, 50, 0, 0, 0, 0, 0, 23, 0, 0, 0, 4, 0, 0, 0, 0, 0, + 0, 0, 97,114,103, 0, 0, 0, 0, 0, 23, 0, 0, 0, 10, 0, 0, 0, 0, 0, + 0, 0,100,115,116, 95,105,109, 97,103,101, 0, 8, 0, 0, 0, 23, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0,114,101,116, 0, 16, 0, 0, 0, 23, 0, 0, 0, + 5, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119,105,100,116,104, 0, 7, 0, + 0, 0, 0, 0, 0, 0,104,101,105,103,104,116, 0, 12, 0, 0, 0, 0, 0, 0, + 0, 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 10, 0, 0, 0, 0, 0, 0, + 0,100, 97,116, 97, 95,116,121,112,101, 0, 5, 0, 0, 0, 0, 0, 0, 0,102, +117,110, 99, 0, 22, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 35, 0, 0, 0, + 35, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, + 35, 0, 0, 0, 35, 0, 0, 0, 38, 0, 0, 0, 38, 0, 0, 0, 38, 0, 0, 0, + 38, 0, 0, 0, 49, 0, 0, 0, 49, 0, 0, 0, 49, 0, 0, 0, 49, 0, 0, 0, + 49, 0, 0, 0, 49, 0, 0, 0, 49, 0, 0, 0, 50, 0, 0, 0, 6, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0,102,117,110, 99,110, 97,109,101, 0, 0, 0, 0, + 0, 21, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119,105,100,116,104, 0, 0, + 0, 0, 0, 21, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0,104,101,105,103,104, +116, 0, 0, 0, 0, 0, 21, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 99,111, +108,111,114, 95,115,112, 97, 99,101, 0, 0, 0, 0, 0, 21, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,102,117,110, 99, 0, 2, 0, 0, + 0, 21, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 25, 0, 0, 0, 50, 0, 0, + 0, 54, 0, 0, 0, 54, 0, 0, 0, 54, 0, 0, 0, 55, 0, 0, 0, 55, 0, 0, + 0, 55, 0, 0, 0, 55, 0, 0, 0, 55, 0, 0, 0, 55, 0, 0, 0, 56, 0, 0, + 0, 56, 0, 0, 0, 56, 0, 0, 0, 57, 0, 0, 0, 57, 0, 0, 0, 57, 0, 0, + 0, 57, 0, 0, 0, 2, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 79,110,101, + 83,111,117,114, 99,101, 79,110,101, 68,101,115,116, 0, 1, 0, 0, 0, 17, 0, + 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 84,119,111, 83,111,117,114, 99,101,115, + 79,110,101, 68,101,115,116, 0, 2, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, + +}; + + if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"../obj/imlua_fftw51/im_fftw_le64.lo")==0) lua_call(L, 0, 0); +} diff --git a/im/src/lua5/loh/im_fftw_le64w.loh b/im/src/lua5/loh/im_fftw_le64w.loh new file mode 100755 index 0000000..51fec14 --- /dev/null +++ b/im/src/lua5/loh/im_fftw_le64w.loh @@ -0,0 +1,115 @@ +/* code automatically generated by bin2c -- DO NOT EDIT */ +{ +/* #include'ing this file in a C program is equivalent to calling + if (luaL_loadfile(L,"../obj/imlua_fftw51/im_fftw_le64w.lo")==0) lua_pcall(L, 0, 0, 0); +*/ +/* ../obj/imlua_fftw51/im_fftw_le64w.lo */ +static const unsigned char B1[]={ + 27, 76,117, 97, 81, 0, 1, 4, 8, 4, 8, 0, 18, 0, 0, 0, 0, 0, 0, 0, + 64,108,117, 97, 53, 47,105,109, 95,102,102,116,119, 46,108,117, 97, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2, 8, 18, 0, 0, 0, 36, 0, 0, 0,100, 64, + 0, 0,128, 0,128, 0,193, 0, 0, 0,156, 64, 0, 1,128, 0, 0, 0,193, 64, + 0, 0, 3, 1, 0, 3,197,129, 0, 0,198,193,192, 3,156, 64, 0, 3,128, 0, + 0, 0,193, 0, 1, 0,156, 64, 0, 1,128, 0, 0, 0,193, 64, 1, 0,156, 64, + 0, 1, 30, 0,128, 0, 6, 0, 0, 0, 4, 24, 0, 0, 0, 0, 0, 0, 0, 80, +114,111, 99,101,115,115, 67,114,111,115,115, 67,111,114,114,101,108, 97,116,105, +111,110, 0, 4, 23, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 65, +117,116,111, 67,111,114,114,101,108, 97,116,105,111,110, 0, 4, 3, 0, 0, 0, + 0, 0, 0, 0,105,109, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0, 67, 70, 76, 79, + 65, 84, 0, 4, 11, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 70, + 70, 84, 0, 4, 12, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 73, + 70, 70, 84, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, + 20, 0, 0, 0, 0, 5, 0, 9, 17, 0, 0, 0, 69, 1, 0, 0, 70, 1,128, 2, +133, 65, 0, 0,192, 1,128, 2,156, 65, 0, 1,133, 1, 0, 0,192, 1, 0, 0, + 1,130, 0, 0,213, 1,130, 3, 36, 2, 0, 0, 0, 0,128, 0, 0, 0, 0, 1, + 0, 0,128, 1, 0, 0, 0, 2, 0, 0,128, 2,137, 1,130, 3, 30, 0,128, 0, + 3, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 7, 0, 0, + 0, 0, 0, 0, 0, 97,115,115,101,114,116, 0, 4, 4, 0, 0, 0, 0, 0, 0, + 0, 78,101,119, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, + 0, 19, 0, 0, 0, 5, 1, 7, 8, 17, 0, 0, 0,133, 0, 0, 0,134, 64, 64, + 1,192, 0, 0, 0, 4, 1, 0, 0, 68, 1,128, 0,132, 1, 0, 1,196, 1,128, + 1,156,128, 0, 3,196, 0, 0, 2, 0, 1, 0, 0, 64, 1, 0, 1,133,129, 0, + 0,192, 1,128, 0,156, 1, 0, 1,220, 64, 0, 0,158, 0, 0, 1, 30, 0,128, + 0, 3, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 17, 0, + 0, 0, 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115, +101,100, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0,117,110,112, 97, 99,107, 0, 0, + 0, 0, 0, 17, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, + 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 17, + 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, + 0, 0, 0, 17, 0, 0, 0, 18, 0, 0, 0, 19, 0, 0, 0, 3, 0, 0, 0, 10, + 0, 0, 0, 0, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 0, 0, 0, 0, + 0, 16, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 97,114,103, 0, 0, 0, 0, + 0, 16, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,100,115,116, 95,105,109, 97, +103,101, 0, 8, 0, 0, 0, 16, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, + 0, 0, 0,119,105,100,116,104, 0, 7, 0, 0, 0, 0, 0, 0, 0,104,101,105, +103,104,116, 0, 12, 0, 0, 0, 0, 0, 0, 0, 99,111,108,111,114, 95,115,112, + 97, 99,101, 0, 10, 0, 0, 0, 0, 0, 0, 0,100, 97,116, 97, 95,116,121,112, +101, 0, 5, 0, 0, 0, 0, 0, 0, 0,102,117,110, 99, 0, 17, 0, 0, 0, 8, + 0, 0, 0, 8, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 12, + 0, 0, 0, 12, 0, 0, 0, 12, 0, 0, 0, 12, 0, 0, 0, 19, 0, 0, 0, 19, + 0, 0, 0, 19, 0, 0, 0, 19, 0, 0, 0, 19, 0, 0, 0, 19, 0, 0, 0, 19, + 0, 0, 0, 20, 0, 0, 0, 6, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,102, +117,110, 99,110, 97,109,101, 0, 0, 0, 0, 0, 16, 0, 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0,119,105,100,116,104, 0, 0, 0, 0, 0, 16, 0, 0, 0, 7, 0, + 0, 0, 0, 0, 0, 0,104,101,105,103,104,116, 0, 0, 0, 0, 0, 16, 0, 0, + 0, 12, 0, 0, 0, 0, 0, 0, 0, 99,111,108,111,114, 95,115,112, 97, 99,101, + 0, 0, 0, 0, 0, 16, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,100, 97,116, + 97, 95,116,121,112,101, 0, 0, 0, 0, 0, 16, 0, 0, 0, 5, 0, 0, 0, 0, + 0, 0, 0,102,117,110, 99, 0, 2, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 41, 0, 0, 0, 0, 5, 0, 11, + 22, 0, 0, 0, 69, 1, 0, 0, 70, 1,128, 2,133, 65, 0, 0,192, 1,128, 2, + 5,130, 0, 0, 6,194, 64, 4, 65, 2, 1, 0,128, 2, 0, 0, 28, 2,128, 1, +156, 65, 0, 0,133, 1, 0, 0,192, 1, 0, 0, 1, 66, 1, 0,213, 1,130, 3, + 36, 2, 0, 0, 0, 0,128, 0, 0, 0, 0, 1, 0, 0,128, 1, 0, 0, 0, 2, + 0, 0,128, 2,137, 1,130, 3, 30, 0,128, 0, 6, 0, 0, 0, 4, 3, 0, 0, + 0, 0, 0, 0, 0,105,109, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0, 97,115,115, +101,114,116, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0,115,116,114,105,110,103, 0, + 4, 7, 0, 0, 0, 0, 0, 0, 0,102,111,114,109, 97,116, 0, 4, 24, 0, 0, + 0, 0, 0, 0, 0,117,110,100,101,102,105,110,101,100, 32,102,117,110, 99,116, +105,111,110, 32, 96, 37,115, 39, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 78,101, +119, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 40, 0, + 0, 0, 5, 2, 7, 10, 18, 0, 0, 0,197, 0, 0, 0,198, 64,192, 1, 0, 1, + 0, 0, 68, 1, 0, 0,132, 1,128, 0,196, 1, 0, 1, 4, 2,128, 1,220,128, + 0, 3, 4, 1, 0, 2, 64, 1, 0, 0,128, 1,128, 0,192, 1,128, 1, 5,130, + 0, 0, 64, 2, 0, 1, 28, 2, 0, 1, 28, 65, 0, 0,222, 0, 0, 1, 30, 0, +128, 0, 3, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 17, + 0, 0, 0, 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97, +115,101,100, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0,117,110,112, 97, 99,107, 0, + 0, 0, 0, 0, 18, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, + 35, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, + 38, 0, 0, 0, 38, 0, 0, 0, 38, 0, 0, 0, 38, 0, 0, 0, 38, 0, 0, 0, + 38, 0, 0, 0, 38, 0, 0, 0, 38, 0, 0, 0, 39, 0, 0, 0, 40, 0, 0, 0, + 4, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0,115,114, 99, 95,105,109, 97,103, +101, 49, 0, 0, 0, 0, 0, 17, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0,115, +114, 99, 95,105,109, 97,103,101, 50, 0, 0, 0, 0, 0, 17, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 97,114,103, 0, 0, 0, 0, 0, 17, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 0, 8, 0, 0, 0, + 17, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119,105,100,116, +104, 0, 7, 0, 0, 0, 0, 0, 0, 0,104,101,105,103,104,116, 0, 12, 0, 0, + 0, 0, 0, 0, 0, 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 10, 0, 0, + 0, 0, 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, 0, 5, 0, 0, 0, 0, + 0, 0, 0,102,117,110, 99, 0, 22, 0, 0, 0, 27, 0, 0, 0, 27, 0, 0, 0, + 30, 0, 0, 0, 30, 0, 0, 0, 30, 0, 0, 0, 30, 0, 0, 0, 30, 0, 0, 0, + 30, 0, 0, 0, 30, 0, 0, 0, 30, 0, 0, 0, 33, 0, 0, 0, 33, 0, 0, 0, + 33, 0, 0, 0, 33, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, + 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 41, 0, 0, 0, + 6, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,102,117,110, 99,110, 97,109,101, + 0, 0, 0, 0, 0, 21, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119,105,100, +116,104, 0, 0, 0, 0, 0, 21, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0,104, +101,105,103,104,116, 0, 0, 0, 0, 0, 21, 0, 0, 0, 12, 0, 0, 0, 0, 0, + 0, 0, 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 0, 0, 0, 0, 21, 0, + 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, 0, + 0, 0, 0, 0, 21, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,102,117,110, 99, + 0, 2, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 20, 0, 0, + 0, 41, 0, 0, 0, 45, 0, 0, 0, 45, 0, 0, 0, 45, 0, 0, 0, 46, 0, 0, + 0, 46, 0, 0, 0, 46, 0, 0, 0, 46, 0, 0, 0, 46, 0, 0, 0, 46, 0, 0, + 0, 47, 0, 0, 0, 47, 0, 0, 0, 47, 0, 0, 0, 48, 0, 0, 0, 48, 0, 0, + 0, 48, 0, 0, 0, 48, 0, 0, 0, 2, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, + 0, 79,110,101, 83,111,117,114, 99,101, 79,110,101, 68,101,115,116, 0, 1, 0, + 0, 0, 17, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 84,119,111, 83,111,117, +114, 99,101,115, 79,110,101, 68,101,115,116, 0, 2, 0, 0, 0, 17, 0, 0, 0, + 0, 0, 0, 0, +}; + + if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"../obj/imlua_fftw51/im_fftw_le64w.lo")==0) lua_pcall(L, 0, 0, 0); +} diff --git a/im/src/lua5/loh/im_image.loh b/im/src/lua5/loh/im_image.loh new file mode 100644 index 0000000..c43eb8c --- /dev/null +++ b/im/src/lua5/loh/im_image.loh @@ -0,0 +1,63 @@ +/* code automatically generated by bin2c -- DO NOT EDIT */ +{ +/* #include'ing this file in a C program is equivalent to calling + if (luaL_loadfile(L,"../obj/imlua51/im_image.lo")==0) lua_call(L, 0, 0); +*/ +/* ../obj/imlua51/im_image.lo */ +static const unsigned char B1[]={ + 27, 76,117, 97, 81, 0, 1, 4, 4, 4, 8, 0, 19, 0, 0, 0, 64,108,117, 97, + 53, 47,105,109, 95,105,109, 97,103,101, 46,108,117, 97, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2, 2, 4, 0, 0, 0, 5, 0, 0, 0,100, 0, 0, 0, 9, + 64,128,128, 30, 0,128, 0, 2, 0, 0, 0, 4, 3, 0, 0, 0,105,109, 0, 4, + 17, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 24, 0, 0, 0, 0, 5, 0, + 10, 74, 0, 0, 0, 90, 64, 0, 0, 22,128, 0,128, 75, 1, 64, 0, 92,129, 0, + 1, 64, 0,128, 2,154, 64, 0, 0, 22,128, 0,128, 75, 65, 64, 0, 92,129, 0, + 1,128, 0,128, 2,218, 64, 0, 0, 22,128, 0,128, 75,129, 64, 0, 92,129, 0, + 1,192, 0,128, 2, 26, 65, 0, 0, 22,128, 0,128, 75,193, 64, 0, 92,129, 0, + 1, 0, 1,128, 2, 69, 1, 1, 0,128, 1,128, 0, 92,129, 0, 1, 23, 64,193, + 2, 22,192, 0,128, 64, 1,128, 0,128, 1, 0, 0, 92,129, 0, 1, 64, 0,128, + 2, 69, 1, 1, 0,128, 1, 0, 1, 92,129, 0, 1, 23, 64,193, 2, 22,192, 0, +128, 64, 1, 0, 1,128, 1, 0, 0, 92,129, 0, 1,128, 0,128, 2, 69, 1, 1, + 0,128, 1,128, 1, 92,129, 0, 1, 23, 64,193, 2, 22,192, 0,128, 64, 1,128, + 1,128, 1, 0, 0, 92,129, 0, 1,192, 0,128, 2, 69, 1, 1, 0,128, 1, 0, + 2, 92,129, 0, 1, 23, 64,193, 2, 22,192, 0,128, 64, 1, 0, 2,128, 1, 0, + 0, 92,129, 0, 1, 0, 1,128, 2, 69,129, 1, 0, 70,193,193, 2,128, 1,128, + 0,192, 1, 0, 1, 0, 2,128, 1, 64, 2, 0, 2, 92,129,128, 2,139, 1, 66, + 0, 0, 2,128, 2,156, 65,128, 1,139, 65, 66, 0,156,129, 0, 1,154, 1, 0, + 0, 22, 64, 0,128,139,129,194, 2,156, 65, 0, 1, 94, 1, 0, 1, 30, 0,128, + 0, 11, 0, 0, 0, 4, 6, 0, 0, 0, 87,105,100,116,104, 0, 4, 7, 0, 0, + 0, 72,101,105,103,104,116, 0, 4, 11, 0, 0, 0, 67,111,108,111,114, 83,112, + 97, 99,101, 0, 4, 9, 0, 0, 0, 68, 97,116, 97, 84,121,112,101, 0, 4, 5, + 0, 0, 0,116,121,112,101, 0, 4, 9, 0, 0, 0,102,117,110, 99,116,105,111, +110, 0, 4, 3, 0, 0, 0,105,109, 0, 4, 12, 0, 0, 0, 73,109, 97,103,101, + 67,114,101, 97,116,101, 0, 4, 15, 0, 0, 0, 67,111,112,121, 65,116,116,114, +105, 98,117,116,101,115, 0, 4, 9, 0, 0, 0, 72, 97,115, 65,108,112,104, 97, + 0, 4, 9, 0, 0, 0, 65,100,100, 65,108,112,104, 97, 0, 0, 0, 0, 0, 74, + 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, + 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, + 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, + 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, + 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, + 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 15, + 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, + 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 16, 0, 0, 0, 16, + 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, + 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, + 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, + 0, 0, 0, 17, 0, 0, 0, 20, 0, 0, 0, 20, 0, 0, 0, 20, 0, 0, 0, 20, + 0, 0, 0, 20, 0, 0, 0, 20, 0, 0, 0, 20, 0, 0, 0, 21, 0, 0, 0, 21, + 0, 0, 0, 21, 0, 0, 0, 22, 0, 0, 0, 22, 0, 0, 0, 22, 0, 0, 0, 22, + 0, 0, 0, 22, 0, 0, 0, 22, 0, 0, 0, 23, 0, 0, 0, 24, 0, 0, 0, 6, + 0, 0, 0, 6, 0, 0, 0,105,109, 97,103,101, 0, 0, 0, 0, 0, 73, 0, 0, + 0, 6, 0, 0, 0,119,105,100,116,104, 0, 0, 0, 0, 0, 73, 0, 0, 0, 7, + 0, 0, 0,104,101,105,103,104,116, 0, 0, 0, 0, 0, 73, 0, 0, 0, 12, 0, + 0, 0, 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 0, 0, 0, 0, 73, 0, + 0, 0, 10, 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, 0, 0, 0, 0, 0, + 73, 0, 0, 0, 10, 0, 0, 0,110,101,119, 95,105,109, 97,103,101, 0, 63, 0, + 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 6, 0, 0, 0, 24, 0, + 0, 0, 6, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + + if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"../obj/imlua51/im_image.lo")==0) lua_call(L, 0, 0); +} diff --git a/im/src/lua5/loh/im_image_be32.loh b/im/src/lua5/loh/im_image_be32.loh new file mode 100755 index 0000000..04bafc0 --- /dev/null +++ b/im/src/lua5/loh/im_image_be32.loh @@ -0,0 +1,63 @@ +/* code automatically generated by bin2c -- DO NOT EDIT */ +{ +/* #include'ing this file in a C program is equivalent to calling + if (luaL_loadfile(L,"../obj/imlua51/im_image_be32.lo")==0) lua_call(L, 0, 0); +*/ +/* ../obj/imlua51/im_image_be32.lo */ +static const unsigned char B1[]={ + 27, 76,117, 97, 81, 0, 0, 4, 4, 4, 8, 0, 0, 0, 0, 19, 64,108,117, 97, + 53, 47,105,109, 95,105,109, 97,103,101, 46,108,117, 97, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0,100,128, +128, 64, 9, 0,128, 0, 30, 0, 0, 0, 2, 4, 0, 0, 0, 3,105,109, 0, 4, + 0, 0, 0, 17, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 24, 0, 5, 0, + 10, 0, 0, 0, 74, 0, 0, 64, 90,128, 0,128, 22, 0, 64, 1, 75, 1, 0,129, + 92, 2,128, 0, 64, 0, 0, 64,154,128, 0,128, 22, 0, 64, 65, 75, 1, 0,129, + 92, 2,128, 0,128, 0, 0, 64,218,128, 0,128, 22, 0, 64,129, 75, 1, 0,129, + 92, 2,128, 0,192, 0, 0, 65, 26,128, 0,128, 22, 0, 64,193, 75, 1, 0,129, + 92, 2,128, 1, 0, 0, 1, 1, 69, 0,128, 1,128, 1, 0,129, 92, 2,193, 64, + 23,128, 0,192, 22, 0,128, 1, 64, 0, 0, 1,128, 1, 0,129, 92, 2,128, 0, + 64, 0, 1, 1, 69, 1, 0, 1,128, 1, 0,129, 92, 2,193, 64, 23,128, 0,192, + 22, 1, 0, 1, 64, 0, 0, 1,128, 1, 0,129, 92, 2,128, 0,128, 0, 1, 1, + 69, 1,128, 1,128, 1, 0,129, 92, 2,193, 64, 23,128, 0,192, 22, 1,128, 1, + 64, 0, 0, 1,128, 1, 0,129, 92, 2,128, 0,192, 0, 1, 1, 69, 2, 0, 1, +128, 1, 0,129, 92, 2,193, 64, 23,128, 0,192, 22, 2, 0, 1, 64, 0, 0, 1, +128, 1, 0,129, 92, 2,128, 1, 0, 0, 1,129, 69, 2,193,193, 70, 0,128, 1, +128, 1, 0, 1,192, 1,128, 2, 0, 2, 0, 2, 64, 2,128,129, 92, 0, 66, 1, +139, 2,128, 2, 0, 1,128, 65,156, 0, 66, 65,139, 1, 0,129,156, 0, 0, 1, +154,128, 0, 64, 22, 2,194,129,139, 1, 0, 65,156, 1, 0, 1, 94, 0,128, 0, + 30, 0, 0, 0, 11, 4, 0, 0, 0, 6, 87,105,100,116,104, 0, 4, 0, 0, 0, + 7, 72,101,105,103,104,116, 0, 4, 0, 0, 0, 11, 67,111,108,111,114, 83,112, + 97, 99,101, 0, 4, 0, 0, 0, 9, 68, 97,116, 97, 84,121,112,101, 0, 4, 0, + 0, 0, 5,116,121,112,101, 0, 4, 0, 0, 0, 9,102,117,110, 99,116,105,111, +110, 0, 4, 0, 0, 0, 3,105,109, 0, 4, 0, 0, 0, 12, 73,109, 97,103,101, + 67,114,101, 97,116,101, 0, 4, 0, 0, 0, 15, 67,111,112,121, 65,116,116,114, +105, 98,117,116,101,115, 0, 4, 0, 0, 0, 9, 72, 97,115, 65,108,112,104, 97, + 0, 4, 0, 0, 0, 9, 65,100,100, 65,108,112,104, 97, 0, 0, 0, 0, 0, 0, + 0, 0, 74, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, + 0, 0, 8, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, + 0, 0, 9, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, + 0, 0, 10, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, + 0, 0, 11, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, + 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, + 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, + 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 16, 0, + 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, + 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 17, 0, 0, 0, 17, 0, + 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, + 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 20, 0, 0, 0, 20, 0, 0, 0, 20, 0, + 0, 0, 20, 0, 0, 0, 20, 0, 0, 0, 20, 0, 0, 0, 20, 0, 0, 0, 21, 0, + 0, 0, 21, 0, 0, 0, 21, 0, 0, 0, 22, 0, 0, 0, 22, 0, 0, 0, 22, 0, + 0, 0, 22, 0, 0, 0, 22, 0, 0, 0, 22, 0, 0, 0, 23, 0, 0, 0, 24, 0, + 0, 0, 6, 0, 0, 0, 6,105,109, 97,103,101, 0, 0, 0, 0, 0, 0, 0, 0, + 73, 0, 0, 0, 6,119,105,100,116,104, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, + 0, 0, 7,104,101,105,103,104,116, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, + 0, 12, 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 0, 0, 0, 0, 0, 0, + 0, 73, 0, 0, 0, 10,100, 97,116, 97, 95,116,121,112,101, 0, 0, 0, 0, 0, + 0, 0, 0, 73, 0, 0, 0, 10,110,101,119, 95,105,109, 97,103,101, 0, 0, 0, + 0, 63, 0, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 6, 0, 0, + 0, 24, 0, 0, 0, 6, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, +}; + + if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"../obj/imlua51/im_image_be32.lo")==0) lua_call(L, 0, 0); +} diff --git a/im/src/lua5/loh/im_image_be64.loh b/im/src/lua5/loh/im_image_be64.loh new file mode 100644 index 0000000..6aed993 --- /dev/null +++ b/im/src/lua5/loh/im_image_be64.loh @@ -0,0 +1,68 @@ +/* code automatically generated by bin2c -- DO NOT EDIT */ +{ +/* #include'ing this file in a C program is equivalent to calling + if (luaL_loadfile(L,"../obj/imlua51/im_image_be64.lo")==0) lua_call(L, 0, 0); +*/ +/* ../obj/imlua51/im_image_be64.lo */ +static const unsigned char B1[]={ + 27, 76,117, 97, 81, 0, 1, 4, 8, 4, 8, 0, 19, 0, 0, 0, 0, 0, 0, 0, + 64,108,117, 97, 53, 47,105,109, 95,105,109, 97,103,101, 46,108,117, 97, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 4, 0, 0, 0, 5, 0, 0, 0,100, + 0, 0, 0, 9, 64,128,128, 30, 0,128, 0, 2, 0, 0, 0, 4, 3, 0, 0, 0, + 0, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 73,109, 97,103, +101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 6, 0, 0, 0, 24, 0, 0, 0, 0, 5, 0, 10, 74, 0, 0, + 0, 90, 64, 0, 0, 22,128, 0,128, 75, 1, 64, 0, 92,129, 0, 1, 64, 0,128, + 2,154, 64, 0, 0, 22,128, 0,128, 75, 65, 64, 0, 92,129, 0, 1,128, 0,128, + 2,218, 64, 0, 0, 22,128, 0,128, 75,129, 64, 0, 92,129, 0, 1,192, 0,128, + 2, 26, 65, 0, 0, 22,128, 0,128, 75,193, 64, 0, 92,129, 0, 1, 0, 1,128, + 2, 69, 1, 1, 0,128, 1,128, 0, 92,129, 0, 1, 23, 64,193, 2, 22,192, 0, +128, 64, 1,128, 0,128, 1, 0, 0, 92,129, 0, 1, 64, 0,128, 2, 69, 1, 1, + 0,128, 1, 0, 1, 92,129, 0, 1, 23, 64,193, 2, 22,192, 0,128, 64, 1, 0, + 1,128, 1, 0, 0, 92,129, 0, 1,128, 0,128, 2, 69, 1, 1, 0,128, 1,128, + 1, 92,129, 0, 1, 23, 64,193, 2, 22,192, 0,128, 64, 1,128, 1,128, 1, 0, + 0, 92,129, 0, 1,192, 0,128, 2, 69, 1, 1, 0,128, 1, 0, 2, 92,129, 0, + 1, 23, 64,193, 2, 22,192, 0,128, 64, 1, 0, 2,128, 1, 0, 0, 92,129, 0, + 1, 0, 1,128, 2, 69,129, 1, 0, 70,193,193, 2,128, 1,128, 0,192, 1, 0, + 1, 0, 2,128, 1, 64, 2, 0, 2, 92,129,128, 2,139, 1, 66, 0, 0, 2,128, + 2,156, 65,128, 1,139, 65, 66, 0,156,129, 0, 1,154, 1, 0, 0, 22, 64, 0, +128,139,129,194, 2,156, 65, 0, 1, 94, 1, 0, 1, 30, 0,128, 0, 11, 0, 0, + 0, 4, 6, 0, 0, 0, 0, 0, 0, 0, 87,105,100,116,104, 0, 4, 7, 0, 0, + 0, 0, 0, 0, 0, 72,101,105,103,104,116, 0, 4, 11, 0, 0, 0, 0, 0, 0, + 0, 67,111,108,111,114, 83,112, 97, 99,101, 0, 4, 9, 0, 0, 0, 0, 0, 0, + 0, 68, 97,116, 97, 84,121,112,101, 0, 4, 5, 0, 0, 0, 0, 0, 0, 0,116, +121,112,101, 0, 4, 9, 0, 0, 0, 0, 0, 0, 0,102,117,110, 99,116,105,111, +110, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 12, 0, 0, 0, 0, + 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 0, 4, 15, 0, 0, 0, + 0, 0, 0, 0, 67,111,112,121, 65,116,116,114,105, 98,117,116,101,115, 0, 4, + 9, 0, 0, 0, 0, 0, 0, 0, 72, 97,115, 65,108,112,104, 97, 0, 4, 9, 0, + 0, 0, 0, 0, 0, 0, 65,100,100, 65,108,112,104, 97, 0, 0, 0, 0, 0, 74, + 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, + 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, + 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, + 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, + 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, + 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 15, + 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, + 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 16, 0, 0, 0, 16, + 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, + 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, + 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, + 0, 0, 0, 17, 0, 0, 0, 20, 0, 0, 0, 20, 0, 0, 0, 20, 0, 0, 0, 20, + 0, 0, 0, 20, 0, 0, 0, 20, 0, 0, 0, 20, 0, 0, 0, 21, 0, 0, 0, 21, + 0, 0, 0, 21, 0, 0, 0, 22, 0, 0, 0, 22, 0, 0, 0, 22, 0, 0, 0, 22, + 0, 0, 0, 22, 0, 0, 0, 22, 0, 0, 0, 23, 0, 0, 0, 24, 0, 0, 0, 6, + 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,105,109, 97,103,101, 0, 0, 0, 0, + 0, 73, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119,105,100,116,104, 0, 0, + 0, 0, 0, 73, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0,104,101,105,103,104, +116, 0, 0, 0, 0, 0, 73, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 99,111, +108,111,114, 95,115,112, 97, 99,101, 0, 0, 0, 0, 0, 73, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, 0, 0, 0, 0, 0, + 73, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,110,101,119, 95,105,109, 97,103, +101, 0, 63, 0, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 6, 0, + 0, 0, 24, 0, 0, 0, 6, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, +}; + + if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"../obj/imlua51/im_image_be64.lo")==0) lua_call(L, 0, 0); +} diff --git a/im/src/lua5/loh/im_image_le64.loh b/im/src/lua5/loh/im_image_le64.loh new file mode 100755 index 0000000..6a4d127 --- /dev/null +++ b/im/src/lua5/loh/im_image_le64.loh @@ -0,0 +1,68 @@ +/* code automatically generated by bin2c -- DO NOT EDIT */ +{ +/* #include'ing this file in a C program is equivalent to calling + if (luaL_loadfile(L,"../obj/imlua51/im_image_le64.lo")==0) lua_call(L, 0, 0); +*/ +/* ../obj/imlua51/im_image_le64.lo */ +static const unsigned char B1[]={ + 27, 76,117, 97, 81, 0, 1, 4, 8, 4, 8, 0, 19, 0, 0, 0, 0, 0, 0, 0, + 64,108,117, 97, 53, 47,105,109, 95,105,109, 97,103,101, 46,108,117, 97, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 4, 0, 0, 0, 5, 0, 0, 0,100, + 0, 0, 0, 9, 64,128,128, 30, 0,128, 0, 2, 0, 0, 0, 4, 3, 0, 0, 0, + 0, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 73,109, 97,103, +101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 6, 0, 0, 0, 24, 0, 0, 0, 0, 5, 0, 10, 74, 0, 0, + 0, 90, 64, 0, 0, 22,128, 0,128, 75, 1, 64, 0, 92,129, 0, 1, 64, 0,128, + 2,154, 64, 0, 0, 22,128, 0,128, 75, 65, 64, 0, 92,129, 0, 1,128, 0,128, + 2,218, 64, 0, 0, 22,128, 0,128, 75,129, 64, 0, 92,129, 0, 1,192, 0,128, + 2, 26, 65, 0, 0, 22,128, 0,128, 75,193, 64, 0, 92,129, 0, 1, 0, 1,128, + 2, 69, 1, 1, 0,128, 1,128, 0, 92,129, 0, 1, 23, 64,193, 2, 22,192, 0, +128, 64, 1,128, 0,128, 1, 0, 0, 92,129, 0, 1, 64, 0,128, 2, 69, 1, 1, + 0,128, 1, 0, 1, 92,129, 0, 1, 23, 64,193, 2, 22,192, 0,128, 64, 1, 0, + 1,128, 1, 0, 0, 92,129, 0, 1,128, 0,128, 2, 69, 1, 1, 0,128, 1,128, + 1, 92,129, 0, 1, 23, 64,193, 2, 22,192, 0,128, 64, 1,128, 1,128, 1, 0, + 0, 92,129, 0, 1,192, 0,128, 2, 69, 1, 1, 0,128, 1, 0, 2, 92,129, 0, + 1, 23, 64,193, 2, 22,192, 0,128, 64, 1, 0, 2,128, 1, 0, 0, 92,129, 0, + 1, 0, 1,128, 2, 69,129, 1, 0, 70,193,193, 2,128, 1,128, 0,192, 1, 0, + 1, 0, 2,128, 1, 64, 2, 0, 2, 92,129,128, 2,139, 1, 66, 0, 0, 2,128, + 2,156, 65,128, 1,139, 65, 66, 0,156,129, 0, 1,154, 1, 0, 0, 22, 64, 0, +128,139,129,194, 2,156, 65, 0, 1, 94, 1, 0, 1, 30, 0,128, 0, 11, 0, 0, + 0, 4, 6, 0, 0, 0, 0, 0, 0, 0, 87,105,100,116,104, 0, 4, 7, 0, 0, + 0, 0, 0, 0, 0, 72,101,105,103,104,116, 0, 4, 11, 0, 0, 0, 0, 0, 0, + 0, 67,111,108,111,114, 83,112, 97, 99,101, 0, 4, 9, 0, 0, 0, 0, 0, 0, + 0, 68, 97,116, 97, 84,121,112,101, 0, 4, 5, 0, 0, 0, 0, 0, 0, 0,116, +121,112,101, 0, 4, 9, 0, 0, 0, 0, 0, 0, 0,102,117,110, 99,116,105,111, +110, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 12, 0, 0, 0, 0, + 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 0, 4, 15, 0, 0, 0, + 0, 0, 0, 0, 67,111,112,121, 65,116,116,114,105, 98,117,116,101,115, 0, 4, + 9, 0, 0, 0, 0, 0, 0, 0, 72, 97,115, 65,108,112,104, 97, 0, 4, 9, 0, + 0, 0, 0, 0, 0, 0, 65,100,100, 65,108,112,104, 97, 0, 0, 0, 0, 0, 74, + 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, + 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, + 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, + 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, + 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, + 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 15, + 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, + 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 16, 0, 0, 0, 16, + 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, + 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, + 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 17, + 0, 0, 0, 17, 0, 0, 0, 20, 0, 0, 0, 20, 0, 0, 0, 20, 0, 0, 0, 20, + 0, 0, 0, 20, 0, 0, 0, 20, 0, 0, 0, 20, 0, 0, 0, 21, 0, 0, 0, 21, + 0, 0, 0, 21, 0, 0, 0, 22, 0, 0, 0, 22, 0, 0, 0, 22, 0, 0, 0, 22, + 0, 0, 0, 22, 0, 0, 0, 22, 0, 0, 0, 23, 0, 0, 0, 24, 0, 0, 0, 6, + 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,105,109, 97,103,101, 0, 0, 0, 0, + 0, 73, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119,105,100,116,104, 0, 0, + 0, 0, 0, 73, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0,104,101,105,103,104, +116, 0, 0, 0, 0, 0, 73, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 99,111, +108,111,114, 95,115,112, 97, 99,101, 0, 0, 0, 0, 0, 73, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, 0, 0, 0, 0, 0, + 73, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,110,101,119, 95,105,109, 97,103, +101, 0, 63, 0, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 6, 0, + 0, 0, 24, 0, 0, 0, 6, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, +}; + + if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"../obj/imlua51/im_image_le64.lo")==0) lua_call(L, 0, 0); +} diff --git a/im/src/lua5/loh/im_process.loh b/im/src/lua5/loh/im_process.loh new file mode 100755 index 0000000..47dc66e --- /dev/null +++ b/im/src/lua5/loh/im_process.loh @@ -0,0 +1,817 @@ +/* code automatically generated by bin2c -- DO NOT EDIT */ +{ +/* #include'ing this file in a C program is equivalent to calling + if (luaL_loadfile(L,"../obj/imlua_process51/im_process.lo")==0) lua_call(L, 0, 0); +*/ +/* ../obj/imlua_process51/im_process.lo */ +static const unsigned char B1[]={ + 27, 76,117, 97, 81, 0, 1, 4, 4, 4, 8, 0, 21, 0, 0, 0, 64,108,117, 97, + 53, 47,105,109, 95,112,114,111, 99,101,115,115, 46,108,117, 97, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2, 13,144, 1, 0, 0, 36, 0, 0, 0,100, 64, 0, + 0,164,128, 0, 0,228,192, 0, 0, 36, 1, 1, 0,100, 65, 1, 0,128, 1, 0, + 0,193, 1, 0, 0, 3, 2, 0, 5,197, 66, 0, 0,198,130,192, 5,156, 65, 0, + 3,128, 1, 0, 0,193,193, 0, 0,156, 65, 0, 1,128, 1, 0, 0,193, 1, 1, + 0,156, 65, 0, 1,128, 1, 0, 0,193, 65, 1, 0,156, 65, 0, 1,128, 1, 0, + 0,193,129, 1, 0, 1,194, 1, 0, 64, 2,128, 2,133, 66, 0, 0,134, 2, 66, + 5,197, 66, 0, 0,198, 66,194, 5,156, 65, 0, 3,128, 1, 0, 0,193,129, 2, + 0,156, 65, 0, 1,128, 1, 0, 0,193,193, 2, 0, 3, 2, 0, 5,197, 66, 0, + 0,198, 2,195, 5,156, 65, 0, 3,128, 1, 0, 0,193, 65, 3, 0, 3, 2,128, + 4,133, 66, 0, 0,134,130, 67, 5,195, 2,128, 5,156, 65, 0, 3,133, 65, 0, + 0,228,129, 1, 0,137,193,129,135,133, 65, 0, 0,228,193, 1, 0,137,193, 1, +136,128, 1, 0, 0,193, 65, 4, 0, 36, 2, 2, 0,100, 66, 2, 0,156, 65, 0, + 2,133, 65, 0, 0,228,129, 2, 0,137,193, 1,137,128, 1,128, 0,193,193, 4, + 0,156, 65, 0, 1,133, 65, 0, 0,228,193, 2, 0,137,193, 1,138,133, 65, 0, + 0,228, 1, 3, 0,137,193,129,138,128, 1, 0, 0,193,129, 5, 0,156, 65, 0, + 1,128, 1, 0, 0,193,193, 5, 0, 36, 66, 3, 0,100,130, 3, 0,156, 65, 0, + 2,128, 1, 0, 0,193, 1, 6, 0,156, 65, 0, 1,128, 1, 0, 0,193, 65, 6, + 0,156, 65, 0, 1,128, 1, 0, 0,193,129, 6, 0,156, 65, 0, 1,128, 1, 0, + 0,193,193, 6, 0,156, 65, 0, 1,128, 1, 0, 0,193, 1, 7, 0,156, 65, 0, + 1,128, 1, 0, 0,193, 65, 7, 0,156, 65, 0, 1,128, 1, 0, 0,193,129, 7, + 0,156, 65, 0, 1,128, 1, 0, 0,193,193, 7, 0,156, 65, 0, 1,128, 1, 0, + 0,193, 1, 8, 0,156, 65, 0, 1,128, 1, 0, 0,193, 65, 8, 0,156, 65, 0, + 1,128, 1, 0, 0,193,129, 8, 0,156, 65, 0, 1,128, 1, 0, 0,193,193, 8, + 0,156, 65, 0, 1,128, 1, 0, 0,193, 1, 9, 0,156, 65, 0, 1,128, 1, 0, + 0,193, 65, 9, 0,156, 65, 0, 1,128, 1, 0, 0,193,129, 9, 0,156, 65, 0, + 1,128, 1, 0, 0,193,193, 9, 0,156, 65, 0, 1,128, 1, 0, 0,193, 1, 10, + 0,156, 65, 0, 1,128, 1, 0, 0,193, 65, 10, 0,156, 65, 0, 1,128, 1, 0, + 0,193,129, 10, 0,156, 65, 0, 1,128, 1, 0, 0,193,193, 10, 0,156, 65, 0, + 1,128, 1, 0, 0,193, 1, 11, 0,156, 65, 0, 1,128, 1, 0, 0,193, 65, 11, + 0,156, 65, 0, 1,128, 1, 0, 0,193,129, 11, 0,156, 65, 0, 1,128, 1, 0, + 0,193,193, 11, 0,156, 65, 0, 1,128, 1, 0, 0,193, 1, 12, 0,156, 65, 0, + 1,128, 1, 0, 0,193, 65, 12, 0,156, 65, 0, 1,128, 1, 0, 0,193,129, 12, + 0,156, 65, 0, 1,128, 1, 0, 0,193,193, 12, 0,156, 65, 0, 1,128, 1, 0, + 0,193, 1, 13, 0,156, 65, 0, 1,128, 1, 0, 0,193, 65, 13, 0,156, 65, 0, + 1,128, 1, 0, 0,193,129, 13, 0,156, 65, 0, 1,128, 1, 0, 0,193,193, 13, + 0,156, 65, 0, 1,128, 1,128, 1,193, 1, 14, 0, 3, 2, 0, 4,100,194, 3, + 0,156, 65, 0, 2,133, 65, 0, 0,228, 1, 4, 0,137,193,129,156,164, 65, 4, + 0,192, 1, 0, 0, 1,130, 14, 0, 67, 2,128, 5, 0, 3, 0, 3,220, 65, 0, + 3,192, 1, 0, 0, 1,194, 14, 0, 67, 2,128, 5, 0, 3, 0, 3,220, 65, 0, + 3,192, 1, 0, 0, 1, 2, 15, 0,220, 65, 0, 1,192, 1, 0, 0, 1, 66, 15, + 0,220, 65, 0, 1,192, 1, 0, 0, 1,130, 15, 0,220, 65, 0, 1,192, 1, 0, + 0, 1,194, 15, 0,220, 65, 0, 1,192, 1, 0, 0, 1, 2, 16, 0,220, 65, 0, + 1,192, 1, 0, 0, 1, 66, 16, 0,220, 65, 0, 1,192, 1,128, 0, 1,130, 16, + 0,220, 65, 0, 1,192, 1, 0, 0, 1,194, 16, 0,220, 65, 0, 1,192, 1, 0, + 0, 1, 2, 17, 0,220, 65, 0, 1,192, 1,128, 0, 1, 66, 17, 0,220, 65, 0, + 1,197, 65, 0, 0, 36,130, 4, 0,201, 1, 2,163,192, 1,128, 0, 1,194, 17, + 0,220, 65, 0, 1,192, 1, 0, 1, 1, 2, 18, 0,220, 65, 0, 1,192, 1,128, + 1, 1, 66, 18, 0,220, 65, 0, 1,192, 1,128, 0, 1,130, 18, 0, 67, 2,128, + 5, 5, 67, 0, 0, 6,195, 82, 6,220, 65, 0, 3,197, 65, 0, 0, 36,194, 4, + 0,201, 1, 2,166,197, 65, 0, 0, 36, 2, 5, 0,201, 1,130,166,192, 1,128, + 0, 1,130, 19, 0,220, 65, 0, 1,192, 1, 0, 0, 1,194, 19, 0,220, 65, 0, + 1,192, 1, 0, 0, 1, 2, 20, 0, 67, 2, 0, 5,197, 66, 0, 0,198, 66,212, + 5, 3, 3, 0, 6,220, 65, 0, 3,192, 1, 0, 0, 1,130, 20, 0,220, 65, 0, + 1,192, 1, 0, 0, 1,194, 20, 0,220, 65, 0, 1,192, 1, 0, 0, 1, 2, 21, + 0,220, 65, 0, 1,197, 65, 0, 0, 36, 66, 5, 0,201, 1,130,170,192, 1, 0, + 2, 1,130, 21, 0, 67, 2, 0, 5,197, 66, 0, 0,198, 2,194, 5, 5, 67, 0, + 0, 6, 3, 67, 6,220, 65, 0, 3,192, 1, 0, 1, 1,194, 21, 0, 67, 2, 0, + 5,197, 66, 0, 0,198, 2,214, 5, 5, 67, 0, 0, 6, 67, 86, 6,220, 65, 0, + 3,197, 65, 0, 0, 36,130, 5, 0,201, 1, 2,173,197, 65, 0, 0, 36,194, 5, + 0,201, 1,130,173,192, 1, 0, 0, 1, 2, 23, 0, 67, 2,128, 5, 5, 67, 0, + 0, 6, 3, 67, 6,220, 65, 0, 3,192, 1, 0, 0, 1, 66, 23, 0,220, 65, 0, + 1,192, 1,128, 0, 1,130, 23, 0,220, 65, 0, 1,192, 1, 0, 0, 1,194, 23, + 0,220, 65, 0, 1,192, 1, 0, 0, 1, 2, 24, 0,220, 65, 0, 1,192, 1, 0, + 0, 1, 66, 24, 0,220, 65, 0, 1,192, 1, 0, 0, 1,130, 24, 0,220, 65, 0, + 1,192, 1, 0, 0, 1,194, 24, 0, 67, 2,128, 5, 5, 67, 0, 0, 6, 67, 86, + 6,220, 65, 0, 3,192, 1, 0, 0, 1, 2, 25, 0, 67, 2,128, 5, 5, 67, 0, + 0, 6, 67, 86, 6,220, 65, 0, 3,192, 1, 0, 0, 1, 66, 25, 0,220, 65, 0, + 1,192, 1, 0, 0, 1,130, 25, 0, 67, 2, 0, 5,197, 66, 0, 0,198,130,195, + 5, 3, 3, 0, 6,220, 65, 0, 3,192, 1, 0, 0, 1,194, 25, 0, 67, 2, 0, + 5,197, 66, 0, 0,198,130,195, 5, 3, 3, 0, 6,220, 65, 0, 3,192, 1, 0, + 0, 1, 2, 26, 0, 67, 2, 0, 5,197, 66, 0, 0,198,130,195, 5, 3, 3, 0, + 6,220, 65, 0, 3,192, 1,128, 0, 1, 66, 26, 0,220, 65, 0, 1,192, 1, 0, + 0, 1,130, 26, 0, 67, 2, 0, 5,197, 66, 0, 0,198,130,195, 5, 3, 3, 0, + 6,220, 65, 0, 3,192, 1, 0, 0, 1,194, 26, 0, 67, 2, 0, 5,197, 66, 0, + 0,198,130,195, 5, 3, 3, 0, 6,220, 65, 0, 3,192, 1, 0, 0, 1, 2, 27, + 0,220, 65, 0, 1,192, 1, 0, 0, 1, 66, 27, 0,220, 65, 0, 1,192, 1, 0, + 0, 1,130, 27, 0,220, 65, 0, 1,192, 1, 0, 0, 1,194, 27, 0, 67, 2, 0, + 5,197, 66, 0, 0,198,130,195, 5, 3, 3, 0, 6,220, 65, 0, 3,192, 1, 0, + 0, 1, 2, 28, 0, 67, 2, 0, 5,197, 66, 0, 0,198,130,195, 5, 3, 3, 0, + 6,220, 65, 0, 3,192, 1, 0, 0, 1, 66, 28, 0,220, 65, 0, 1,192, 1, 0, + 0, 1,130, 28, 0,220, 65, 0, 1, 30, 0,128, 0,115, 0, 0, 0, 4, 19, 0, + 0, 0, 65,110, 97,108,121,122,101, 70,105,110,100, 82,101,103,105,111,110,115, + 0, 4, 3, 0, 0, 0,105,109, 0, 4, 7, 0, 0, 0, 85, 83, 72, 79, 82, 84, + 0, 4, 21, 0, 0, 0, 80,114,111, 99,101,115,115, 80,101,114,105,109,101,116, +101,114, 76,105,110,101, 0, 4, 20, 0, 0, 0, 80,114,111, 99,101,115,115, 82, +101,109,111,118,101, 66,121, 65,114,101, 97, 0, 4, 17, 0, 0, 0, 80,114,111, + 99,101,115,115, 70,105,108,108, 72,111,108,101,115, 0, 4, 18, 0, 0, 0, 80, +114,111, 99,101,115,115, 72,111,117,103,104, 76,105,110,101,115, 0, 3, 0, 0, + 0, 0, 0,128,102, 64, 4, 5, 0, 0, 0, 71, 82, 65, 89, 0, 4, 4, 0, 0, + 0, 73, 78, 84, 0, 4, 22, 0, 0, 0, 80,114,111, 99,101,115,115, 72,111,117, +103,104, 76,105,110,101,115, 68,114, 97,119, 0, 4, 25, 0, 0, 0, 80,114,111, + 99,101,115,115, 68,105,115,116, 97,110, 99,101, 84,114, 97,110,115,102,111,114, +109, 0, 4, 6, 0, 0, 0, 70, 76, 79, 65, 84, 0, 4, 23, 0, 0, 0, 80,114, +111, 99,101,115,115, 82,101,103,105,111,110, 97,108, 77, 97,120,105,109,117,109, + 0, 4, 7, 0, 0, 0, 66, 73, 78, 65, 82, 89, 0, 4, 17, 0, 0, 0, 80,114, +111, 99,101,115,115, 82,101,100,117, 99,101, 78,101,119, 0, 4, 17, 0, 0, 0, + 80,114,111, 99,101,115,115, 82,101,115,105,122,101, 78,101,119, 0, 4, 17, 0, + 0, 0, 80,114,111, 99,101,115,115, 82,101,100,117, 99,101, 66,121, 52, 0, 4, + 15, 0, 0, 0, 80,114,111, 99,101,115,115, 67,114,111,112, 78,101,119, 0, 4, + 14, 0, 0, 0, 80,114,111, 99,101,115,115, 73,110,115,101,114,116, 0, 4, 21, + 0, 0, 0, 80,114,111, 99,101,115,115, 65,100,100, 77, 97,114,103,105,110,115, + 78,101,119, 0, 4, 17, 0, 0, 0, 80,114,111, 99,101,115,115, 82,111,116, 97, +116,101, 78,101,119, 0, 4, 17, 0, 0, 0, 80,114,111, 99,101,115,115, 82,111, +116, 97,116,101, 82,101,102, 0, 4, 16, 0, 0, 0, 80,114,111, 99,101,115,115, + 82,111,116, 97,116,101, 57, 48, 0, 4, 17, 0, 0, 0, 80,114,111, 99,101,115, +115, 82,111,116, 97,116,101, 49, 56, 48, 0, 4, 14, 0, 0, 0, 80,114,111, 99, +101,115,115, 77,105,114,114,111,114, 0, 4, 12, 0, 0, 0, 80,114,111, 99,101, +115,115, 70,108,105,112, 0, 4, 14, 0, 0, 0, 80,114,111, 99,101,115,115, 82, + 97,100,105, 97,108, 0, 4, 25, 0, 0, 0, 80,114,111, 99,101,115,115, 71,114, + 97,121, 77,111,114,112,104, 67,111,110,118,111,108,118,101, 0, 4, 22, 0, 0, + 0, 80,114,111, 99,101,115,115, 71,114, 97,121, 77,111,114,112,104, 69,114,111, +100,101, 0, 4, 23, 0, 0, 0, 80,114,111, 99,101,115,115, 71,114, 97,121, 77, +111,114,112,104, 68,105,108, 97,116,101, 0, 4, 21, 0, 0, 0, 80,114,111, 99, +101,115,115, 71,114, 97,121, 77,111,114,112,104, 79,112,101,110, 0, 4, 22, 0, + 0, 0, 80,114,111, 99,101,115,115, 71,114, 97,121, 77,111,114,112,104, 67,108, +111,115,101, 0, 4, 23, 0, 0, 0, 80,114,111, 99,101,115,115, 71,114, 97,121, + 77,111,114,112,104, 84,111,112, 72, 97,116, 0, 4, 21, 0, 0, 0, 80,114,111, + 99,101,115,115, 71,114, 97,121, 77,111,114,112,104, 87,101,108,108, 0, 4, 25, + 0, 0, 0, 80,114,111, 99,101,115,115, 71,114, 97,121, 77,111,114,112,104, 71, +114, 97,100,105,101,110,116, 0, 4, 24, 0, 0, 0, 80,114,111, 99,101,115,115, + 66,105,110, 77,111,114,112,104, 67,111,110,118,111,108,118,101, 0, 4, 21, 0, + 0, 0, 80,114,111, 99,101,115,115, 66,105,110, 77,111,114,112,104, 69,114,111, +100,101, 0, 4, 22, 0, 0, 0, 80,114,111, 99,101,115,115, 66,105,110, 77,111, +114,112,104, 68,105,108, 97,116,101, 0, 4, 20, 0, 0, 0, 80,114,111, 99,101, +115,115, 66,105,110, 77,111,114,112,104, 79,112,101,110, 0, 4, 21, 0, 0, 0, + 80,114,111, 99,101,115,115, 66,105,110, 77,111,114,112,104, 67,108,111,115,101, + 0, 4, 23, 0, 0, 0, 80,114,111, 99,101,115,115, 66,105,110, 77,111,114,112, +104, 79,117,116,108,105,110,101, 0, 4, 20, 0, 0, 0, 80,114,111, 99,101,115, +115, 66,105,110, 77,111,114,112,104, 84,104,105,110, 0, 4, 22, 0, 0, 0, 80, +114,111, 99,101,115,115, 77,101,100,105, 97,110, 67,111,110,118,111,108,118,101, + 0, 4, 21, 0, 0, 0, 80,114,111, 99,101,115,115, 82, 97,110,103,101, 67,111, +110,118,111,108,118,101, 0, 4, 27, 0, 0, 0, 80,114,111, 99,101,115,115, 82, + 97,110,107, 67,108,111,115,101,115,116, 67,111,110,118,111,108,118,101, 0, 4, + 23, 0, 0, 0, 80,114,111, 99,101,115,115, 82, 97,110,107, 77, 97,120, 67,111, +110,118,111,108,118,101, 0, 4, 23, 0, 0, 0, 80,114,111, 99,101,115,115, 82, + 97,110,107, 77,105,110, 67,111,110,118,111,108,118,101, 0, 4, 16, 0, 0, 0, + 80,114,111, 99,101,115,115, 67,111,110,118,111,108,118,101, 0, 4, 19, 0, 0, + 0, 80,114,111, 99,101,115,115, 67,111,110,118,111,108,118,101, 83,101,112, 0, + 4, 19, 0, 0, 0, 80,114,111, 99,101,115,115, 67,111,110,118,111,108,118,101, + 82,101,112, 0, 4, 20, 0, 0, 0, 80,114,111, 99,101,115,115, 67,111,110,118, +111,108,118,101, 68,117, 97,108, 0, 4, 23, 0, 0, 0, 80,114,111, 99,101,115, +115, 67,111,109,112, 97,115,115, 67,111,110,118,111,108,118,101, 0, 4, 20, 0, + 0, 0, 80,114,111, 99,101,115,115, 77,101, 97,110, 67,111,110,118,111,108,118, +101, 0, 4, 24, 0, 0, 0, 80,114,111, 99,101,115,115, 71, 97,117,115,115,105, + 97,110, 67,111,110,118,111,108,118,101, 0, 4, 23, 0, 0, 0, 80,114,111, 99, +101,115,115, 66, 97,114,108,101,116,116, 67,111,110,118,111,108,118,101, 0, 4, + 22, 0, 0, 0, 80,114,111, 99,101,115,115, 73,110,116,101,114,108, 97, 99,101, + 83,112,108,105,116, 0, 4, 25, 0, 0, 0, 80,114,111, 99,101,115,115, 73,110, +116,101,114,108, 97, 99,101, 83,112,108,105,116, 78,101,119, 0, 4, 30, 0, 0, + 0, 80,114,111, 99,101,115,115, 68,105,102,102, 79,102, 71, 97,117,115,115,105, + 97,110, 67,111,110,118,111,108,118,101, 0, 4, 29, 0, 0, 0, 80,114,111, 99, +101,115,115, 76, 97,112, 79,102, 71, 97,117,115,115,105, 97,110, 67,111,110,118, +111,108,118,101, 0, 4, 21, 0, 0, 0, 80,114,111, 99,101,115,115, 83,111, 98, +101,108, 67,111,110,118,111,108,118,101, 0, 4, 26, 0, 0, 0, 80,114,111, 99, +101,115,115, 83,112,108,105,110,101, 69,100,103,101, 67,111,110,118,111,108,118, +101, 0, 4, 23, 0, 0, 0, 80,114,111, 99,101,115,115, 80,114,101,119,105,116, +116, 67,111,110,118,111,108,118,101, 0, 4, 20, 0, 0, 0, 80,114,111, 99,101, +115,115, 90,101,114,111, 67,114,111,115,115,105,110,103, 0, 4, 13, 0, 0, 0, + 80,114,111, 99,101,115,115, 67, 97,110,110,121, 0, 4, 22, 0, 0, 0, 80,114, +111, 99,101,115,115, 85,110, 65,114,105,116,104,109,101,116,105, 99, 79,112, 0, + 4, 20, 0, 0, 0, 80,114,111, 99,101,115,115, 65,114,105,116,104,109,101,116, +105, 99, 79,112, 0, 4, 15, 0, 0, 0, 80,114,111, 99,101,115,115, 85,110,115, +104, 97,114,112, 0, 4, 13, 0, 0, 0, 80,114,111, 99,101,115,115, 83,104, 97, +114,112, 0, 4, 19, 0, 0, 0, 80,114,111, 99,101,115,115, 83,104, 97,114,112, + 75,101,114,110,101,108, 0, 4, 28, 0, 0, 0, 80,114,111, 99,101,115,115, 65, +114,105,116,104,109,101,116,105, 99, 67,111,110,115,116, 79,112, 78,101,119, 0, + 4, 18, 0, 0, 0, 80,114,111, 99,101,115,115, 66,108,101,110,100, 67,111,110, +115,116, 0, 4, 13, 0, 0, 0, 80,114,111, 99,101,115,115, 66,108,101,110,100, + 0, 4, 20, 0, 0, 0, 80,114,111, 99,101,115,115, 83,112,108,105,116, 67,111, +109,112,108,101,120, 0, 4, 20, 0, 0, 0, 80,114,111, 99,101,115,115, 77,101, +114,103,101, 67,111,109,112,108,101,120, 0, 4, 7, 0, 0, 0, 67, 70, 76, 79, + 65, 84, 0, 4, 23, 0, 0, 0, 80,114,111, 99,101,115,115, 77,117,108,116,105, +112,108,101, 77,101, 97,110, 78,101,119, 0, 4, 25, 0, 0, 0, 80,114,111, 99, +101,115,115, 77,117,108,116,105,112,108,101, 83,116,100, 68,101,118, 78,101,119, + 0, 4, 22, 0, 0, 0, 80,114,111, 99,101,115,115, 65,117,116,111, 67,111,118, + 97,114,105, 97,110, 99,101, 0, 4, 20, 0, 0, 0, 80,114,111, 99,101,115,115, + 77,117,108,116,105,112,108,121, 67,111,110,106, 0, 4, 26, 0, 0, 0, 80,114, +111, 99,101,115,115, 81,117, 97,110,116,105,122,101, 82, 71, 66, 85,110,105,102, +111,114,109, 0, 4, 4, 0, 0, 0, 77, 65, 80, 0, 4, 27, 0, 0, 0, 80,114, +111, 99,101,115,115, 81,117, 97,110,116,105,122,101, 71,114, 97,121, 85,110,105, +102,111,114,109, 0, 4, 23, 0, 0, 0, 80,114,111, 99,101,115,115, 69,120,112, + 97,110,100, 72,105,115,116,111,103,114, 97,109, 0, 4, 25, 0, 0, 0, 80,114, +111, 99,101,115,115, 69,113,117, 97,108,105,122,101, 72,105,115,116,111,103,114, + 97,109, 0, 4, 23, 0, 0, 0, 80,114,111, 99,101,115,115, 83,112,108,105,116, + 89, 67,104,114,111,109, 97, 78,101,119, 0, 4, 16, 0, 0, 0, 80,114,111, 99, +101,115,115, 83,112,108,105,116, 72, 83, 73, 0, 4, 16, 0, 0, 0, 80,114,111, + 99,101,115,115, 77,101,114,103,101, 72, 83, 73, 0, 4, 4, 0, 0, 0, 82, 71, + 66, 0, 4, 5, 0, 0, 0, 66, 89, 84, 69, 0, 4, 26, 0, 0, 0, 80,114,111, + 99,101,115,115, 83,112,108,105,116, 67,111,109,112,111,110,101,110,116,115, 78, +101,119, 0, 4, 26, 0, 0, 0, 80,114,111, 99,101,115,115, 77,101,114,103,101, + 67,111,109,112,111,110,101,110,116,115, 78,101,119, 0, 4, 27, 0, 0, 0, 80, +114,111, 99,101,115,115, 78,111,114,109, 97,108,105,122,101, 67,111,109,112,111, +110,101,110,116,115, 0, 4, 20, 0, 0, 0, 80,114,111, 99,101,115,115, 82,101, +112,108, 97, 99,101, 67,111,108,111,114, 0, 4, 17, 0, 0, 0, 80,114,111, 99, +101,115,115, 66,105,116,119,105,115,101, 79,112, 0, 4, 18, 0, 0, 0, 80,114, +111, 99,101,115,115, 66,105,116,119,105,115,101, 78,111,116, 0, 4, 15, 0, 0, + 0, 80,114,111, 99,101,115,115, 66,105,116, 77, 97,115,107, 0, 4, 16, 0, 0, + 0, 80,114,111, 99,101,115,115, 66,105,116, 80,108, 97,110,101, 0, 4, 17, 0, + 0, 0, 80,114,111, 99,101,115,115, 84,111,110,101, 71, 97,109,117,116, 0, 4, + 19, 0, 0, 0, 80,114,111, 99,101,115,115, 85,110, 78,111,114,109, 97,108,105, +122,101, 0, 4, 18, 0, 0, 0, 80,114,111, 99,101,115,115, 68,105,114,101, 99, +116, 67,111,110,118, 0, 4, 16, 0, 0, 0, 80,114,111, 99,101,115,115, 78,101, +103, 97,116,105,118,101, 0, 4, 30, 0, 0, 0, 80,114,111, 99,101,115,115, 82, + 97,110,103,101, 67,111,110,116,114, 97,115,116, 84,104,114,101,115,104,111,108, +100, 0, 4, 25, 0, 0, 0, 80,114,111, 99,101,115,115, 76,111, 99, 97,108, 77, + 97,120, 84,104,114,101,115,104,111,108,100, 0, 4, 17, 0, 0, 0, 80,114,111, + 99,101,115,115, 84,104,114,101,115,104,111,108,100, 0, 4, 23, 0, 0, 0, 80, +114,111, 99,101,115,115, 84,104,114,101,115,104,111,108,100, 66,121, 68,105,102, +102, 0, 4, 27, 0, 0, 0, 80,114,111, 99,101,115,115, 72,121,115,116,101,114, +101,115,105,115, 84,104,114,101,115,104,111,108,100, 0, 4, 27, 0, 0, 0, 80, +114,111, 99,101,115,115, 85,110,105,102,111,114,109, 69,114,114, 84,104,114,101, +115,104,111,108,100, 0, 4, 28, 0, 0, 0, 80,114,111, 99,101,115,115, 68,105, +102,117,115,105,111,110, 69,114,114, 84,104,114,101,115,104,111,108,100, 0, 4, + 24, 0, 0, 0, 80,114,111, 99,101,115,115, 80,101,114, 99,101,110,116, 84,104, +114,101,115,104,111,108,100, 0, 4, 21, 0, 0, 0, 80,114,111, 99,101,115,115, + 79,116,115,117, 84,104,114,101,115,104,111,108,100, 0, 4, 23, 0, 0, 0, 80, +114,111, 99,101,115,115, 77,105,110, 77, 97,120, 84,104,114,101,115,104,111,108, +100, 0, 4, 22, 0, 0, 0, 80,114,111, 99,101,115,115, 83,108,105, 99,101, 84, +104,114,101,115,104,111,108,100, 0, 4, 16, 0, 0, 0, 80,114,111, 99,101,115, +115, 80,105,120,101,108, 97,116,101, 0, 4, 17, 0, 0, 0, 80,114,111, 99,101, +115,115, 80,111,115,116,101,114,105,122,101, 0, 24, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 25, 0, 0, 0, 0, 5, 0, 9, 17, 0, 0, 0, 69, 1, 0, 0, + 70, 1,128, 2,133, 65, 0, 0,192, 1,128, 2,156, 65, 0, 1,133, 1, 0, 0, +192, 1, 0, 0, 1,130, 0, 0,213, 1,130, 3, 36, 2, 0, 0, 0, 0,128, 0, + 0, 0, 0, 1, 0, 0,128, 1, 0, 0, 0, 2, 0, 0,128, 2,137, 1,130, 3, + 30, 0,128, 0, 3, 0, 0, 0, 4, 3, 0, 0, 0,105,109, 0, 4, 7, 0, 0, + 0, 97,115,115,101,114,116, 0, 4, 4, 0, 0, 0, 78,101,119, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 13, 0, 0, 0, 24, 0, 0, 0, 5, 1, 7, 8, 23, 0, 0, + 0,133, 0, 0, 0,134, 64, 64, 1,192, 0, 0, 0, 4, 1, 0, 0, 68, 1,128, + 0,132, 1, 0, 1,196, 1,128, 1,156,128, 0, 3,196, 0, 0, 2, 0, 1, 0, + 0, 64, 1, 0, 1,133,129, 0, 0,192, 1,128, 0,156, 1, 0, 1,220,128, 0, + 0,218, 0, 0, 0, 22,192, 0,128, 0, 1,128, 1, 64, 1, 0, 1, 30, 1,128, + 1, 22, 0, 0,128,158, 0, 0, 1, 30, 0,128, 0, 3, 0, 0, 0, 4, 3, 0, + 0, 0,105,109, 0, 4, 17, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116, +101, 66, 97,115,101,100, 0, 4, 7, 0, 0, 0,117,110,112, 97, 99,107, 0, 0, + 0, 0, 0, 23, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, + 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 18, + 0, 0, 0, 18, 0, 0, 0, 18, 0, 0, 0, 18, 0, 0, 0, 18, 0, 0, 0, 18, + 0, 0, 0, 18, 0, 0, 0, 19, 0, 0, 0, 19, 0, 0, 0, 20, 0, 0, 0, 20, + 0, 0, 0, 20, 0, 0, 0, 20, 0, 0, 0, 22, 0, 0, 0, 24, 0, 0, 0, 4, + 0, 0, 0, 10, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 0, 0, 0, 0, + 0, 22, 0, 0, 0, 4, 0, 0, 0, 97,114,103, 0, 0, 0, 0, 0, 22, 0, 0, + 0, 10, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 0, 8, 0, 0, 0, 22, + 0, 0, 0, 4, 0, 0, 0,114,101,116, 0, 15, 0, 0, 0, 22, 0, 0, 0, 5, + 0, 0, 0, 6, 0, 0, 0,119,105,100,116,104, 0, 7, 0, 0, 0,104,101,105, +103,104,116, 0, 12, 0, 0, 0, 99,111,108,111,114, 95,115,112, 97, 99,101, 0, + 10, 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, 0, 5, 0, 0, 0,102,117, +110, 99, 0, 17, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 10, 0, 0, 0, 10, + 0, 0, 0, 10, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, + 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, + 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 25, 0, 0, 0, 6, 0, 0, 0, 9, + 0, 0, 0,102,117,110, 99,110, 97,109,101, 0, 0, 0, 0, 0, 16, 0, 0, 0, + 6, 0, 0, 0,119,105,100,116,104, 0, 0, 0, 0, 0, 16, 0, 0, 0, 7, 0, + 0, 0,104,101,105,103,104,116, 0, 0, 0, 0, 0, 16, 0, 0, 0, 12, 0, 0, + 0, 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 0, 0, 0, 0, 16, 0, 0, + 0, 10, 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, 0, 0, 0, 0, 0, 16, + 0, 0, 0, 5, 0, 0, 0,102,117,110, 99, 0, 2, 0, 0, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, 50, 0, 0, 0, 0, 5, 0, 11, + 22, 0, 0, 0, 69, 1, 0, 0, 70, 1,128, 2,133, 65, 0, 0,192, 1,128, 2, + 5,130, 0, 0, 6,194, 64, 4, 65, 2, 1, 0,128, 2, 0, 0, 28, 2,128, 1, +156, 65, 0, 0,133, 1, 0, 0,192, 1, 0, 0, 1, 66, 1, 0,213, 1,130, 3, + 36, 2, 0, 0, 0, 0,128, 0, 0, 0, 0, 1, 0, 0,128, 1, 0, 0, 0, 2, + 0, 0,128, 2,137, 1,130, 3, 30, 0,128, 0, 6, 0, 0, 0, 4, 3, 0, 0, + 0,105,109, 0, 4, 7, 0, 0, 0, 97,115,115,101,114,116, 0, 4, 7, 0, 0, + 0,115,116,114,105,110,103, 0, 4, 7, 0, 0, 0,102,111,114,109, 97,116, 0, + 4, 24, 0, 0, 0,117,110,100,101,102,105,110,101,100, 32,102,117,110, 99,116, +105,111,110, 32, 96, 37,115, 39, 0, 4, 4, 0, 0, 0, 78,101,119, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, 49, 0, 0, 0, 5, 2, 7, 10, 24, 0, + 0, 0,197, 0, 0, 0,198, 64,192, 1, 0, 1, 0, 0, 68, 1, 0, 0,132, 1, +128, 0,196, 1, 0, 1, 4, 2,128, 1,220,128, 0, 3, 4, 1, 0, 2, 64, 1, + 0, 0,128, 1,128, 0,192, 1,128, 1, 5,130, 0, 0, 64, 2, 0, 1, 28, 2, + 0, 1, 28,129, 0, 0, 26, 1, 0, 0, 22,192, 0,128, 64, 1, 0, 2,128, 1, +128, 1, 94, 1,128, 1, 22, 0, 0,128,222, 0, 0, 1, 30, 0,128, 0, 3, 0, + 0, 0, 4, 3, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, 73,109, 97,103,101, + 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 4, 7, 0, 0, 0,117,110,112, + 97, 99,107, 0, 0, 0, 0, 0, 24, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, + 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, + 40, 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, + 43, 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, 44, 0, 0, 0, + 44, 0, 0, 0, 45, 0, 0, 0, 45, 0, 0, 0, 45, 0, 0, 0, 45, 0, 0, 0, + 47, 0, 0, 0, 49, 0, 0, 0, 5, 0, 0, 0, 11, 0, 0, 0,115,114, 99, 95, +105,109, 97,103,101, 49, 0, 0, 0, 0, 0, 23, 0, 0, 0, 11, 0, 0, 0,115, +114, 99, 95,105,109, 97,103,101, 50, 0, 0, 0, 0, 0, 23, 0, 0, 0, 4, 0, + 0, 0, 97,114,103, 0, 0, 0, 0, 0, 23, 0, 0, 0, 10, 0, 0, 0,100,115, +116, 95,105,109, 97,103,101, 0, 8, 0, 0, 0, 23, 0, 0, 0, 4, 0, 0, 0, +114,101,116, 0, 16, 0, 0, 0, 23, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, +119,105,100,116,104, 0, 7, 0, 0, 0,104,101,105,103,104,116, 0, 12, 0, 0, + 0, 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 10, 0, 0, 0,100, 97,116, + 97, 95,116,121,112,101, 0, 5, 0, 0, 0,102,117,110, 99, 0, 22, 0, 0, 0, + 32, 0, 0, 0, 32, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, + 35, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, + 38, 0, 0, 0, 38, 0, 0, 0, 38, 0, 0, 0, 38, 0, 0, 0, 49, 0, 0, 0, + 49, 0, 0, 0, 49, 0, 0, 0, 49, 0, 0, 0, 49, 0, 0, 0, 49, 0, 0, 0, + 49, 0, 0, 0, 50, 0, 0, 0, 6, 0, 0, 0, 9, 0, 0, 0,102,117,110, 99, +110, 97,109,101, 0, 0, 0, 0, 0, 21, 0, 0, 0, 6, 0, 0, 0,119,105,100, +116,104, 0, 0, 0, 0, 0, 21, 0, 0, 0, 7, 0, 0, 0,104,101,105,103,104, +116, 0, 0, 0, 0, 0, 21, 0, 0, 0, 12, 0, 0, 0, 99,111,108,111,114, 95, +115,112, 97, 99,101, 0, 0, 0, 0, 0, 21, 0, 0, 0, 10, 0, 0, 0,100, 97, +116, 97, 95,116,121,112,101, 0, 0, 0, 0, 0, 21, 0, 0, 0, 5, 0, 0, 0, +102,117,110, 99, 0, 2, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 56, 0, 0, 0, 73, 0, 0, 0, 0, 5, 0, 9, 17, 0, 0, 0, 69, 1, 0, + 0, 70, 1,128, 2,133, 65, 0, 0,192, 1,128, 2,156, 65, 0, 1,133, 1, 0, + 0,192, 1, 0, 0, 1,130, 0, 0,213, 1,130, 3, 36, 2, 0, 0, 0, 0,128, + 0, 0, 0, 0, 1, 0, 0,128, 1, 0, 0, 0, 2, 0, 0,128, 2,137, 1,130, + 3, 30, 0,128, 0, 3, 0, 0, 0, 4, 3, 0, 0, 0,105,109, 0, 4, 7, 0, + 0, 0, 97,115,115,101,114,116, 0, 4, 4, 0, 0, 0, 78,101,119, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 61, 0, 0, 0, 72, 0, 0, 0, 5, 3, 7, 12, 25, 0, + 0, 0, 5, 1, 0, 0, 6, 65, 64, 2, 64, 1, 0, 0,132, 1, 0, 0,196, 1, +128, 0, 4, 2, 0, 1, 68, 2,128, 1, 28,129, 0, 3, 68, 1, 0, 2,128, 1, + 0, 0,192, 1,128, 0, 0, 2, 0, 1, 64, 2, 0, 2,133,130, 0, 0,192, 2, +128, 1,156, 2, 0, 1, 92,129, 0, 0, 90, 1, 0, 0, 22,192, 0,128,128, 1, +128, 2,192, 1, 0, 2,158, 1,128, 1, 22, 0, 0,128, 30, 1, 0, 1, 30, 0, +128, 0, 3, 0, 0, 0, 4, 3, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, 73, +109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 4, 7, 0, 0, + 0,117,110,112, 97, 99,107, 0, 0, 0, 0, 0, 25, 0, 0, 0, 63, 0, 0, 0, + 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, + 63, 0, 0, 0, 63, 0, 0, 0, 66, 0, 0, 0, 66, 0, 0, 0, 66, 0, 0, 0, + 66, 0, 0, 0, 66, 0, 0, 0, 66, 0, 0, 0, 66, 0, 0, 0, 66, 0, 0, 0, + 66, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, + 68, 0, 0, 0, 68, 0, 0, 0, 70, 0, 0, 0, 72, 0, 0, 0, 6, 0, 0, 0, + 11, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 49, 0, 0, 0, 0, 0, 24, + 0, 0, 0, 11, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 50, 0, 0, 0, + 0, 0, 24, 0, 0, 0, 11, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 51, + 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 97,114,103, 0, 0, 0, 0, + 0, 24, 0, 0, 0, 10, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 0, 8, + 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0,114,101,116, 0, 17, 0, 0, 0, 24, + 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0,119,105,100,116,104, 0, 7, 0, 0, + 0,104,101,105,103,104,116, 0, 12, 0, 0, 0, 99,111,108,111,114, 95,115,112, + 97, 99,101, 0, 10, 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, 0, 5, 0, + 0, 0,102,117,110, 99, 0, 17, 0, 0, 0, 57, 0, 0, 0, 57, 0, 0, 0, 58, + 0, 0, 0, 58, 0, 0, 0, 58, 0, 0, 0, 61, 0, 0, 0, 61, 0, 0, 0, 61, + 0, 0, 0, 61, 0, 0, 0, 72, 0, 0, 0, 72, 0, 0, 0, 72, 0, 0, 0, 72, + 0, 0, 0, 72, 0, 0, 0, 72, 0, 0, 0, 72, 0, 0, 0, 73, 0, 0, 0, 6, + 0, 0, 0, 9, 0, 0, 0,102,117,110, 99,110, 97,109,101, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 6, 0, 0, 0,119,105,100,116,104, 0, 0, 0, 0, 0, 16, 0, + 0, 0, 7, 0, 0, 0,104,101,105,103,104,116, 0, 0, 0, 0, 0, 16, 0, 0, + 0, 12, 0, 0, 0, 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 0, 0, 0, + 0, 16, 0, 0, 0, 10, 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, 0, 0, + 0, 0, 0, 16, 0, 0, 0, 5, 0, 0, 0,102,117,110, 99, 0, 2, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 0, 0, 0, 97, 0, 0, 0, + 0, 5, 0, 9, 17, 0, 0, 0, 69, 1, 0, 0, 70, 1,128, 2,133, 65, 0, 0, +192, 1,128, 2,156, 65, 0, 1,133, 1, 0, 0,192, 1, 0, 0, 1,130, 0, 0, +213, 1,130, 3, 36, 2, 0, 0, 0, 0,128, 0, 0, 0, 0, 1, 0, 0,128, 1, + 0, 0, 0, 2, 0, 0,128, 2,137, 1,130, 3, 30, 0,128, 0, 3, 0, 0, 0, + 4, 3, 0, 0, 0,105,109, 0, 4, 7, 0, 0, 0, 97,115,115,101,114,116, 0, + 4, 4, 0, 0, 0, 78,101,119, 0, 1, 0, 0, 0, 0, 0, 0, 0, 84, 0, 0, + 0, 96, 0, 0, 0, 5, 1, 7, 10, 35, 0, 0, 0,133, 0, 0, 0,134, 64, 64, + 1,192, 0, 0, 0, 4, 1, 0, 0, 68, 1,128, 0,132, 1, 0, 1,196, 1,128, + 1,156,128, 0, 3,197, 0, 0, 0,198, 64,192, 1, 0, 1, 0, 0, 68, 1, 0, + 0,132, 1,128, 0,196, 1, 0, 1, 4, 2,128, 1,220,128, 0, 3, 4, 1, 0, + 2, 64, 1, 0, 0,128, 1, 0, 1,192, 1,128, 1, 5,130, 0, 0, 64, 2,128, + 0, 28, 2, 0, 1, 28,129, 0, 0, 26, 1, 0, 0, 22, 0, 1,128, 64, 1, 0, + 2,128, 1, 0, 1,192, 1,128, 1, 94, 1, 0, 2, 22,128, 0,128, 64, 1, 0, + 1,128, 1,128, 1, 94, 1,128, 1, 30, 0,128, 0, 3, 0, 0, 0, 4, 3, 0, + 0, 0,105,109, 0, 4, 17, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116, +101, 66, 97,115,101,100, 0, 4, 7, 0, 0, 0,117,110,112, 97, 99,107, 0, 0, + 0, 0, 0, 35, 0, 0, 0, 86, 0, 0, 0, 86, 0, 0, 0, 86, 0, 0, 0, 86, + 0, 0, 0, 86, 0, 0, 0, 86, 0, 0, 0, 86, 0, 0, 0, 86, 0, 0, 0, 87, + 0, 0, 0, 87, 0, 0, 0, 87, 0, 0, 0, 87, 0, 0, 0, 87, 0, 0, 0, 87, + 0, 0, 0, 87, 0, 0, 0, 87, 0, 0, 0, 90, 0, 0, 0, 90, 0, 0, 0, 90, + 0, 0, 0, 90, 0, 0, 0, 90, 0, 0, 0, 90, 0, 0, 0, 90, 0, 0, 0, 90, + 0, 0, 0, 91, 0, 0, 0, 91, 0, 0, 0, 92, 0, 0, 0, 92, 0, 0, 0, 92, + 0, 0, 0, 92, 0, 0, 0, 92, 0, 0, 0, 94, 0, 0, 0, 94, 0, 0, 0, 94, + 0, 0, 0, 96, 0, 0, 0, 5, 0, 0, 0, 10, 0, 0, 0,115,114, 99, 95,105, +109, 97,103,101, 0, 0, 0, 0, 0, 34, 0, 0, 0, 4, 0, 0, 0, 97,114,103, + 0, 0, 0, 0, 0, 34, 0, 0, 0, 11, 0, 0, 0,100,115,116, 95,105,109, 97, +103,101, 49, 0, 8, 0, 0, 0, 34, 0, 0, 0, 11, 0, 0, 0,100,115,116, 95, +105,109, 97,103,101, 50, 0, 16, 0, 0, 0, 34, 0, 0, 0, 4, 0, 0, 0,114, +101,116, 0, 24, 0, 0, 0, 34, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0,119, +105,100,116,104, 0, 7, 0, 0, 0,104,101,105,103,104,116, 0, 12, 0, 0, 0, + 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 10, 0, 0, 0,100, 97,116, 97, + 95,116,121,112,101, 0, 5, 0, 0, 0,102,117,110, 99, 0, 17, 0, 0, 0, 80, + 0, 0, 0, 80, 0, 0, 0, 81, 0, 0, 0, 81, 0, 0, 0, 81, 0, 0, 0, 84, + 0, 0, 0, 84, 0, 0, 0, 84, 0, 0, 0, 84, 0, 0, 0, 96, 0, 0, 0, 96, + 0, 0, 0, 96, 0, 0, 0, 96, 0, 0, 0, 96, 0, 0, 0, 96, 0, 0, 0, 96, + 0, 0, 0, 97, 0, 0, 0, 6, 0, 0, 0, 9, 0, 0, 0,102,117,110, 99,110, + 97,109,101, 0, 0, 0, 0, 0, 16, 0, 0, 0, 6, 0, 0, 0,119,105,100,116, +104, 0, 0, 0, 0, 0, 16, 0, 0, 0, 7, 0, 0, 0,104,101,105,103,104,116, + 0, 0, 0, 0, 0, 16, 0, 0, 0, 12, 0, 0, 0, 99,111,108,111,114, 95,115, +112, 97, 99,101, 0, 0, 0, 0, 0, 16, 0, 0, 0, 10, 0, 0, 0,100, 97,116, + 97, 95,116,121,112,101, 0, 0, 0, 0, 0, 16, 0, 0, 0, 5, 0, 0, 0,102, +117,110, 99, 0, 2, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +103, 0, 0, 0,122, 0, 0, 0, 0, 5, 0, 9, 17, 0, 0, 0, 69, 1, 0, 0, + 70, 1,128, 2,133, 65, 0, 0,192, 1,128, 2,156, 65, 0, 1,133, 1, 0, 0, +192, 1, 0, 0, 1,130, 0, 0,213, 1,130, 3, 36, 2, 0, 0, 0, 0,128, 0, + 0, 0, 0, 1, 0, 0,128, 1, 0, 0, 0, 2, 0, 0,128, 2,137, 1,130, 3, + 30, 0,128, 0, 3, 0, 0, 0, 4, 3, 0, 0, 0,105,109, 0, 4, 7, 0, 0, + 0, 97,115,115,101,114,116, 0, 4, 4, 0, 0, 0, 78,101,119, 0, 1, 0, 0, + 0, 0, 0, 0, 0,108, 0, 0, 0,121, 0, 0, 0, 5, 1, 7, 12, 46, 0, 0, + 0,133, 0, 0, 0,134, 64, 64, 1,192, 0, 0, 0, 4, 1, 0, 0, 68, 1,128, + 0,132, 1, 0, 1,196, 1,128, 1,156,128, 0, 3,197, 0, 0, 0,198, 64,192, + 1, 0, 1, 0, 0, 68, 1, 0, 0,132, 1,128, 0,196, 1, 0, 1, 4, 2,128, + 1,220,128, 0, 3, 5, 1, 0, 0, 6, 65, 64, 2, 64, 1, 0, 0,132, 1, 0, + 0,196, 1,128, 0, 4, 2, 0, 1, 68, 2,128, 1, 28,129, 0, 3, 68, 1, 0, + 2,128, 1, 0, 0,192, 1, 0, 1, 0, 2,128, 1, 64, 2, 0, 2,133,130, 0, + 0,192, 2,128, 0,156, 2, 0, 1, 92,129, 0, 0, 90, 1, 0, 0, 22, 64, 1, +128,128, 1,128, 2,192, 1, 0, 1, 0, 2,128, 1, 64, 2, 0, 2,158, 1,128, + 2, 22,192, 0,128,128, 1, 0, 1,192, 1,128, 1, 0, 2, 0, 2,158, 1, 0, + 2, 30, 0,128, 0, 3, 0, 0, 0, 4, 3, 0, 0, 0,105,109, 0, 4, 17, 0, + 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 4, + 7, 0, 0, 0,117,110,112, 97, 99,107, 0, 0, 0, 0, 0, 46, 0, 0, 0,110, + 0, 0, 0,110, 0, 0, 0,110, 0, 0, 0,110, 0, 0, 0,110, 0, 0, 0,110, + 0, 0, 0,110, 0, 0, 0,110, 0, 0, 0,111, 0, 0, 0,111, 0, 0, 0,111, + 0, 0, 0,111, 0, 0, 0,111, 0, 0, 0,111, 0, 0, 0,111, 0, 0, 0,111, + 0, 0, 0,112, 0, 0, 0,112, 0, 0, 0,112, 0, 0, 0,112, 0, 0, 0,112, + 0, 0, 0,112, 0, 0, 0,112, 0, 0, 0,112, 0, 0, 0,115, 0, 0, 0,115, + 0, 0, 0,115, 0, 0, 0,115, 0, 0, 0,115, 0, 0, 0,115, 0, 0, 0,115, + 0, 0, 0,115, 0, 0, 0,115, 0, 0, 0,116, 0, 0, 0,116, 0, 0, 0,117, + 0, 0, 0,117, 0, 0, 0,117, 0, 0, 0,117, 0, 0, 0,117, 0, 0, 0,117, + 0, 0, 0,119, 0, 0, 0,119, 0, 0, 0,119, 0, 0, 0,119, 0, 0, 0,121, + 0, 0, 0, 6, 0, 0, 0, 10, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, + 0, 0, 0, 0, 0, 45, 0, 0, 0, 4, 0, 0, 0, 97,114,103, 0, 0, 0, 0, + 0, 45, 0, 0, 0, 11, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 49, 0, + 8, 0, 0, 0, 45, 0, 0, 0, 11, 0, 0, 0,100,115,116, 95,105,109, 97,103, +101, 50, 0, 16, 0, 0, 0, 45, 0, 0, 0, 11, 0, 0, 0,100,115,116, 95,105, +109, 97,103,101, 51, 0, 24, 0, 0, 0, 45, 0, 0, 0, 4, 0, 0, 0,114,101, +116, 0, 33, 0, 0, 0, 45, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0,119,105, +100,116,104, 0, 7, 0, 0, 0,104,101,105,103,104,116, 0, 12, 0, 0, 0, 99, +111,108,111,114, 95,115,112, 97, 99,101, 0, 10, 0, 0, 0,100, 97,116, 97, 95, +116,121,112,101, 0, 5, 0, 0, 0,102,117,110, 99, 0, 17, 0, 0, 0,104, 0, + 0, 0,104, 0, 0, 0,105, 0, 0, 0,105, 0, 0, 0,105, 0, 0, 0,108, 0, + 0, 0,108, 0, 0, 0,108, 0, 0, 0,108, 0, 0, 0,121, 0, 0, 0,121, 0, + 0, 0,121, 0, 0, 0,121, 0, 0, 0,121, 0, 0, 0,121, 0, 0, 0,121, 0, + 0, 0,122, 0, 0, 0, 6, 0, 0, 0, 9, 0, 0, 0,102,117,110, 99,110, 97, +109,101, 0, 0, 0, 0, 0, 16, 0, 0, 0, 6, 0, 0, 0,119,105,100,116,104, + 0, 0, 0, 0, 0, 16, 0, 0, 0, 7, 0, 0, 0,104,101,105,103,104,116, 0, + 0, 0, 0, 0, 16, 0, 0, 0, 12, 0, 0, 0, 99,111,108,111,114, 95,115,112, + 97, 99,101, 0, 0, 0, 0, 0, 16, 0, 0, 0, 10, 0, 0, 0,100, 97,116, 97, + 95,116,121,112,101, 0, 0, 0, 0, 0, 16, 0, 0, 0, 5, 0, 0, 0,102,117, +110, 99, 0, 2, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, + 0, 0, 0,130, 0, 0, 0, 0, 1, 0, 7, 18, 0, 0, 0,100, 0, 0, 0,133, + 0, 0, 0,134, 64, 64, 1,192, 0,128, 0, 11,129, 64, 0, 28, 1, 0, 1,220, +128, 0, 0, 0, 1,128, 0, 75,193, 64, 0, 92, 1, 0, 1, 28,129, 0, 0,204, + 0,129, 1,156,128, 0, 1,143, 0, 65, 1,206,128, 0,130,204, 64,193, 1,222, + 0, 0, 1, 30, 0,128, 0, 6, 0, 0, 0, 4, 5, 0, 0, 0,109, 97,116,104, + 0, 4, 5, 0, 0, 0,115,113,114,116, 0, 4, 6, 0, 0, 0, 87,105,100,116, +104, 0, 4, 7, 0, 0, 0, 72,101,105,103,104,116, 0, 3, 0, 0, 0, 0, 0, + 0, 0, 64, 3, 0, 0, 0, 0, 0, 0,240, 63, 1, 0, 0, 0, 0, 0, 0, 0, +127, 0, 0, 0,127, 0, 0, 0, 0, 1, 0, 2, 3, 0, 0, 0, 78, 0, 0, 0, + 94, 0, 0, 1, 30, 0,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, +127, 0, 0, 0,127, 0, 0, 0,127, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, +120, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0,127, 0, + 0, 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, + 0, 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, + 0, 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, 0, 0,129, 0, 0, 0,129, 0, + 0, 0,129, 0, 0, 0,130, 0, 0, 0, 3, 0, 0, 0, 6, 0, 0, 0,105,109, + 97,103,101, 0, 0, 0, 0, 0, 17, 0, 0, 0, 4, 0, 0, 0,115,113,114, 0, + 1, 0, 0, 0, 17, 0, 0, 0, 5, 0, 0, 0,114,109, 97,120, 0, 14, 0, 0, + 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,141, 0, 0, 0,144, 0, 0, + 0, 0, 3, 0, 7, 14, 0, 0, 0,197, 0, 0, 0,198, 64,192, 1, 0, 1, 0, + 0, 64, 1,128, 0,128, 1, 0, 1,220,128, 0, 2, 5, 1, 0, 0, 6,129, 64, + 2, 64, 1, 0, 0,128, 1,128, 1, 28,129,128, 1, 64, 1,128, 1, 30, 1,128, + 1, 30, 0,128, 0, 3, 0, 0, 0, 4, 3, 0, 0, 0,105,109, 0, 4, 17, 0, + 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 4, + 14, 0, 0, 0, 80,114,111, 99,101,115,115, 82,101,100,117, 99,101, 0, 0, 0, + 0, 0, 14, 0, 0, 0,142, 0, 0, 0,142, 0, 0, 0,142, 0, 0, 0,142, 0, + 0, 0,142, 0, 0, 0,142, 0, 0, 0,143, 0, 0, 0,143, 0, 0, 0,143, 0, + 0, 0,143, 0, 0, 0,143, 0, 0, 0,143, 0, 0, 0,143, 0, 0, 0,144, 0, + 0, 0, 4, 0, 0, 0, 10, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 0, + 0, 0, 0, 0, 13, 0, 0, 0, 6, 0, 0, 0,119,105,100,116,104, 0, 0, 0, + 0, 0, 13, 0, 0, 0, 7, 0, 0, 0,104,101,105,103,104,116, 0, 0, 0, 0, + 0, 13, 0, 0, 0, 10, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 0, 6, + 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,146, 0, 0, 0,149, + 0, 0, 0, 0, 3, 0, 7, 14, 0, 0, 0,197, 0, 0, 0,198, 64,192, 1, 0, + 1, 0, 0, 64, 1,128, 0,128, 1, 0, 1,220,128, 0, 2, 5, 1, 0, 0, 6, +129, 64, 2, 64, 1, 0, 0,128, 1,128, 1, 28,129,128, 1, 64, 1,128, 1, 30, + 1,128, 1, 30, 0,128, 0, 3, 0, 0, 0, 4, 3, 0, 0, 0,105,109, 0, 4, + 17, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, + 0, 4, 14, 0, 0, 0, 80,114,111, 99,101,115,115, 82,101,115,105,122,101, 0, + 0, 0, 0, 0, 14, 0, 0, 0,147, 0, 0, 0,147, 0, 0, 0,147, 0, 0, 0, +147, 0, 0, 0,147, 0, 0, 0,147, 0, 0, 0,148, 0, 0, 0,148, 0, 0, 0, +148, 0, 0, 0,148, 0, 0, 0,148, 0, 0, 0,148, 0, 0, 0,148, 0, 0, 0, +149, 0, 0, 0, 4, 0, 0, 0, 10, 0, 0, 0,115,114, 99, 95,105,109, 97,103, +101, 0, 0, 0, 0, 0, 13, 0, 0, 0, 6, 0, 0, 0,119,105,100,116,104, 0, + 0, 0, 0, 0, 13, 0, 0, 0, 7, 0, 0, 0,104,101,105,103,104,116, 0, 0, + 0, 0, 0, 13, 0, 0, 0, 10, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, + 0, 6, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,151, 0, 0, + 0,151, 0, 0, 0, 0, 1, 0, 3, 5, 0, 0, 0, 75, 0, 64, 0, 92,128, 0, + 1, 79, 64,192, 0, 94, 0, 0, 1, 30, 0,128, 0, 2, 0, 0, 0, 4, 6, 0, + 0, 0, 87,105,100,116,104, 0, 3, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, + 0, 5, 0, 0, 0,151, 0, 0, 0,151, 0, 0, 0,151, 0, 0, 0,151, 0, 0, + 0,151, 0, 0, 0, 1, 0, 0, 0, 6, 0, 0, 0,105,109, 97,103,101, 0, 0, + 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,152, 0, 0, 0,152, + 0, 0, 0, 0, 1, 0, 3, 5, 0, 0, 0, 75, 0, 64, 0, 92,128, 0, 1, 79, + 64,192, 0, 94, 0, 0, 1, 30, 0,128, 0, 2, 0, 0, 0, 4, 7, 0, 0, 0, + 72,101,105,103,104,116, 0, 3, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, + 5, 0, 0, 0,152, 0, 0, 0,152, 0, 0, 0,152, 0, 0, 0,152, 0, 0, 0, +152, 0, 0, 0, 1, 0, 0, 0, 6, 0, 0, 0,105,109, 97,103,101, 0, 0, 0, + 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,154, 0, 0, 0,160, 0, + 0, 0, 0, 5, 0, 13, 19, 0, 0, 0, 77, 65, 0, 1, 76, 1,192, 2,141,193, + 0, 2,140, 1, 64, 3,197, 65, 0, 0,198,129,192, 3, 0, 2, 0, 0, 64, 2, +128, 2,128, 2, 0, 3,220,129, 0, 2, 5, 66, 0, 0, 6,194, 64, 4, 64, 2, + 0, 0,128, 2,128, 3,192, 2,128, 0, 0, 3,128, 1, 28, 66,128, 2,222, 1, + 0, 1, 30, 0,128, 0, 4, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,240, 63, 4, + 3, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, 73,109, 97,103,101, 67,114,101, + 97,116,101, 66, 97,115,101,100, 0, 4, 12, 0, 0, 0, 80,114,111, 99,101,115, +115, 67,114,111,112, 0, 0, 0, 0, 0, 19, 0, 0, 0,155, 0, 0, 0,155, 0, + 0, 0,156, 0, 0, 0,156, 0, 0, 0,157, 0, 0, 0,157, 0, 0, 0,157, 0, + 0, 0,157, 0, 0, 0,157, 0, 0, 0,157, 0, 0, 0,158, 0, 0, 0,158, 0, + 0, 0,158, 0, 0, 0,158, 0, 0, 0,158, 0, 0, 0,158, 0, 0, 0,158, 0, + 0, 0,159, 0, 0, 0,160, 0, 0, 0, 8, 0, 0, 0, 10, 0, 0, 0,115,114, + 99, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 18, 0, 0, 0, 5, 0, 0, 0, +120,109,105,110, 0, 0, 0, 0, 0, 18, 0, 0, 0, 5, 0, 0, 0,120,109, 97, +120, 0, 0, 0, 0, 0, 18, 0, 0, 0, 5, 0, 0, 0,121,109,105,110, 0, 0, + 0, 0, 0, 18, 0, 0, 0, 5, 0, 0, 0,121,109, 97,120, 0, 0, 0, 0, 0, + 18, 0, 0, 0, 6, 0, 0, 0,119,105,100,116,104, 0, 2, 0, 0, 0, 18, 0, + 0, 0, 7, 0, 0, 0,104,101,105,103,104,116, 0, 4, 0, 0, 0, 18, 0, 0, + 0, 10, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 0, 10, 0, 0, 0, 18, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,164, 0, 0, 0,170, 0, 0, 0, 0, + 5, 0, 13, 19, 0, 0, 0, 77, 65, 0, 1, 76, 1,192, 2,141,193, 0, 2,140, + 1, 64, 3,197, 65, 0, 0,198,129,192, 3, 0, 2, 0, 0, 64, 2,128, 2,128, + 2, 0, 3,220,129, 0, 2, 5, 66, 0, 0, 6,194, 64, 4, 64, 2, 0, 0,128, + 2,128, 3,192, 2,128, 0, 0, 3,128, 1, 28, 66,128, 2,222, 1, 0, 1, 30, + 0,128, 0, 4, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,240, 63, 4, 3, 0, 0, + 0,105,109, 0, 4, 17, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, + 66, 97,115,101,100, 0, 4, 18, 0, 0, 0, 80,114,111, 99,101,115,115, 65,100, +100, 77, 97,114,103,105,110,115, 0, 0, 0, 0, 0, 19, 0, 0, 0,165, 0, 0, + 0,165, 0, 0, 0,166, 0, 0, 0,166, 0, 0, 0,167, 0, 0, 0,167, 0, 0, + 0,167, 0, 0, 0,167, 0, 0, 0,167, 0, 0, 0,167, 0, 0, 0,168, 0, 0, + 0,168, 0, 0, 0,168, 0, 0, 0,168, 0, 0, 0,168, 0, 0, 0,168, 0, 0, + 0,168, 0, 0, 0,169, 0, 0, 0,170, 0, 0, 0, 8, 0, 0, 0, 10, 0, 0, + 0,115,114, 99, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 18, 0, 0, 0, 5, + 0, 0, 0,120,109,105,110, 0, 0, 0, 0, 0, 18, 0, 0, 0, 5, 0, 0, 0, +120,109, 97,120, 0, 0, 0, 0, 0, 18, 0, 0, 0, 5, 0, 0, 0,121,109,105, +110, 0, 0, 0, 0, 0, 18, 0, 0, 0, 5, 0, 0, 0,121,109, 97,120, 0, 0, + 0, 0, 0, 18, 0, 0, 0, 6, 0, 0, 0,119,105,100,116,104, 0, 2, 0, 0, + 0, 18, 0, 0, 0, 7, 0, 0, 0,104,101,105,103,104,116, 0, 4, 0, 0, 0, + 18, 0, 0, 0, 10, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 0, 10, 0, + 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,172, 0, 0, 0,176, 0, + 0, 0, 0, 4, 0, 13, 26, 0, 0, 0, 5, 1, 0, 0, 6, 65, 64, 2, 75,129, + 64, 0, 92,129, 0, 1,139,193, 64, 0,156,129, 0, 1,192, 1,128, 0, 0, 2, + 0, 1, 28,193,128, 2,133, 1, 0, 0,134, 1, 65, 3,192, 1, 0, 0, 0, 2, + 0, 2, 64, 2,128, 2,156,129, 0, 2,197, 1, 0, 0,198, 65,193, 3, 0, 2, + 0, 0, 64, 2, 0, 3,128, 2,128, 0,192, 2, 0, 1, 0, 3,128, 1,220,129, + 0, 3, 0, 2, 0, 3,222, 1,128, 1, 30, 0,128, 0, 6, 0, 0, 0, 4, 3, + 0, 0, 0,105,109, 0, 4, 22, 0, 0, 0, 80,114,111, 99,101,115,115, 67, 97, +108, 99, 82,111,116, 97,116,101, 83,105,122,101, 0, 4, 6, 0, 0, 0, 87,105, +100,116,104, 0, 4, 7, 0, 0, 0, 72,101,105,103,104,116, 0, 4, 17, 0, 0, + 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 4, 14, + 0, 0, 0, 80,114,111, 99,101,115,115, 82,111,116, 97,116,101, 0, 0, 0, 0, + 0, 26, 0, 0, 0,173, 0, 0, 0,173, 0, 0, 0,173, 0, 0, 0,173, 0, 0, + 0,173, 0, 0, 0,173, 0, 0, 0,173, 0, 0, 0,173, 0, 0, 0,173, 0, 0, + 0,174, 0, 0, 0,174, 0, 0, 0,174, 0, 0, 0,174, 0, 0, 0,174, 0, 0, + 0,174, 0, 0, 0,175, 0, 0, 0,175, 0, 0, 0,175, 0, 0, 0,175, 0, 0, + 0,175, 0, 0, 0,175, 0, 0, 0,175, 0, 0, 0,175, 0, 0, 0,175, 0, 0, + 0,175, 0, 0, 0,176, 0, 0, 0, 7, 0, 0, 0, 10, 0, 0, 0,115,114, 99, + 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 25, 0, 0, 0, 5, 0, 0, 0, 99, +111,115, 48, 0, 0, 0, 0, 0, 25, 0, 0, 0, 5, 0, 0, 0,115,105,110, 48, + 0, 0, 0, 0, 0, 25, 0, 0, 0, 6, 0, 0, 0,111,114,100,101,114, 0, 0, + 0, 0, 0, 25, 0, 0, 0, 6, 0, 0, 0,119,105,100,116,104, 0, 9, 0, 0, + 0, 25, 0, 0, 0, 7, 0, 0, 0,104,101,105,103,104,116, 0, 9, 0, 0, 0, + 25, 0, 0, 0, 10, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 0, 15, 0, + 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,179, 0, 0, 0,179, 0, + 0, 0, 0, 1, 0, 3, 4, 0, 0, 0, 75, 0, 64, 0, 93, 0, 0, 1, 94, 0, + 0, 0, 30, 0,128, 0, 1, 0, 0, 0, 4, 7, 0, 0, 0, 72,101,105,103,104, +116, 0, 0, 0, 0, 0, 4, 0, 0, 0,179, 0, 0, 0,179, 0, 0, 0,179, 0, + 0, 0,179, 0, 0, 0, 1, 0, 0, 0, 6, 0, 0, 0,105,109, 97,103,101, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,179, 0, 0, 0, +179, 0, 0, 0, 0, 1, 0, 3, 4, 0, 0, 0, 75, 0, 64, 0, 93, 0, 0, 1, + 94, 0, 0, 0, 30, 0,128, 0, 1, 0, 0, 0, 4, 6, 0, 0, 0, 87,105,100, +116,104, 0, 0, 0, 0, 0, 4, 0, 0, 0,179, 0, 0, 0,179, 0, 0, 0,179, + 0, 0, 0,179, 0, 0, 0, 1, 0, 0, 0, 6, 0, 0, 0,105,109, 97,103,101, + 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,212, 0, 0, + 0,212, 0, 0, 0, 0, 1, 0, 3, 13, 0, 0, 0, 75, 0, 64, 0, 92,128, 0, + 1, 90, 0, 0, 0, 22,192, 0,128, 75, 0, 64, 0, 93, 0, 0, 1, 94, 0, 0, + 0, 22,192, 0,128, 75, 0, 64, 0, 92,128, 0, 1, 79, 64,192, 0, 94, 0, 0, + 1, 30, 0,128, 0, 2, 0, 0, 0, 4, 7, 0, 0, 0, 72,101,105,103,104,116, + 0, 3, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 13, 0, 0, 0,212, 0, + 0, 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, + 0, 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, + 0, 0,212, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 6, 0, 0, 0,105,109, + 97,103,101, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +214, 0, 0, 0,227, 0, 0, 0, 0, 1, 0, 8, 36, 0, 0, 0, 75, 0, 64, 0, + 92,128, 0, 1, 79, 64,192, 0,133,128, 0, 0,134,192, 64, 1,203, 0, 64, 0, +220,128, 0, 1, 1, 65, 0, 0,156,128,128, 1,154, 0, 0, 0, 22, 0, 0,128, + 76, 0,193, 0,133, 64, 1, 0,134,128, 65, 1,192, 0, 0, 0, 3, 1, 0, 2, + 64, 1,128, 0,156,128, 0, 2,197, 64, 1, 0,198,128,193, 1, 0, 1, 0, 0, + 67, 1,128, 2,139, 1, 64, 0,156,129, 0, 1,143, 65, 64, 3,220,128, 0, 2, + 5, 65, 1, 0, 6,193, 65, 2, 64, 1, 0, 0,128, 1, 0, 1,192, 1,128, 1, + 28, 65, 0, 2, 0, 1, 0, 1, 64, 1,128, 1, 30, 1,128, 1, 30, 0,128, 0, + 8, 0, 0, 0, 4, 7, 0, 0, 0, 72,101,105,103,104,116, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 64, 4, 5, 0, 0, 0,109, 97,116,104, 0, 4, 4, 0, 0, 0, +109,111,100, 0, 3, 0, 0, 0, 0, 0, 0,240, 63, 4, 3, 0, 0, 0,105,109, + 0, 4, 17, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115, +101,100, 0, 4, 22, 0, 0, 0, 80,114,111, 99,101,115,115, 73,110,116,101,114, +108, 97, 99,101, 83,112,108,105,116, 0, 0, 0, 0, 0, 36, 0, 0, 0,216, 0, + 0, 0,216, 0, 0, 0,216, 0, 0, 0,217, 0, 0, 0,217, 0, 0, 0,217, 0, + 0, 0,217, 0, 0, 0,217, 0, 0, 0,217, 0, 0, 0,217, 0, 0, 0,217, 0, + 0, 0,218, 0, 0, 0,221, 0, 0, 0,221, 0, 0, 0,221, 0, 0, 0,221, 0, + 0, 0,221, 0, 0, 0,221, 0, 0, 0,222, 0, 0, 0,222, 0, 0, 0,222, 0, + 0, 0,222, 0, 0, 0,222, 0, 0, 0,222, 0, 0, 0,222, 0, 0, 0,222, 0, + 0, 0,225, 0, 0, 0,225, 0, 0, 0,225, 0, 0, 0,225, 0, 0, 0,225, 0, + 0, 0,225, 0, 0, 0,226, 0, 0, 0,226, 0, 0, 0,226, 0, 0, 0,227, 0, + 0, 0, 4, 0, 0, 0, 10, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 0, + 0, 0, 0, 0, 35, 0, 0, 0, 12, 0, 0, 0,100,115,116, 95,104,101,105,103, +104,116, 49, 0, 3, 0, 0, 0, 35, 0, 0, 0, 11, 0, 0, 0,100,115,116, 95, +105,109, 97,103,101, 49, 0, 18, 0, 0, 0, 35, 0, 0, 0, 11, 0, 0, 0,100, +115,116, 95,105,109, 97,103,101, 50, 0, 26, 0, 0, 0, 35, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,229, 0, 0, 0,235, 0, 0, 0, 0, 1, 0, 3, 14, 0, + 0, 0, 75, 0, 64, 0, 92,128, 0, 1,133, 64, 0, 0,134,128, 64, 1, 87,128, +128, 0, 22,192, 0,128,133, 64, 0, 0,134,192, 64, 1, 23,128,128, 0, 22, 64, + 0,128,133, 64, 0, 0, 70, 0, 65, 1, 94, 0, 0, 1, 30, 0,128, 0, 5, 0, + 0, 0, 4, 9, 0, 0, 0, 68, 97,116, 97, 84,121,112,101, 0, 4, 3, 0, 0, + 0,105,109, 0, 4, 5, 0, 0, 0, 66, 89, 84, 69, 0, 4, 7, 0, 0, 0, 85, + 83, 72, 79, 82, 84, 0, 4, 4, 0, 0, 0, 73, 78, 84, 0, 0, 0, 0, 0, 14, + 0, 0, 0,230, 0, 0, 0,230, 0, 0, 0,231, 0, 0, 0,231, 0, 0, 0,231, + 0, 0, 0,231, 0, 0, 0,231, 0, 0, 0,231, 0, 0, 0,231, 0, 0, 0,231, + 0, 0, 0,232, 0, 0, 0,232, 0, 0, 0,234, 0, 0, 0,235, 0, 0, 0, 2, + 0, 0, 0, 6, 0, 0, 0,105,109, 97,103,101, 0, 0, 0, 0, 0, 13, 0, 0, + 0, 10, 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, 0, 2, 0, 0, 0, 13, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,250, 0, 0, 0,254, 0, 0, 0, 0, + 3, 0, 9, 13, 0, 0, 0,197, 0, 0, 0,198, 64,192, 1, 0, 1, 0, 0,220, +128, 0, 1, 5, 1, 0, 0, 6,129, 64, 2, 64, 1, 0, 0,128, 1,128, 0,192, + 1,128, 1, 0, 2, 0, 1, 28, 65,128, 2,222, 0, 0, 1, 30, 0,128, 0, 3, + 0, 0, 0, 4, 3, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, 73,109, 97,103, +101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 4, 25, 0, 0, 0, 80,114, +111, 99,101,115,115, 65,114,105,116,104,109,101,116,105, 99, 67,111,110,115,116, + 79,112, 0, 0, 0, 0, 0, 13, 0, 0, 0,251, 0, 0, 0,251, 0, 0, 0,251, + 0, 0, 0,251, 0, 0, 0,252, 0, 0, 0,252, 0, 0, 0,252, 0, 0, 0,252, + 0, 0, 0,252, 0, 0, 0,252, 0, 0, 0,252, 0, 0, 0,253, 0, 0, 0,254, + 0, 0, 0, 4, 0, 0, 0, 10, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, + 0, 0, 0, 0, 0, 12, 0, 0, 0, 10, 0, 0, 0,115,114, 99, 95, 99,111,110, +115,116, 0, 0, 0, 0, 0, 12, 0, 0, 0, 3, 0, 0, 0,111,112, 0, 0, 0, + 0, 0, 12, 0, 0, 0, 10, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 0, + 4, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 1, 0, 0, + 9, 1, 0, 0, 0, 2, 0, 6, 11, 0, 0, 0,133, 0, 0, 0,134, 64, 64, 1, +198,128, 64, 0,156,128, 0, 1,197, 0, 0, 0,198,192,192, 1, 0, 1, 0, 0, + 64, 1, 0, 1,220, 64,128, 1,158, 0, 0, 1, 30, 0,128, 0, 4, 0, 0, 0, + 4, 3, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, 73,109, 97,103,101, 67,114, +101, 97,116,101, 66, 97,115,101,100, 0, 3, 0, 0, 0, 0, 0, 0,240, 63, 4, + 20, 0, 0, 0, 80,114,111, 99,101,115,115, 77,117,108,116,105,112,108,101, 77, +101, 97,110, 0, 0, 0, 0, 0, 11, 0, 0, 0, 6, 1, 0, 0, 6, 1, 0, 0, + 6, 1, 0, 0, 6, 1, 0, 0, 7, 1, 0, 0, 7, 1, 0, 0, 7, 1, 0, 0, + 7, 1, 0, 0, 7, 1, 0, 0, 8, 1, 0, 0, 9, 1, 0, 0, 3, 0, 0, 0, + 15, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 95,108,105,115,116, 0, 0, + 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, + 0, 0, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0,100,115,116, 95,105,109, 97, +103,101, 0, 4, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, + 1, 0, 0, 15, 1, 0, 0, 0, 2, 0, 7, 12, 0, 0, 0,133, 0, 0, 0,134, + 64, 64, 1,198,128, 64, 0,156,128, 0, 1,197, 0, 0, 0,198,192,192, 1, 0, + 1, 0, 0, 64, 1,128, 0,128, 1, 0, 1,220, 64, 0, 2,158, 0, 0, 1, 30, + 0,128, 0, 4, 0, 0, 0, 4, 3, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, + 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 3, 0, 0, + 0, 0, 0, 0,240, 63, 4, 22, 0, 0, 0, 80,114,111, 99,101,115,115, 77,117, +108,116,105,112,108,101, 83,116,100, 68,101,118, 0, 0, 0, 0, 0, 12, 0, 0, + 0, 12, 1, 0, 0, 12, 1, 0, 0, 12, 1, 0, 0, 12, 1, 0, 0, 13, 1, 0, + 0, 13, 1, 0, 0, 13, 1, 0, 0, 13, 1, 0, 0, 13, 1, 0, 0, 13, 1, 0, + 0, 14, 1, 0, 0, 15, 1, 0, 0, 3, 0, 0, 0, 15, 0, 0, 0,115,114, 99, + 95,105,109, 97,103,101, 95,108,105,115,116, 0, 0, 0, 0, 0, 11, 0, 0, 0, + 11, 0, 0, 0,109,101, 97,110, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 11, + 0, 0, 0, 10, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 0, 4, 0, 0, + 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 1, 0, 0, 29, 1, 0, + 0, 0, 1, 0, 8, 28, 0, 0, 0, 69, 0, 0, 0, 70, 64,192, 0,128, 0, 0, + 0,195, 0, 0, 2, 69, 1, 0, 0, 70,129,192, 2,133, 1, 0, 0,134,193, 64, + 3, 92,128, 0, 3,133, 0, 0, 0,134, 64, 64, 1,192, 0, 0, 0, 3, 1,128, + 2,133, 1, 0, 0,134, 1, 65, 3,197, 1, 0, 0,198,193,192, 3,156,128, 0, + 3,197, 0, 0, 0,198, 64,193, 1, 0, 1, 0, 0, 64, 1,128, 0,128, 1, 0, + 1,220, 64, 0, 2,192, 0,128, 0, 0, 1, 0, 1,222, 0,128, 1, 30, 0,128, + 0, 6, 0, 0, 0, 4, 3, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, 73,109, + 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 4, 5, 0, 0, 0, + 71, 82, 65, 89, 0, 4, 5, 0, 0, 0, 66, 89, 84, 69, 0, 4, 4, 0, 0, 0, + 82, 71, 66, 0, 4, 20, 0, 0, 0, 80,114,111, 99,101,115,115, 83,112,108,105, +116, 89, 67,104,114,111,109, 97, 0, 0, 0, 0, 0, 28, 0, 0, 0, 25, 1, 0, + 0, 25, 1, 0, 0, 25, 1, 0, 0, 25, 1, 0, 0, 25, 1, 0, 0, 25, 1, 0, + 0, 25, 1, 0, 0, 25, 1, 0, 0, 25, 1, 0, 0, 26, 1, 0, 0, 26, 1, 0, + 0, 26, 1, 0, 0, 26, 1, 0, 0, 26, 1, 0, 0, 26, 1, 0, 0, 26, 1, 0, + 0, 26, 1, 0, 0, 26, 1, 0, 0, 27, 1, 0, 0, 27, 1, 0, 0, 27, 1, 0, + 0, 27, 1, 0, 0, 27, 1, 0, 0, 27, 1, 0, 0, 28, 1, 0, 0, 28, 1, 0, + 0, 28, 1, 0, 0, 29, 1, 0, 0, 3, 0, 0, 0, 10, 0, 0, 0,115,114, 99, + 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 27, 0, 0, 0, 8, 0, 0, 0,121, + 95,105,109, 97,103,101, 0, 9, 0, 0, 0, 27, 0, 0, 0, 13, 0, 0, 0, 99, +104,114,111,109, 97, 95,105,109, 97,103,101, 0, 18, 0, 0, 0, 27, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 34, 1, 0, 0, 42, 1, 0, 0, 0, 1, 0, 14, + 29, 0, 0, 0, 75, 0, 64, 0, 92,128, 0, 1,138, 0, 0, 0,193, 64, 0, 0, + 0, 1,128, 0, 65, 65, 0, 0,224,128, 2,128,197,129, 0, 0,198,193,192, 3, + 0, 2, 0, 1, 69, 2, 1, 0, 70, 66,193, 4,128, 2, 0, 0,195, 2, 0, 6, + 69, 3, 1, 0, 70,131,193, 6, 92, 2,128, 2,220, 65, 0, 0,223,192,252,127, +197, 0, 1, 0,198,192,193, 1, 0, 1, 0, 0, 64, 1, 0, 1,220, 64,128, 1, +197, 0, 2, 0, 0, 1, 0, 1,221, 0, 0, 1,222, 0, 0, 0, 30, 0,128, 0, + 9, 0, 0, 0, 4, 6, 0, 0, 0, 68,101,112,116,104, 0, 3, 0, 0, 0, 0, + 0, 0,240, 63, 4, 6, 0, 0, 0,116, 97, 98,108,101, 0, 4, 7, 0, 0, 0, +105,110,115,101,114,116, 0, 4, 3, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, + 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 4, 5, 0, + 0, 0, 71, 82, 65, 89, 0, 4, 23, 0, 0, 0, 80,114,111, 99,101,115,115, 83, +112,108,105,116, 67,111,109,112,111,110,101,110,116,115, 0, 4, 7, 0, 0, 0, +117,110,112, 97, 99,107, 0, 0, 0, 0, 0, 29, 0, 0, 0, 35, 1, 0, 0, 35, + 1, 0, 0, 36, 1, 0, 0, 37, 1, 0, 0, 37, 1, 0, 0, 37, 1, 0, 0, 37, + 1, 0, 0, 38, 1, 0, 0, 38, 1, 0, 0, 38, 1, 0, 0, 38, 1, 0, 0, 38, + 1, 0, 0, 38, 1, 0, 0, 38, 1, 0, 0, 38, 1, 0, 0, 38, 1, 0, 0, 38, + 1, 0, 0, 38, 1, 0, 0, 37, 1, 0, 0, 40, 1, 0, 0, 40, 1, 0, 0, 40, + 1, 0, 0, 40, 1, 0, 0, 40, 1, 0, 0, 41, 1, 0, 0, 41, 1, 0, 0, 41, + 1, 0, 0, 41, 1, 0, 0, 42, 1, 0, 0, 7, 0, 0, 0, 10, 0, 0, 0,115, +114, 99, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 28, 0, 0, 0, 6, 0, 0, + 0,100,101,112,116,104, 0, 2, 0, 0, 0, 28, 0, 0, 0, 11, 0, 0, 0,100, +115,116, 95,105,109, 97,103,101,115, 0, 3, 0, 0, 0, 28, 0, 0, 0, 12, 0, + 0, 0, 40,102,111,114, 32,105,110,100,101,120, 41, 0, 6, 0, 0, 0, 19, 0, + 0, 0, 12, 0, 0, 0, 40,102,111,114, 32,108,105,109,105,116, 41, 0, 6, 0, + 0, 0, 19, 0, 0, 0, 11, 0, 0, 0, 40,102,111,114, 32,115,116,101,112, 41, + 0, 6, 0, 0, 0, 19, 0, 0, 0, 2, 0, 0, 0,105, 0, 7, 0, 0, 0, 18, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 1, 0, 0, 48, 1, 0, 0, 0, + 1, 0, 6, 14, 0, 0, 0, 69, 0, 0, 0, 70, 64,192, 0,134,128, 64, 0,195, + 0, 0, 2, 69, 1, 0, 0, 70,193,192, 2, 92,128,128, 2,133, 0, 0, 0,134, + 0, 65, 1,192, 0, 0, 0, 0, 1,128, 0,156, 64,128, 1, 94, 0, 0, 1, 30, + 0,128, 0, 5, 0, 0, 0, 4, 3, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, + 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 3, 0, 0, + 0, 0, 0, 0,240, 63, 4, 4, 0, 0, 0, 82, 71, 66, 0, 4, 23, 0, 0, 0, + 80,114,111, 99,101,115,115, 77,101,114,103,101, 67,111,109,112,111,110,101,110, +116,115, 0, 0, 0, 0, 0, 14, 0, 0, 0, 45, 1, 0, 0, 45, 1, 0, 0, 45, + 1, 0, 0, 45, 1, 0, 0, 45, 1, 0, 0, 45, 1, 0, 0, 45, 1, 0, 0, 46, + 1, 0, 0, 46, 1, 0, 0, 46, 1, 0, 0, 46, 1, 0, 0, 46, 1, 0, 0, 47, + 1, 0, 0, 48, 1, 0, 0, 2, 0, 0, 0, 15, 0, 0, 0,115,114, 99, 95,105, +109, 97,103,101, 95,108,105,115,116, 0, 0, 0, 0, 0, 13, 0, 0, 0, 10, 0, + 0, 0,100,115,116, 95,105,109, 97,103,101, 0, 7, 0, 0, 0, 13, 0, 0, 0, + 0, 0, 0, 0,144, 1, 0, 0, 25, 0, 0, 0, 50, 0, 0, 0, 73, 0, 0, 0, + 97, 0, 0, 0,122, 0, 0, 0,130, 0, 0, 0,132, 0, 0, 0,132, 0, 0, 0, +132, 0, 0, 0,132, 0, 0, 0,132, 0, 0, 0,132, 0, 0, 0,133, 0, 0, 0, +133, 0, 0, 0,133, 0, 0, 0,134, 0, 0, 0,134, 0, 0, 0,134, 0, 0, 0, +135, 0, 0, 0,135, 0, 0, 0,135, 0, 0, 0,136, 0, 0, 0,136, 0, 0, 0, +136, 0, 0, 0,136, 0, 0, 0,136, 0, 0, 0,136, 0, 0, 0,136, 0, 0, 0, +136, 0, 0, 0,136, 0, 0, 0,137, 0, 0, 0,137, 0, 0, 0,137, 0, 0, 0, +138, 0, 0, 0,138, 0, 0, 0,138, 0, 0, 0,138, 0, 0, 0,138, 0, 0, 0, +138, 0, 0, 0,139, 0, 0, 0,139, 0, 0, 0,139, 0, 0, 0,139, 0, 0, 0, +139, 0, 0, 0,139, 0, 0, 0,139, 0, 0, 0,141, 0, 0, 0,144, 0, 0, 0, +141, 0, 0, 0,146, 0, 0, 0,149, 0, 0, 0,146, 0, 0, 0,151, 0, 0, 0, +151, 0, 0, 0,151, 0, 0, 0,152, 0, 0, 0,151, 0, 0, 0,154, 0, 0, 0, +160, 0, 0, 0,154, 0, 0, 0,162, 0, 0, 0,162, 0, 0, 0,162, 0, 0, 0, +164, 0, 0, 0,170, 0, 0, 0,164, 0, 0, 0,172, 0, 0, 0,176, 0, 0, 0, +172, 0, 0, 0,178, 0, 0, 0,178, 0, 0, 0,178, 0, 0, 0,179, 0, 0, 0, +179, 0, 0, 0,179, 0, 0, 0,179, 0, 0, 0,179, 0, 0, 0,180, 0, 0, 0, +180, 0, 0, 0,180, 0, 0, 0,181, 0, 0, 0,181, 0, 0, 0,181, 0, 0, 0, +182, 0, 0, 0,182, 0, 0, 0,182, 0, 0, 0,183, 0, 0, 0,183, 0, 0, 0, +183, 0, 0, 0,184, 0, 0, 0,184, 0, 0, 0,184, 0, 0, 0,185, 0, 0, 0, +185, 0, 0, 0,185, 0, 0, 0,186, 0, 0, 0,186, 0, 0, 0,186, 0, 0, 0, +187, 0, 0, 0,187, 0, 0, 0,187, 0, 0, 0,188, 0, 0, 0,188, 0, 0, 0, +188, 0, 0, 0,189, 0, 0, 0,189, 0, 0, 0,189, 0, 0, 0,190, 0, 0, 0, +190, 0, 0, 0,190, 0, 0, 0,191, 0, 0, 0,191, 0, 0, 0,191, 0, 0, 0, +192, 0, 0, 0,192, 0, 0, 0,192, 0, 0, 0,193, 0, 0, 0,193, 0, 0, 0, +193, 0, 0, 0,194, 0, 0, 0,194, 0, 0, 0,194, 0, 0, 0,195, 0, 0, 0, +195, 0, 0, 0,195, 0, 0, 0,196, 0, 0, 0,196, 0, 0, 0,196, 0, 0, 0, +197, 0, 0, 0,197, 0, 0, 0,197, 0, 0, 0,198, 0, 0, 0,198, 0, 0, 0, +198, 0, 0, 0,199, 0, 0, 0,199, 0, 0, 0,199, 0, 0, 0,200, 0, 0, 0, +200, 0, 0, 0,200, 0, 0, 0,201, 0, 0, 0,201, 0, 0, 0,201, 0, 0, 0, +202, 0, 0, 0,202, 0, 0, 0,202, 0, 0, 0,203, 0, 0, 0,203, 0, 0, 0, +203, 0, 0, 0,204, 0, 0, 0,204, 0, 0, 0,204, 0, 0, 0,205, 0, 0, 0, +205, 0, 0, 0,205, 0, 0, 0,206, 0, 0, 0,206, 0, 0, 0,206, 0, 0, 0, +207, 0, 0, 0,207, 0, 0, 0,207, 0, 0, 0,208, 0, 0, 0,208, 0, 0, 0, +208, 0, 0, 0,209, 0, 0, 0,209, 0, 0, 0,209, 0, 0, 0,210, 0, 0, 0, +210, 0, 0, 0,210, 0, 0, 0,211, 0, 0, 0,211, 0, 0, 0,211, 0, 0, 0, +212, 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0, +214, 0, 0, 0,227, 0, 0, 0,214, 0, 0, 0,235, 0, 0, 0,237, 0, 0, 0, +237, 0, 0, 0,237, 0, 0, 0,237, 0, 0, 0,237, 0, 0, 0,238, 0, 0, 0, +238, 0, 0, 0,238, 0, 0, 0,238, 0, 0, 0,238, 0, 0, 0,239, 0, 0, 0, +239, 0, 0, 0,239, 0, 0, 0,240, 0, 0, 0,240, 0, 0, 0,240, 0, 0, 0, +241, 0, 0, 0,241, 0, 0, 0,241, 0, 0, 0,242, 0, 0, 0,242, 0, 0, 0, +242, 0, 0, 0,243, 0, 0, 0,243, 0, 0, 0,243, 0, 0, 0,244, 0, 0, 0, +244, 0, 0, 0,244, 0, 0, 0,245, 0, 0, 0,245, 0, 0, 0,245, 0, 0, 0, +246, 0, 0, 0,246, 0, 0, 0,246, 0, 0, 0,247, 0, 0, 0,247, 0, 0, 0, +247, 0, 0, 0,248, 0, 0, 0,248, 0, 0, 0,248, 0, 0, 0,250, 0, 0, 0, +254, 0, 0, 0,250, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, + 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 2, 1, 0, 0, 2, 1, 0, 0, + 2, 1, 0, 0, 3, 1, 0, 0, 3, 1, 0, 0, 3, 1, 0, 0, 3, 1, 0, 0, + 3, 1, 0, 0, 3, 1, 0, 0, 5, 1, 0, 0, 9, 1, 0, 0, 5, 1, 0, 0, + 11, 1, 0, 0, 15, 1, 0, 0, 11, 1, 0, 0, 17, 1, 0, 0, 17, 1, 0, 0, + 17, 1, 0, 0, 18, 1, 0, 0, 18, 1, 0, 0, 18, 1, 0, 0, 19, 1, 0, 0, + 19, 1, 0, 0, 19, 1, 0, 0, 19, 1, 0, 0, 19, 1, 0, 0, 19, 1, 0, 0, + 19, 1, 0, 0, 20, 1, 0, 0, 20, 1, 0, 0, 20, 1, 0, 0, 21, 1, 0, 0, + 21, 1, 0, 0, 21, 1, 0, 0, 22, 1, 0, 0, 22, 1, 0, 0, 22, 1, 0, 0, + 24, 1, 0, 0, 29, 1, 0, 0, 24, 1, 0, 0, 31, 1, 0, 0, 31, 1, 0, 0, + 31, 1, 0, 0, 31, 1, 0, 0, 31, 1, 0, 0, 31, 1, 0, 0, 31, 1, 0, 0, + 31, 1, 0, 0, 32, 1, 0, 0, 32, 1, 0, 0, 32, 1, 0, 0, 32, 1, 0, 0, + 32, 1, 0, 0, 32, 1, 0, 0, 32, 1, 0, 0, 32, 1, 0, 0, 34, 1, 0, 0, + 42, 1, 0, 0, 34, 1, 0, 0, 44, 1, 0, 0, 48, 1, 0, 0, 44, 1, 0, 0, + 50, 1, 0, 0, 50, 1, 0, 0, 50, 1, 0, 0, 50, 1, 0, 0, 50, 1, 0, 0, + 50, 1, 0, 0, 51, 1, 0, 0, 51, 1, 0, 0, 51, 1, 0, 0, 52, 1, 0, 0, + 52, 1, 0, 0, 52, 1, 0, 0, 53, 1, 0, 0, 53, 1, 0, 0, 53, 1, 0, 0, + 54, 1, 0, 0, 54, 1, 0, 0, 54, 1, 0, 0, 55, 1, 0, 0, 55, 1, 0, 0, + 55, 1, 0, 0, 56, 1, 0, 0, 56, 1, 0, 0, 56, 1, 0, 0, 57, 1, 0, 0, + 57, 1, 0, 0, 57, 1, 0, 0, 57, 1, 0, 0, 57, 1, 0, 0, 57, 1, 0, 0, + 58, 1, 0, 0, 58, 1, 0, 0, 58, 1, 0, 0, 58, 1, 0, 0, 58, 1, 0, 0, + 58, 1, 0, 0, 59, 1, 0, 0, 59, 1, 0, 0, 59, 1, 0, 0, 60, 1, 0, 0, + 60, 1, 0, 0, 60, 1, 0, 0, 60, 1, 0, 0, 60, 1, 0, 0, 60, 1, 0, 0, + 60, 1, 0, 0, 61, 1, 0, 0, 61, 1, 0, 0, 61, 1, 0, 0, 61, 1, 0, 0, + 61, 1, 0, 0, 61, 1, 0, 0, 61, 1, 0, 0, 62, 1, 0, 0, 62, 1, 0, 0, + 62, 1, 0, 0, 62, 1, 0, 0, 62, 1, 0, 0, 62, 1, 0, 0, 62, 1, 0, 0, + 63, 1, 0, 0, 63, 1, 0, 0, 63, 1, 0, 0, 64, 1, 0, 0, 64, 1, 0, 0, + 64, 1, 0, 0, 64, 1, 0, 0, 64, 1, 0, 0, 64, 1, 0, 0, 64, 1, 0, 0, + 65, 1, 0, 0, 65, 1, 0, 0, 65, 1, 0, 0, 65, 1, 0, 0, 65, 1, 0, 0, + 65, 1, 0, 0, 65, 1, 0, 0, 66, 1, 0, 0, 66, 1, 0, 0, 66, 1, 0, 0, + 67, 1, 0, 0, 67, 1, 0, 0, 67, 1, 0, 0, 68, 1, 0, 0, 68, 1, 0, 0, + 68, 1, 0, 0, 69, 1, 0, 0, 69, 1, 0, 0, 69, 1, 0, 0, 69, 1, 0, 0, + 69, 1, 0, 0, 69, 1, 0, 0, 69, 1, 0, 0, 70, 1, 0, 0, 70, 1, 0, 0, + 70, 1, 0, 0, 70, 1, 0, 0, 70, 1, 0, 0, 70, 1, 0, 0, 70, 1, 0, 0, + 71, 1, 0, 0, 71, 1, 0, 0, 71, 1, 0, 0, 72, 1, 0, 0, 72, 1, 0, 0, + 72, 1, 0, 0, 72, 1, 0, 0, 7, 0, 0, 0, 17, 0, 0, 0, 79,110,101, 83, +111,117,114, 99,101, 79,110,101, 68,101,115,116, 0, 1, 0, 0, 0,143, 1, 0, + 0, 18, 0, 0, 0, 84,119,111, 83,111,117,114, 99,101,115, 79,110,101, 68,101, +115,116, 0, 2, 0, 0, 0,143, 1, 0, 0, 20, 0, 0, 0, 84,104,114,101,101, + 83,111,117,114, 99,101,115, 79,110,101, 68,101,115,116, 0, 3, 0, 0, 0,143, + 1, 0, 0, 18, 0, 0, 0, 79,110,101, 83,111,117,114, 99,101, 84,119,111, 68, +101,115,116,115, 0, 4, 0, 0, 0,143, 1, 0, 0, 20, 0, 0, 0, 79,110,101, + 83,111,117,114, 99,101, 84,104,114,101,101, 68,101,115,116,115, 0, 5, 0, 0, + 0,143, 1, 0, 0, 13, 0, 0, 0,104,111,117,103,104, 95,104,101,105,103,104, +116, 0, 6, 0, 0, 0,143, 1, 0, 0, 13, 0, 0, 0,105,110,116, 95,100, 97, +116, 97,116,121,112,101, 0,182, 0, 0, 0,143, 1, 0, 0, 0, 0, 0, 0, +}; + + if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"../obj/imlua_process51/im_process.lo")==0) lua_call(L, 0, 0); +} diff --git a/im/src/lua5/loh/im_process_be32.loh b/im/src/lua5/loh/im_process_be32.loh new file mode 100755 index 0000000..be77d66 --- /dev/null +++ b/im/src/lua5/loh/im_process_be32.loh @@ -0,0 +1,817 @@ +/* code automatically generated by bin2c -- DO NOT EDIT */ +{ +/* #include'ing this file in a C program is equivalent to calling + if (luaL_loadfile(L,"../obj/imlua_process51/im_process_be32.lo")==0) lua_call(L, 0, 0); +*/ +/* ../obj/imlua_process51/im_process_be32.lo */ +static const unsigned char B1[]={ + 27, 76,117, 97, 81, 0, 0, 4, 4, 4, 8, 0, 0, 0, 0, 21, 64,108,117, 97, + 53, 47,105,109, 95,112,114,111, 99,101,115,115, 46,108,117, 97, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2, 13, 0, 0, 1,144, 0, 0, 0, 36, 0, 0, 64, +100, 0, 0,128,164, 0, 0,192,228, 0, 1, 1, 36, 0, 1, 65,100, 0, 0, 1, +128, 0, 0, 1,193, 5, 0, 2, 3, 0, 0, 66,197, 5,192,130,198, 3, 0, 65, +156, 0, 0, 1,128, 0, 0,193,193, 1, 0, 65,156, 0, 0, 1,128, 0, 1, 1, +193, 1, 0, 65,156, 0, 0, 1,128, 0, 1, 65,193, 1, 0, 65,156, 0, 0, 1, +128, 0, 1,129,193, 0, 1,194, 1, 2,128, 2, 64, 0, 0, 66,133, 5, 66, 2, +134, 0, 0, 66,197, 5,194, 66,198, 3, 0, 65,156, 0, 0, 1,128, 0, 2,129, +193, 1, 0, 65,156, 0, 0, 1,128, 0, 2,193,193, 5, 0, 2, 3, 0, 0, 66, +197, 5,195, 2,198, 3, 0, 65,156, 0, 0, 1,128, 0, 3, 65,193, 4,128, 2, + 3, 0, 0, 66,133, 5, 67,130,134, 5,128, 2,195, 3, 0, 65,156, 0, 0, 65, +133, 0, 1,129,228,135,129,193,137, 0, 0, 65,133, 0, 1,193,228,136, 1,193, +137, 0, 0, 1,128, 0, 4, 65,193, 0, 2, 2, 36, 0, 2, 66,100, 2, 0, 65, +156, 0, 0, 65,133, 0, 2,129,228,137, 1,193,137, 0,128, 1,128, 0, 4,193, +193, 1, 0, 65,156, 0, 0, 65,133, 0, 2,193,228,138, 1,193,137, 0, 0, 65, +133, 0, 3, 1,228,138,129,193,137, 0, 0, 1,128, 0, 5,129,193, 1, 0, 65, +156, 0, 0, 1,128, 0, 5,193,193, 0, 3, 66, 36, 0, 3,130,100, 2, 0, 65, +156, 0, 0, 1,128, 0, 6, 1,193, 1, 0, 65,156, 0, 0, 1,128, 0, 6, 65, +193, 1, 0, 65,156, 0, 0, 1,128, 0, 6,129,193, 1, 0, 65,156, 0, 0, 1, +128, 0, 6,193,193, 1, 0, 65,156, 0, 0, 1,128, 0, 7, 1,193, 1, 0, 65, +156, 0, 0, 1,128, 0, 7, 65,193, 1, 0, 65,156, 0, 0, 1,128, 0, 7,129, +193, 1, 0, 65,156, 0, 0, 1,128, 0, 7,193,193, 1, 0, 65,156, 0, 0, 1, +128, 0, 8, 1,193, 1, 0, 65,156, 0, 0, 1,128, 0, 8, 65,193, 1, 0, 65, +156, 0, 0, 1,128, 0, 8,129,193, 1, 0, 65,156, 0, 0, 1,128, 0, 8,193, +193, 1, 0, 65,156, 0, 0, 1,128, 0, 9, 1,193, 1, 0, 65,156, 0, 0, 1, +128, 0, 9, 65,193, 1, 0, 65,156, 0, 0, 1,128, 0, 9,129,193, 1, 0, 65, +156, 0, 0, 1,128, 0, 9,193,193, 1, 0, 65,156, 0, 0, 1,128, 0, 10, 1, +193, 1, 0, 65,156, 0, 0, 1,128, 0, 10, 65,193, 1, 0, 65,156, 0, 0, 1, +128, 0, 10,129,193, 1, 0, 65,156, 0, 0, 1,128, 0, 10,193,193, 1, 0, 65, +156, 0, 0, 1,128, 0, 11, 1,193, 1, 0, 65,156, 0, 0, 1,128, 0, 11, 65, +193, 1, 0, 65,156, 0, 0, 1,128, 0, 11,129,193, 1, 0, 65,156, 0, 0, 1, +128, 0, 11,193,193, 1, 0, 65,156, 0, 0, 1,128, 0, 12, 1,193, 1, 0, 65, +156, 0, 0, 1,128, 0, 12, 65,193, 1, 0, 65,156, 0, 0, 1,128, 0, 12,129, +193, 1, 0, 65,156, 0, 0, 1,128, 0, 12,193,193, 1, 0, 65,156, 0, 0, 1, +128, 0, 13, 1,193, 1, 0, 65,156, 0, 0, 1,128, 0, 13, 65,193, 1, 0, 65, +156, 0, 0, 1,128, 0, 13,129,193, 1, 0, 65,156, 0, 0, 1,128, 0, 13,193, +193, 1, 0, 65,156, 1,128, 1,128, 0, 14, 1,193, 4, 0, 2, 3, 0, 3,194, +100, 2, 0, 65,156, 0, 0, 65,133, 0, 4, 1,228,156,129,193,137, 0, 4, 65, +164, 0, 0, 1,192, 0, 14,130, 1, 5,128, 2, 67, 3, 0, 3, 0, 3, 0, 65, +220, 0, 0, 1,192, 0, 14,194, 1, 5,128, 2, 67, 3, 0, 3, 0, 3, 0, 65, +220, 0, 0, 1,192, 0, 15, 2, 1, 1, 0, 65,220, 0, 0, 1,192, 0, 15, 66, + 1, 1, 0, 65,220, 0, 0, 1,192, 0, 15,130, 1, 1, 0, 65,220, 0, 0, 1, +192, 0, 15,194, 1, 1, 0, 65,220, 0, 0, 1,192, 0, 16, 2, 1, 1, 0, 65, +220, 0, 0, 1,192, 0, 16, 66, 1, 1, 0, 65,220, 0,128, 1,192, 0, 16,130, + 1, 1, 0, 65,220, 0, 0, 1,192, 0, 16,194, 1, 1, 0, 65,220, 0, 0, 1, +192, 0, 17, 2, 1, 1, 0, 65,220, 0,128, 1,192, 0, 17, 66, 1, 1, 0, 65, +220, 0, 0, 65,197, 0, 4,130, 36,163, 2, 1,201, 0,128, 1,192, 0, 17,194, + 1, 1, 0, 65,220, 1, 0, 1,192, 0, 18, 2, 1, 1, 0, 65,220, 1,128, 1, +192, 0, 18, 66, 1, 1, 0, 65,220, 0,128, 1,192, 0, 18,130, 1, 5,128, 2, + 67, 0, 0, 67, 5, 6, 82,195, 6, 3, 0, 65,220, 0, 0, 65,197, 0, 4,194, + 36,166, 2, 1,201, 0, 0, 65,197, 0, 5, 2, 36,166,130, 1,201, 0,128, 1, +192, 0, 19,130, 1, 1, 0, 65,220, 0, 0, 1,192, 0, 19,194, 1, 1, 0, 65, +220, 0, 0, 1,192, 0, 20, 2, 1, 5, 0, 2, 67, 0, 0, 66,197, 5,212, 66, +198, 6, 0, 3, 3, 3, 0, 65,220, 0, 0, 1,192, 0, 20,130, 1, 1, 0, 65, +220, 0, 0, 1,192, 0, 20,194, 1, 1, 0, 65,220, 0, 0, 1,192, 0, 21, 2, + 1, 1, 0, 65,220, 0, 0, 65,197, 0, 5, 66, 36,170,130, 1,201, 2, 0, 1, +192, 0, 21,130, 1, 5, 0, 2, 67, 0, 0, 66,197, 5,194, 2,198, 0, 0, 67, + 5, 6, 67, 3, 6, 3, 0, 65,220, 1, 0, 1,192, 0, 21,194, 1, 5, 0, 2, + 67, 0, 0, 66,197, 5,214, 2,198, 0, 0, 67, 5, 6, 86, 67, 6, 3, 0, 65, +220, 0, 0, 65,197, 0, 5,130, 36,173, 2, 1,201, 0, 0, 65,197, 0, 5,194, + 36,173,130, 1,201, 0, 0, 1,192, 0, 23, 2, 1, 5,128, 2, 67, 0, 0, 67, + 5, 6, 67, 3, 6, 3, 0, 65,220, 0, 0, 1,192, 0, 23, 66, 1, 1, 0, 65, +220, 0,128, 1,192, 0, 23,130, 1, 1, 0, 65,220, 0, 0, 1,192, 0, 23,194, + 1, 1, 0, 65,220, 0, 0, 1,192, 0, 24, 2, 1, 1, 0, 65,220, 0, 0, 1, +192, 0, 24, 66, 1, 1, 0, 65,220, 0, 0, 1,192, 0, 24,130, 1, 1, 0, 65, +220, 0, 0, 1,192, 0, 24,194, 1, 5,128, 2, 67, 0, 0, 67, 5, 6, 86, 67, + 6, 3, 0, 65,220, 0, 0, 1,192, 0, 25, 2, 1, 5,128, 2, 67, 0, 0, 67, + 5, 6, 86, 67, 6, 3, 0, 65,220, 0, 0, 1,192, 0, 25, 66, 1, 1, 0, 65, +220, 0, 0, 1,192, 0, 25,130, 1, 5, 0, 2, 67, 0, 0, 66,197, 5,195,130, +198, 6, 0, 3, 3, 3, 0, 65,220, 0, 0, 1,192, 0, 25,194, 1, 5, 0, 2, + 67, 0, 0, 66,197, 5,195,130,198, 6, 0, 3, 3, 3, 0, 65,220, 0, 0, 1, +192, 0, 26, 2, 1, 5, 0, 2, 67, 0, 0, 66,197, 5,195,130,198, 6, 0, 3, + 3, 3, 0, 65,220, 0,128, 1,192, 0, 26, 66, 1, 1, 0, 65,220, 0, 0, 1, +192, 0, 26,130, 1, 5, 0, 2, 67, 0, 0, 66,197, 5,195,130,198, 6, 0, 3, + 3, 3, 0, 65,220, 0, 0, 1,192, 0, 26,194, 1, 5, 0, 2, 67, 0, 0, 66, +197, 5,195,130,198, 6, 0, 3, 3, 3, 0, 65,220, 0, 0, 1,192, 0, 27, 2, + 1, 1, 0, 65,220, 0, 0, 1,192, 0, 27, 66, 1, 1, 0, 65,220, 0, 0, 1, +192, 0, 27,130, 1, 1, 0, 65,220, 0, 0, 1,192, 0, 27,194, 1, 5, 0, 2, + 67, 0, 0, 66,197, 5,195,130,198, 6, 0, 3, 3, 3, 0, 65,220, 0, 0, 1, +192, 0, 28, 2, 1, 5, 0, 2, 67, 0, 0, 66,197, 5,195,130,198, 6, 0, 3, + 3, 3, 0, 65,220, 0, 0, 1,192, 0, 28, 66, 1, 1, 0, 65,220, 0, 0, 1, +192, 0, 28,130, 1, 1, 0, 65,220, 0,128, 0, 30, 0, 0, 0,115, 4, 0, 0, + 0, 19, 65,110, 97,108,121,122,101, 70,105,110,100, 82,101,103,105,111,110,115, + 0, 4, 0, 0, 0, 3,105,109, 0, 4, 0, 0, 0, 7, 85, 83, 72, 79, 82, 84, + 0, 4, 0, 0, 0, 21, 80,114,111, 99,101,115,115, 80,101,114,105,109,101,116, +101,114, 76,105,110,101, 0, 4, 0, 0, 0, 20, 80,114,111, 99,101,115,115, 82, +101,109,111,118,101, 66,121, 65,114,101, 97, 0, 4, 0, 0, 0, 17, 80,114,111, + 99,101,115,115, 70,105,108,108, 72,111,108,101,115, 0, 4, 0, 0, 0, 18, 80, +114,111, 99,101,115,115, 72,111,117,103,104, 76,105,110,101,115, 0, 3, 64,102, +128, 0, 0, 0, 0, 0, 4, 0, 0, 0, 5, 71, 82, 65, 89, 0, 4, 0, 0, 0, + 4, 73, 78, 84, 0, 4, 0, 0, 0, 22, 80,114,111, 99,101,115,115, 72,111,117, +103,104, 76,105,110,101,115, 68,114, 97,119, 0, 4, 0, 0, 0, 25, 80,114,111, + 99,101,115,115, 68,105,115,116, 97,110, 99,101, 84,114, 97,110,115,102,111,114, +109, 0, 4, 0, 0, 0, 6, 70, 76, 79, 65, 84, 0, 4, 0, 0, 0, 23, 80,114, +111, 99,101,115,115, 82,101,103,105,111,110, 97,108, 77, 97,120,105,109,117,109, + 0, 4, 0, 0, 0, 7, 66, 73, 78, 65, 82, 89, 0, 4, 0, 0, 0, 17, 80,114, +111, 99,101,115,115, 82,101,100,117, 99,101, 78,101,119, 0, 4, 0, 0, 0, 17, + 80,114,111, 99,101,115,115, 82,101,115,105,122,101, 78,101,119, 0, 4, 0, 0, + 0, 17, 80,114,111, 99,101,115,115, 82,101,100,117, 99,101, 66,121, 52, 0, 4, + 0, 0, 0, 15, 80,114,111, 99,101,115,115, 67,114,111,112, 78,101,119, 0, 4, + 0, 0, 0, 14, 80,114,111, 99,101,115,115, 73,110,115,101,114,116, 0, 4, 0, + 0, 0, 21, 80,114,111, 99,101,115,115, 65,100,100, 77, 97,114,103,105,110,115, + 78,101,119, 0, 4, 0, 0, 0, 17, 80,114,111, 99,101,115,115, 82,111,116, 97, +116,101, 78,101,119, 0, 4, 0, 0, 0, 17, 80,114,111, 99,101,115,115, 82,111, +116, 97,116,101, 82,101,102, 0, 4, 0, 0, 0, 16, 80,114,111, 99,101,115,115, + 82,111,116, 97,116,101, 57, 48, 0, 4, 0, 0, 0, 17, 80,114,111, 99,101,115, +115, 82,111,116, 97,116,101, 49, 56, 48, 0, 4, 0, 0, 0, 14, 80,114,111, 99, +101,115,115, 77,105,114,114,111,114, 0, 4, 0, 0, 0, 12, 80,114,111, 99,101, +115,115, 70,108,105,112, 0, 4, 0, 0, 0, 14, 80,114,111, 99,101,115,115, 82, + 97,100,105, 97,108, 0, 4, 0, 0, 0, 25, 80,114,111, 99,101,115,115, 71,114, + 97,121, 77,111,114,112,104, 67,111,110,118,111,108,118,101, 0, 4, 0, 0, 0, + 22, 80,114,111, 99,101,115,115, 71,114, 97,121, 77,111,114,112,104, 69,114,111, +100,101, 0, 4, 0, 0, 0, 23, 80,114,111, 99,101,115,115, 71,114, 97,121, 77, +111,114,112,104, 68,105,108, 97,116,101, 0, 4, 0, 0, 0, 21, 80,114,111, 99, +101,115,115, 71,114, 97,121, 77,111,114,112,104, 79,112,101,110, 0, 4, 0, 0, + 0, 22, 80,114,111, 99,101,115,115, 71,114, 97,121, 77,111,114,112,104, 67,108, +111,115,101, 0, 4, 0, 0, 0, 23, 80,114,111, 99,101,115,115, 71,114, 97,121, + 77,111,114,112,104, 84,111,112, 72, 97,116, 0, 4, 0, 0, 0, 21, 80,114,111, + 99,101,115,115, 71,114, 97,121, 77,111,114,112,104, 87,101,108,108, 0, 4, 0, + 0, 0, 25, 80,114,111, 99,101,115,115, 71,114, 97,121, 77,111,114,112,104, 71, +114, 97,100,105,101,110,116, 0, 4, 0, 0, 0, 24, 80,114,111, 99,101,115,115, + 66,105,110, 77,111,114,112,104, 67,111,110,118,111,108,118,101, 0, 4, 0, 0, + 0, 21, 80,114,111, 99,101,115,115, 66,105,110, 77,111,114,112,104, 69,114,111, +100,101, 0, 4, 0, 0, 0, 22, 80,114,111, 99,101,115,115, 66,105,110, 77,111, +114,112,104, 68,105,108, 97,116,101, 0, 4, 0, 0, 0, 20, 80,114,111, 99,101, +115,115, 66,105,110, 77,111,114,112,104, 79,112,101,110, 0, 4, 0, 0, 0, 21, + 80,114,111, 99,101,115,115, 66,105,110, 77,111,114,112,104, 67,108,111,115,101, + 0, 4, 0, 0, 0, 23, 80,114,111, 99,101,115,115, 66,105,110, 77,111,114,112, +104, 79,117,116,108,105,110,101, 0, 4, 0, 0, 0, 20, 80,114,111, 99,101,115, +115, 66,105,110, 77,111,114,112,104, 84,104,105,110, 0, 4, 0, 0, 0, 22, 80, +114,111, 99,101,115,115, 77,101,100,105, 97,110, 67,111,110,118,111,108,118,101, + 0, 4, 0, 0, 0, 21, 80,114,111, 99,101,115,115, 82, 97,110,103,101, 67,111, +110,118,111,108,118,101, 0, 4, 0, 0, 0, 27, 80,114,111, 99,101,115,115, 82, + 97,110,107, 67,108,111,115,101,115,116, 67,111,110,118,111,108,118,101, 0, 4, + 0, 0, 0, 23, 80,114,111, 99,101,115,115, 82, 97,110,107, 77, 97,120, 67,111, +110,118,111,108,118,101, 0, 4, 0, 0, 0, 23, 80,114,111, 99,101,115,115, 82, + 97,110,107, 77,105,110, 67,111,110,118,111,108,118,101, 0, 4, 0, 0, 0, 16, + 80,114,111, 99,101,115,115, 67,111,110,118,111,108,118,101, 0, 4, 0, 0, 0, + 19, 80,114,111, 99,101,115,115, 67,111,110,118,111,108,118,101, 83,101,112, 0, + 4, 0, 0, 0, 19, 80,114,111, 99,101,115,115, 67,111,110,118,111,108,118,101, + 82,101,112, 0, 4, 0, 0, 0, 20, 80,114,111, 99,101,115,115, 67,111,110,118, +111,108,118,101, 68,117, 97,108, 0, 4, 0, 0, 0, 23, 80,114,111, 99,101,115, +115, 67,111,109,112, 97,115,115, 67,111,110,118,111,108,118,101, 0, 4, 0, 0, + 0, 20, 80,114,111, 99,101,115,115, 77,101, 97,110, 67,111,110,118,111,108,118, +101, 0, 4, 0, 0, 0, 24, 80,114,111, 99,101,115,115, 71, 97,117,115,115,105, + 97,110, 67,111,110,118,111,108,118,101, 0, 4, 0, 0, 0, 23, 80,114,111, 99, +101,115,115, 66, 97,114,108,101,116,116, 67,111,110,118,111,108,118,101, 0, 4, + 0, 0, 0, 22, 80,114,111, 99,101,115,115, 73,110,116,101,114,108, 97, 99,101, + 83,112,108,105,116, 0, 4, 0, 0, 0, 25, 80,114,111, 99,101,115,115, 73,110, +116,101,114,108, 97, 99,101, 83,112,108,105,116, 78,101,119, 0, 4, 0, 0, 0, + 30, 80,114,111, 99,101,115,115, 68,105,102,102, 79,102, 71, 97,117,115,115,105, + 97,110, 67,111,110,118,111,108,118,101, 0, 4, 0, 0, 0, 29, 80,114,111, 99, +101,115,115, 76, 97,112, 79,102, 71, 97,117,115,115,105, 97,110, 67,111,110,118, +111,108,118,101, 0, 4, 0, 0, 0, 21, 80,114,111, 99,101,115,115, 83,111, 98, +101,108, 67,111,110,118,111,108,118,101, 0, 4, 0, 0, 0, 26, 80,114,111, 99, +101,115,115, 83,112,108,105,110,101, 69,100,103,101, 67,111,110,118,111,108,118, +101, 0, 4, 0, 0, 0, 23, 80,114,111, 99,101,115,115, 80,114,101,119,105,116, +116, 67,111,110,118,111,108,118,101, 0, 4, 0, 0, 0, 20, 80,114,111, 99,101, +115,115, 90,101,114,111, 67,114,111,115,115,105,110,103, 0, 4, 0, 0, 0, 13, + 80,114,111, 99,101,115,115, 67, 97,110,110,121, 0, 4, 0, 0, 0, 22, 80,114, +111, 99,101,115,115, 85,110, 65,114,105,116,104,109,101,116,105, 99, 79,112, 0, + 4, 0, 0, 0, 20, 80,114,111, 99,101,115,115, 65,114,105,116,104,109,101,116, +105, 99, 79,112, 0, 4, 0, 0, 0, 15, 80,114,111, 99,101,115,115, 85,110,115, +104, 97,114,112, 0, 4, 0, 0, 0, 13, 80,114,111, 99,101,115,115, 83,104, 97, +114,112, 0, 4, 0, 0, 0, 19, 80,114,111, 99,101,115,115, 83,104, 97,114,112, + 75,101,114,110,101,108, 0, 4, 0, 0, 0, 28, 80,114,111, 99,101,115,115, 65, +114,105,116,104,109,101,116,105, 99, 67,111,110,115,116, 79,112, 78,101,119, 0, + 4, 0, 0, 0, 18, 80,114,111, 99,101,115,115, 66,108,101,110,100, 67,111,110, +115,116, 0, 4, 0, 0, 0, 13, 80,114,111, 99,101,115,115, 66,108,101,110,100, + 0, 4, 0, 0, 0, 20, 80,114,111, 99,101,115,115, 83,112,108,105,116, 67,111, +109,112,108,101,120, 0, 4, 0, 0, 0, 20, 80,114,111, 99,101,115,115, 77,101, +114,103,101, 67,111,109,112,108,101,120, 0, 4, 0, 0, 0, 7, 67, 70, 76, 79, + 65, 84, 0, 4, 0, 0, 0, 23, 80,114,111, 99,101,115,115, 77,117,108,116,105, +112,108,101, 77,101, 97,110, 78,101,119, 0, 4, 0, 0, 0, 25, 80,114,111, 99, +101,115,115, 77,117,108,116,105,112,108,101, 83,116,100, 68,101,118, 78,101,119, + 0, 4, 0, 0, 0, 22, 80,114,111, 99,101,115,115, 65,117,116,111, 67,111,118, + 97,114,105, 97,110, 99,101, 0, 4, 0, 0, 0, 20, 80,114,111, 99,101,115,115, + 77,117,108,116,105,112,108,121, 67,111,110,106, 0, 4, 0, 0, 0, 26, 80,114, +111, 99,101,115,115, 81,117, 97,110,116,105,122,101, 82, 71, 66, 85,110,105,102, +111,114,109, 0, 4, 0, 0, 0, 4, 77, 65, 80, 0, 4, 0, 0, 0, 27, 80,114, +111, 99,101,115,115, 81,117, 97,110,116,105,122,101, 71,114, 97,121, 85,110,105, +102,111,114,109, 0, 4, 0, 0, 0, 23, 80,114,111, 99,101,115,115, 69,120,112, + 97,110,100, 72,105,115,116,111,103,114, 97,109, 0, 4, 0, 0, 0, 25, 80,114, +111, 99,101,115,115, 69,113,117, 97,108,105,122,101, 72,105,115,116,111,103,114, + 97,109, 0, 4, 0, 0, 0, 23, 80,114,111, 99,101,115,115, 83,112,108,105,116, + 89, 67,104,114,111,109, 97, 78,101,119, 0, 4, 0, 0, 0, 16, 80,114,111, 99, +101,115,115, 83,112,108,105,116, 72, 83, 73, 0, 4, 0, 0, 0, 16, 80,114,111, + 99,101,115,115, 77,101,114,103,101, 72, 83, 73, 0, 4, 0, 0, 0, 4, 82, 71, + 66, 0, 4, 0, 0, 0, 5, 66, 89, 84, 69, 0, 4, 0, 0, 0, 26, 80,114,111, + 99,101,115,115, 83,112,108,105,116, 67,111,109,112,111,110,101,110,116,115, 78, +101,119, 0, 4, 0, 0, 0, 26, 80,114,111, 99,101,115,115, 77,101,114,103,101, + 67,111,109,112,111,110,101,110,116,115, 78,101,119, 0, 4, 0, 0, 0, 27, 80, +114,111, 99,101,115,115, 78,111,114,109, 97,108,105,122,101, 67,111,109,112,111, +110,101,110,116,115, 0, 4, 0, 0, 0, 20, 80,114,111, 99,101,115,115, 82,101, +112,108, 97, 99,101, 67,111,108,111,114, 0, 4, 0, 0, 0, 17, 80,114,111, 99, +101,115,115, 66,105,116,119,105,115,101, 79,112, 0, 4, 0, 0, 0, 18, 80,114, +111, 99,101,115,115, 66,105,116,119,105,115,101, 78,111,116, 0, 4, 0, 0, 0, + 15, 80,114,111, 99,101,115,115, 66,105,116, 77, 97,115,107, 0, 4, 0, 0, 0, + 16, 80,114,111, 99,101,115,115, 66,105,116, 80,108, 97,110,101, 0, 4, 0, 0, + 0, 17, 80,114,111, 99,101,115,115, 84,111,110,101, 71, 97,109,117,116, 0, 4, + 0, 0, 0, 19, 80,114,111, 99,101,115,115, 85,110, 78,111,114,109, 97,108,105, +122,101, 0, 4, 0, 0, 0, 18, 80,114,111, 99,101,115,115, 68,105,114,101, 99, +116, 67,111,110,118, 0, 4, 0, 0, 0, 16, 80,114,111, 99,101,115,115, 78,101, +103, 97,116,105,118,101, 0, 4, 0, 0, 0, 30, 80,114,111, 99,101,115,115, 82, + 97,110,103,101, 67,111,110,116,114, 97,115,116, 84,104,114,101,115,104,111,108, +100, 0, 4, 0, 0, 0, 25, 80,114,111, 99,101,115,115, 76,111, 99, 97,108, 77, + 97,120, 84,104,114,101,115,104,111,108,100, 0, 4, 0, 0, 0, 17, 80,114,111, + 99,101,115,115, 84,104,114,101,115,104,111,108,100, 0, 4, 0, 0, 0, 23, 80, +114,111, 99,101,115,115, 84,104,114,101,115,104,111,108,100, 66,121, 68,105,102, +102, 0, 4, 0, 0, 0, 27, 80,114,111, 99,101,115,115, 72,121,115,116,101,114, +101,115,105,115, 84,104,114,101,115,104,111,108,100, 0, 4, 0, 0, 0, 27, 80, +114,111, 99,101,115,115, 85,110,105,102,111,114,109, 69,114,114, 84,104,114,101, +115,104,111,108,100, 0, 4, 0, 0, 0, 28, 80,114,111, 99,101,115,115, 68,105, +102,117,115,105,111,110, 69,114,114, 84,104,114,101,115,104,111,108,100, 0, 4, + 0, 0, 0, 24, 80,114,111, 99,101,115,115, 80,101,114, 99,101,110,116, 84,104, +114,101,115,104,111,108,100, 0, 4, 0, 0, 0, 21, 80,114,111, 99,101,115,115, + 79,116,115,117, 84,104,114,101,115,104,111,108,100, 0, 4, 0, 0, 0, 23, 80, +114,111, 99,101,115,115, 77,105,110, 77, 97,120, 84,104,114,101,115,104,111,108, +100, 0, 4, 0, 0, 0, 22, 80,114,111, 99,101,115,115, 83,108,105, 99,101, 84, +104,114,101,115,104,111,108,100, 0, 4, 0, 0, 0, 16, 80,114,111, 99,101,115, +115, 80,105,120,101,108, 97,116,101, 0, 4, 0, 0, 0, 17, 80,114,111, 99,101, +115,115, 80,111,115,116,101,114,105,122,101, 0, 0, 0, 0, 24, 0, 0, 0, 0, + 0, 0, 0, 8, 0, 0, 0, 25, 0, 5, 0, 9, 0, 0, 0, 17, 0, 0, 1, 69, + 2,128, 1, 70, 0, 0, 65,133, 2,128, 1,192, 1, 0, 65,156, 0, 0, 1,133, + 0, 0, 1,192, 0, 0,130, 1, 3,130, 1,213, 0, 0, 2, 36, 0,128, 0, 0, + 1, 0, 0, 0, 1,128, 0, 0, 2, 0, 0, 0, 2,128, 0, 0, 3,130, 1,137, + 0,128, 0, 30, 0, 0, 0, 3, 4, 0, 0, 0, 3,105,109, 0, 4, 0, 0, 0, + 7, 97,115,115,101,114,116, 0, 4, 0, 0, 0, 4, 78,101,119, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 24, 5, 1, 7, 8, 0, 0, 0, + 23, 0, 0, 0,133, 1, 64, 64,134, 0, 0, 0,192, 0, 0, 1, 4, 0,128, 1, + 68, 1, 0, 1,132, 1,128, 1,196, 3, 0,128,156, 2, 0, 0,196, 0, 0, 1, + 0, 1, 0, 1, 64, 0, 0,129,133, 0,128, 1,192, 1, 0, 1,156, 0, 0,128, +220, 0, 0, 0,218,128, 0,192, 22, 1,128, 1, 0, 1, 0, 1, 64, 1,128, 1, + 30,128, 0, 0, 22, 1, 0, 0,158, 0,128, 0, 30, 0, 0, 0, 3, 4, 0, 0, + 0, 3,105,109, 0, 4, 0, 0, 0, 17, 73,109, 97,103,101, 67,114,101, 97,116, +101, 66, 97,115,101,100, 0, 4, 0, 0, 0, 7,117,110,112, 97, 99,107, 0, 0, + 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, + 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, + 0, 0, 18, 0, 0, 0, 18, 0, 0, 0, 18, 0, 0, 0, 18, 0, 0, 0, 18, 0, + 0, 0, 18, 0, 0, 0, 18, 0, 0, 0, 19, 0, 0, 0, 19, 0, 0, 0, 20, 0, + 0, 0, 20, 0, 0, 0, 20, 0, 0, 0, 20, 0, 0, 0, 22, 0, 0, 0, 24, 0, + 0, 0, 4, 0, 0, 0, 10,115,114, 99, 95,105,109, 97,103,101, 0, 0, 0, 0, + 0, 0, 0, 0, 22, 0, 0, 0, 4, 97,114,103, 0, 0, 0, 0, 0, 0, 0, 0, + 22, 0, 0, 0, 10,100,115,116, 95,105,109, 97,103,101, 0, 0, 0, 0, 8, 0, + 0, 0, 22, 0, 0, 0, 4,114,101,116, 0, 0, 0, 0, 15, 0, 0, 0, 22, 0, + 0, 0, 5, 0, 0, 0, 6,119,105,100,116,104, 0, 0, 0, 0, 7,104,101,105, +103,104,116, 0, 0, 0, 0, 12, 99,111,108,111,114, 95,115,112, 97, 99,101, 0, + 0, 0, 0, 10,100, 97,116, 97, 95,116,121,112,101, 0, 0, 0, 0, 5,102,117, +110, 99, 0, 0, 0, 0, 17, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 10, 0, + 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, + 0, 0, 13, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, + 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 25, 0, 0, 0, 6, 0, + 0, 0, 9,102,117,110, 99,110, 97,109,101, 0, 0, 0, 0, 0, 0, 0, 0, 16, + 0, 0, 0, 6,119,105,100,116,104, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, + 0, 7,104,101,105,103,104,116, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, + 12, 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 10,100, 97,116, 97, 95,116,121,112,101, 0, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 0, 5,102,117,110, 99, 0, 0, 0, 0, 2, 0, 0, 0, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, 50, 0, 5, 0, 11, + 0, 0, 0, 22, 0, 0, 1, 69, 2,128, 1, 70, 0, 0, 65,133, 2,128, 1,192, + 0, 0,130, 5, 4, 64,194, 6, 0, 1, 2, 65, 0, 0, 2,128, 1,128, 2, 28, + 0, 0, 65,156, 0, 0, 1,133, 0, 0, 1,192, 0, 1, 66, 1, 3,130, 1,213, + 0, 0, 2, 36, 0,128, 0, 0, 1, 0, 0, 0, 1,128, 0, 0, 2, 0, 0, 0, + 2,128, 0, 0, 3,130, 1,137, 0,128, 0, 30, 0, 0, 0, 6, 4, 0, 0, 0, + 3,105,109, 0, 4, 0, 0, 0, 7, 97,115,115,101,114,116, 0, 4, 0, 0, 0, + 7,115,116,114,105,110,103, 0, 4, 0, 0, 0, 7,102,111,114,109, 97,116, 0, + 4, 0, 0, 0, 24,117,110,100,101,102,105,110,101,100, 32,102,117,110, 99,116, +105,111,110, 32, 96, 37,115, 39, 0, 4, 0, 0, 0, 4, 78,101,119, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, 49, 5, 2, 7, 10, 0, 0, + 0, 24, 0, 0, 0,197, 1,192, 64,198, 0, 0, 1, 0, 0, 0, 1, 68, 0,128, + 1,132, 1, 0, 1,196, 1,128, 2, 4, 3, 0,128,220, 2, 0, 1, 4, 0, 0, + 1, 64, 0,128, 1,128, 1,128, 1,192, 0, 0,130, 5, 1, 0, 2, 64, 1, 0, + 2, 28, 0, 0,129, 28, 0, 0, 1, 26,128, 0,192, 22, 2, 0, 1, 64, 1,128, + 1,128, 1,128, 1, 94,128, 0, 0, 22, 1, 0, 0,222, 0,128, 0, 30, 0, 0, + 0, 3, 4, 0, 0, 0, 3,105,109, 0, 4, 0, 0, 0, 17, 73,109, 97,103,101, + 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 4, 0, 0, 0, 7,117,110,112, + 97, 99,107, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 40, 0, 0, 0, 40, + 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, + 0, 0, 0, 40, 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, 43, + 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, 44, + 0, 0, 0, 44, 0, 0, 0, 45, 0, 0, 0, 45, 0, 0, 0, 45, 0, 0, 0, 45, + 0, 0, 0, 47, 0, 0, 0, 49, 0, 0, 0, 5, 0, 0, 0, 11,115,114, 99, 95, +105,109, 97,103,101, 49, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 11,115, +114, 99, 95,105,109, 97,103,101, 50, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 0, + 0, 4, 97,114,103, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 10,100,115, +116, 95,105,109, 97,103,101, 0, 0, 0, 0, 8, 0, 0, 0, 23, 0, 0, 0, 4, +114,101,116, 0, 0, 0, 0, 16, 0, 0, 0, 23, 0, 0, 0, 5, 0, 0, 0, 6, +119,105,100,116,104, 0, 0, 0, 0, 7,104,101,105,103,104,116, 0, 0, 0, 0, + 12, 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 0, 0, 0, 10,100, 97,116, + 97, 95,116,121,112,101, 0, 0, 0, 0, 5,102,117,110, 99, 0, 0, 0, 0, 22, + 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, 35, + 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, 35, + 0, 0, 0, 38, 0, 0, 0, 38, 0, 0, 0, 38, 0, 0, 0, 38, 0, 0, 0, 49, + 0, 0, 0, 49, 0, 0, 0, 49, 0, 0, 0, 49, 0, 0, 0, 49, 0, 0, 0, 49, + 0, 0, 0, 49, 0, 0, 0, 50, 0, 0, 0, 6, 0, 0, 0, 9,102,117,110, 99, +110, 97,109,101, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 6,119,105,100, +116,104, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 7,104,101,105,103,104, +116, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 12, 99,111,108,111,114, 95, +115,112, 97, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 10,100, 97, +116, 97, 95,116,121,112,101, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 5, +102,117,110, 99, 0, 0, 0, 0, 2, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 56, 0, 0, 0, 73, 0, 5, 0, 9, 0, 0, 0, 17, 0, 0, 1, + 69, 2,128, 1, 70, 0, 0, 65,133, 2,128, 1,192, 1, 0, 65,156, 0, 0, 1, +133, 0, 0, 1,192, 0, 0,130, 1, 3,130, 1,213, 0, 0, 2, 36, 0,128, 0, + 0, 1, 0, 0, 0, 1,128, 0, 0, 2, 0, 0, 0, 2,128, 0, 0, 3,130, 1, +137, 0,128, 0, 30, 0, 0, 0, 3, 4, 0, 0, 0, 3,105,109, 0, 4, 0, 0, + 0, 7, 97,115,115,101,114,116, 0, 4, 0, 0, 0, 4, 78,101,119, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 61, 0, 0, 0, 72, 5, 3, 7, 12, 0, 0, + 0, 25, 0, 0, 1, 5, 2, 64, 65, 6, 0, 0, 1, 64, 0, 0, 1,132, 0,128, + 1,196, 1, 0, 2, 4, 1,128, 2, 68, 3, 0,129, 28, 2, 0, 1, 68, 0, 0, + 1,128, 0,128, 1,192, 1, 0, 2, 0, 2, 0, 2, 64, 0, 0,130,133, 1,128, + 2,192, 1, 0, 2,156, 0, 0,129, 92, 0, 0, 1, 90,128, 0,192, 22, 2,128, + 1,128, 2, 0, 1,192, 1,128, 1,158,128, 0, 0, 22, 1, 0, 1, 30, 0,128, + 0, 30, 0, 0, 0, 3, 4, 0, 0, 0, 3,105,109, 0, 4, 0, 0, 0, 17, 73, +109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 4, 0, 0, 0, + 7,117,110,112, 97, 99,107, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 63, + 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, + 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 66, 0, 0, 0, 66, 0, 0, 0, 66, + 0, 0, 0, 66, 0, 0, 0, 66, 0, 0, 0, 66, 0, 0, 0, 66, 0, 0, 0, 66, + 0, 0, 0, 66, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 68, 0, 0, 0, 68, + 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 70, 0, 0, 0, 72, 0, 0, 0, 6, + 0, 0, 0, 11,115,114, 99, 95,105,109, 97,103,101, 49, 0, 0, 0, 0, 0, 0, + 0, 0, 24, 0, 0, 0, 11,115,114, 99, 95,105,109, 97,103,101, 50, 0, 0, 0, + 0, 0, 0, 0, 0, 24, 0, 0, 0, 11,115,114, 99, 95,105,109, 97,103,101, 51, + 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 97,114,103, 0, 0, 0, 0, + 0, 0, 0, 0, 24, 0, 0, 0, 10,100,115,116, 95,105,109, 97,103,101, 0, 0, + 0, 0, 8, 0, 0, 0, 24, 0, 0, 0, 4,114,101,116, 0, 0, 0, 0, 17, 0, + 0, 0, 24, 0, 0, 0, 5, 0, 0, 0, 6,119,105,100,116,104, 0, 0, 0, 0, + 7,104,101,105,103,104,116, 0, 0, 0, 0, 12, 99,111,108,111,114, 95,115,112, + 97, 99,101, 0, 0, 0, 0, 10,100, 97,116, 97, 95,116,121,112,101, 0, 0, 0, + 0, 5,102,117,110, 99, 0, 0, 0, 0, 17, 0, 0, 0, 57, 0, 0, 0, 57, 0, + 0, 0, 58, 0, 0, 0, 58, 0, 0, 0, 58, 0, 0, 0, 61, 0, 0, 0, 61, 0, + 0, 0, 61, 0, 0, 0, 61, 0, 0, 0, 72, 0, 0, 0, 72, 0, 0, 0, 72, 0, + 0, 0, 72, 0, 0, 0, 72, 0, 0, 0, 72, 0, 0, 0, 72, 0, 0, 0, 73, 0, + 0, 0, 6, 0, 0, 0, 9,102,117,110, 99,110, 97,109,101, 0, 0, 0, 0, 0, + 0, 0, 0, 16, 0, 0, 0, 6,119,105,100,116,104, 0, 0, 0, 0, 0, 0, 0, + 0, 16, 0, 0, 0, 7,104,101,105,103,104,116, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 12, 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 0, 0, 0, + 0, 0, 0, 0, 16, 0, 0, 0, 10,100, 97,116, 97, 95,116,121,112,101, 0, 0, + 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 5,102,117,110, 99, 0, 0, 0, 0, 2, + 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 0, 0, 0, 97, + 0, 5, 0, 9, 0, 0, 0, 17, 0, 0, 1, 69, 2,128, 1, 70, 0, 0, 65,133, + 2,128, 1,192, 1, 0, 65,156, 0, 0, 1,133, 0, 0, 1,192, 0, 0,130, 1, + 3,130, 1,213, 0, 0, 2, 36, 0,128, 0, 0, 1, 0, 0, 0, 1,128, 0, 0, + 2, 0, 0, 0, 2,128, 0, 0, 3,130, 1,137, 0,128, 0, 30, 0, 0, 0, 3, + 4, 0, 0, 0, 3,105,109, 0, 4, 0, 0, 0, 7, 97,115,115,101,114,116, 0, + 4, 0, 0, 0, 4, 78,101,119, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 84, 0, 0, 0, 96, 5, 1, 7, 10, 0, 0, 0, 35, 0, 0, 0,133, 1, 64, 64, +134, 0, 0, 0,192, 0, 0, 1, 4, 0,128, 1, 68, 1, 0, 1,132, 1,128, 1, +196, 3, 0,128,156, 0, 0, 0,197, 1,192, 64,198, 0, 0, 1, 0, 0, 0, 1, + 68, 0,128, 1,132, 1, 0, 1,196, 1,128, 2, 4, 3, 0,128,220, 2, 0, 1, + 4, 0, 0, 1, 64, 1, 0, 1,128, 1,128, 1,192, 0, 0,130, 5, 0,128, 2, + 64, 1, 0, 2, 28, 0, 0,129, 28, 0, 0, 1, 26,128, 1, 0, 22, 2, 0, 1, + 64, 1, 0, 1,128, 1,128, 1,192, 2, 0, 1, 94,128, 0,128, 22, 1, 0, 1, + 64, 1,128, 1,128, 1,128, 1, 94, 0,128, 0, 30, 0, 0, 0, 3, 4, 0, 0, + 0, 3,105,109, 0, 4, 0, 0, 0, 17, 73,109, 97,103,101, 67,114,101, 97,116, +101, 66, 97,115,101,100, 0, 4, 0, 0, 0, 7,117,110,112, 97, 99,107, 0, 0, + 0, 0, 0, 0, 0, 0, 35, 0, 0, 0, 86, 0, 0, 0, 86, 0, 0, 0, 86, 0, + 0, 0, 86, 0, 0, 0, 86, 0, 0, 0, 86, 0, 0, 0, 86, 0, 0, 0, 86, 0, + 0, 0, 87, 0, 0, 0, 87, 0, 0, 0, 87, 0, 0, 0, 87, 0, 0, 0, 87, 0, + 0, 0, 87, 0, 0, 0, 87, 0, 0, 0, 87, 0, 0, 0, 90, 0, 0, 0, 90, 0, + 0, 0, 90, 0, 0, 0, 90, 0, 0, 0, 90, 0, 0, 0, 90, 0, 0, 0, 90, 0, + 0, 0, 90, 0, 0, 0, 91, 0, 0, 0, 91, 0, 0, 0, 92, 0, 0, 0, 92, 0, + 0, 0, 92, 0, 0, 0, 92, 0, 0, 0, 92, 0, 0, 0, 94, 0, 0, 0, 94, 0, + 0, 0, 94, 0, 0, 0, 96, 0, 0, 0, 5, 0, 0, 0, 10,115,114, 99, 95,105, +109, 97,103,101, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 4, 97,114,103, + 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 11,100,115,116, 95,105,109, 97, +103,101, 49, 0, 0, 0, 0, 8, 0, 0, 0, 34, 0, 0, 0, 11,100,115,116, 95, +105,109, 97,103,101, 50, 0, 0, 0, 0, 16, 0, 0, 0, 34, 0, 0, 0, 4,114, +101,116, 0, 0, 0, 0, 24, 0, 0, 0, 34, 0, 0, 0, 5, 0, 0, 0, 6,119, +105,100,116,104, 0, 0, 0, 0, 7,104,101,105,103,104,116, 0, 0, 0, 0, 12, + 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 0, 0, 0, 10,100, 97,116, 97, + 95,116,121,112,101, 0, 0, 0, 0, 5,102,117,110, 99, 0, 0, 0, 0, 17, 0, + 0, 0, 80, 0, 0, 0, 80, 0, 0, 0, 81, 0, 0, 0, 81, 0, 0, 0, 81, 0, + 0, 0, 84, 0, 0, 0, 84, 0, 0, 0, 84, 0, 0, 0, 84, 0, 0, 0, 96, 0, + 0, 0, 96, 0, 0, 0, 96, 0, 0, 0, 96, 0, 0, 0, 96, 0, 0, 0, 96, 0, + 0, 0, 96, 0, 0, 0, 97, 0, 0, 0, 6, 0, 0, 0, 9,102,117,110, 99,110, + 97,109,101, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 6,119,105,100,116, +104, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 7,104,101,105,103,104,116, + 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 12, 99,111,108,111,114, 95,115, +112, 97, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 10,100, 97,116, + 97, 95,116,121,112,101, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 5,102, +117,110, 99, 0, 0, 0, 0, 2, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,103, 0, 0, 0,122, 0, 5, 0, 9, 0, 0, 0, 17, 0, 0, 1, 69, + 2,128, 1, 70, 0, 0, 65,133, 2,128, 1,192, 1, 0, 65,156, 0, 0, 1,133, + 0, 0, 1,192, 0, 0,130, 1, 3,130, 1,213, 0, 0, 2, 36, 0,128, 0, 0, + 1, 0, 0, 0, 1,128, 0, 0, 2, 0, 0, 0, 2,128, 0, 0, 3,130, 1,137, + 0,128, 0, 30, 0, 0, 0, 3, 4, 0, 0, 0, 3,105,109, 0, 4, 0, 0, 0, + 7, 97,115,115,101,114,116, 0, 4, 0, 0, 0, 4, 78,101,119, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0,108, 0, 0, 0,121, 5, 1, 7, 12, 0, 0, 0, + 46, 0, 0, 0,133, 1, 64, 64,134, 0, 0, 0,192, 0, 0, 1, 4, 0,128, 1, + 68, 1, 0, 1,132, 1,128, 1,196, 3, 0,128,156, 0, 0, 0,197, 1,192, 64, +198, 0, 0, 1, 0, 0, 0, 1, 68, 0,128, 1,132, 1, 0, 1,196, 1,128, 2, + 4, 3, 0,128,220, 0, 0, 1, 5, 2, 64, 65, 6, 0, 0, 1, 64, 0, 0, 1, +132, 0,128, 1,196, 1, 0, 2, 4, 1,128, 2, 68, 3, 0,129, 28, 2, 0, 1, + 68, 0, 0, 1,128, 1, 0, 1,192, 1,128, 2, 0, 2, 0, 2, 64, 0, 0,130, +133, 0,128, 2,192, 1, 0, 2,156, 0, 0,129, 92, 0, 0, 1, 90,128, 1, 64, + 22, 2,128, 1,128, 1, 0, 1,192, 1,128, 2, 0, 2, 0, 2, 64, 2,128, 1, +158,128, 0,192, 22, 1, 0, 1,128, 1,128, 1,192, 2, 0, 2, 0, 2, 0, 1, +158, 0,128, 0, 30, 0, 0, 0, 3, 4, 0, 0, 0, 3,105,109, 0, 4, 0, 0, + 0, 17, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 4, + 0, 0, 0, 7,117,110,112, 97, 99,107, 0, 0, 0, 0, 0, 0, 0, 0, 46, 0, + 0, 0,110, 0, 0, 0,110, 0, 0, 0,110, 0, 0, 0,110, 0, 0, 0,110, 0, + 0, 0,110, 0, 0, 0,110, 0, 0, 0,110, 0, 0, 0,111, 0, 0, 0,111, 0, + 0, 0,111, 0, 0, 0,111, 0, 0, 0,111, 0, 0, 0,111, 0, 0, 0,111, 0, + 0, 0,111, 0, 0, 0,112, 0, 0, 0,112, 0, 0, 0,112, 0, 0, 0,112, 0, + 0, 0,112, 0, 0, 0,112, 0, 0, 0,112, 0, 0, 0,112, 0, 0, 0,115, 0, + 0, 0,115, 0, 0, 0,115, 0, 0, 0,115, 0, 0, 0,115, 0, 0, 0,115, 0, + 0, 0,115, 0, 0, 0,115, 0, 0, 0,115, 0, 0, 0,116, 0, 0, 0,116, 0, + 0, 0,117, 0, 0, 0,117, 0, 0, 0,117, 0, 0, 0,117, 0, 0, 0,117, 0, + 0, 0,117, 0, 0, 0,119, 0, 0, 0,119, 0, 0, 0,119, 0, 0, 0,119, 0, + 0, 0,121, 0, 0, 0, 6, 0, 0, 0, 10,115,114, 99, 95,105,109, 97,103,101, + 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 4, 97,114,103, 0, 0, 0, 0, + 0, 0, 0, 0, 45, 0, 0, 0, 11,100,115,116, 95,105,109, 97,103,101, 49, 0, + 0, 0, 0, 8, 0, 0, 0, 45, 0, 0, 0, 11,100,115,116, 95,105,109, 97,103, +101, 50, 0, 0, 0, 0, 16, 0, 0, 0, 45, 0, 0, 0, 11,100,115,116, 95,105, +109, 97,103,101, 51, 0, 0, 0, 0, 24, 0, 0, 0, 45, 0, 0, 0, 4,114,101, +116, 0, 0, 0, 0, 33, 0, 0, 0, 45, 0, 0, 0, 5, 0, 0, 0, 6,119,105, +100,116,104, 0, 0, 0, 0, 7,104,101,105,103,104,116, 0, 0, 0, 0, 12, 99, +111,108,111,114, 95,115,112, 97, 99,101, 0, 0, 0, 0, 10,100, 97,116, 97, 95, +116,121,112,101, 0, 0, 0, 0, 5,102,117,110, 99, 0, 0, 0, 0, 17, 0, 0, + 0,104, 0, 0, 0,104, 0, 0, 0,105, 0, 0, 0,105, 0, 0, 0,105, 0, 0, + 0,108, 0, 0, 0,108, 0, 0, 0,108, 0, 0, 0,108, 0, 0, 0,121, 0, 0, + 0,121, 0, 0, 0,121, 0, 0, 0,121, 0, 0, 0,121, 0, 0, 0,121, 0, 0, + 0,121, 0, 0, 0,122, 0, 0, 0, 6, 0, 0, 0, 9,102,117,110, 99,110, 97, +109,101, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 6,119,105,100,116,104, + 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 7,104,101,105,103,104,116, 0, + 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 12, 99,111,108,111,114, 95,115,112, + 97, 99,101, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 10,100, 97,116, 97, + 95,116,121,112,101, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 5,102,117, +110, 99, 0, 0, 0, 0, 2, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,126, 0, 0, 0,130, 0, 1, 0, 7, 0, 0, 0, 18, 0, 0, 0,100, 0, + 0, 0,133, 1, 64, 64,134, 0,128, 0,192, 0, 64,129, 11, 1, 0, 1, 28, 0, + 0,128,220, 0,128, 1, 0, 0, 64,193, 75, 1, 0, 1, 92, 0, 0,129, 28, 1, +129, 0,204, 1, 0,128,156, 1, 65, 0,143,130, 0,128,206, 1,193, 64,204, 1, + 0, 0,222, 0,128, 0, 30, 0, 0, 0, 6, 4, 0, 0, 0, 5,109, 97,116,104, + 0, 4, 0, 0, 0, 5,115,113,114,116, 0, 4, 0, 0, 0, 6, 87,105,100,116, +104, 0, 4, 0, 0, 0, 7, 72,101,105,103,104,116, 0, 3, 64, 0, 0, 0, 0, + 0, 0, 0, 3, 63,240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0,127, 0, 0, 0,127, 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 78, + 1, 0, 0, 94, 0,128, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, + 0, 0, 0,127, 0, 0, 0,127, 0, 0, 0,127, 0, 0, 0, 1, 0, 0, 0, 2, +120, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, + 0,127, 0, 0, 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, 0, + 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, 0, + 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, 0, 0,129, 0, 0, + 0,129, 0, 0, 0,129, 0, 0, 0,130, 0, 0, 0, 3, 0, 0, 0, 6,105,109, + 97,103,101, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 4,115,113,114, 0, + 0, 0, 0, 1, 0, 0, 0, 17, 0, 0, 0, 5,114,109, 97,120, 0, 0, 0, 0, + 14, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,141, 0, 0, 0, +144, 0, 3, 0, 7, 0, 0, 0, 14, 0, 0, 0,197, 1,192, 64,198, 0, 0, 1, + 0, 0,128, 1, 64, 1, 0, 1,128, 2, 0,128,220, 0, 0, 1, 5, 2, 64,129, + 6, 0, 0, 1, 64, 1,128, 1,128, 1,128,129, 28, 1,128, 1, 64, 1,128, 1, + 30, 0,128, 0, 30, 0, 0, 0, 3, 4, 0, 0, 0, 3,105,109, 0, 4, 0, 0, + 0, 17, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 4, + 0, 0, 0, 14, 80,114,111, 99,101,115,115, 82,101,100,117, 99,101, 0, 0, 0, + 0, 0, 0, 0, 0, 14, 0, 0, 0,142, 0, 0, 0,142, 0, 0, 0,142, 0, 0, + 0,142, 0, 0, 0,142, 0, 0, 0,142, 0, 0, 0,143, 0, 0, 0,143, 0, 0, + 0,143, 0, 0, 0,143, 0, 0, 0,143, 0, 0, 0,143, 0, 0, 0,143, 0, 0, + 0,144, 0, 0, 0, 4, 0, 0, 0, 10,115,114, 99, 95,105,109, 97,103,101, 0, + 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 6,119,105,100,116,104, 0, 0, 0, + 0, 0, 0, 0, 0, 13, 0, 0, 0, 7,104,101,105,103,104,116, 0, 0, 0, 0, + 0, 0, 0, 0, 13, 0, 0, 0, 10,100,115,116, 95,105,109, 97,103,101, 0, 0, + 0, 0, 6, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,146, 0, + 0, 0,149, 0, 3, 0, 7, 0, 0, 0, 14, 0, 0, 0,197, 1,192, 64,198, 0, + 0, 1, 0, 0,128, 1, 64, 1, 0, 1,128, 2, 0,128,220, 0, 0, 1, 5, 2, + 64,129, 6, 0, 0, 1, 64, 1,128, 1,128, 1,128,129, 28, 1,128, 1, 64, 1, +128, 1, 30, 0,128, 0, 30, 0, 0, 0, 3, 4, 0, 0, 0, 3,105,109, 0, 4, + 0, 0, 0, 17, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, + 0, 4, 0, 0, 0, 14, 80,114,111, 99,101,115,115, 82,101,115,105,122,101, 0, + 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0,147, 0, 0, 0,147, 0, 0, 0,147, + 0, 0, 0,147, 0, 0, 0,147, 0, 0, 0,147, 0, 0, 0,148, 0, 0, 0,148, + 0, 0, 0,148, 0, 0, 0,148, 0, 0, 0,148, 0, 0, 0,148, 0, 0, 0,148, + 0, 0, 0,149, 0, 0, 0, 4, 0, 0, 0, 10,115,114, 99, 95,105,109, 97,103, +101, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 6,119,105,100,116,104, 0, + 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 7,104,101,105,103,104,116, 0, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 10,100,115,116, 95,105,109, 97,103,101, + 0, 0, 0, 0, 6, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +151, 0, 0, 0,151, 0, 1, 0, 3, 0, 0, 0, 5, 0, 64, 0, 75, 1, 0,128, + 92, 0,192, 64, 79, 1, 0, 0, 94, 0,128, 0, 30, 0, 0, 0, 2, 4, 0, 0, + 0, 6, 87,105,100,116,104, 0, 3, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, 0, 0,151, 0, 0, 0,151, 0, 0, 0,151, 0, 0, 0, +151, 0, 0, 0,151, 0, 0, 0, 1, 0, 0, 0, 6,105,109, 97,103,101, 0, 0, + 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,152, 0, + 0, 0,152, 0, 1, 0, 3, 0, 0, 0, 5, 0, 64, 0, 75, 1, 0,128, 92, 0, +192, 64, 79, 1, 0, 0, 94, 0,128, 0, 30, 0, 0, 0, 2, 4, 0, 0, 0, 7, + 72,101,105,103,104,116, 0, 3, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 0, 0, 0,152, 0, 0, 0,152, 0, 0, 0,152, 0, 0, 0,152, + 0, 0, 0,152, 0, 0, 0, 1, 0, 0, 0, 6,105,109, 97,103,101, 0, 0, 0, + 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,154, 0, 0, + 0,160, 0, 5, 0, 13, 0, 0, 0, 19, 1, 0, 65, 77, 2,192, 1, 76, 2, 0, +193,141, 3, 64, 1,140, 0, 0, 65,197, 3,192,129,198, 0, 0, 2, 0, 2,128, + 2, 64, 3, 0, 2,128, 2, 0,129,220, 0, 0, 66, 5, 4, 64,194, 6, 0, 0, + 2, 64, 3,128, 2,128, 0,128, 2,192, 1,128, 3, 0, 2,128, 66, 28, 1, 0, + 1,222, 0,128, 0, 30, 0, 0, 0, 4, 3, 63,240, 0, 0, 0, 0, 0, 0, 4, + 0, 0, 0, 3,105,109, 0, 4, 0, 0, 0, 17, 73,109, 97,103,101, 67,114,101, + 97,116,101, 66, 97,115,101,100, 0, 4, 0, 0, 0, 12, 80,114,111, 99,101,115, +115, 67,114,111,112, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0,155, 0, 0, + 0,155, 0, 0, 0,156, 0, 0, 0,156, 0, 0, 0,157, 0, 0, 0,157, 0, 0, + 0,157, 0, 0, 0,157, 0, 0, 0,157, 0, 0, 0,157, 0, 0, 0,158, 0, 0, + 0,158, 0, 0, 0,158, 0, 0, 0,158, 0, 0, 0,158, 0, 0, 0,158, 0, 0, + 0,158, 0, 0, 0,159, 0, 0, 0,160, 0, 0, 0, 8, 0, 0, 0, 10,115,114, + 99, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 5, +120,109,105,110, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 5,120,109, 97, +120, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 5,121,109,105,110, 0, 0, + 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 5,121,109, 97,120, 0, 0, 0, 0, 0, + 0, 0, 0, 18, 0, 0, 0, 6,119,105,100,116,104, 0, 0, 0, 0, 2, 0, 0, + 0, 18, 0, 0, 0, 7,104,101,105,103,104,116, 0, 0, 0, 0, 4, 0, 0, 0, + 18, 0, 0, 0, 10,100,115,116, 95,105,109, 97,103,101, 0, 0, 0, 0, 10, 0, + 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,164, 0, 0, 0,170, 0, + 5, 0, 13, 0, 0, 0, 19, 1, 0, 65, 77, 2,192, 1, 76, 2, 0,193,141, 3, + 64, 1,140, 0, 0, 65,197, 3,192,129,198, 0, 0, 2, 0, 2,128, 2, 64, 3, + 0, 2,128, 2, 0,129,220, 0, 0, 66, 5, 4, 64,194, 6, 0, 0, 2, 64, 3, +128, 2,128, 0,128, 2,192, 1,128, 3, 0, 2,128, 66, 28, 1, 0, 1,222, 0, +128, 0, 30, 0, 0, 0, 4, 3, 63,240, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, + 3,105,109, 0, 4, 0, 0, 0, 17, 73,109, 97,103,101, 67,114,101, 97,116,101, + 66, 97,115,101,100, 0, 4, 0, 0, 0, 18, 80,114,111, 99,101,115,115, 65,100, +100, 77, 97,114,103,105,110,115, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, +165, 0, 0, 0,165, 0, 0, 0,166, 0, 0, 0,166, 0, 0, 0,167, 0, 0, 0, +167, 0, 0, 0,167, 0, 0, 0,167, 0, 0, 0,167, 0, 0, 0,167, 0, 0, 0, +168, 0, 0, 0,168, 0, 0, 0,168, 0, 0, 0,168, 0, 0, 0,168, 0, 0, 0, +168, 0, 0, 0,168, 0, 0, 0,169, 0, 0, 0,170, 0, 0, 0, 8, 0, 0, 0, + 10,115,114, 99, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, + 0, 0, 5,120,109,105,110, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 5, +120,109, 97,120, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 5,121,109,105, +110, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 5,121,109, 97,120, 0, 0, + 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 6,119,105,100,116,104, 0, 0, 0, 0, + 2, 0, 0, 0, 18, 0, 0, 0, 7,104,101,105,103,104,116, 0, 0, 0, 0, 4, + 0, 0, 0, 18, 0, 0, 0, 10,100,115,116, 95,105,109, 97,103,101, 0, 0, 0, + 0, 10, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,172, 0, 0, + 0,176, 0, 4, 0, 13, 0, 0, 0, 26, 0, 0, 1, 5, 2, 64, 65, 6, 0, 64, +129, 75, 1, 0,129, 92, 0, 64,193,139, 1, 0,129,156, 0,128, 1,192, 1, 0, + 2, 0, 2,128,193, 28, 0, 0, 1,133, 3, 65, 1,134, 0, 0, 1,192, 2, 0, + 2, 0, 2,128, 2, 64, 2, 0,129,156, 0, 0, 1,197, 3,193, 65,198, 0, 0, + 2, 0, 3, 0, 2, 64, 0,128, 2,128, 1, 0, 2,192, 1,128, 3, 0, 3, 0, +129,220, 3, 0, 2, 0, 1,128, 1,222, 0,128, 0, 30, 0, 0, 0, 6, 4, 0, + 0, 0, 3,105,109, 0, 4, 0, 0, 0, 22, 80,114,111, 99,101,115,115, 67, 97, +108, 99, 82,111,116, 97,116,101, 83,105,122,101, 0, 4, 0, 0, 0, 6, 87,105, +100,116,104, 0, 4, 0, 0, 0, 7, 72,101,105,103,104,116, 0, 4, 0, 0, 0, + 17, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 4, 0, + 0, 0, 14, 80,114,111, 99,101,115,115, 82,111,116, 97,116,101, 0, 0, 0, 0, + 0, 0, 0, 0, 26, 0, 0, 0,173, 0, 0, 0,173, 0, 0, 0,173, 0, 0, 0, +173, 0, 0, 0,173, 0, 0, 0,173, 0, 0, 0,173, 0, 0, 0,173, 0, 0, 0, +173, 0, 0, 0,174, 0, 0, 0,174, 0, 0, 0,174, 0, 0, 0,174, 0, 0, 0, +174, 0, 0, 0,174, 0, 0, 0,175, 0, 0, 0,175, 0, 0, 0,175, 0, 0, 0, +175, 0, 0, 0,175, 0, 0, 0,175, 0, 0, 0,175, 0, 0, 0,175, 0, 0, 0, +175, 0, 0, 0,175, 0, 0, 0,176, 0, 0, 0, 7, 0, 0, 0, 10,115,114, 99, + 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 5, 99, +111,115, 48, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 5,115,105,110, 48, + 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 6,111,114,100,101,114, 0, 0, + 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 6,119,105,100,116,104, 0, 0, 0, 0, + 9, 0, 0, 0, 25, 0, 0, 0, 7,104,101,105,103,104,116, 0, 0, 0, 0, 9, + 0, 0, 0, 25, 0, 0, 0, 10,100,115,116, 95,105,109, 97,103,101, 0, 0, 0, + 0, 15, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,179, 0, 0, + 0,179, 0, 1, 0, 3, 0, 0, 0, 4, 0, 64, 0, 75, 1, 0, 0, 93, 0, 0, + 0, 94, 0,128, 0, 30, 0, 0, 0, 1, 4, 0, 0, 0, 7, 72,101,105,103,104, +116, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0,179, 0, 0, 0,179, 0, 0, + 0,179, 0, 0, 0,179, 0, 0, 0, 1, 0, 0, 0, 6,105,109, 97,103,101, 0, + 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,179, + 0, 0, 0,179, 0, 1, 0, 3, 0, 0, 0, 4, 0, 64, 0, 75, 1, 0, 0, 93, + 0, 0, 0, 94, 0,128, 0, 30, 0, 0, 0, 1, 4, 0, 0, 0, 6, 87,105,100, +116,104, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0,179, 0, 0, 0,179, 0, + 0, 0,179, 0, 0, 0,179, 0, 0, 0, 1, 0, 0, 0, 6,105,109, 97,103,101, + 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +212, 0, 0, 0,212, 0, 1, 0, 3, 0, 0, 0, 13, 0, 64, 0, 75, 1, 0,128, + 92, 0, 0, 0, 90,128, 0,192, 22, 0, 64, 0, 75, 1, 0, 0, 93, 0, 0, 0, + 94,128, 0,192, 22, 0, 64, 0, 75, 1, 0,128, 92, 0,192, 64, 79, 1, 0, 0, + 94, 0,128, 0, 30, 0, 0, 0, 2, 4, 0, 0, 0, 7, 72,101,105,103,104,116, + 0, 3, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, + 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, 0, + 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, 0, + 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0, 1, 0, 0, 0, 6,105,109, + 97,103,101, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,214, 0, 0, 0,227, 0, 1, 0, 8, 0, 0, 0, 36, 0, 64, 0, 75, + 1, 0,128, 92, 0,192, 64, 79, 0, 0,128,133, 1, 64,192,134, 0, 64, 0,203, + 1, 0,128,220, 0, 0, 65, 1, 1,128,128,156, 0, 0, 0,154,128, 0, 0, 22, + 0,193, 0, 76, 0, 1, 64,133, 1, 65,128,134, 0, 0, 0,192, 2, 0, 1, 3, + 0,128, 1, 64, 2, 0,128,156, 0, 1, 64,197, 1,193,128,198, 0, 0, 1, 0, + 2,128, 1, 67, 0, 64, 1,139, 1, 0,129,156, 3, 64, 65,143, 2, 0,128,220, + 0, 1, 65, 5, 2, 65,193, 6, 0, 0, 1, 64, 1, 0, 1,128, 1,128, 1,192, + 2, 0, 65, 28, 1, 0, 1, 0, 1,128, 1, 64, 1,128, 1, 30, 0,128, 0, 30, + 0, 0, 0, 8, 4, 0, 0, 0, 7, 72,101,105,103,104,116, 0, 3, 64, 0, 0, + 0, 0, 0, 0, 0, 4, 0, 0, 0, 5,109, 97,116,104, 0, 4, 0, 0, 0, 4, +109,111,100, 0, 3, 63,240, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 3,105,109, + 0, 4, 0, 0, 0, 17, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115, +101,100, 0, 4, 0, 0, 0, 22, 80,114,111, 99,101,115,115, 73,110,116,101,114, +108, 97, 99,101, 83,112,108,105,116, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, + 0,216, 0, 0, 0,216, 0, 0, 0,216, 0, 0, 0,217, 0, 0, 0,217, 0, 0, + 0,217, 0, 0, 0,217, 0, 0, 0,217, 0, 0, 0,217, 0, 0, 0,217, 0, 0, + 0,217, 0, 0, 0,218, 0, 0, 0,221, 0, 0, 0,221, 0, 0, 0,221, 0, 0, + 0,221, 0, 0, 0,221, 0, 0, 0,221, 0, 0, 0,222, 0, 0, 0,222, 0, 0, + 0,222, 0, 0, 0,222, 0, 0, 0,222, 0, 0, 0,222, 0, 0, 0,222, 0, 0, + 0,222, 0, 0, 0,225, 0, 0, 0,225, 0, 0, 0,225, 0, 0, 0,225, 0, 0, + 0,225, 0, 0, 0,225, 0, 0, 0,226, 0, 0, 0,226, 0, 0, 0,226, 0, 0, + 0,227, 0, 0, 0, 4, 0, 0, 0, 10,115,114, 99, 95,105,109, 97,103,101, 0, + 0, 0, 0, 0, 0, 0, 0, 35, 0, 0, 0, 12,100,115,116, 95,104,101,105,103, +104,116, 49, 0, 0, 0, 0, 3, 0, 0, 0, 35, 0, 0, 0, 11,100,115,116, 95, +105,109, 97,103,101, 49, 0, 0, 0, 0, 18, 0, 0, 0, 35, 0, 0, 0, 11,100, +115,116, 95,105,109, 97,103,101, 50, 0, 0, 0, 0, 26, 0, 0, 0, 35, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,229, 0, 0, 0,235, 0, 1, 0, 3, 0, 0, + 0, 14, 0, 64, 0, 75, 1, 0,128, 92, 0, 0, 64,133, 1, 64,128,134, 0,128, +128, 87,128, 0,192, 22, 0, 0, 64,133, 1, 64,192,134, 0,128,128, 23,128, 0, + 64, 22, 0, 0, 64,133, 1, 65, 0, 70, 1, 0, 0, 94, 0,128, 0, 30, 0, 0, + 0, 5, 4, 0, 0, 0, 9, 68, 97,116, 97, 84,121,112,101, 0, 4, 0, 0, 0, + 3,105,109, 0, 4, 0, 0, 0, 5, 66, 89, 84, 69, 0, 4, 0, 0, 0, 7, 85, + 83, 72, 79, 82, 84, 0, 4, 0, 0, 0, 4, 73, 78, 84, 0, 0, 0, 0, 0, 0, + 0, 0, 14, 0, 0, 0,230, 0, 0, 0,230, 0, 0, 0,231, 0, 0, 0,231, 0, + 0, 0,231, 0, 0, 0,231, 0, 0, 0,231, 0, 0, 0,231, 0, 0, 0,231, 0, + 0, 0,231, 0, 0, 0,232, 0, 0, 0,232, 0, 0, 0,234, 0, 0, 0,235, 0, + 0, 0, 2, 0, 0, 0, 6,105,109, 97,103,101, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 0, 0, 0, 10,100, 97,116, 97, 95,116,121,112,101, 0, 0, 0, 0, 2, 0, + 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,250, 0, 0, 0,254, 0, + 3, 0, 9, 0, 0, 0, 13, 0, 0, 0,197, 1,192, 64,198, 0, 0, 1, 0, 1, + 0,128,220, 0, 0, 1, 5, 2, 64,129, 6, 0, 0, 1, 64, 0,128, 1,128, 1, +128, 1,192, 1, 0, 2, 0, 2,128, 65, 28, 1, 0, 0,222, 0,128, 0, 30, 0, + 0, 0, 3, 4, 0, 0, 0, 3,105,109, 0, 4, 0, 0, 0, 17, 73,109, 97,103, +101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 4, 0, 0, 0, 25, 80,114, +111, 99,101,115,115, 65,114,105,116,104,109,101,116,105, 99, 67,111,110,115,116, + 79,112, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0,251, 0, 0, 0,251, 0, + 0, 0,251, 0, 0, 0,251, 0, 0, 0,252, 0, 0, 0,252, 0, 0, 0,252, 0, + 0, 0,252, 0, 0, 0,252, 0, 0, 0,252, 0, 0, 0,252, 0, 0, 0,253, 0, + 0, 0,254, 0, 0, 0, 4, 0, 0, 0, 10,115,114, 99, 95,105,109, 97,103,101, + 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 10,115,114, 99, 95, 99,111,110, +115,116, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 3,111,112, 0, 0, 0, + 0, 0, 0, 0, 0, 12, 0, 0, 0, 10,100,115,116, 95,105,109, 97,103,101, 0, + 0, 0, 0, 4, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 5, + 0, 0, 1, 9, 0, 2, 0, 6, 0, 0, 0, 11, 0, 0, 0,133, 1, 64, 64,134, + 0, 64,128,198, 1, 0,128,156, 0, 0, 0,197, 1,192,192,198, 0, 0, 1, 0, + 1, 0, 1, 64, 1,128, 64,220, 1, 0, 0,158, 0,128, 0, 30, 0, 0, 0, 4, + 4, 0, 0, 0, 3,105,109, 0, 4, 0, 0, 0, 17, 73,109, 97,103,101, 67,114, +101, 97,116,101, 66, 97,115,101,100, 0, 3, 63,240, 0, 0, 0, 0, 0, 0, 4, + 0, 0, 0, 20, 80,114,111, 99,101,115,115, 77,117,108,116,105,112,108,101, 77, +101, 97,110, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 1, 6, 0, 0, 1, 6, + 0, 0, 1, 6, 0, 0, 1, 6, 0, 0, 1, 7, 0, 0, 1, 7, 0, 0, 1, 7, + 0, 0, 1, 7, 0, 0, 1, 7, 0, 0, 1, 8, 0, 0, 1, 9, 0, 0, 0, 3, + 0, 0, 0, 15,115,114, 99, 95,105,109, 97,103,101, 95,108,105,115,116, 0, 0, + 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 10,100,115,116, 95,105,109, 97,103,101, + 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 10,100,115,116, 95,105,109, 97, +103,101, 0, 0, 0, 0, 4, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 11, 0, 0, 1, 15, 0, 2, 0, 7, 0, 0, 0, 12, 0, 0, 0,133, 1, + 64, 64,134, 0, 64,128,198, 1, 0,128,156, 0, 0, 0,197, 1,192,192,198, 0, + 0, 1, 0, 0,128, 1, 64, 1, 0, 1,128, 2, 0, 64,220, 1, 0, 0,158, 0, +128, 0, 30, 0, 0, 0, 4, 4, 0, 0, 0, 3,105,109, 0, 4, 0, 0, 0, 17, + 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 3, 63,240, + 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 22, 80,114,111, 99,101,115,115, 77,117, +108,116,105,112,108,101, 83,116,100, 68,101,118, 0, 0, 0, 0, 0, 0, 0, 0, + 12, 0, 0, 1, 12, 0, 0, 1, 12, 0, 0, 1, 12, 0, 0, 1, 12, 0, 0, 1, + 13, 0, 0, 1, 13, 0, 0, 1, 13, 0, 0, 1, 13, 0, 0, 1, 13, 0, 0, 1, + 13, 0, 0, 1, 14, 0, 0, 1, 15, 0, 0, 0, 3, 0, 0, 0, 15,115,114, 99, + 95,105,109, 97,103,101, 95,108,105,115,116, 0, 0, 0, 0, 0, 0, 0, 0, 11, + 0, 0, 0, 11,109,101, 97,110, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 0, + 0, 0, 11, 0, 0, 0, 10,100,115,116, 95,105,109, 97,103,101, 0, 0, 0, 0, + 4, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 24, 0, 0, 1, + 29, 0, 1, 0, 8, 0, 0, 0, 28, 0, 0, 0, 69, 0,192, 64, 70, 0, 0, 0, +128, 2, 0, 0,195, 0, 0, 1, 69, 2,192,129, 70, 0, 0, 1,133, 3, 64,193, +134, 3, 0,128, 92, 0, 0, 0,133, 1, 64, 64,134, 0, 0, 0,192, 2,128, 1, + 3, 0, 0, 1,133, 3, 65, 1,134, 0, 0, 1,197, 3,192,193,198, 3, 0,128, +156, 0, 0, 0,197, 1,193, 64,198, 0, 0, 1, 0, 0,128, 1, 64, 1, 0, 1, +128, 2, 0, 64,220, 0,128, 0,192, 1, 0, 1, 0, 1,128, 0,222, 0,128, 0, + 30, 0, 0, 0, 6, 4, 0, 0, 0, 3,105,109, 0, 4, 0, 0, 0, 17, 73,109, + 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 4, 0, 0, 0, 5, + 71, 82, 65, 89, 0, 4, 0, 0, 0, 5, 66, 89, 84, 69, 0, 4, 0, 0, 0, 4, + 82, 71, 66, 0, 4, 0, 0, 0, 20, 80,114,111, 99,101,115,115, 83,112,108,105, +116, 89, 67,104,114,111,109, 97, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 1, + 25, 0, 0, 1, 25, 0, 0, 1, 25, 0, 0, 1, 25, 0, 0, 1, 25, 0, 0, 1, + 25, 0, 0, 1, 25, 0, 0, 1, 25, 0, 0, 1, 25, 0, 0, 1, 26, 0, 0, 1, + 26, 0, 0, 1, 26, 0, 0, 1, 26, 0, 0, 1, 26, 0, 0, 1, 26, 0, 0, 1, + 26, 0, 0, 1, 26, 0, 0, 1, 26, 0, 0, 1, 27, 0, 0, 1, 27, 0, 0, 1, + 27, 0, 0, 1, 27, 0, 0, 1, 27, 0, 0, 1, 27, 0, 0, 1, 28, 0, 0, 1, + 28, 0, 0, 1, 28, 0, 0, 1, 29, 0, 0, 0, 3, 0, 0, 0, 10,115,114, 99, + 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 8,121, + 95,105,109, 97,103,101, 0, 0, 0, 0, 9, 0, 0, 0, 27, 0, 0, 0, 13, 99, +104,114,111,109, 97, 95,105,109, 97,103,101, 0, 0, 0, 0, 18, 0, 0, 0, 27, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 34, 0, 0, 1, 42, 0, 1, 0, 14, + 0, 0, 0, 29, 0, 64, 0, 75, 1, 0,128, 92, 0, 0, 0,138, 0, 0, 64,193, + 0,128, 1, 0, 0, 0, 65, 65,128, 2,128,224, 0, 0,129,197, 3,192,193,198, + 1, 0, 2, 0, 0, 1, 2, 69, 4,193, 66, 70, 0, 0, 2,128, 6, 0, 2,195, + 0, 1, 3, 69, 6,193,131, 70, 2,128, 2, 92, 0, 0, 65,220,127,252,192,223, + 0, 1, 0,197, 1,193,192,198, 0, 0, 1, 0, 1, 0, 1, 64, 1,128, 64,220, + 0, 2, 0,197, 1, 0, 1, 0, 1, 0, 0,221, 0, 0, 0,222, 0,128, 0, 30, + 0, 0, 0, 9, 4, 0, 0, 0, 6, 68,101,112,116,104, 0, 3, 63,240, 0, 0, + 0, 0, 0, 0, 4, 0, 0, 0, 6,116, 97, 98,108,101, 0, 4, 0, 0, 0, 7, +105,110,115,101,114,116, 0, 4, 0, 0, 0, 3,105,109, 0, 4, 0, 0, 0, 17, + 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 4, 0, 0, + 0, 5, 71, 82, 65, 89, 0, 4, 0, 0, 0, 23, 80,114,111, 99,101,115,115, 83, +112,108,105,116, 67,111,109,112,111,110,101,110,116,115, 0, 4, 0, 0, 0, 7, +117,110,112, 97, 99,107, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 1, 35, 0, + 0, 1, 35, 0, 0, 1, 36, 0, 0, 1, 37, 0, 0, 1, 37, 0, 0, 1, 37, 0, + 0, 1, 37, 0, 0, 1, 38, 0, 0, 1, 38, 0, 0, 1, 38, 0, 0, 1, 38, 0, + 0, 1, 38, 0, 0, 1, 38, 0, 0, 1, 38, 0, 0, 1, 38, 0, 0, 1, 38, 0, + 0, 1, 38, 0, 0, 1, 38, 0, 0, 1, 37, 0, 0, 1, 40, 0, 0, 1, 40, 0, + 0, 1, 40, 0, 0, 1, 40, 0, 0, 1, 40, 0, 0, 1, 41, 0, 0, 1, 41, 0, + 0, 1, 41, 0, 0, 1, 41, 0, 0, 1, 42, 0, 0, 0, 7, 0, 0, 0, 10,115, +114, 99, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, + 6,100,101,112,116,104, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0, 11,100, +115,116, 95,105,109, 97,103,101,115, 0, 0, 0, 0, 3, 0, 0, 0, 28, 0, 0, + 0, 12, 40,102,111,114, 32,105,110,100,101,120, 41, 0, 0, 0, 0, 6, 0, 0, + 0, 19, 0, 0, 0, 12, 40,102,111,114, 32,108,105,109,105,116, 41, 0, 0, 0, + 0, 6, 0, 0, 0, 19, 0, 0, 0, 11, 40,102,111,114, 32,115,116,101,112, 41, + 0, 0, 0, 0, 6, 0, 0, 0, 19, 0, 0, 0, 2,105, 0, 0, 0, 0, 7, 0, + 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 44, 0, 0, 1, 48, 0, + 1, 0, 6, 0, 0, 0, 14, 0, 0, 0, 69, 0,192, 64, 70, 0, 64,128,134, 2, + 0, 0,195, 0, 0, 1, 69, 2,192,193, 70, 2,128,128, 92, 0, 0, 0,133, 1, + 65, 0,134, 0, 0, 0,192, 0,128, 1, 0, 1,128, 64,156, 1, 0, 0, 94, 0, +128, 0, 30, 0, 0, 0, 5, 4, 0, 0, 0, 3,105,109, 0, 4, 0, 0, 0, 17, + 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 3, 63,240, + 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 82, 71, 66, 0, 4, 0, 0, 0, 23, + 80,114,111, 99,101,115,115, 77,101,114,103,101, 67,111,109,112,111,110,101,110, +116,115, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 1, 45, 0, 0, 1, 45, 0, + 0, 1, 45, 0, 0, 1, 45, 0, 0, 1, 45, 0, 0, 1, 45, 0, 0, 1, 45, 0, + 0, 1, 46, 0, 0, 1, 46, 0, 0, 1, 46, 0, 0, 1, 46, 0, 0, 1, 46, 0, + 0, 1, 47, 0, 0, 1, 48, 0, 0, 0, 2, 0, 0, 0, 15,115,114, 99, 95,105, +109, 97,103,101, 95,108,105,115,116, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, + 0, 10,100,115,116, 95,105,109, 97,103,101, 0, 0, 0, 0, 7, 0, 0, 0, 13, + 0, 0, 0, 0, 0, 0, 1,144, 0, 0, 0, 25, 0, 0, 0, 50, 0, 0, 0, 73, + 0, 0, 0, 97, 0, 0, 0,122, 0, 0, 0,130, 0, 0, 0,132, 0, 0, 0,132, + 0, 0, 0,132, 0, 0, 0,132, 0, 0, 0,132, 0, 0, 0,132, 0, 0, 0,133, + 0, 0, 0,133, 0, 0, 0,133, 0, 0, 0,134, 0, 0, 0,134, 0, 0, 0,134, + 0, 0, 0,135, 0, 0, 0,135, 0, 0, 0,135, 0, 0, 0,136, 0, 0, 0,136, + 0, 0, 0,136, 0, 0, 0,136, 0, 0, 0,136, 0, 0, 0,136, 0, 0, 0,136, + 0, 0, 0,136, 0, 0, 0,136, 0, 0, 0,137, 0, 0, 0,137, 0, 0, 0,137, + 0, 0, 0,138, 0, 0, 0,138, 0, 0, 0,138, 0, 0, 0,138, 0, 0, 0,138, + 0, 0, 0,138, 0, 0, 0,139, 0, 0, 0,139, 0, 0, 0,139, 0, 0, 0,139, + 0, 0, 0,139, 0, 0, 0,139, 0, 0, 0,139, 0, 0, 0,141, 0, 0, 0,144, + 0, 0, 0,141, 0, 0, 0,146, 0, 0, 0,149, 0, 0, 0,146, 0, 0, 0,151, + 0, 0, 0,151, 0, 0, 0,151, 0, 0, 0,152, 0, 0, 0,151, 0, 0, 0,154, + 0, 0, 0,160, 0, 0, 0,154, 0, 0, 0,162, 0, 0, 0,162, 0, 0, 0,162, + 0, 0, 0,164, 0, 0, 0,170, 0, 0, 0,164, 0, 0, 0,172, 0, 0, 0,176, + 0, 0, 0,172, 0, 0, 0,178, 0, 0, 0,178, 0, 0, 0,178, 0, 0, 0,179, + 0, 0, 0,179, 0, 0, 0,179, 0, 0, 0,179, 0, 0, 0,179, 0, 0, 0,180, + 0, 0, 0,180, 0, 0, 0,180, 0, 0, 0,181, 0, 0, 0,181, 0, 0, 0,181, + 0, 0, 0,182, 0, 0, 0,182, 0, 0, 0,182, 0, 0, 0,183, 0, 0, 0,183, + 0, 0, 0,183, 0, 0, 0,184, 0, 0, 0,184, 0, 0, 0,184, 0, 0, 0,185, + 0, 0, 0,185, 0, 0, 0,185, 0, 0, 0,186, 0, 0, 0,186, 0, 0, 0,186, + 0, 0, 0,187, 0, 0, 0,187, 0, 0, 0,187, 0, 0, 0,188, 0, 0, 0,188, + 0, 0, 0,188, 0, 0, 0,189, 0, 0, 0,189, 0, 0, 0,189, 0, 0, 0,190, + 0, 0, 0,190, 0, 0, 0,190, 0, 0, 0,191, 0, 0, 0,191, 0, 0, 0,191, + 0, 0, 0,192, 0, 0, 0,192, 0, 0, 0,192, 0, 0, 0,193, 0, 0, 0,193, + 0, 0, 0,193, 0, 0, 0,194, 0, 0, 0,194, 0, 0, 0,194, 0, 0, 0,195, + 0, 0, 0,195, 0, 0, 0,195, 0, 0, 0,196, 0, 0, 0,196, 0, 0, 0,196, + 0, 0, 0,197, 0, 0, 0,197, 0, 0, 0,197, 0, 0, 0,198, 0, 0, 0,198, + 0, 0, 0,198, 0, 0, 0,199, 0, 0, 0,199, 0, 0, 0,199, 0, 0, 0,200, + 0, 0, 0,200, 0, 0, 0,200, 0, 0, 0,201, 0, 0, 0,201, 0, 0, 0,201, + 0, 0, 0,202, 0, 0, 0,202, 0, 0, 0,202, 0, 0, 0,203, 0, 0, 0,203, + 0, 0, 0,203, 0, 0, 0,204, 0, 0, 0,204, 0, 0, 0,204, 0, 0, 0,205, + 0, 0, 0,205, 0, 0, 0,205, 0, 0, 0,206, 0, 0, 0,206, 0, 0, 0,206, + 0, 0, 0,207, 0, 0, 0,207, 0, 0, 0,207, 0, 0, 0,208, 0, 0, 0,208, + 0, 0, 0,208, 0, 0, 0,209, 0, 0, 0,209, 0, 0, 0,209, 0, 0, 0,210, + 0, 0, 0,210, 0, 0, 0,210, 0, 0, 0,211, 0, 0, 0,211, 0, 0, 0,211, + 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0,212, + 0, 0, 0,214, 0, 0, 0,227, 0, 0, 0,214, 0, 0, 0,235, 0, 0, 0,237, + 0, 0, 0,237, 0, 0, 0,237, 0, 0, 0,237, 0, 0, 0,237, 0, 0, 0,238, + 0, 0, 0,238, 0, 0, 0,238, 0, 0, 0,238, 0, 0, 0,238, 0, 0, 0,239, + 0, 0, 0,239, 0, 0, 0,239, 0, 0, 0,240, 0, 0, 0,240, 0, 0, 0,240, + 0, 0, 0,241, 0, 0, 0,241, 0, 0, 0,241, 0, 0, 0,242, 0, 0, 0,242, + 0, 0, 0,242, 0, 0, 0,243, 0, 0, 0,243, 0, 0, 0,243, 0, 0, 0,244, + 0, 0, 0,244, 0, 0, 0,244, 0, 0, 0,245, 0, 0, 0,245, 0, 0, 0,245, + 0, 0, 0,246, 0, 0, 0,246, 0, 0, 0,246, 0, 0, 0,247, 0, 0, 0,247, + 0, 0, 0,247, 0, 0, 0,248, 0, 0, 0,248, 0, 0, 0,248, 0, 0, 0,250, + 0, 0, 0,254, 0, 0, 0,250, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, + 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 2, 0, 0, 1, 2, + 0, 0, 1, 2, 0, 0, 1, 3, 0, 0, 1, 3, 0, 0, 1, 3, 0, 0, 1, 3, + 0, 0, 1, 3, 0, 0, 1, 3, 0, 0, 1, 5, 0, 0, 1, 9, 0, 0, 1, 5, + 0, 0, 1, 11, 0, 0, 1, 15, 0, 0, 1, 11, 0, 0, 1, 17, 0, 0, 1, 17, + 0, 0, 1, 17, 0, 0, 1, 18, 0, 0, 1, 18, 0, 0, 1, 18, 0, 0, 1, 19, + 0, 0, 1, 19, 0, 0, 1, 19, 0, 0, 1, 19, 0, 0, 1, 19, 0, 0, 1, 19, + 0, 0, 1, 19, 0, 0, 1, 20, 0, 0, 1, 20, 0, 0, 1, 20, 0, 0, 1, 21, + 0, 0, 1, 21, 0, 0, 1, 21, 0, 0, 1, 22, 0, 0, 1, 22, 0, 0, 1, 22, + 0, 0, 1, 24, 0, 0, 1, 29, 0, 0, 1, 24, 0, 0, 1, 31, 0, 0, 1, 31, + 0, 0, 1, 31, 0, 0, 1, 31, 0, 0, 1, 31, 0, 0, 1, 31, 0, 0, 1, 31, + 0, 0, 1, 31, 0, 0, 1, 32, 0, 0, 1, 32, 0, 0, 1, 32, 0, 0, 1, 32, + 0, 0, 1, 32, 0, 0, 1, 32, 0, 0, 1, 32, 0, 0, 1, 32, 0, 0, 1, 34, + 0, 0, 1, 42, 0, 0, 1, 34, 0, 0, 1, 44, 0, 0, 1, 48, 0, 0, 1, 44, + 0, 0, 1, 50, 0, 0, 1, 50, 0, 0, 1, 50, 0, 0, 1, 50, 0, 0, 1, 50, + 0, 0, 1, 50, 0, 0, 1, 51, 0, 0, 1, 51, 0, 0, 1, 51, 0, 0, 1, 52, + 0, 0, 1, 52, 0, 0, 1, 52, 0, 0, 1, 53, 0, 0, 1, 53, 0, 0, 1, 53, + 0, 0, 1, 54, 0, 0, 1, 54, 0, 0, 1, 54, 0, 0, 1, 55, 0, 0, 1, 55, + 0, 0, 1, 55, 0, 0, 1, 56, 0, 0, 1, 56, 0, 0, 1, 56, 0, 0, 1, 57, + 0, 0, 1, 57, 0, 0, 1, 57, 0, 0, 1, 57, 0, 0, 1, 57, 0, 0, 1, 57, + 0, 0, 1, 58, 0, 0, 1, 58, 0, 0, 1, 58, 0, 0, 1, 58, 0, 0, 1, 58, + 0, 0, 1, 58, 0, 0, 1, 59, 0, 0, 1, 59, 0, 0, 1, 59, 0, 0, 1, 60, + 0, 0, 1, 60, 0, 0, 1, 60, 0, 0, 1, 60, 0, 0, 1, 60, 0, 0, 1, 60, + 0, 0, 1, 60, 0, 0, 1, 61, 0, 0, 1, 61, 0, 0, 1, 61, 0, 0, 1, 61, + 0, 0, 1, 61, 0, 0, 1, 61, 0, 0, 1, 61, 0, 0, 1, 62, 0, 0, 1, 62, + 0, 0, 1, 62, 0, 0, 1, 62, 0, 0, 1, 62, 0, 0, 1, 62, 0, 0, 1, 62, + 0, 0, 1, 63, 0, 0, 1, 63, 0, 0, 1, 63, 0, 0, 1, 64, 0, 0, 1, 64, + 0, 0, 1, 64, 0, 0, 1, 64, 0, 0, 1, 64, 0, 0, 1, 64, 0, 0, 1, 64, + 0, 0, 1, 65, 0, 0, 1, 65, 0, 0, 1, 65, 0, 0, 1, 65, 0, 0, 1, 65, + 0, 0, 1, 65, 0, 0, 1, 65, 0, 0, 1, 66, 0, 0, 1, 66, 0, 0, 1, 66, + 0, 0, 1, 67, 0, 0, 1, 67, 0, 0, 1, 67, 0, 0, 1, 68, 0, 0, 1, 68, + 0, 0, 1, 68, 0, 0, 1, 69, 0, 0, 1, 69, 0, 0, 1, 69, 0, 0, 1, 69, + 0, 0, 1, 69, 0, 0, 1, 69, 0, 0, 1, 69, 0, 0, 1, 70, 0, 0, 1, 70, + 0, 0, 1, 70, 0, 0, 1, 70, 0, 0, 1, 70, 0, 0, 1, 70, 0, 0, 1, 70, + 0, 0, 1, 71, 0, 0, 1, 71, 0, 0, 1, 71, 0, 0, 1, 72, 0, 0, 1, 72, + 0, 0, 1, 72, 0, 0, 1, 72, 0, 0, 0, 7, 0, 0, 0, 17, 79,110,101, 83, +111,117,114, 99,101, 79,110,101, 68,101,115,116, 0, 0, 0, 0, 1, 0, 0, 1, +143, 0, 0, 0, 18, 84,119,111, 83,111,117,114, 99,101,115, 79,110,101, 68,101, +115,116, 0, 0, 0, 0, 2, 0, 0, 1,143, 0, 0, 0, 20, 84,104,114,101,101, + 83,111,117,114, 99,101,115, 79,110,101, 68,101,115,116, 0, 0, 0, 0, 3, 0, + 0, 1,143, 0, 0, 0, 18, 79,110,101, 83,111,117,114, 99,101, 84,119,111, 68, +101,115,116,115, 0, 0, 0, 0, 4, 0, 0, 1,143, 0, 0, 0, 20, 79,110,101, + 83,111,117,114, 99,101, 84,104,114,101,101, 68,101,115,116,115, 0, 0, 0, 0, + 5, 0, 0, 1,143, 0, 0, 0, 13,104,111,117,103,104, 95,104,101,105,103,104, +116, 0, 0, 0, 0, 6, 0, 0, 1,143, 0, 0, 0, 13,105,110,116, 95,100, 97, +116, 97,116,121,112,101, 0, 0, 0, 0,182, 0, 0, 1,143, 0, 0, 0, 0, +}; + + if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"../obj/imlua_process51/im_process_be32.lo")==0) lua_call(L, 0, 0); +} diff --git a/im/src/lua5/loh/im_process_be64.loh b/im/src/lua5/loh/im_process_be64.loh new file mode 100644 index 0000000..ee881bb --- /dev/null +++ b/im/src/lua5/loh/im_process_be64.loh @@ -0,0 +1,897 @@ +/* code automatically generated by bin2c -- DO NOT EDIT */ +{ +/* #include'ing this file in a C program is equivalent to calling + if (luaL_loadfile(L,"../obj/imlua_process51/im_process_be64.lo")==0) lua_call(L, 0, 0); +*/ +/* ../obj/imlua_process51/im_process_be64.lo */ +static const unsigned char B1[]={ + 27, 76,117, 97, 81, 0, 1, 4, 8, 4, 8, 0, 21, 0, 0, 0, 0, 0, 0, 0, + 64,108,117, 97, 53, 47,105,109, 95,112,114,111, 99,101,115,115, 46,108,117, 97, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 13,144, 1, 0, 0, 36, 0, 0, + 0,100, 64, 0, 0,164,128, 0, 0,228,192, 0, 0, 36, 1, 1, 0,100, 65, 1, + 0,128, 1, 0, 0,193, 1, 0, 0, 3, 2, 0, 5,197, 66, 0, 0,198,130,192, + 5,156, 65, 0, 3,128, 1, 0, 0,193,193, 0, 0,156, 65, 0, 1,128, 1, 0, + 0,193, 1, 1, 0,156, 65, 0, 1,128, 1, 0, 0,193, 65, 1, 0,156, 65, 0, + 1,128, 1, 0, 0,193,129, 1, 0, 1,194, 1, 0, 64, 2,128, 2,133, 66, 0, + 0,134, 2, 66, 5,197, 66, 0, 0,198, 66,194, 5,156, 65, 0, 3,128, 1, 0, + 0,193,129, 2, 0,156, 65, 0, 1,128, 1, 0, 0,193,193, 2, 0, 3, 2, 0, + 5,197, 66, 0, 0,198, 2,195, 5,156, 65, 0, 3,128, 1, 0, 0,193, 65, 3, + 0, 3, 2,128, 4,133, 66, 0, 0,134,130, 67, 5,195, 2,128, 5,156, 65, 0, + 3,133, 65, 0, 0,228,129, 1, 0,137,193,129,135,133, 65, 0, 0,228,193, 1, + 0,137,193, 1,136,128, 1, 0, 0,193, 65, 4, 0, 36, 2, 2, 0,100, 66, 2, + 0,156, 65, 0, 2,133, 65, 0, 0,228,129, 2, 0,137,193, 1,137,128, 1,128, + 0,193,193, 4, 0,156, 65, 0, 1,133, 65, 0, 0,228,193, 2, 0,137,193, 1, +138,133, 65, 0, 0,228, 1, 3, 0,137,193,129,138,128, 1, 0, 0,193,129, 5, + 0,156, 65, 0, 1,128, 1, 0, 0,193,193, 5, 0, 36, 66, 3, 0,100,130, 3, + 0,156, 65, 0, 2,128, 1, 0, 0,193, 1, 6, 0,156, 65, 0, 1,128, 1, 0, + 0,193, 65, 6, 0,156, 65, 0, 1,128, 1, 0, 0,193,129, 6, 0,156, 65, 0, + 1,128, 1, 0, 0,193,193, 6, 0,156, 65, 0, 1,128, 1, 0, 0,193, 1, 7, + 0,156, 65, 0, 1,128, 1, 0, 0,193, 65, 7, 0,156, 65, 0, 1,128, 1, 0, + 0,193,129, 7, 0,156, 65, 0, 1,128, 1, 0, 0,193,193, 7, 0,156, 65, 0, + 1,128, 1, 0, 0,193, 1, 8, 0,156, 65, 0, 1,128, 1, 0, 0,193, 65, 8, + 0,156, 65, 0, 1,128, 1, 0, 0,193,129, 8, 0,156, 65, 0, 1,128, 1, 0, + 0,193,193, 8, 0,156, 65, 0, 1,128, 1, 0, 0,193, 1, 9, 0,156, 65, 0, + 1,128, 1, 0, 0,193, 65, 9, 0,156, 65, 0, 1,128, 1, 0, 0,193,129, 9, + 0,156, 65, 0, 1,128, 1, 0, 0,193,193, 9, 0,156, 65, 0, 1,128, 1, 0, + 0,193, 1, 10, 0,156, 65, 0, 1,128, 1, 0, 0,193, 65, 10, 0,156, 65, 0, + 1,128, 1, 0, 0,193,129, 10, 0,156, 65, 0, 1,128, 1, 0, 0,193,193, 10, + 0,156, 65, 0, 1,128, 1, 0, 0,193, 1, 11, 0,156, 65, 0, 1,128, 1, 0, + 0,193, 65, 11, 0,156, 65, 0, 1,128, 1, 0, 0,193,129, 11, 0,156, 65, 0, + 1,128, 1, 0, 0,193,193, 11, 0,156, 65, 0, 1,128, 1, 0, 0,193, 1, 12, + 0,156, 65, 0, 1,128, 1, 0, 0,193, 65, 12, 0,156, 65, 0, 1,128, 1, 0, + 0,193,129, 12, 0,156, 65, 0, 1,128, 1, 0, 0,193,193, 12, 0,156, 65, 0, + 1,128, 1, 0, 0,193, 1, 13, 0,156, 65, 0, 1,128, 1, 0, 0,193, 65, 13, + 0,156, 65, 0, 1,128, 1, 0, 0,193,129, 13, 0,156, 65, 0, 1,128, 1, 0, + 0,193,193, 13, 0,156, 65, 0, 1,128, 1,128, 1,193, 1, 14, 0, 3, 2, 0, + 4,100,194, 3, 0,156, 65, 0, 2,133, 65, 0, 0,228, 1, 4, 0,137,193,129, +156,164, 65, 4, 0,192, 1, 0, 0, 1,130, 14, 0, 67, 2,128, 5, 0, 3, 0, + 3,220, 65, 0, 3,192, 1, 0, 0, 1,194, 14, 0, 67, 2,128, 5, 0, 3, 0, + 3,220, 65, 0, 3,192, 1, 0, 0, 1, 2, 15, 0,220, 65, 0, 1,192, 1, 0, + 0, 1, 66, 15, 0,220, 65, 0, 1,192, 1, 0, 0, 1,130, 15, 0,220, 65, 0, + 1,192, 1, 0, 0, 1,194, 15, 0,220, 65, 0, 1,192, 1, 0, 0, 1, 2, 16, + 0,220, 65, 0, 1,192, 1, 0, 0, 1, 66, 16, 0,220, 65, 0, 1,192, 1,128, + 0, 1,130, 16, 0,220, 65, 0, 1,192, 1, 0, 0, 1,194, 16, 0,220, 65, 0, + 1,192, 1, 0, 0, 1, 2, 17, 0,220, 65, 0, 1,192, 1,128, 0, 1, 66, 17, + 0,220, 65, 0, 1,197, 65, 0, 0, 36,130, 4, 0,201, 1, 2,163,192, 1,128, + 0, 1,194, 17, 0,220, 65, 0, 1,192, 1, 0, 1, 1, 2, 18, 0,220, 65, 0, + 1,192, 1,128, 1, 1, 66, 18, 0,220, 65, 0, 1,192, 1,128, 0, 1,130, 18, + 0, 67, 2,128, 5, 5, 67, 0, 0, 6,195, 82, 6,220, 65, 0, 3,197, 65, 0, + 0, 36,194, 4, 0,201, 1, 2,166,197, 65, 0, 0, 36, 2, 5, 0,201, 1,130, +166,192, 1,128, 0, 1,130, 19, 0,220, 65, 0, 1,192, 1, 0, 0, 1,194, 19, + 0,220, 65, 0, 1,192, 1, 0, 0, 1, 2, 20, 0, 67, 2, 0, 5,197, 66, 0, + 0,198, 66,212, 5, 3, 3, 0, 6,220, 65, 0, 3,192, 1, 0, 0, 1,130, 20, + 0,220, 65, 0, 1,192, 1, 0, 0, 1,194, 20, 0,220, 65, 0, 1,192, 1, 0, + 0, 1, 2, 21, 0,220, 65, 0, 1,197, 65, 0, 0, 36, 66, 5, 0,201, 1,130, +170,192, 1, 0, 2, 1,130, 21, 0, 67, 2, 0, 5,197, 66, 0, 0,198, 2,194, + 5, 5, 67, 0, 0, 6, 3, 67, 6,220, 65, 0, 3,192, 1, 0, 1, 1,194, 21, + 0, 67, 2, 0, 5,197, 66, 0, 0,198, 2,214, 5, 5, 67, 0, 0, 6, 67, 86, + 6,220, 65, 0, 3,197, 65, 0, 0, 36,130, 5, 0,201, 1, 2,173,197, 65, 0, + 0, 36,194, 5, 0,201, 1,130,173,192, 1, 0, 0, 1, 2, 23, 0, 67, 2,128, + 5, 5, 67, 0, 0, 6, 3, 67, 6,220, 65, 0, 3,192, 1, 0, 0, 1, 66, 23, + 0,220, 65, 0, 1,192, 1,128, 0, 1,130, 23, 0,220, 65, 0, 1,192, 1, 0, + 0, 1,194, 23, 0,220, 65, 0, 1,192, 1, 0, 0, 1, 2, 24, 0,220, 65, 0, + 1,192, 1, 0, 0, 1, 66, 24, 0,220, 65, 0, 1,192, 1, 0, 0, 1,130, 24, + 0,220, 65, 0, 1,192, 1, 0, 0, 1,194, 24, 0, 67, 2,128, 5, 5, 67, 0, + 0, 6, 67, 86, 6,220, 65, 0, 3,192, 1, 0, 0, 1, 2, 25, 0, 67, 2,128, + 5, 5, 67, 0, 0, 6, 67, 86, 6,220, 65, 0, 3,192, 1, 0, 0, 1, 66, 25, + 0,220, 65, 0, 1,192, 1, 0, 0, 1,130, 25, 0, 67, 2, 0, 5,197, 66, 0, + 0,198,130,195, 5, 3, 3, 0, 6,220, 65, 0, 3,192, 1, 0, 0, 1,194, 25, + 0, 67, 2, 0, 5,197, 66, 0, 0,198,130,195, 5, 3, 3, 0, 6,220, 65, 0, + 3,192, 1, 0, 0, 1, 2, 26, 0, 67, 2, 0, 5,197, 66, 0, 0,198,130,195, + 5, 3, 3, 0, 6,220, 65, 0, 3,192, 1,128, 0, 1, 66, 26, 0,220, 65, 0, + 1,192, 1, 0, 0, 1,130, 26, 0, 67, 2, 0, 5,197, 66, 0, 0,198,130,195, + 5, 3, 3, 0, 6,220, 65, 0, 3,192, 1, 0, 0, 1,194, 26, 0, 67, 2, 0, + 5,197, 66, 0, 0,198,130,195, 5, 3, 3, 0, 6,220, 65, 0, 3,192, 1, 0, + 0, 1, 2, 27, 0,220, 65, 0, 1,192, 1, 0, 0, 1, 66, 27, 0,220, 65, 0, + 1,192, 1, 0, 0, 1,130, 27, 0,220, 65, 0, 1,192, 1, 0, 0, 1,194, 27, + 0, 67, 2, 0, 5,197, 66, 0, 0,198,130,195, 5, 3, 3, 0, 6,220, 65, 0, + 3,192, 1, 0, 0, 1, 2, 28, 0, 67, 2, 0, 5,197, 66, 0, 0,198,130,195, + 5, 3, 3, 0, 6,220, 65, 0, 3,192, 1, 0, 0, 1, 66, 28, 0,220, 65, 0, + 1,192, 1, 0, 0, 1,130, 28, 0,220, 65, 0, 1, 30, 0,128, 0,115, 0, 0, + 0, 4, 19, 0, 0, 0, 0, 0, 0, 0, 65,110, 97,108,121,122,101, 70,105,110, +100, 82,101,103,105,111,110,115, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, + 0, 4, 7, 0, 0, 0, 0, 0, 0, 0, 85, 83, 72, 79, 82, 84, 0, 4, 21, 0, + 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 80,101,114,105,109,101,116, +101,114, 76,105,110,101, 0, 4, 20, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99, +101,115,115, 82,101,109,111,118,101, 66,121, 65,114,101, 97, 0, 4, 17, 0, 0, + 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 70,105,108,108, 72,111,108,101, +115, 0, 4, 18, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 72,111, +117,103,104, 76,105,110,101,115, 0, 3, 0, 0, 0, 0, 0,128,102, 64, 4, 5, + 0, 0, 0, 0, 0, 0, 0, 71, 82, 65, 89, 0, 4, 4, 0, 0, 0, 0, 0, 0, + 0, 73, 78, 84, 0, 4, 22, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115, +115, 72,111,117,103,104, 76,105,110,101,115, 68,114, 97,119, 0, 4, 25, 0, 0, + 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 68,105,115,116, 97,110, 99,101, + 84,114, 97,110,115,102,111,114,109, 0, 4, 6, 0, 0, 0, 0, 0, 0, 0, 70, + 76, 79, 65, 84, 0, 4, 23, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115, +115, 82,101,103,105,111,110, 97,108, 77, 97,120,105,109,117,109, 0, 4, 7, 0, + 0, 0, 0, 0, 0, 0, 66, 73, 78, 65, 82, 89, 0, 4, 17, 0, 0, 0, 0, 0, + 0, 0, 80,114,111, 99,101,115,115, 82,101,100,117, 99,101, 78,101,119, 0, 4, + 17, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 82,101,115,105,122, +101, 78,101,119, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115, +115, 82,101,100,117, 99,101, 66,121, 52, 0, 4, 15, 0, 0, 0, 0, 0, 0, 0, + 80,114,111, 99,101,115,115, 67,114,111,112, 78,101,119, 0, 4, 14, 0, 0, 0, + 0, 0, 0, 0, 80,114,111, 99,101,115,115, 73,110,115,101,114,116, 0, 4, 21, + 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 65,100,100, 77, 97,114, +103,105,110,115, 78,101,119, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 80,114,111, + 99,101,115,115, 82,111,116, 97,116,101, 78,101,119, 0, 4, 17, 0, 0, 0, 0, + 0, 0, 0, 80,114,111, 99,101,115,115, 82,111,116, 97,116,101, 82,101,102, 0, + 4, 16, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 82,111,116, 97, +116,101, 57, 48, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115, +115, 82,111,116, 97,116,101, 49, 56, 48, 0, 4, 14, 0, 0, 0, 0, 0, 0, 0, + 80,114,111, 99,101,115,115, 77,105,114,114,111,114, 0, 4, 12, 0, 0, 0, 0, + 0, 0, 0, 80,114,111, 99,101,115,115, 70,108,105,112, 0, 4, 14, 0, 0, 0, + 0, 0, 0, 0, 80,114,111, 99,101,115,115, 82, 97,100,105, 97,108, 0, 4, 25, + 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 71,114, 97,121, 77,111, +114,112,104, 67,111,110,118,111,108,118,101, 0, 4, 22, 0, 0, 0, 0, 0, 0, + 0, 80,114,111, 99,101,115,115, 71,114, 97,121, 77,111,114,112,104, 69,114,111, +100,101, 0, 4, 23, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 71, +114, 97,121, 77,111,114,112,104, 68,105,108, 97,116,101, 0, 4, 21, 0, 0, 0, + 0, 0, 0, 0, 80,114,111, 99,101,115,115, 71,114, 97,121, 77,111,114,112,104, + 79,112,101,110, 0, 4, 22, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115, +115, 71,114, 97,121, 77,111,114,112,104, 67,108,111,115,101, 0, 4, 23, 0, 0, + 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 71,114, 97,121, 77,111,114,112, +104, 84,111,112, 72, 97,116, 0, 4, 21, 0, 0, 0, 0, 0, 0, 0, 80,114,111, + 99,101,115,115, 71,114, 97,121, 77,111,114,112,104, 87,101,108,108, 0, 4, 25, + 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 71,114, 97,121, 77,111, +114,112,104, 71,114, 97,100,105,101,110,116, 0, 4, 24, 0, 0, 0, 0, 0, 0, + 0, 80,114,111, 99,101,115,115, 66,105,110, 77,111,114,112,104, 67,111,110,118, +111,108,118,101, 0, 4, 21, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115, +115, 66,105,110, 77,111,114,112,104, 69,114,111,100,101, 0, 4, 22, 0, 0, 0, + 0, 0, 0, 0, 80,114,111, 99,101,115,115, 66,105,110, 77,111,114,112,104, 68, +105,108, 97,116,101, 0, 4, 20, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101, +115,115, 66,105,110, 77,111,114,112,104, 79,112,101,110, 0, 4, 21, 0, 0, 0, + 0, 0, 0, 0, 80,114,111, 99,101,115,115, 66,105,110, 77,111,114,112,104, 67, +108,111,115,101, 0, 4, 23, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115, +115, 66,105,110, 77,111,114,112,104, 79,117,116,108,105,110,101, 0, 4, 20, 0, + 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 66,105,110, 77,111,114,112, +104, 84,104,105,110, 0, 4, 22, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101, +115,115, 77,101,100,105, 97,110, 67,111,110,118,111,108,118,101, 0, 4, 21, 0, + 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 82, 97,110,103,101, 67,111, +110,118,111,108,118,101, 0, 4, 27, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99, +101,115,115, 82, 97,110,107, 67,108,111,115,101,115,116, 67,111,110,118,111,108, +118,101, 0, 4, 23, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 82, + 97,110,107, 77, 97,120, 67,111,110,118,111,108,118,101, 0, 4, 23, 0, 0, 0, + 0, 0, 0, 0, 80,114,111, 99,101,115,115, 82, 97,110,107, 77,105,110, 67,111, +110,118,111,108,118,101, 0, 4, 16, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99, +101,115,115, 67,111,110,118,111,108,118,101, 0, 4, 19, 0, 0, 0, 0, 0, 0, + 0, 80,114,111, 99,101,115,115, 67,111,110,118,111,108,118,101, 83,101,112, 0, + 4, 19, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 67,111,110,118, +111,108,118,101, 82,101,112, 0, 4, 20, 0, 0, 0, 0, 0, 0, 0, 80,114,111, + 99,101,115,115, 67,111,110,118,111,108,118,101, 68,117, 97,108, 0, 4, 23, 0, + 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 67,111,109,112, 97,115,115, + 67,111,110,118,111,108,118,101, 0, 4, 20, 0, 0, 0, 0, 0, 0, 0, 80,114, +111, 99,101,115,115, 77,101, 97,110, 67,111,110,118,111,108,118,101, 0, 4, 24, + 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 71, 97,117,115,115,105, + 97,110, 67,111,110,118,111,108,118,101, 0, 4, 23, 0, 0, 0, 0, 0, 0, 0, + 80,114,111, 99,101,115,115, 66, 97,114,108,101,116,116, 67,111,110,118,111,108, +118,101, 0, 4, 22, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 73, +110,116,101,114,108, 97, 99,101, 83,112,108,105,116, 0, 4, 25, 0, 0, 0, 0, + 0, 0, 0, 80,114,111, 99,101,115,115, 73,110,116,101,114,108, 97, 99,101, 83, +112,108,105,116, 78,101,119, 0, 4, 30, 0, 0, 0, 0, 0, 0, 0, 80,114,111, + 99,101,115,115, 68,105,102,102, 79,102, 71, 97,117,115,115,105, 97,110, 67,111, +110,118,111,108,118,101, 0, 4, 29, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99, +101,115,115, 76, 97,112, 79,102, 71, 97,117,115,115,105, 97,110, 67,111,110,118, +111,108,118,101, 0, 4, 21, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115, +115, 83,111, 98,101,108, 67,111,110,118,111,108,118,101, 0, 4, 26, 0, 0, 0, + 0, 0, 0, 0, 80,114,111, 99,101,115,115, 83,112,108,105,110,101, 69,100,103, +101, 67,111,110,118,111,108,118,101, 0, 4, 23, 0, 0, 0, 0, 0, 0, 0, 80, +114,111, 99,101,115,115, 80,114,101,119,105,116,116, 67,111,110,118,111,108,118, +101, 0, 4, 20, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 90,101, +114,111, 67,114,111,115,115,105,110,103, 0, 4, 13, 0, 0, 0, 0, 0, 0, 0, + 80,114,111, 99,101,115,115, 67, 97,110,110,121, 0, 4, 22, 0, 0, 0, 0, 0, + 0, 0, 80,114,111, 99,101,115,115, 85,110, 65,114,105,116,104,109,101,116,105, + 99, 79,112, 0, 4, 20, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, + 65,114,105,116,104,109,101,116,105, 99, 79,112, 0, 4, 15, 0, 0, 0, 0, 0, + 0, 0, 80,114,111, 99,101,115,115, 85,110,115,104, 97,114,112, 0, 4, 13, 0, + 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 83,104, 97,114,112, 0, 4, + 19, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 83,104, 97,114,112, + 75,101,114,110,101,108, 0, 4, 28, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99, +101,115,115, 65,114,105,116,104,109,101,116,105, 99, 67,111,110,115,116, 79,112, + 78,101,119, 0, 4, 18, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, + 66,108,101,110,100, 67,111,110,115,116, 0, 4, 13, 0, 0, 0, 0, 0, 0, 0, + 80,114,111, 99,101,115,115, 66,108,101,110,100, 0, 4, 20, 0, 0, 0, 0, 0, + 0, 0, 80,114,111, 99,101,115,115, 83,112,108,105,116, 67,111,109,112,108,101, +120, 0, 4, 20, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 77,101, +114,103,101, 67,111,109,112,108,101,120, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0, + 67, 70, 76, 79, 65, 84, 0, 4, 23, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99, +101,115,115, 77,117,108,116,105,112,108,101, 77,101, 97,110, 78,101,119, 0, 4, + 25, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 77,117,108,116,105, +112,108,101, 83,116,100, 68,101,118, 78,101,119, 0, 4, 22, 0, 0, 0, 0, 0, + 0, 0, 80,114,111, 99,101,115,115, 65,117,116,111, 67,111,118, 97,114,105, 97, +110, 99,101, 0, 4, 20, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, + 77,117,108,116,105,112,108,121, 67,111,110,106, 0, 4, 26, 0, 0, 0, 0, 0, + 0, 0, 80,114,111, 99,101,115,115, 81,117, 97,110,116,105,122,101, 82, 71, 66, + 85,110,105,102,111,114,109, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 77, 65, 80, + 0, 4, 27, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 81,117, 97, +110,116,105,122,101, 71,114, 97,121, 85,110,105,102,111,114,109, 0, 4, 23, 0, + 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 69,120,112, 97,110,100, 72, +105,115,116,111,103,114, 97,109, 0, 4, 25, 0, 0, 0, 0, 0, 0, 0, 80,114, +111, 99,101,115,115, 69,113,117, 97,108,105,122,101, 72,105,115,116,111,103,114, + 97,109, 0, 4, 23, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 83, +112,108,105,116, 89, 67,104,114,111,109, 97, 78,101,119, 0, 4, 16, 0, 0, 0, + 0, 0, 0, 0, 80,114,111, 99,101,115,115, 83,112,108,105,116, 72, 83, 73, 0, + 4, 16, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 77,101,114,103, +101, 72, 83, 73, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 82, 71, 66, 0, 4, 5, + 0, 0, 0, 0, 0, 0, 0, 66, 89, 84, 69, 0, 4, 26, 0, 0, 0, 0, 0, 0, + 0, 80,114,111, 99,101,115,115, 83,112,108,105,116, 67,111,109,112,111,110,101, +110,116,115, 78,101,119, 0, 4, 26, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99, +101,115,115, 77,101,114,103,101, 67,111,109,112,111,110,101,110,116,115, 78,101, +119, 0, 4, 27, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 78,111, +114,109, 97,108,105,122,101, 67,111,109,112,111,110,101,110,116,115, 0, 4, 20, + 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 82,101,112,108, 97, 99, +101, 67,111,108,111,114, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99, +101,115,115, 66,105,116,119,105,115,101, 79,112, 0, 4, 18, 0, 0, 0, 0, 0, + 0, 0, 80,114,111, 99,101,115,115, 66,105,116,119,105,115,101, 78,111,116, 0, + 4, 15, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 66,105,116, 77, + 97,115,107, 0, 4, 16, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, + 66,105,116, 80,108, 97,110,101, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 80,114, +111, 99,101,115,115, 84,111,110,101, 71, 97,109,117,116, 0, 4, 19, 0, 0, 0, + 0, 0, 0, 0, 80,114,111, 99,101,115,115, 85,110, 78,111,114,109, 97,108,105, +122,101, 0, 4, 18, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 68, +105,114,101, 99,116, 67,111,110,118, 0, 4, 16, 0, 0, 0, 0, 0, 0, 0, 80, +114,111, 99,101,115,115, 78,101,103, 97,116,105,118,101, 0, 4, 30, 0, 0, 0, + 0, 0, 0, 0, 80,114,111, 99,101,115,115, 82, 97,110,103,101, 67,111,110,116, +114, 97,115,116, 84,104,114,101,115,104,111,108,100, 0, 4, 25, 0, 0, 0, 0, + 0, 0, 0, 80,114,111, 99,101,115,115, 76,111, 99, 97,108, 77, 97,120, 84,104, +114,101,115,104,111,108,100, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 80,114,111, + 99,101,115,115, 84,104,114,101,115,104,111,108,100, 0, 4, 23, 0, 0, 0, 0, + 0, 0, 0, 80,114,111, 99,101,115,115, 84,104,114,101,115,104,111,108,100, 66, +121, 68,105,102,102, 0, 4, 27, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101, +115,115, 72,121,115,116,101,114,101,115,105,115, 84,104,114,101,115,104,111,108, +100, 0, 4, 27, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 85,110, +105,102,111,114,109, 69,114,114, 84,104,114,101,115,104,111,108,100, 0, 4, 28, + 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 68,105,102,117,115,105, +111,110, 69,114,114, 84,104,114,101,115,104,111,108,100, 0, 4, 24, 0, 0, 0, + 0, 0, 0, 0, 80,114,111, 99,101,115,115, 80,101,114, 99,101,110,116, 84,104, +114,101,115,104,111,108,100, 0, 4, 21, 0, 0, 0, 0, 0, 0, 0, 80,114,111, + 99,101,115,115, 79,116,115,117, 84,104,114,101,115,104,111,108,100, 0, 4, 23, + 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 77,105,110, 77, 97,120, + 84,104,114,101,115,104,111,108,100, 0, 4, 22, 0, 0, 0, 0, 0, 0, 0, 80, +114,111, 99,101,115,115, 83,108,105, 99,101, 84,104,114,101,115,104,111,108,100, + 0, 4, 16, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 80,105,120, +101,108, 97,116,101, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101, +115,115, 80,111,115,116,101,114,105,122,101, 0, 24, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 8, 0, 0, 0, 25, 0, 0, 0, 0, 5, 0, 9, 17, 0, 0, 0, + 69, 1, 0, 0, 70, 1,128, 2,133, 65, 0, 0,192, 1,128, 2,156, 65, 0, 1, +133, 1, 0, 0,192, 1, 0, 0, 1,130, 0, 0,213, 1,130, 3, 36, 2, 0, 0, + 0, 0,128, 0, 0, 0, 0, 1, 0, 0,128, 1, 0, 0, 0, 2, 0, 0,128, 2, +137, 1,130, 3, 30, 0,128, 0, 3, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, + 0,105,109, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0, 97,115,115,101,114,116, 0, + 4, 4, 0, 0, 0, 0, 0, 0, 0, 78,101,119, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 13, 0, 0, 0, 24, 0, 0, 0, 5, 1, 7, 8, 23, 0, 0, + 0,133, 0, 0, 0,134, 64, 64, 1,192, 0, 0, 0, 4, 1, 0, 0, 68, 1,128, + 0,132, 1, 0, 1,196, 1,128, 1,156,128, 0, 3,196, 0, 0, 2, 0, 1, 0, + 0, 64, 1, 0, 1,133,129, 0, 0,192, 1,128, 0,156, 1, 0, 1,220,128, 0, + 0,218, 0, 0, 0, 22,192, 0,128, 0, 1,128, 1, 64, 1, 0, 1, 30, 1,128, + 1, 22, 0, 0,128,158, 0, 0, 1, 30, 0,128, 0, 3, 0, 0, 0, 4, 3, 0, + 0, 0, 0, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 73,109, + 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 4, 7, 0, 0, 0, + 0, 0, 0, 0,117,110,112, 97, 99,107, 0, 0, 0, 0, 0, 23, 0, 0, 0, 15, + 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, + 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 18, 0, 0, 0, 18, 0, 0, 0, 18, + 0, 0, 0, 18, 0, 0, 0, 18, 0, 0, 0, 18, 0, 0, 0, 18, 0, 0, 0, 19, + 0, 0, 0, 19, 0, 0, 0, 20, 0, 0, 0, 20, 0, 0, 0, 20, 0, 0, 0, 20, + 0, 0, 0, 22, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 10, 0, 0, 0, 0, + 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 22, 0, 0, + 0, 4, 0, 0, 0, 0, 0, 0, 0, 97,114,103, 0, 0, 0, 0, 0, 22, 0, 0, + 0, 10, 0, 0, 0, 0, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 0, 8, + 0, 0, 0, 22, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0,114,101,116, 0, 15, + 0, 0, 0, 22, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119, +105,100,116,104, 0, 7, 0, 0, 0, 0, 0, 0, 0,104,101,105,103,104,116, 0, + 12, 0, 0, 0, 0, 0, 0, 0, 99,111,108,111,114, 95,115,112, 97, 99,101, 0, + 10, 0, 0, 0, 0, 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, 0, 5, 0, + 0, 0, 0, 0, 0, 0,102,117,110, 99, 0, 17, 0, 0, 0, 9, 0, 0, 0, 9, + 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 13, 0, 0, 0, 13, + 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, + 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 25, + 0, 0, 0, 6, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,102,117,110, 99,110, + 97,109,101, 0, 0, 0, 0, 0, 16, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, +119,105,100,116,104, 0, 0, 0, 0, 0, 16, 0, 0, 0, 7, 0, 0, 0, 0, 0, + 0, 0,104,101,105,103,104,116, 0, 0, 0, 0, 0, 16, 0, 0, 0, 12, 0, 0, + 0, 0, 0, 0, 0, 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 0, 0, 0, + 0, 16, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,100, 97,116, 97, 95,116,121, +112,101, 0, 0, 0, 0, 0, 16, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,102, +117,110, 99, 0, 2, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 31, 0, 0, 0, 50, 0, 0, 0, 0, 5, 0, 11, 22, 0, 0, 0, + 69, 1, 0, 0, 70, 1,128, 2,133, 65, 0, 0,192, 1,128, 2, 5,130, 0, 0, + 6,194, 64, 4, 65, 2, 1, 0,128, 2, 0, 0, 28, 2,128, 1,156, 65, 0, 0, +133, 1, 0, 0,192, 1, 0, 0, 1, 66, 1, 0,213, 1,130, 3, 36, 2, 0, 0, + 0, 0,128, 0, 0, 0, 0, 1, 0, 0,128, 1, 0, 0, 0, 2, 0, 0,128, 2, +137, 1,130, 3, 30, 0,128, 0, 6, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, + 0,105,109, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0, 97,115,115,101,114,116, 0, + 4, 7, 0, 0, 0, 0, 0, 0, 0,115,116,114,105,110,103, 0, 4, 7, 0, 0, + 0, 0, 0, 0, 0,102,111,114,109, 97,116, 0, 4, 24, 0, 0, 0, 0, 0, 0, + 0,117,110,100,101,102,105,110,101,100, 32,102,117,110, 99,116,105,111,110, 32, + 96, 37,115, 39, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 78,101,119, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, 49, 0, 0, 0, 5, 2, + 7, 10, 24, 0, 0, 0,197, 0, 0, 0,198, 64,192, 1, 0, 1, 0, 0, 68, 1, + 0, 0,132, 1,128, 0,196, 1, 0, 1, 4, 2,128, 1,220,128, 0, 3, 4, 1, + 0, 2, 64, 1, 0, 0,128, 1,128, 0,192, 1,128, 1, 5,130, 0, 0, 64, 2, + 0, 1, 28, 2, 0, 1, 28,129, 0, 0, 26, 1, 0, 0, 22,192, 0,128, 64, 1, + 0, 2,128, 1,128, 1, 94, 1,128, 1, 22, 0, 0,128,222, 0, 0, 1, 30, 0, +128, 0, 3, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 17, + 0, 0, 0, 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97, +115,101,100, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0,117,110,112, 97, 99,107, 0, + 0, 0, 0, 0, 24, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, + 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, + 43, 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, + 43, 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, 44, 0, 0, 0, 44, 0, 0, 0, + 45, 0, 0, 0, 45, 0, 0, 0, 45, 0, 0, 0, 45, 0, 0, 0, 47, 0, 0, 0, + 49, 0, 0, 0, 5, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0,115,114, 99, 95, +105,109, 97,103,101, 49, 0, 0, 0, 0, 0, 23, 0, 0, 0, 11, 0, 0, 0, 0, + 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 50, 0, 0, 0, 0, 0, 23, 0, + 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 97,114,103, 0, 0, 0, 0, 0, 23, 0, + 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 0, + 8, 0, 0, 0, 23, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0,114,101,116, 0, + 16, 0, 0, 0, 23, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, +119,105,100,116,104, 0, 7, 0, 0, 0, 0, 0, 0, 0,104,101,105,103,104,116, + 0, 12, 0, 0, 0, 0, 0, 0, 0, 99,111,108,111,114, 95,115,112, 97, 99,101, + 0, 10, 0, 0, 0, 0, 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, 0, 5, + 0, 0, 0, 0, 0, 0, 0,102,117,110, 99, 0, 22, 0, 0, 0, 32, 0, 0, 0, + 32, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, + 35, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, 38, 0, 0, 0, + 38, 0, 0, 0, 38, 0, 0, 0, 38, 0, 0, 0, 49, 0, 0, 0, 49, 0, 0, 0, + 49, 0, 0, 0, 49, 0, 0, 0, 49, 0, 0, 0, 49, 0, 0, 0, 49, 0, 0, 0, + 50, 0, 0, 0, 6, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,102,117,110, 99, +110, 97,109,101, 0, 0, 0, 0, 0, 21, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, + 0,119,105,100,116,104, 0, 0, 0, 0, 0, 21, 0, 0, 0, 7, 0, 0, 0, 0, + 0, 0, 0,104,101,105,103,104,116, 0, 0, 0, 0, 0, 21, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 0, 0, + 0, 0, 21, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,100, 97,116, 97, 95,116, +121,112,101, 0, 0, 0, 0, 0, 21, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, +102,117,110, 99, 0, 2, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 56, 0, 0, 0, 73, 0, 0, 0, 0, 5, 0, 9, 17, 0, 0, + 0, 69, 1, 0, 0, 70, 1,128, 2,133, 65, 0, 0,192, 1,128, 2,156, 65, 0, + 1,133, 1, 0, 0,192, 1, 0, 0, 1,130, 0, 0,213, 1,130, 3, 36, 2, 0, + 0, 0, 0,128, 0, 0, 0, 0, 1, 0, 0,128, 1, 0, 0, 0, 2, 0, 0,128, + 2,137, 1,130, 3, 30, 0,128, 0, 3, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, + 0, 0,105,109, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0, 97,115,115,101,114,116, + 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 78,101,119, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 61, 0, 0, 0, 72, 0, 0, 0, 5, 3, 7, 12, 25, 0, + 0, 0, 5, 1, 0, 0, 6, 65, 64, 2, 64, 1, 0, 0,132, 1, 0, 0,196, 1, +128, 0, 4, 2, 0, 1, 68, 2,128, 1, 28,129, 0, 3, 68, 1, 0, 2,128, 1, + 0, 0,192, 1,128, 0, 0, 2, 0, 1, 64, 2, 0, 2,133,130, 0, 0,192, 2, +128, 1,156, 2, 0, 1, 92,129, 0, 0, 90, 1, 0, 0, 22,192, 0,128,128, 1, +128, 2,192, 1, 0, 2,158, 1,128, 1, 22, 0, 0,128, 30, 1, 0, 1, 30, 0, +128, 0, 3, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 17, + 0, 0, 0, 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97, +115,101,100, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0,117,110,112, 97, 99,107, 0, + 0, 0, 0, 0, 25, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, + 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, + 66, 0, 0, 0, 66, 0, 0, 0, 66, 0, 0, 0, 66, 0, 0, 0, 66, 0, 0, 0, + 66, 0, 0, 0, 66, 0, 0, 0, 66, 0, 0, 0, 66, 0, 0, 0, 67, 0, 0, 0, + 67, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, + 70, 0, 0, 0, 72, 0, 0, 0, 6, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, +115,114, 99, 95,105,109, 97,103,101, 49, 0, 0, 0, 0, 0, 24, 0, 0, 0, 11, + 0, 0, 0, 0, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 50, 0, 0, 0, + 0, 0, 24, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0,115,114, 99, 95,105,109, + 97,103,101, 51, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, + 0, 97,114,103, 0, 0, 0, 0, 0, 24, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, + 0,100,115,116, 95,105,109, 97,103,101, 0, 8, 0, 0, 0, 24, 0, 0, 0, 4, + 0, 0, 0, 0, 0, 0, 0,114,101,116, 0, 17, 0, 0, 0, 24, 0, 0, 0, 5, + 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119,105,100,116,104, 0, 7, 0, 0, + 0, 0, 0, 0, 0,104,101,105,103,104,116, 0, 12, 0, 0, 0, 0, 0, 0, 0, + 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 10, 0, 0, 0, 0, 0, 0, 0, +100, 97,116, 97, 95,116,121,112,101, 0, 5, 0, 0, 0, 0, 0, 0, 0,102,117, +110, 99, 0, 17, 0, 0, 0, 57, 0, 0, 0, 57, 0, 0, 0, 58, 0, 0, 0, 58, + 0, 0, 0, 58, 0, 0, 0, 61, 0, 0, 0, 61, 0, 0, 0, 61, 0, 0, 0, 61, + 0, 0, 0, 72, 0, 0, 0, 72, 0, 0, 0, 72, 0, 0, 0, 72, 0, 0, 0, 72, + 0, 0, 0, 72, 0, 0, 0, 72, 0, 0, 0, 73, 0, 0, 0, 6, 0, 0, 0, 9, + 0, 0, 0, 0, 0, 0, 0,102,117,110, 99,110, 97,109,101, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119,105,100,116,104, 0, 0, 0, + 0, 0, 16, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0,104,101,105,103,104,116, + 0, 0, 0, 0, 0, 16, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 99,111,108, +111,114, 95,115,112, 97, 99,101, 0, 0, 0, 0, 0, 16, 0, 0, 0, 10, 0, 0, + 0, 0, 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, 0, 0, 0, 0, 0, 16, + 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,102,117,110, 99, 0, 2, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 0, 0, 0, + 97, 0, 0, 0, 0, 5, 0, 9, 17, 0, 0, 0, 69, 1, 0, 0, 70, 1,128, 2, +133, 65, 0, 0,192, 1,128, 2,156, 65, 0, 1,133, 1, 0, 0,192, 1, 0, 0, + 1,130, 0, 0,213, 1,130, 3, 36, 2, 0, 0, 0, 0,128, 0, 0, 0, 0, 1, + 0, 0,128, 1, 0, 0, 0, 2, 0, 0,128, 2,137, 1,130, 3, 30, 0,128, 0, + 3, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 7, 0, 0, + 0, 0, 0, 0, 0, 97,115,115,101,114,116, 0, 4, 4, 0, 0, 0, 0, 0, 0, + 0, 78,101,119, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 0, 0, + 0, 96, 0, 0, 0, 5, 1, 7, 10, 35, 0, 0, 0,133, 0, 0, 0,134, 64, 64, + 1,192, 0, 0, 0, 4, 1, 0, 0, 68, 1,128, 0,132, 1, 0, 1,196, 1,128, + 1,156,128, 0, 3,197, 0, 0, 0,198, 64,192, 1, 0, 1, 0, 0, 68, 1, 0, + 0,132, 1,128, 0,196, 1, 0, 1, 4, 2,128, 1,220,128, 0, 3, 4, 1, 0, + 2, 64, 1, 0, 0,128, 1, 0, 1,192, 1,128, 1, 5,130, 0, 0, 64, 2,128, + 0, 28, 2, 0, 1, 28,129, 0, 0, 26, 1, 0, 0, 22, 0, 1,128, 64, 1, 0, + 2,128, 1, 0, 1,192, 1,128, 1, 94, 1, 0, 2, 22,128, 0,128, 64, 1, 0, + 1,128, 1,128, 1, 94, 1,128, 1, 30, 0,128, 0, 3, 0, 0, 0, 4, 3, 0, + 0, 0, 0, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 73,109, + 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 4, 7, 0, 0, 0, + 0, 0, 0, 0,117,110,112, 97, 99,107, 0, 0, 0, 0, 0, 35, 0, 0, 0, 86, + 0, 0, 0, 86, 0, 0, 0, 86, 0, 0, 0, 86, 0, 0, 0, 86, 0, 0, 0, 86, + 0, 0, 0, 86, 0, 0, 0, 86, 0, 0, 0, 87, 0, 0, 0, 87, 0, 0, 0, 87, + 0, 0, 0, 87, 0, 0, 0, 87, 0, 0, 0, 87, 0, 0, 0, 87, 0, 0, 0, 87, + 0, 0, 0, 90, 0, 0, 0, 90, 0, 0, 0, 90, 0, 0, 0, 90, 0, 0, 0, 90, + 0, 0, 0, 90, 0, 0, 0, 90, 0, 0, 0, 90, 0, 0, 0, 91, 0, 0, 0, 91, + 0, 0, 0, 92, 0, 0, 0, 92, 0, 0, 0, 92, 0, 0, 0, 92, 0, 0, 0, 92, + 0, 0, 0, 94, 0, 0, 0, 94, 0, 0, 0, 94, 0, 0, 0, 96, 0, 0, 0, 5, + 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, + 0, 0, 0, 0, 0, 34, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 97,114,103, + 0, 0, 0, 0, 0, 34, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0,100,115,116, + 95,105,109, 97,103,101, 49, 0, 8, 0, 0, 0, 34, 0, 0, 0, 11, 0, 0, 0, + 0, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 50, 0, 16, 0, 0, 0, 34, + 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0,114,101,116, 0, 24, 0, 0, 0, 34, + 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119,105,100,116,104, + 0, 7, 0, 0, 0, 0, 0, 0, 0,104,101,105,103,104,116, 0, 12, 0, 0, 0, + 0, 0, 0, 0, 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 10, 0, 0, 0, + 0, 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, 0, 5, 0, 0, 0, 0, 0, + 0, 0,102,117,110, 99, 0, 17, 0, 0, 0, 80, 0, 0, 0, 80, 0, 0, 0, 81, + 0, 0, 0, 81, 0, 0, 0, 81, 0, 0, 0, 84, 0, 0, 0, 84, 0, 0, 0, 84, + 0, 0, 0, 84, 0, 0, 0, 96, 0, 0, 0, 96, 0, 0, 0, 96, 0, 0, 0, 96, + 0, 0, 0, 96, 0, 0, 0, 96, 0, 0, 0, 96, 0, 0, 0, 97, 0, 0, 0, 6, + 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,102,117,110, 99,110, 97,109,101, 0, + 0, 0, 0, 0, 16, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119,105,100,116, +104, 0, 0, 0, 0, 0, 16, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0,104,101, +105,103,104,116, 0, 0, 0, 0, 0, 16, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, + 0, 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 0, 0, 0, 0, 16, 0, 0, + 0, 10, 0, 0, 0, 0, 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, 0, 0, + 0, 0, 0, 16, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,102,117,110, 99, 0, + 2, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +103, 0, 0, 0,122, 0, 0, 0, 0, 5, 0, 9, 17, 0, 0, 0, 69, 1, 0, 0, + 70, 1,128, 2,133, 65, 0, 0,192, 1,128, 2,156, 65, 0, 1,133, 1, 0, 0, +192, 1, 0, 0, 1,130, 0, 0,213, 1,130, 3, 36, 2, 0, 0, 0, 0,128, 0, + 0, 0, 0, 1, 0, 0,128, 1, 0, 0, 0, 2, 0, 0,128, 2,137, 1,130, 3, + 30, 0,128, 0, 3, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, + 4, 7, 0, 0, 0, 0, 0, 0, 0, 97,115,115,101,114,116, 0, 4, 4, 0, 0, + 0, 0, 0, 0, 0, 78,101,119, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0,108, 0, 0, 0,121, 0, 0, 0, 5, 1, 7, 12, 46, 0, 0, 0,133, 0, 0, + 0,134, 64, 64, 1,192, 0, 0, 0, 4, 1, 0, 0, 68, 1,128, 0,132, 1, 0, + 1,196, 1,128, 1,156,128, 0, 3,197, 0, 0, 0,198, 64,192, 1, 0, 1, 0, + 0, 68, 1, 0, 0,132, 1,128, 0,196, 1, 0, 1, 4, 2,128, 1,220,128, 0, + 3, 5, 1, 0, 0, 6, 65, 64, 2, 64, 1, 0, 0,132, 1, 0, 0,196, 1,128, + 0, 4, 2, 0, 1, 68, 2,128, 1, 28,129, 0, 3, 68, 1, 0, 2,128, 1, 0, + 0,192, 1, 0, 1, 0, 2,128, 1, 64, 2, 0, 2,133,130, 0, 0,192, 2,128, + 0,156, 2, 0, 1, 92,129, 0, 0, 90, 1, 0, 0, 22, 64, 1,128,128, 1,128, + 2,192, 1, 0, 1, 0, 2,128, 1, 64, 2, 0, 2,158, 1,128, 2, 22,192, 0, +128,128, 1, 0, 1,192, 1,128, 1, 0, 2, 0, 2,158, 1, 0, 2, 30, 0,128, + 0, 3, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 17, 0, + 0, 0, 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115, +101,100, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0,117,110,112, 97, 99,107, 0, 0, + 0, 0, 0, 46, 0, 0, 0,110, 0, 0, 0,110, 0, 0, 0,110, 0, 0, 0,110, + 0, 0, 0,110, 0, 0, 0,110, 0, 0, 0,110, 0, 0, 0,110, 0, 0, 0,111, + 0, 0, 0,111, 0, 0, 0,111, 0, 0, 0,111, 0, 0, 0,111, 0, 0, 0,111, + 0, 0, 0,111, 0, 0, 0,111, 0, 0, 0,112, 0, 0, 0,112, 0, 0, 0,112, + 0, 0, 0,112, 0, 0, 0,112, 0, 0, 0,112, 0, 0, 0,112, 0, 0, 0,112, + 0, 0, 0,115, 0, 0, 0,115, 0, 0, 0,115, 0, 0, 0,115, 0, 0, 0,115, + 0, 0, 0,115, 0, 0, 0,115, 0, 0, 0,115, 0, 0, 0,115, 0, 0, 0,116, + 0, 0, 0,116, 0, 0, 0,117, 0, 0, 0,117, 0, 0, 0,117, 0, 0, 0,117, + 0, 0, 0,117, 0, 0, 0,117, 0, 0, 0,119, 0, 0, 0,119, 0, 0, 0,119, + 0, 0, 0,119, 0, 0, 0,121, 0, 0, 0, 6, 0, 0, 0, 10, 0, 0, 0, 0, + 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 45, 0, 0, + 0, 4, 0, 0, 0, 0, 0, 0, 0, 97,114,103, 0, 0, 0, 0, 0, 45, 0, 0, + 0, 11, 0, 0, 0, 0, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 49, 0, + 8, 0, 0, 0, 45, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0,100,115,116, 95, +105,109, 97,103,101, 50, 0, 16, 0, 0, 0, 45, 0, 0, 0, 11, 0, 0, 0, 0, + 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 51, 0, 24, 0, 0, 0, 45, 0, + 0, 0, 4, 0, 0, 0, 0, 0, 0, 0,114,101,116, 0, 33, 0, 0, 0, 45, 0, + 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119,105,100,116,104, 0, + 7, 0, 0, 0, 0, 0, 0, 0,104,101,105,103,104,116, 0, 12, 0, 0, 0, 0, + 0, 0, 0, 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 10, 0, 0, 0, 0, + 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, 0, 5, 0, 0, 0, 0, 0, 0, + 0,102,117,110, 99, 0, 17, 0, 0, 0,104, 0, 0, 0,104, 0, 0, 0,105, 0, + 0, 0,105, 0, 0, 0,105, 0, 0, 0,108, 0, 0, 0,108, 0, 0, 0,108, 0, + 0, 0,108, 0, 0, 0,121, 0, 0, 0,121, 0, 0, 0,121, 0, 0, 0,121, 0, + 0, 0,121, 0, 0, 0,121, 0, 0, 0,121, 0, 0, 0,122, 0, 0, 0, 6, 0, + 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,102,117,110, 99,110, 97,109,101, 0, 0, + 0, 0, 0, 16, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119,105,100,116,104, + 0, 0, 0, 0, 0, 16, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0,104,101,105, +103,104,116, 0, 0, 0, 0, 0, 16, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, + 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 0, 0, 0, 0, 16, 0, 0, 0, + 10, 0, 0, 0, 0, 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, 0, 0, 0, + 0, 0, 16, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,102,117,110, 99, 0, 2, + 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, + 0, 0, 0,130, 0, 0, 0, 0, 1, 0, 7, 18, 0, 0, 0,100, 0, 0, 0,133, + 0, 0, 0,134, 64, 64, 1,192, 0,128, 0, 11,129, 64, 0, 28, 1, 0, 1,220, +128, 0, 0, 0, 1,128, 0, 75,193, 64, 0, 92, 1, 0, 1, 28,129, 0, 0,204, + 0,129, 1,156,128, 0, 1,143, 0, 65, 1,206,128, 0,130,204, 64,193, 1,222, + 0, 0, 1, 30, 0,128, 0, 6, 0, 0, 0, 4, 5, 0, 0, 0, 0, 0, 0, 0, +109, 97,116,104, 0, 4, 5, 0, 0, 0, 0, 0, 0, 0,115,113,114,116, 0, 4, + 6, 0, 0, 0, 0, 0, 0, 0, 87,105,100,116,104, 0, 4, 7, 0, 0, 0, 0, + 0, 0, 0, 72,101,105,103,104,116, 0, 3, 0, 0, 0, 0, 0, 0, 0, 64, 3, + 0, 0, 0, 0, 0, 0,240, 63, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +127, 0, 0, 0,127, 0, 0, 0, 0, 1, 0, 2, 3, 0, 0, 0, 78, 0, 0, 0, + 94, 0, 0, 1, 30, 0,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, +127, 0, 0, 0,127, 0, 0, 0,127, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0,120, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 18, 0, + 0, 0,127, 0, 0, 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, + 0, 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, + 0, 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, 0, 0,129, 0, + 0, 0,129, 0, 0, 0,129, 0, 0, 0,130, 0, 0, 0, 3, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0,105,109, 97,103,101, 0, 0, 0, 0, 0, 17, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0,115,113,114, 0, 1, 0, 0, 0, 17, 0, 0, 0, + 5, 0, 0, 0, 0, 0, 0, 0,114,109, 97,120, 0, 14, 0, 0, 0, 17, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,141, 0, 0, 0,144, 0, 0, + 0, 0, 3, 0, 7, 14, 0, 0, 0,197, 0, 0, 0,198, 64,192, 1, 0, 1, 0, + 0, 64, 1,128, 0,128, 1, 0, 1,220,128, 0, 2, 5, 1, 0, 0, 6,129, 64, + 2, 64, 1, 0, 0,128, 1,128, 1, 28,129,128, 1, 64, 1,128, 1, 30, 1,128, + 1, 30, 0,128, 0, 3, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, + 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116, +101, 66, 97,115,101,100, 0, 4, 14, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99, +101,115,115, 82,101,100,117, 99,101, 0, 0, 0, 0, 0, 14, 0, 0, 0,142, 0, + 0, 0,142, 0, 0, 0,142, 0, 0, 0,142, 0, 0, 0,142, 0, 0, 0,142, 0, + 0, 0,143, 0, 0, 0,143, 0, 0, 0,143, 0, 0, 0,143, 0, 0, 0,143, 0, + 0, 0,143, 0, 0, 0,143, 0, 0, 0,144, 0, 0, 0, 4, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, + 13, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119,105,100,116,104, 0, 0, 0, + 0, 0, 13, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0,104,101,105,103,104,116, + 0, 0, 0, 0, 0, 13, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,100,115,116, + 95,105,109, 97,103,101, 0, 6, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,146, 0, 0, 0,149, 0, 0, 0, 0, 3, 0, 7, 14, + 0, 0, 0,197, 0, 0, 0,198, 64,192, 1, 0, 1, 0, 0, 64, 1,128, 0,128, + 1, 0, 1,220,128, 0, 2, 5, 1, 0, 0, 6,129, 64, 2, 64, 1, 0, 0,128, + 1,128, 1, 28,129,128, 1, 64, 1,128, 1, 30, 1,128, 1, 30, 0,128, 0, 3, + 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, + 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, + 0, 4, 14, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 82,101,115, +105,122,101, 0, 0, 0, 0, 0, 14, 0, 0, 0,147, 0, 0, 0,147, 0, 0, 0, +147, 0, 0, 0,147, 0, 0, 0,147, 0, 0, 0,147, 0, 0, 0,148, 0, 0, 0, +148, 0, 0, 0,148, 0, 0, 0,148, 0, 0, 0,148, 0, 0, 0,148, 0, 0, 0, +148, 0, 0, 0,149, 0, 0, 0, 4, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, +115,114, 99, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 13, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0,119,105,100,116,104, 0, 0, 0, 0, 0, 13, 0, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0,104,101,105,103,104,116, 0, 0, 0, 0, 0, 13, + 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, + 0, 6, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0,151, 0, 0, 0,151, 0, 0, 0, 0, 1, 0, 3, 5, 0, 0, 0, 75, 0, 64, + 0, 92,128, 0, 1, 79, 64,192, 0, 94, 0, 0, 1, 30, 0,128, 0, 2, 0, 0, + 0, 4, 6, 0, 0, 0, 0, 0, 0, 0, 87,105,100,116,104, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 64, 0, 0, 0, 0, 5, 0, 0, 0,151, 0, 0, 0,151, 0, 0, + 0,151, 0, 0, 0,151, 0, 0, 0,151, 0, 0, 0, 1, 0, 0, 0, 6, 0, 0, + 0, 0, 0, 0, 0,105,109, 97,103,101, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,152, 0, 0, 0,152, 0, 0, 0, 0, + 1, 0, 3, 5, 0, 0, 0, 75, 0, 64, 0, 92,128, 0, 1, 79, 64,192, 0, 94, + 0, 0, 1, 30, 0,128, 0, 2, 0, 0, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0, + 72,101,105,103,104,116, 0, 3, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, + 5, 0, 0, 0,152, 0, 0, 0,152, 0, 0, 0,152, 0, 0, 0,152, 0, 0, 0, +152, 0, 0, 0, 1, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,105,109, 97,103, +101, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,154, 0, 0, 0,160, 0, 0, 0, 0, 5, 0, 13, 19, 0, 0, 0, 77, 65, + 0, 1, 76, 1,192, 2,141,193, 0, 2,140, 1, 64, 3,197, 65, 0, 0,198,129, +192, 3, 0, 2, 0, 0, 64, 2,128, 2,128, 2, 0, 3,220,129, 0, 2, 5, 66, + 0, 0, 6,194, 64, 4, 64, 2, 0, 0,128, 2,128, 3,192, 2,128, 0, 0, 3, +128, 1, 28, 66,128, 2,222, 1, 0, 1, 30, 0,128, 0, 4, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0,240, 63, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, + 17, 0, 0, 0, 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, + 97,115,101,100, 0, 4, 12, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115, +115, 67,114,111,112, 0, 0, 0, 0, 0, 19, 0, 0, 0,155, 0, 0, 0,155, 0, + 0, 0,156, 0, 0, 0,156, 0, 0, 0,157, 0, 0, 0,157, 0, 0, 0,157, 0, + 0, 0,157, 0, 0, 0,157, 0, 0, 0,157, 0, 0, 0,158, 0, 0, 0,158, 0, + 0, 0,158, 0, 0, 0,158, 0, 0, 0,158, 0, 0, 0,158, 0, 0, 0,158, 0, + 0, 0,159, 0, 0, 0,160, 0, 0, 0, 8, 0, 0, 0, 10, 0, 0, 0, 0, 0, + 0, 0,115,114, 99, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 18, 0, 0, 0, + 5, 0, 0, 0, 0, 0, 0, 0,120,109,105,110, 0, 0, 0, 0, 0, 18, 0, 0, + 0, 5, 0, 0, 0, 0, 0, 0, 0,120,109, 97,120, 0, 0, 0, 0, 0, 18, 0, + 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,121,109,105,110, 0, 0, 0, 0, 0, 18, + 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,121,109, 97,120, 0, 0, 0, 0, 0, + 18, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119,105,100,116,104, 0, 2, 0, + 0, 0, 18, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0,104,101,105,103,104,116, + 0, 4, 0, 0, 0, 18, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,100,115,116, + 95,105,109, 97,103,101, 0, 10, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,164, 0, 0, 0,170, 0, 0, 0, 0, 5, 0, 13, 19, + 0, 0, 0, 77, 65, 0, 1, 76, 1,192, 2,141,193, 0, 2,140, 1, 64, 3,197, + 65, 0, 0,198,129,192, 3, 0, 2, 0, 0, 64, 2,128, 2,128, 2, 0, 3,220, +129, 0, 2, 5, 66, 0, 0, 6,194, 64, 4, 64, 2, 0, 0,128, 2,128, 3,192, + 2,128, 0, 0, 3,128, 1, 28, 66,128, 2,222, 1, 0, 1, 30, 0,128, 0, 4, + 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,240, 63, 4, 3, 0, 0, 0, 0, 0, 0, + 0,105,109, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 73,109, 97,103,101, 67,114, +101, 97,116,101, 66, 97,115,101,100, 0, 4, 18, 0, 0, 0, 0, 0, 0, 0, 80, +114,111, 99,101,115,115, 65,100,100, 77, 97,114,103,105,110,115, 0, 0, 0, 0, + 0, 19, 0, 0, 0,165, 0, 0, 0,165, 0, 0, 0,166, 0, 0, 0,166, 0, 0, + 0,167, 0, 0, 0,167, 0, 0, 0,167, 0, 0, 0,167, 0, 0, 0,167, 0, 0, + 0,167, 0, 0, 0,168, 0, 0, 0,168, 0, 0, 0,168, 0, 0, 0,168, 0, 0, + 0,168, 0, 0, 0,168, 0, 0, 0,168, 0, 0, 0,169, 0, 0, 0,170, 0, 0, + 0, 8, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,115,114, 99, 95,105,109, 97, +103,101, 0, 0, 0, 0, 0, 18, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,120, +109,105,110, 0, 0, 0, 0, 0, 18, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, +120,109, 97,120, 0, 0, 0, 0, 0, 18, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, + 0,121,109,105,110, 0, 0, 0, 0, 0, 18, 0, 0, 0, 5, 0, 0, 0, 0, 0, + 0, 0,121,109, 97,120, 0, 0, 0, 0, 0, 18, 0, 0, 0, 6, 0, 0, 0, 0, + 0, 0, 0,119,105,100,116,104, 0, 2, 0, 0, 0, 18, 0, 0, 0, 7, 0, 0, + 0, 0, 0, 0, 0,104,101,105,103,104,116, 0, 4, 0, 0, 0, 18, 0, 0, 0, + 10, 0, 0, 0, 0, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 0, 10, 0, + 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,172, 0, + 0, 0,176, 0, 0, 0, 0, 4, 0, 13, 26, 0, 0, 0, 5, 1, 0, 0, 6, 65, + 64, 2, 75,129, 64, 0, 92,129, 0, 1,139,193, 64, 0,156,129, 0, 1,192, 1, +128, 0, 0, 2, 0, 1, 28,193,128, 2,133, 1, 0, 0,134, 1, 65, 3,192, 1, + 0, 0, 0, 2, 0, 2, 64, 2,128, 2,156,129, 0, 2,197, 1, 0, 0,198, 65, +193, 3, 0, 2, 0, 0, 64, 2, 0, 3,128, 2,128, 0,192, 2, 0, 1, 0, 3, +128, 1,220,129, 0, 3, 0, 2, 0, 3,222, 1,128, 1, 30, 0,128, 0, 6, 0, + 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 22, 0, 0, 0, 0, + 0, 0, 0, 80,114,111, 99,101,115,115, 67, 97,108, 99, 82,111,116, 97,116,101, + 83,105,122,101, 0, 4, 6, 0, 0, 0, 0, 0, 0, 0, 87,105,100,116,104, 0, + 4, 7, 0, 0, 0, 0, 0, 0, 0, 72,101,105,103,104,116, 0, 4, 17, 0, 0, + 0, 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101, +100, 0, 4, 14, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 82,111, +116, 97,116,101, 0, 0, 0, 0, 0, 26, 0, 0, 0,173, 0, 0, 0,173, 0, 0, + 0,173, 0, 0, 0,173, 0, 0, 0,173, 0, 0, 0,173, 0, 0, 0,173, 0, 0, + 0,173, 0, 0, 0,173, 0, 0, 0,174, 0, 0, 0,174, 0, 0, 0,174, 0, 0, + 0,174, 0, 0, 0,174, 0, 0, 0,174, 0, 0, 0,175, 0, 0, 0,175, 0, 0, + 0,175, 0, 0, 0,175, 0, 0, 0,175, 0, 0, 0,175, 0, 0, 0,175, 0, 0, + 0,175, 0, 0, 0,175, 0, 0, 0,175, 0, 0, 0,176, 0, 0, 0, 7, 0, 0, + 0, 10, 0, 0, 0, 0, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 0, 0, + 0, 0, 0, 25, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 99,111,115, 48, 0, + 0, 0, 0, 0, 25, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,115,105,110, 48, + 0, 0, 0, 0, 0, 25, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,111,114,100, +101,114, 0, 0, 0, 0, 0, 25, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119, +105,100,116,104, 0, 9, 0, 0, 0, 25, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, + 0,104,101,105,103,104,116, 0, 9, 0, 0, 0, 25, 0, 0, 0, 10, 0, 0, 0, + 0, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 0, 15, 0, 0, 0, 25, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,179, 0, 0, 0,179, 0, + 0, 0, 0, 1, 0, 3, 4, 0, 0, 0, 75, 0, 64, 0, 93, 0, 0, 1, 94, 0, + 0, 0, 30, 0,128, 0, 1, 0, 0, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0, 72, +101,105,103,104,116, 0, 0, 0, 0, 0, 4, 0, 0, 0,179, 0, 0, 0,179, 0, + 0, 0,179, 0, 0, 0,179, 0, 0, 0, 1, 0, 0, 0, 6, 0, 0, 0, 0, 0, + 0, 0,105,109, 97,103,101, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,179, 0, 0, 0,179, 0, 0, 0, 0, 1, 0, 3, + 4, 0, 0, 0, 75, 0, 64, 0, 93, 0, 0, 1, 94, 0, 0, 0, 30, 0,128, 0, + 1, 0, 0, 0, 4, 6, 0, 0, 0, 0, 0, 0, 0, 87,105,100,116,104, 0, 0, + 0, 0, 0, 4, 0, 0, 0,179, 0, 0, 0,179, 0, 0, 0,179, 0, 0, 0,179, + 0, 0, 0, 1, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,105,109, 97,103,101, + 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0,212, 0, 0, 0,212, 0, 0, 0, 0, 1, 0, 3, 13, 0, 0, 0, 75, 0, 64, + 0, 92,128, 0, 1, 90, 0, 0, 0, 22,192, 0,128, 75, 0, 64, 0, 93, 0, 0, + 1, 94, 0, 0, 0, 22,192, 0,128, 75, 0, 64, 0, 92,128, 0, 1, 79, 64,192, + 0, 94, 0, 0, 1, 30, 0,128, 0, 2, 0, 0, 0, 4, 7, 0, 0, 0, 0, 0, + 0, 0, 72,101,105,103,104,116, 0, 3, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, + 0, 0, 13, 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, + 0, 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, + 0, 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0, 1, 0, + 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,105,109, 97,103,101, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,214, 0, 0, 0, +227, 0, 0, 0, 0, 1, 0, 8, 36, 0, 0, 0, 75, 0, 64, 0, 92,128, 0, 1, + 79, 64,192, 0,133,128, 0, 0,134,192, 64, 1,203, 0, 64, 0,220,128, 0, 1, + 1, 65, 0, 0,156,128,128, 1,154, 0, 0, 0, 22, 0, 0,128, 76, 0,193, 0, +133, 64, 1, 0,134,128, 65, 1,192, 0, 0, 0, 3, 1, 0, 2, 64, 1,128, 0, +156,128, 0, 2,197, 64, 1, 0,198,128,193, 1, 0, 1, 0, 0, 67, 1,128, 2, +139, 1, 64, 0,156,129, 0, 1,143, 65, 64, 3,220,128, 0, 2, 5, 65, 1, 0, + 6,193, 65, 2, 64, 1, 0, 0,128, 1, 0, 1,192, 1,128, 1, 28, 65, 0, 2, + 0, 1, 0, 1, 64, 1,128, 1, 30, 1,128, 1, 30, 0,128, 0, 8, 0, 0, 0, + 4, 7, 0, 0, 0, 0, 0, 0, 0, 72,101,105,103,104,116, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 64, 4, 5, 0, 0, 0, 0, 0, 0, 0,109, 97,116,104, 0, 4, + 4, 0, 0, 0, 0, 0, 0, 0,109,111,100, 0, 3, 0, 0, 0, 0, 0, 0,240, + 63, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, 0, 0, + 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 4, + 22, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 73,110,116,101,114, +108, 97, 99,101, 83,112,108,105,116, 0, 0, 0, 0, 0, 36, 0, 0, 0,216, 0, + 0, 0,216, 0, 0, 0,216, 0, 0, 0,217, 0, 0, 0,217, 0, 0, 0,217, 0, + 0, 0,217, 0, 0, 0,217, 0, 0, 0,217, 0, 0, 0,217, 0, 0, 0,217, 0, + 0, 0,218, 0, 0, 0,221, 0, 0, 0,221, 0, 0, 0,221, 0, 0, 0,221, 0, + 0, 0,221, 0, 0, 0,221, 0, 0, 0,222, 0, 0, 0,222, 0, 0, 0,222, 0, + 0, 0,222, 0, 0, 0,222, 0, 0, 0,222, 0, 0, 0,222, 0, 0, 0,222, 0, + 0, 0,225, 0, 0, 0,225, 0, 0, 0,225, 0, 0, 0,225, 0, 0, 0,225, 0, + 0, 0,225, 0, 0, 0,226, 0, 0, 0,226, 0, 0, 0,226, 0, 0, 0,227, 0, + 0, 0, 4, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,115,114, 99, 95,105,109, + 97,103,101, 0, 0, 0, 0, 0, 35, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, +100,115,116, 95,104,101,105,103,104,116, 49, 0, 3, 0, 0, 0, 35, 0, 0, 0, + 11, 0, 0, 0, 0, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 49, 0, 18, + 0, 0, 0, 35, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0,100,115,116, 95,105, +109, 97,103,101, 50, 0, 26, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,229, 0, 0, 0,235, 0, 0, 0, 0, 1, 0, 3, 14, 0, + 0, 0, 75, 0, 64, 0, 92,128, 0, 1,133, 64, 0, 0,134,128, 64, 1, 87,128, +128, 0, 22,192, 0,128,133, 64, 0, 0,134,192, 64, 1, 23,128,128, 0, 22, 64, + 0,128,133, 64, 0, 0, 70, 0, 65, 1, 94, 0, 0, 1, 30, 0,128, 0, 5, 0, + 0, 0, 4, 9, 0, 0, 0, 0, 0, 0, 0, 68, 97,116, 97, 84,121,112,101, 0, + 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 5, 0, 0, 0, 0, 0, 0, + 0, 66, 89, 84, 69, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0, 85, 83, 72, 79, 82, + 84, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 73, 78, 84, 0, 0, 0, 0, 0, 14, + 0, 0, 0,230, 0, 0, 0,230, 0, 0, 0,231, 0, 0, 0,231, 0, 0, 0,231, + 0, 0, 0,231, 0, 0, 0,231, 0, 0, 0,231, 0, 0, 0,231, 0, 0, 0,231, + 0, 0, 0,232, 0, 0, 0,232, 0, 0, 0,234, 0, 0, 0,235, 0, 0, 0, 2, + 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,105,109, 97,103,101, 0, 0, 0, 0, + 0, 13, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,100, 97,116, 97, 95,116,121, +112,101, 0, 2, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,250, 0, 0, 0,254, 0, 0, 0, 0, 3, 0, 9, 13, 0, 0, 0,197, + 0, 0, 0,198, 64,192, 1, 0, 1, 0, 0,220,128, 0, 1, 5, 1, 0, 0, 6, +129, 64, 2, 64, 1, 0, 0,128, 1,128, 0,192, 1,128, 1, 0, 2, 0, 1, 28, + 65,128, 2,222, 0, 0, 1, 30, 0,128, 0, 3, 0, 0, 0, 4, 3, 0, 0, 0, + 0, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 73,109, 97,103, +101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 4, 25, 0, 0, 0, 0, 0, + 0, 0, 80,114,111, 99,101,115,115, 65,114,105,116,104,109,101,116,105, 99, 67, +111,110,115,116, 79,112, 0, 0, 0, 0, 0, 13, 0, 0, 0,251, 0, 0, 0,251, + 0, 0, 0,251, 0, 0, 0,251, 0, 0, 0,252, 0, 0, 0,252, 0, 0, 0,252, + 0, 0, 0,252, 0, 0, 0,252, 0, 0, 0,252, 0, 0, 0,252, 0, 0, 0,253, + 0, 0, 0,254, 0, 0, 0, 4, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,115, +114, 99, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 12, 0, 0, 0, 10, 0, 0, + 0, 0, 0, 0, 0,115,114, 99, 95, 99,111,110,115,116, 0, 0, 0, 0, 0, 12, + 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0,111,112, 0, 0, 0, 0, 0, 12, 0, + 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 0, + 4, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 1, 0, 0, 9, 1, 0, 0, 0, 2, 0, 6, 11, 0, 0, 0,133, 0, 0, 0, +134, 64, 64, 1,198,128, 64, 0,156,128, 0, 1,197, 0, 0, 0,198,192,192, 1, + 0, 1, 0, 0, 64, 1, 0, 1,220, 64,128, 1,158, 0, 0, 1, 30, 0,128, 0, + 4, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 17, 0, 0, + 0, 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101, +100, 0, 3, 0, 0, 0, 0, 0, 0,240, 63, 4, 20, 0, 0, 0, 0, 0, 0, 0, + 80,114,111, 99,101,115,115, 77,117,108,116,105,112,108,101, 77,101, 97,110, 0, + 0, 0, 0, 0, 11, 0, 0, 0, 6, 1, 0, 0, 6, 1, 0, 0, 6, 1, 0, 0, + 6, 1, 0, 0, 7, 1, 0, 0, 7, 1, 0, 0, 7, 1, 0, 0, 7, 1, 0, 0, + 7, 1, 0, 0, 8, 1, 0, 0, 9, 1, 0, 0, 3, 0, 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 95,108,105,115,116, 0, 0, + 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,100,115,116, 95,105, +109, 97,103,101, 0, 0, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, + 0,100,115,116, 95,105,109, 97,103,101, 0, 4, 0, 0, 0, 10, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 1, 0, 0, 15, 1, 0, 0, 0, + 2, 0, 7, 12, 0, 0, 0,133, 0, 0, 0,134, 64, 64, 1,198,128, 64, 0,156, +128, 0, 1,197, 0, 0, 0,198,192,192, 1, 0, 1, 0, 0, 64, 1,128, 0,128, + 1, 0, 1,220, 64, 0, 2,158, 0, 0, 1, 30, 0,128, 0, 4, 0, 0, 0, 4, + 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, + 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 3, 0, 0, + 0, 0, 0, 0,240, 63, 4, 22, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101, +115,115, 77,117,108,116,105,112,108,101, 83,116,100, 68,101,118, 0, 0, 0, 0, + 0, 12, 0, 0, 0, 12, 1, 0, 0, 12, 1, 0, 0, 12, 1, 0, 0, 12, 1, 0, + 0, 13, 1, 0, 0, 13, 1, 0, 0, 13, 1, 0, 0, 13, 1, 0, 0, 13, 1, 0, + 0, 13, 1, 0, 0, 14, 1, 0, 0, 15, 1, 0, 0, 3, 0, 0, 0, 15, 0, 0, + 0, 0, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 95,108,105,115,116, 0, + 0, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0,109,101, 97,110, + 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 11, 0, 0, 0, 10, 0, 0, 0, 0, + 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 0, 4, 0, 0, 0, 11, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 1, 0, 0, 29, 1, 0, + 0, 0, 1, 0, 8, 28, 0, 0, 0, 69, 0, 0, 0, 70, 64,192, 0,128, 0, 0, + 0,195, 0, 0, 2, 69, 1, 0, 0, 70,129,192, 2,133, 1, 0, 0,134,193, 64, + 3, 92,128, 0, 3,133, 0, 0, 0,134, 64, 64, 1,192, 0, 0, 0, 3, 1,128, + 2,133, 1, 0, 0,134, 1, 65, 3,197, 1, 0, 0,198,193,192, 3,156,128, 0, + 3,197, 0, 0, 0,198, 64,193, 1, 0, 1, 0, 0, 64, 1,128, 0,128, 1, 0, + 1,220, 64, 0, 2,192, 0,128, 0, 0, 1, 0, 1,222, 0,128, 1, 30, 0,128, + 0, 6, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 17, 0, + 0, 0, 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115, +101,100, 0, 4, 5, 0, 0, 0, 0, 0, 0, 0, 71, 82, 65, 89, 0, 4, 5, 0, + 0, 0, 0, 0, 0, 0, 66, 89, 84, 69, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, + 82, 71, 66, 0, 4, 20, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, + 83,112,108,105,116, 89, 67,104,114,111,109, 97, 0, 0, 0, 0, 0, 28, 0, 0, + 0, 25, 1, 0, 0, 25, 1, 0, 0, 25, 1, 0, 0, 25, 1, 0, 0, 25, 1, 0, + 0, 25, 1, 0, 0, 25, 1, 0, 0, 25, 1, 0, 0, 25, 1, 0, 0, 26, 1, 0, + 0, 26, 1, 0, 0, 26, 1, 0, 0, 26, 1, 0, 0, 26, 1, 0, 0, 26, 1, 0, + 0, 26, 1, 0, 0, 26, 1, 0, 0, 26, 1, 0, 0, 27, 1, 0, 0, 27, 1, 0, + 0, 27, 1, 0, 0, 27, 1, 0, 0, 27, 1, 0, 0, 27, 1, 0, 0, 28, 1, 0, + 0, 28, 1, 0, 0, 28, 1, 0, 0, 29, 1, 0, 0, 3, 0, 0, 0, 10, 0, 0, + 0, 0, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 27, + 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0,121, 95,105,109, 97,103,101, 0, 9, + 0, 0, 0, 27, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 99,104,114,111,109, + 97, 95,105,109, 97,103,101, 0, 18, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 34, 1, 0, 0, 42, 1, 0, 0, 0, 1, 0, 14, + 29, 0, 0, 0, 75, 0, 64, 0, 92,128, 0, 1,138, 0, 0, 0,193, 64, 0, 0, + 0, 1,128, 0, 65, 65, 0, 0,224,128, 2,128,197,129, 0, 0,198,193,192, 3, + 0, 2, 0, 1, 69, 2, 1, 0, 70, 66,193, 4,128, 2, 0, 0,195, 2, 0, 6, + 69, 3, 1, 0, 70,131,193, 6, 92, 2,128, 2,220, 65, 0, 0,223,192,252,127, +197, 0, 1, 0,198,192,193, 1, 0, 1, 0, 0, 64, 1, 0, 1,220, 64,128, 1, +197, 0, 2, 0, 0, 1, 0, 1,221, 0, 0, 1,222, 0, 0, 0, 30, 0,128, 0, + 9, 0, 0, 0, 4, 6, 0, 0, 0, 0, 0, 0, 0, 68,101,112,116,104, 0, 3, + 0, 0, 0, 0, 0, 0,240, 63, 4, 6, 0, 0, 0, 0, 0, 0, 0,116, 97, 98, +108,101, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0,105,110,115,101,114,116, 0, 4, + 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, + 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 4, 5, 0, + 0, 0, 0, 0, 0, 0, 71, 82, 65, 89, 0, 4, 23, 0, 0, 0, 0, 0, 0, 0, + 80,114,111, 99,101,115,115, 83,112,108,105,116, 67,111,109,112,111,110,101,110, +116,115, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0,117,110,112, 97, 99,107, 0, 0, + 0, 0, 0, 29, 0, 0, 0, 35, 1, 0, 0, 35, 1, 0, 0, 36, 1, 0, 0, 37, + 1, 0, 0, 37, 1, 0, 0, 37, 1, 0, 0, 37, 1, 0, 0, 38, 1, 0, 0, 38, + 1, 0, 0, 38, 1, 0, 0, 38, 1, 0, 0, 38, 1, 0, 0, 38, 1, 0, 0, 38, + 1, 0, 0, 38, 1, 0, 0, 38, 1, 0, 0, 38, 1, 0, 0, 38, 1, 0, 0, 37, + 1, 0, 0, 40, 1, 0, 0, 40, 1, 0, 0, 40, 1, 0, 0, 40, 1, 0, 0, 40, + 1, 0, 0, 41, 1, 0, 0, 41, 1, 0, 0, 41, 1, 0, 0, 41, 1, 0, 0, 42, + 1, 0, 0, 7, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,115,114, 99, 95,105, +109, 97,103,101, 0, 0, 0, 0, 0, 28, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, + 0,100,101,112,116,104, 0, 2, 0, 0, 0, 28, 0, 0, 0, 11, 0, 0, 0, 0, + 0, 0, 0,100,115,116, 95,105,109, 97,103,101,115, 0, 3, 0, 0, 0, 28, 0, + 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 40,102,111,114, 32,105,110,100,101,120, + 41, 0, 6, 0, 0, 0, 19, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 40,102, +111,114, 32,108,105,109,105,116, 41, 0, 6, 0, 0, 0, 19, 0, 0, 0, 11, 0, + 0, 0, 0, 0, 0, 0, 40,102,111,114, 32,115,116,101,112, 41, 0, 6, 0, 0, + 0, 19, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,105, 0, 7, 0, 0, 0, 18, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 1, 0, 0, 48, + 1, 0, 0, 0, 1, 0, 6, 14, 0, 0, 0, 69, 0, 0, 0, 70, 64,192, 0,134, +128, 64, 0,195, 0, 0, 2, 69, 1, 0, 0, 70,193,192, 2, 92,128,128, 2,133, + 0, 0, 0,134, 0, 65, 1,192, 0, 0, 0, 0, 1,128, 0,156, 64,128, 1, 94, + 0, 0, 1, 30, 0,128, 0, 5, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0, +105,109, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, + 97,116,101, 66, 97,115,101,100, 0, 3, 0, 0, 0, 0, 0, 0,240, 63, 4, 4, + 0, 0, 0, 0, 0, 0, 0, 82, 71, 66, 0, 4, 23, 0, 0, 0, 0, 0, 0, 0, + 80,114,111, 99,101,115,115, 77,101,114,103,101, 67,111,109,112,111,110,101,110, +116,115, 0, 0, 0, 0, 0, 14, 0, 0, 0, 45, 1, 0, 0, 45, 1, 0, 0, 45, + 1, 0, 0, 45, 1, 0, 0, 45, 1, 0, 0, 45, 1, 0, 0, 45, 1, 0, 0, 46, + 1, 0, 0, 46, 1, 0, 0, 46, 1, 0, 0, 46, 1, 0, 0, 46, 1, 0, 0, 47, + 1, 0, 0, 48, 1, 0, 0, 2, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0,115, +114, 99, 95,105,109, 97,103,101, 95,108,105,115,116, 0, 0, 0, 0, 0, 13, 0, + 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 0, + 7, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0,144, 1, 0, 0, 25, 0, 0, 0, + 50, 0, 0, 0, 73, 0, 0, 0, 97, 0, 0, 0,122, 0, 0, 0,130, 0, 0, 0, +132, 0, 0, 0,132, 0, 0, 0,132, 0, 0, 0,132, 0, 0, 0,132, 0, 0, 0, +132, 0, 0, 0,133, 0, 0, 0,133, 0, 0, 0,133, 0, 0, 0,134, 0, 0, 0, +134, 0, 0, 0,134, 0, 0, 0,135, 0, 0, 0,135, 0, 0, 0,135, 0, 0, 0, +136, 0, 0, 0,136, 0, 0, 0,136, 0, 0, 0,136, 0, 0, 0,136, 0, 0, 0, +136, 0, 0, 0,136, 0, 0, 0,136, 0, 0, 0,136, 0, 0, 0,137, 0, 0, 0, +137, 0, 0, 0,137, 0, 0, 0,138, 0, 0, 0,138, 0, 0, 0,138, 0, 0, 0, +138, 0, 0, 0,138, 0, 0, 0,138, 0, 0, 0,139, 0, 0, 0,139, 0, 0, 0, +139, 0, 0, 0,139, 0, 0, 0,139, 0, 0, 0,139, 0, 0, 0,139, 0, 0, 0, +141, 0, 0, 0,144, 0, 0, 0,141, 0, 0, 0,146, 0, 0, 0,149, 0, 0, 0, +146, 0, 0, 0,151, 0, 0, 0,151, 0, 0, 0,151, 0, 0, 0,152, 0, 0, 0, +151, 0, 0, 0,154, 0, 0, 0,160, 0, 0, 0,154, 0, 0, 0,162, 0, 0, 0, +162, 0, 0, 0,162, 0, 0, 0,164, 0, 0, 0,170, 0, 0, 0,164, 0, 0, 0, +172, 0, 0, 0,176, 0, 0, 0,172, 0, 0, 0,178, 0, 0, 0,178, 0, 0, 0, +178, 0, 0, 0,179, 0, 0, 0,179, 0, 0, 0,179, 0, 0, 0,179, 0, 0, 0, +179, 0, 0, 0,180, 0, 0, 0,180, 0, 0, 0,180, 0, 0, 0,181, 0, 0, 0, +181, 0, 0, 0,181, 0, 0, 0,182, 0, 0, 0,182, 0, 0, 0,182, 0, 0, 0, +183, 0, 0, 0,183, 0, 0, 0,183, 0, 0, 0,184, 0, 0, 0,184, 0, 0, 0, +184, 0, 0, 0,185, 0, 0, 0,185, 0, 0, 0,185, 0, 0, 0,186, 0, 0, 0, +186, 0, 0, 0,186, 0, 0, 0,187, 0, 0, 0,187, 0, 0, 0,187, 0, 0, 0, +188, 0, 0, 0,188, 0, 0, 0,188, 0, 0, 0,189, 0, 0, 0,189, 0, 0, 0, +189, 0, 0, 0,190, 0, 0, 0,190, 0, 0, 0,190, 0, 0, 0,191, 0, 0, 0, +191, 0, 0, 0,191, 0, 0, 0,192, 0, 0, 0,192, 0, 0, 0,192, 0, 0, 0, +193, 0, 0, 0,193, 0, 0, 0,193, 0, 0, 0,194, 0, 0, 0,194, 0, 0, 0, +194, 0, 0, 0,195, 0, 0, 0,195, 0, 0, 0,195, 0, 0, 0,196, 0, 0, 0, +196, 0, 0, 0,196, 0, 0, 0,197, 0, 0, 0,197, 0, 0, 0,197, 0, 0, 0, +198, 0, 0, 0,198, 0, 0, 0,198, 0, 0, 0,199, 0, 0, 0,199, 0, 0, 0, +199, 0, 0, 0,200, 0, 0, 0,200, 0, 0, 0,200, 0, 0, 0,201, 0, 0, 0, +201, 0, 0, 0,201, 0, 0, 0,202, 0, 0, 0,202, 0, 0, 0,202, 0, 0, 0, +203, 0, 0, 0,203, 0, 0, 0,203, 0, 0, 0,204, 0, 0, 0,204, 0, 0, 0, +204, 0, 0, 0,205, 0, 0, 0,205, 0, 0, 0,205, 0, 0, 0,206, 0, 0, 0, +206, 0, 0, 0,206, 0, 0, 0,207, 0, 0, 0,207, 0, 0, 0,207, 0, 0, 0, +208, 0, 0, 0,208, 0, 0, 0,208, 0, 0, 0,209, 0, 0, 0,209, 0, 0, 0, +209, 0, 0, 0,210, 0, 0, 0,210, 0, 0, 0,210, 0, 0, 0,211, 0, 0, 0, +211, 0, 0, 0,211, 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0, +212, 0, 0, 0,212, 0, 0, 0,214, 0, 0, 0,227, 0, 0, 0,214, 0, 0, 0, +235, 0, 0, 0,237, 0, 0, 0,237, 0, 0, 0,237, 0, 0, 0,237, 0, 0, 0, +237, 0, 0, 0,238, 0, 0, 0,238, 0, 0, 0,238, 0, 0, 0,238, 0, 0, 0, +238, 0, 0, 0,239, 0, 0, 0,239, 0, 0, 0,239, 0, 0, 0,240, 0, 0, 0, +240, 0, 0, 0,240, 0, 0, 0,241, 0, 0, 0,241, 0, 0, 0,241, 0, 0, 0, +242, 0, 0, 0,242, 0, 0, 0,242, 0, 0, 0,243, 0, 0, 0,243, 0, 0, 0, +243, 0, 0, 0,244, 0, 0, 0,244, 0, 0, 0,244, 0, 0, 0,245, 0, 0, 0, +245, 0, 0, 0,245, 0, 0, 0,246, 0, 0, 0,246, 0, 0, 0,246, 0, 0, 0, +247, 0, 0, 0,247, 0, 0, 0,247, 0, 0, 0,248, 0, 0, 0,248, 0, 0, 0, +248, 0, 0, 0,250, 0, 0, 0,254, 0, 0, 0,250, 0, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, + 2, 1, 0, 0, 2, 1, 0, 0, 2, 1, 0, 0, 3, 1, 0, 0, 3, 1, 0, 0, + 3, 1, 0, 0, 3, 1, 0, 0, 3, 1, 0, 0, 3, 1, 0, 0, 5, 1, 0, 0, + 9, 1, 0, 0, 5, 1, 0, 0, 11, 1, 0, 0, 15, 1, 0, 0, 11, 1, 0, 0, + 17, 1, 0, 0, 17, 1, 0, 0, 17, 1, 0, 0, 18, 1, 0, 0, 18, 1, 0, 0, + 18, 1, 0, 0, 19, 1, 0, 0, 19, 1, 0, 0, 19, 1, 0, 0, 19, 1, 0, 0, + 19, 1, 0, 0, 19, 1, 0, 0, 19, 1, 0, 0, 20, 1, 0, 0, 20, 1, 0, 0, + 20, 1, 0, 0, 21, 1, 0, 0, 21, 1, 0, 0, 21, 1, 0, 0, 22, 1, 0, 0, + 22, 1, 0, 0, 22, 1, 0, 0, 24, 1, 0, 0, 29, 1, 0, 0, 24, 1, 0, 0, + 31, 1, 0, 0, 31, 1, 0, 0, 31, 1, 0, 0, 31, 1, 0, 0, 31, 1, 0, 0, + 31, 1, 0, 0, 31, 1, 0, 0, 31, 1, 0, 0, 32, 1, 0, 0, 32, 1, 0, 0, + 32, 1, 0, 0, 32, 1, 0, 0, 32, 1, 0, 0, 32, 1, 0, 0, 32, 1, 0, 0, + 32, 1, 0, 0, 34, 1, 0, 0, 42, 1, 0, 0, 34, 1, 0, 0, 44, 1, 0, 0, + 48, 1, 0, 0, 44, 1, 0, 0, 50, 1, 0, 0, 50, 1, 0, 0, 50, 1, 0, 0, + 50, 1, 0, 0, 50, 1, 0, 0, 50, 1, 0, 0, 51, 1, 0, 0, 51, 1, 0, 0, + 51, 1, 0, 0, 52, 1, 0, 0, 52, 1, 0, 0, 52, 1, 0, 0, 53, 1, 0, 0, + 53, 1, 0, 0, 53, 1, 0, 0, 54, 1, 0, 0, 54, 1, 0, 0, 54, 1, 0, 0, + 55, 1, 0, 0, 55, 1, 0, 0, 55, 1, 0, 0, 56, 1, 0, 0, 56, 1, 0, 0, + 56, 1, 0, 0, 57, 1, 0, 0, 57, 1, 0, 0, 57, 1, 0, 0, 57, 1, 0, 0, + 57, 1, 0, 0, 57, 1, 0, 0, 58, 1, 0, 0, 58, 1, 0, 0, 58, 1, 0, 0, + 58, 1, 0, 0, 58, 1, 0, 0, 58, 1, 0, 0, 59, 1, 0, 0, 59, 1, 0, 0, + 59, 1, 0, 0, 60, 1, 0, 0, 60, 1, 0, 0, 60, 1, 0, 0, 60, 1, 0, 0, + 60, 1, 0, 0, 60, 1, 0, 0, 60, 1, 0, 0, 61, 1, 0, 0, 61, 1, 0, 0, + 61, 1, 0, 0, 61, 1, 0, 0, 61, 1, 0, 0, 61, 1, 0, 0, 61, 1, 0, 0, + 62, 1, 0, 0, 62, 1, 0, 0, 62, 1, 0, 0, 62, 1, 0, 0, 62, 1, 0, 0, + 62, 1, 0, 0, 62, 1, 0, 0, 63, 1, 0, 0, 63, 1, 0, 0, 63, 1, 0, 0, + 64, 1, 0, 0, 64, 1, 0, 0, 64, 1, 0, 0, 64, 1, 0, 0, 64, 1, 0, 0, + 64, 1, 0, 0, 64, 1, 0, 0, 65, 1, 0, 0, 65, 1, 0, 0, 65, 1, 0, 0, + 65, 1, 0, 0, 65, 1, 0, 0, 65, 1, 0, 0, 65, 1, 0, 0, 66, 1, 0, 0, + 66, 1, 0, 0, 66, 1, 0, 0, 67, 1, 0, 0, 67, 1, 0, 0, 67, 1, 0, 0, + 68, 1, 0, 0, 68, 1, 0, 0, 68, 1, 0, 0, 69, 1, 0, 0, 69, 1, 0, 0, + 69, 1, 0, 0, 69, 1, 0, 0, 69, 1, 0, 0, 69, 1, 0, 0, 69, 1, 0, 0, + 70, 1, 0, 0, 70, 1, 0, 0, 70, 1, 0, 0, 70, 1, 0, 0, 70, 1, 0, 0, + 70, 1, 0, 0, 70, 1, 0, 0, 71, 1, 0, 0, 71, 1, 0, 0, 71, 1, 0, 0, + 72, 1, 0, 0, 72, 1, 0, 0, 72, 1, 0, 0, 72, 1, 0, 0, 7, 0, 0, 0, + 17, 0, 0, 0, 0, 0, 0, 0, 79,110,101, 83,111,117,114, 99,101, 79,110,101, + 68,101,115,116, 0, 1, 0, 0, 0,143, 1, 0, 0, 18, 0, 0, 0, 0, 0, 0, + 0, 84,119,111, 83,111,117,114, 99,101,115, 79,110,101, 68,101,115,116, 0, 2, + 0, 0, 0,143, 1, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 84,104,114,101,101, + 83,111,117,114, 99,101,115, 79,110,101, 68,101,115,116, 0, 3, 0, 0, 0,143, + 1, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 79,110,101, 83,111,117,114, 99,101, + 84,119,111, 68,101,115,116,115, 0, 4, 0, 0, 0,143, 1, 0, 0, 20, 0, 0, + 0, 0, 0, 0, 0, 79,110,101, 83,111,117,114, 99,101, 84,104,114,101,101, 68, +101,115,116,115, 0, 5, 0, 0, 0,143, 1, 0, 0, 13, 0, 0, 0, 0, 0, 0, + 0,104,111,117,103,104, 95,104,101,105,103,104,116, 0, 6, 0, 0, 0,143, 1, + 0, 0, 13, 0, 0, 0, 0, 0, 0, 0,105,110,116, 95,100, 97,116, 97,116,121, +112,101, 0,182, 0, 0, 0,143, 1, 0, 0, 0, 0, 0, 0, +}; + + if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"../obj/imlua_process51/im_process_be64.lo")==0) lua_call(L, 0, 0); +} diff --git a/im/src/lua5/loh/im_process_le64.loh b/im/src/lua5/loh/im_process_le64.loh new file mode 100755 index 0000000..fc76f99 --- /dev/null +++ b/im/src/lua5/loh/im_process_le64.loh @@ -0,0 +1,897 @@ +/* code automatically generated by bin2c -- DO NOT EDIT */ +{ +/* #include'ing this file in a C program is equivalent to calling + if (luaL_loadfile(L,"../obj/imlua_process51/im_process_le64.lo")==0) lua_call(L, 0, 0); +*/ +/* ../obj/imlua_process51/im_process_le64.lo */ +static const unsigned char B1[]={ + 27, 76,117, 97, 81, 0, 1, 4, 8, 4, 8, 0, 21, 0, 0, 0, 0, 0, 0, 0, + 64,108,117, 97, 53, 47,105,109, 95,112,114,111, 99,101,115,115, 46,108,117, 97, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 13,144, 1, 0, 0, 36, 0, 0, + 0,100, 64, 0, 0,164,128, 0, 0,228,192, 0, 0, 36, 1, 1, 0,100, 65, 1, + 0,128, 1, 0, 0,193, 1, 0, 0, 3, 2, 0, 5,197, 66, 0, 0,198,130,192, + 5,156, 65, 0, 3,128, 1, 0, 0,193,193, 0, 0,156, 65, 0, 1,128, 1, 0, + 0,193, 1, 1, 0,156, 65, 0, 1,128, 1, 0, 0,193, 65, 1, 0,156, 65, 0, + 1,128, 1, 0, 0,193,129, 1, 0, 1,194, 1, 0, 64, 2,128, 2,133, 66, 0, + 0,134, 2, 66, 5,197, 66, 0, 0,198, 66,194, 5,156, 65, 0, 3,128, 1, 0, + 0,193,129, 2, 0,156, 65, 0, 1,128, 1, 0, 0,193,193, 2, 0, 3, 2, 0, + 5,197, 66, 0, 0,198, 2,195, 5,156, 65, 0, 3,128, 1, 0, 0,193, 65, 3, + 0, 3, 2,128, 4,133, 66, 0, 0,134,130, 67, 5,195, 2,128, 5,156, 65, 0, + 3,133, 65, 0, 0,228,129, 1, 0,137,193,129,135,133, 65, 0, 0,228,193, 1, + 0,137,193, 1,136,128, 1, 0, 0,193, 65, 4, 0, 36, 2, 2, 0,100, 66, 2, + 0,156, 65, 0, 2,133, 65, 0, 0,228,129, 2, 0,137,193, 1,137,128, 1,128, + 0,193,193, 4, 0,156, 65, 0, 1,133, 65, 0, 0,228,193, 2, 0,137,193, 1, +138,133, 65, 0, 0,228, 1, 3, 0,137,193,129,138,128, 1, 0, 0,193,129, 5, + 0,156, 65, 0, 1,128, 1, 0, 0,193,193, 5, 0, 36, 66, 3, 0,100,130, 3, + 0,156, 65, 0, 2,128, 1, 0, 0,193, 1, 6, 0,156, 65, 0, 1,128, 1, 0, + 0,193, 65, 6, 0,156, 65, 0, 1,128, 1, 0, 0,193,129, 6, 0,156, 65, 0, + 1,128, 1, 0, 0,193,193, 6, 0,156, 65, 0, 1,128, 1, 0, 0,193, 1, 7, + 0,156, 65, 0, 1,128, 1, 0, 0,193, 65, 7, 0,156, 65, 0, 1,128, 1, 0, + 0,193,129, 7, 0,156, 65, 0, 1,128, 1, 0, 0,193,193, 7, 0,156, 65, 0, + 1,128, 1, 0, 0,193, 1, 8, 0,156, 65, 0, 1,128, 1, 0, 0,193, 65, 8, + 0,156, 65, 0, 1,128, 1, 0, 0,193,129, 8, 0,156, 65, 0, 1,128, 1, 0, + 0,193,193, 8, 0,156, 65, 0, 1,128, 1, 0, 0,193, 1, 9, 0,156, 65, 0, + 1,128, 1, 0, 0,193, 65, 9, 0,156, 65, 0, 1,128, 1, 0, 0,193,129, 9, + 0,156, 65, 0, 1,128, 1, 0, 0,193,193, 9, 0,156, 65, 0, 1,128, 1, 0, + 0,193, 1, 10, 0,156, 65, 0, 1,128, 1, 0, 0,193, 65, 10, 0,156, 65, 0, + 1,128, 1, 0, 0,193,129, 10, 0,156, 65, 0, 1,128, 1, 0, 0,193,193, 10, + 0,156, 65, 0, 1,128, 1, 0, 0,193, 1, 11, 0,156, 65, 0, 1,128, 1, 0, + 0,193, 65, 11, 0,156, 65, 0, 1,128, 1, 0, 0,193,129, 11, 0,156, 65, 0, + 1,128, 1, 0, 0,193,193, 11, 0,156, 65, 0, 1,128, 1, 0, 0,193, 1, 12, + 0,156, 65, 0, 1,128, 1, 0, 0,193, 65, 12, 0,156, 65, 0, 1,128, 1, 0, + 0,193,129, 12, 0,156, 65, 0, 1,128, 1, 0, 0,193,193, 12, 0,156, 65, 0, + 1,128, 1, 0, 0,193, 1, 13, 0,156, 65, 0, 1,128, 1, 0, 0,193, 65, 13, + 0,156, 65, 0, 1,128, 1, 0, 0,193,129, 13, 0,156, 65, 0, 1,128, 1, 0, + 0,193,193, 13, 0,156, 65, 0, 1,128, 1,128, 1,193, 1, 14, 0, 3, 2, 0, + 4,100,194, 3, 0,156, 65, 0, 2,133, 65, 0, 0,228, 1, 4, 0,137,193,129, +156,164, 65, 4, 0,192, 1, 0, 0, 1,130, 14, 0, 67, 2,128, 5, 0, 3, 0, + 3,220, 65, 0, 3,192, 1, 0, 0, 1,194, 14, 0, 67, 2,128, 5, 0, 3, 0, + 3,220, 65, 0, 3,192, 1, 0, 0, 1, 2, 15, 0,220, 65, 0, 1,192, 1, 0, + 0, 1, 66, 15, 0,220, 65, 0, 1,192, 1, 0, 0, 1,130, 15, 0,220, 65, 0, + 1,192, 1, 0, 0, 1,194, 15, 0,220, 65, 0, 1,192, 1, 0, 0, 1, 2, 16, + 0,220, 65, 0, 1,192, 1, 0, 0, 1, 66, 16, 0,220, 65, 0, 1,192, 1,128, + 0, 1,130, 16, 0,220, 65, 0, 1,192, 1, 0, 0, 1,194, 16, 0,220, 65, 0, + 1,192, 1, 0, 0, 1, 2, 17, 0,220, 65, 0, 1,192, 1,128, 0, 1, 66, 17, + 0,220, 65, 0, 1,197, 65, 0, 0, 36,130, 4, 0,201, 1, 2,163,192, 1,128, + 0, 1,194, 17, 0,220, 65, 0, 1,192, 1, 0, 1, 1, 2, 18, 0,220, 65, 0, + 1,192, 1,128, 1, 1, 66, 18, 0,220, 65, 0, 1,192, 1,128, 0, 1,130, 18, + 0, 67, 2,128, 5, 5, 67, 0, 0, 6,195, 82, 6,220, 65, 0, 3,197, 65, 0, + 0, 36,194, 4, 0,201, 1, 2,166,197, 65, 0, 0, 36, 2, 5, 0,201, 1,130, +166,192, 1,128, 0, 1,130, 19, 0,220, 65, 0, 1,192, 1, 0, 0, 1,194, 19, + 0,220, 65, 0, 1,192, 1, 0, 0, 1, 2, 20, 0, 67, 2, 0, 5,197, 66, 0, + 0,198, 66,212, 5, 3, 3, 0, 6,220, 65, 0, 3,192, 1, 0, 0, 1,130, 20, + 0,220, 65, 0, 1,192, 1, 0, 0, 1,194, 20, 0,220, 65, 0, 1,192, 1, 0, + 0, 1, 2, 21, 0,220, 65, 0, 1,197, 65, 0, 0, 36, 66, 5, 0,201, 1,130, +170,192, 1, 0, 2, 1,130, 21, 0, 67, 2, 0, 5,197, 66, 0, 0,198, 2,194, + 5, 5, 67, 0, 0, 6, 3, 67, 6,220, 65, 0, 3,192, 1, 0, 1, 1,194, 21, + 0, 67, 2, 0, 5,197, 66, 0, 0,198, 2,214, 5, 5, 67, 0, 0, 6, 67, 86, + 6,220, 65, 0, 3,197, 65, 0, 0, 36,130, 5, 0,201, 1, 2,173,197, 65, 0, + 0, 36,194, 5, 0,201, 1,130,173,192, 1, 0, 0, 1, 2, 23, 0, 67, 2,128, + 5, 5, 67, 0, 0, 6, 3, 67, 6,220, 65, 0, 3,192, 1, 0, 0, 1, 66, 23, + 0,220, 65, 0, 1,192, 1,128, 0, 1,130, 23, 0,220, 65, 0, 1,192, 1, 0, + 0, 1,194, 23, 0,220, 65, 0, 1,192, 1, 0, 0, 1, 2, 24, 0,220, 65, 0, + 1,192, 1, 0, 0, 1, 66, 24, 0,220, 65, 0, 1,192, 1, 0, 0, 1,130, 24, + 0,220, 65, 0, 1,192, 1, 0, 0, 1,194, 24, 0, 67, 2,128, 5, 5, 67, 0, + 0, 6, 67, 86, 6,220, 65, 0, 3,192, 1, 0, 0, 1, 2, 25, 0, 67, 2,128, + 5, 5, 67, 0, 0, 6, 67, 86, 6,220, 65, 0, 3,192, 1, 0, 0, 1, 66, 25, + 0,220, 65, 0, 1,192, 1, 0, 0, 1,130, 25, 0, 67, 2, 0, 5,197, 66, 0, + 0,198,130,195, 5, 3, 3, 0, 6,220, 65, 0, 3,192, 1, 0, 0, 1,194, 25, + 0, 67, 2, 0, 5,197, 66, 0, 0,198,130,195, 5, 3, 3, 0, 6,220, 65, 0, + 3,192, 1, 0, 0, 1, 2, 26, 0, 67, 2, 0, 5,197, 66, 0, 0,198,130,195, + 5, 3, 3, 0, 6,220, 65, 0, 3,192, 1,128, 0, 1, 66, 26, 0,220, 65, 0, + 1,192, 1, 0, 0, 1,130, 26, 0, 67, 2, 0, 5,197, 66, 0, 0,198,130,195, + 5, 3, 3, 0, 6,220, 65, 0, 3,192, 1, 0, 0, 1,194, 26, 0, 67, 2, 0, + 5,197, 66, 0, 0,198,130,195, 5, 3, 3, 0, 6,220, 65, 0, 3,192, 1, 0, + 0, 1, 2, 27, 0,220, 65, 0, 1,192, 1, 0, 0, 1, 66, 27, 0,220, 65, 0, + 1,192, 1, 0, 0, 1,130, 27, 0,220, 65, 0, 1,192, 1, 0, 0, 1,194, 27, + 0, 67, 2, 0, 5,197, 66, 0, 0,198,130,195, 5, 3, 3, 0, 6,220, 65, 0, + 3,192, 1, 0, 0, 1, 2, 28, 0, 67, 2, 0, 5,197, 66, 0, 0,198,130,195, + 5, 3, 3, 0, 6,220, 65, 0, 3,192, 1, 0, 0, 1, 66, 28, 0,220, 65, 0, + 1,192, 1, 0, 0, 1,130, 28, 0,220, 65, 0, 1, 30, 0,128, 0,115, 0, 0, + 0, 4, 19, 0, 0, 0, 0, 0, 0, 0, 65,110, 97,108,121,122,101, 70,105,110, +100, 82,101,103,105,111,110,115, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, + 0, 4, 7, 0, 0, 0, 0, 0, 0, 0, 85, 83, 72, 79, 82, 84, 0, 4, 21, 0, + 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 80,101,114,105,109,101,116, +101,114, 76,105,110,101, 0, 4, 20, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99, +101,115,115, 82,101,109,111,118,101, 66,121, 65,114,101, 97, 0, 4, 17, 0, 0, + 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 70,105,108,108, 72,111,108,101, +115, 0, 4, 18, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 72,111, +117,103,104, 76,105,110,101,115, 0, 3, 0, 0, 0, 0, 0,128,102, 64, 4, 5, + 0, 0, 0, 0, 0, 0, 0, 71, 82, 65, 89, 0, 4, 4, 0, 0, 0, 0, 0, 0, + 0, 73, 78, 84, 0, 4, 22, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115, +115, 72,111,117,103,104, 76,105,110,101,115, 68,114, 97,119, 0, 4, 25, 0, 0, + 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 68,105,115,116, 97,110, 99,101, + 84,114, 97,110,115,102,111,114,109, 0, 4, 6, 0, 0, 0, 0, 0, 0, 0, 70, + 76, 79, 65, 84, 0, 4, 23, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115, +115, 82,101,103,105,111,110, 97,108, 77, 97,120,105,109,117,109, 0, 4, 7, 0, + 0, 0, 0, 0, 0, 0, 66, 73, 78, 65, 82, 89, 0, 4, 17, 0, 0, 0, 0, 0, + 0, 0, 80,114,111, 99,101,115,115, 82,101,100,117, 99,101, 78,101,119, 0, 4, + 17, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 82,101,115,105,122, +101, 78,101,119, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115, +115, 82,101,100,117, 99,101, 66,121, 52, 0, 4, 15, 0, 0, 0, 0, 0, 0, 0, + 80,114,111, 99,101,115,115, 67,114,111,112, 78,101,119, 0, 4, 14, 0, 0, 0, + 0, 0, 0, 0, 80,114,111, 99,101,115,115, 73,110,115,101,114,116, 0, 4, 21, + 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 65,100,100, 77, 97,114, +103,105,110,115, 78,101,119, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 80,114,111, + 99,101,115,115, 82,111,116, 97,116,101, 78,101,119, 0, 4, 17, 0, 0, 0, 0, + 0, 0, 0, 80,114,111, 99,101,115,115, 82,111,116, 97,116,101, 82,101,102, 0, + 4, 16, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 82,111,116, 97, +116,101, 57, 48, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115, +115, 82,111,116, 97,116,101, 49, 56, 48, 0, 4, 14, 0, 0, 0, 0, 0, 0, 0, + 80,114,111, 99,101,115,115, 77,105,114,114,111,114, 0, 4, 12, 0, 0, 0, 0, + 0, 0, 0, 80,114,111, 99,101,115,115, 70,108,105,112, 0, 4, 14, 0, 0, 0, + 0, 0, 0, 0, 80,114,111, 99,101,115,115, 82, 97,100,105, 97,108, 0, 4, 25, + 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 71,114, 97,121, 77,111, +114,112,104, 67,111,110,118,111,108,118,101, 0, 4, 22, 0, 0, 0, 0, 0, 0, + 0, 80,114,111, 99,101,115,115, 71,114, 97,121, 77,111,114,112,104, 69,114,111, +100,101, 0, 4, 23, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 71, +114, 97,121, 77,111,114,112,104, 68,105,108, 97,116,101, 0, 4, 21, 0, 0, 0, + 0, 0, 0, 0, 80,114,111, 99,101,115,115, 71,114, 97,121, 77,111,114,112,104, + 79,112,101,110, 0, 4, 22, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115, +115, 71,114, 97,121, 77,111,114,112,104, 67,108,111,115,101, 0, 4, 23, 0, 0, + 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 71,114, 97,121, 77,111,114,112, +104, 84,111,112, 72, 97,116, 0, 4, 21, 0, 0, 0, 0, 0, 0, 0, 80,114,111, + 99,101,115,115, 71,114, 97,121, 77,111,114,112,104, 87,101,108,108, 0, 4, 25, + 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 71,114, 97,121, 77,111, +114,112,104, 71,114, 97,100,105,101,110,116, 0, 4, 24, 0, 0, 0, 0, 0, 0, + 0, 80,114,111, 99,101,115,115, 66,105,110, 77,111,114,112,104, 67,111,110,118, +111,108,118,101, 0, 4, 21, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115, +115, 66,105,110, 77,111,114,112,104, 69,114,111,100,101, 0, 4, 22, 0, 0, 0, + 0, 0, 0, 0, 80,114,111, 99,101,115,115, 66,105,110, 77,111,114,112,104, 68, +105,108, 97,116,101, 0, 4, 20, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101, +115,115, 66,105,110, 77,111,114,112,104, 79,112,101,110, 0, 4, 21, 0, 0, 0, + 0, 0, 0, 0, 80,114,111, 99,101,115,115, 66,105,110, 77,111,114,112,104, 67, +108,111,115,101, 0, 4, 23, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115, +115, 66,105,110, 77,111,114,112,104, 79,117,116,108,105,110,101, 0, 4, 20, 0, + 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 66,105,110, 77,111,114,112, +104, 84,104,105,110, 0, 4, 22, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101, +115,115, 77,101,100,105, 97,110, 67,111,110,118,111,108,118,101, 0, 4, 21, 0, + 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 82, 97,110,103,101, 67,111, +110,118,111,108,118,101, 0, 4, 27, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99, +101,115,115, 82, 97,110,107, 67,108,111,115,101,115,116, 67,111,110,118,111,108, +118,101, 0, 4, 23, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 82, + 97,110,107, 77, 97,120, 67,111,110,118,111,108,118,101, 0, 4, 23, 0, 0, 0, + 0, 0, 0, 0, 80,114,111, 99,101,115,115, 82, 97,110,107, 77,105,110, 67,111, +110,118,111,108,118,101, 0, 4, 16, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99, +101,115,115, 67,111,110,118,111,108,118,101, 0, 4, 19, 0, 0, 0, 0, 0, 0, + 0, 80,114,111, 99,101,115,115, 67,111,110,118,111,108,118,101, 83,101,112, 0, + 4, 19, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 67,111,110,118, +111,108,118,101, 82,101,112, 0, 4, 20, 0, 0, 0, 0, 0, 0, 0, 80,114,111, + 99,101,115,115, 67,111,110,118,111,108,118,101, 68,117, 97,108, 0, 4, 23, 0, + 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 67,111,109,112, 97,115,115, + 67,111,110,118,111,108,118,101, 0, 4, 20, 0, 0, 0, 0, 0, 0, 0, 80,114, +111, 99,101,115,115, 77,101, 97,110, 67,111,110,118,111,108,118,101, 0, 4, 24, + 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 71, 97,117,115,115,105, + 97,110, 67,111,110,118,111,108,118,101, 0, 4, 23, 0, 0, 0, 0, 0, 0, 0, + 80,114,111, 99,101,115,115, 66, 97,114,108,101,116,116, 67,111,110,118,111,108, +118,101, 0, 4, 22, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 73, +110,116,101,114,108, 97, 99,101, 83,112,108,105,116, 0, 4, 25, 0, 0, 0, 0, + 0, 0, 0, 80,114,111, 99,101,115,115, 73,110,116,101,114,108, 97, 99,101, 83, +112,108,105,116, 78,101,119, 0, 4, 30, 0, 0, 0, 0, 0, 0, 0, 80,114,111, + 99,101,115,115, 68,105,102,102, 79,102, 71, 97,117,115,115,105, 97,110, 67,111, +110,118,111,108,118,101, 0, 4, 29, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99, +101,115,115, 76, 97,112, 79,102, 71, 97,117,115,115,105, 97,110, 67,111,110,118, +111,108,118,101, 0, 4, 21, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115, +115, 83,111, 98,101,108, 67,111,110,118,111,108,118,101, 0, 4, 26, 0, 0, 0, + 0, 0, 0, 0, 80,114,111, 99,101,115,115, 83,112,108,105,110,101, 69,100,103, +101, 67,111,110,118,111,108,118,101, 0, 4, 23, 0, 0, 0, 0, 0, 0, 0, 80, +114,111, 99,101,115,115, 80,114,101,119,105,116,116, 67,111,110,118,111,108,118, +101, 0, 4, 20, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 90,101, +114,111, 67,114,111,115,115,105,110,103, 0, 4, 13, 0, 0, 0, 0, 0, 0, 0, + 80,114,111, 99,101,115,115, 67, 97,110,110,121, 0, 4, 22, 0, 0, 0, 0, 0, + 0, 0, 80,114,111, 99,101,115,115, 85,110, 65,114,105,116,104,109,101,116,105, + 99, 79,112, 0, 4, 20, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, + 65,114,105,116,104,109,101,116,105, 99, 79,112, 0, 4, 15, 0, 0, 0, 0, 0, + 0, 0, 80,114,111, 99,101,115,115, 85,110,115,104, 97,114,112, 0, 4, 13, 0, + 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 83,104, 97,114,112, 0, 4, + 19, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 83,104, 97,114,112, + 75,101,114,110,101,108, 0, 4, 28, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99, +101,115,115, 65,114,105,116,104,109,101,116,105, 99, 67,111,110,115,116, 79,112, + 78,101,119, 0, 4, 18, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, + 66,108,101,110,100, 67,111,110,115,116, 0, 4, 13, 0, 0, 0, 0, 0, 0, 0, + 80,114,111, 99,101,115,115, 66,108,101,110,100, 0, 4, 20, 0, 0, 0, 0, 0, + 0, 0, 80,114,111, 99,101,115,115, 83,112,108,105,116, 67,111,109,112,108,101, +120, 0, 4, 20, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 77,101, +114,103,101, 67,111,109,112,108,101,120, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0, + 67, 70, 76, 79, 65, 84, 0, 4, 23, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99, +101,115,115, 77,117,108,116,105,112,108,101, 77,101, 97,110, 78,101,119, 0, 4, + 25, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 77,117,108,116,105, +112,108,101, 83,116,100, 68,101,118, 78,101,119, 0, 4, 22, 0, 0, 0, 0, 0, + 0, 0, 80,114,111, 99,101,115,115, 65,117,116,111, 67,111,118, 97,114,105, 97, +110, 99,101, 0, 4, 20, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, + 77,117,108,116,105,112,108,121, 67,111,110,106, 0, 4, 26, 0, 0, 0, 0, 0, + 0, 0, 80,114,111, 99,101,115,115, 81,117, 97,110,116,105,122,101, 82, 71, 66, + 85,110,105,102,111,114,109, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 77, 65, 80, + 0, 4, 27, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 81,117, 97, +110,116,105,122,101, 71,114, 97,121, 85,110,105,102,111,114,109, 0, 4, 23, 0, + 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 69,120,112, 97,110,100, 72, +105,115,116,111,103,114, 97,109, 0, 4, 25, 0, 0, 0, 0, 0, 0, 0, 80,114, +111, 99,101,115,115, 69,113,117, 97,108,105,122,101, 72,105,115,116,111,103,114, + 97,109, 0, 4, 23, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 83, +112,108,105,116, 89, 67,104,114,111,109, 97, 78,101,119, 0, 4, 16, 0, 0, 0, + 0, 0, 0, 0, 80,114,111, 99,101,115,115, 83,112,108,105,116, 72, 83, 73, 0, + 4, 16, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 77,101,114,103, +101, 72, 83, 73, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 82, 71, 66, 0, 4, 5, + 0, 0, 0, 0, 0, 0, 0, 66, 89, 84, 69, 0, 4, 26, 0, 0, 0, 0, 0, 0, + 0, 80,114,111, 99,101,115,115, 83,112,108,105,116, 67,111,109,112,111,110,101, +110,116,115, 78,101,119, 0, 4, 26, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99, +101,115,115, 77,101,114,103,101, 67,111,109,112,111,110,101,110,116,115, 78,101, +119, 0, 4, 27, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 78,111, +114,109, 97,108,105,122,101, 67,111,109,112,111,110,101,110,116,115, 0, 4, 20, + 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 82,101,112,108, 97, 99, +101, 67,111,108,111,114, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99, +101,115,115, 66,105,116,119,105,115,101, 79,112, 0, 4, 18, 0, 0, 0, 0, 0, + 0, 0, 80,114,111, 99,101,115,115, 66,105,116,119,105,115,101, 78,111,116, 0, + 4, 15, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 66,105,116, 77, + 97,115,107, 0, 4, 16, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, + 66,105,116, 80,108, 97,110,101, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 80,114, +111, 99,101,115,115, 84,111,110,101, 71, 97,109,117,116, 0, 4, 19, 0, 0, 0, + 0, 0, 0, 0, 80,114,111, 99,101,115,115, 85,110, 78,111,114,109, 97,108,105, +122,101, 0, 4, 18, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 68, +105,114,101, 99,116, 67,111,110,118, 0, 4, 16, 0, 0, 0, 0, 0, 0, 0, 80, +114,111, 99,101,115,115, 78,101,103, 97,116,105,118,101, 0, 4, 30, 0, 0, 0, + 0, 0, 0, 0, 80,114,111, 99,101,115,115, 82, 97,110,103,101, 67,111,110,116, +114, 97,115,116, 84,104,114,101,115,104,111,108,100, 0, 4, 25, 0, 0, 0, 0, + 0, 0, 0, 80,114,111, 99,101,115,115, 76,111, 99, 97,108, 77, 97,120, 84,104, +114,101,115,104,111,108,100, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 80,114,111, + 99,101,115,115, 84,104,114,101,115,104,111,108,100, 0, 4, 23, 0, 0, 0, 0, + 0, 0, 0, 80,114,111, 99,101,115,115, 84,104,114,101,115,104,111,108,100, 66, +121, 68,105,102,102, 0, 4, 27, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101, +115,115, 72,121,115,116,101,114,101,115,105,115, 84,104,114,101,115,104,111,108, +100, 0, 4, 27, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 85,110, +105,102,111,114,109, 69,114,114, 84,104,114,101,115,104,111,108,100, 0, 4, 28, + 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 68,105,102,117,115,105, +111,110, 69,114,114, 84,104,114,101,115,104,111,108,100, 0, 4, 24, 0, 0, 0, + 0, 0, 0, 0, 80,114,111, 99,101,115,115, 80,101,114, 99,101,110,116, 84,104, +114,101,115,104,111,108,100, 0, 4, 21, 0, 0, 0, 0, 0, 0, 0, 80,114,111, + 99,101,115,115, 79,116,115,117, 84,104,114,101,115,104,111,108,100, 0, 4, 23, + 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 77,105,110, 77, 97,120, + 84,104,114,101,115,104,111,108,100, 0, 4, 22, 0, 0, 0, 0, 0, 0, 0, 80, +114,111, 99,101,115,115, 83,108,105, 99,101, 84,104,114,101,115,104,111,108,100, + 0, 4, 16, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 80,105,120, +101,108, 97,116,101, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101, +115,115, 80,111,115,116,101,114,105,122,101, 0, 24, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 8, 0, 0, 0, 25, 0, 0, 0, 0, 5, 0, 9, 17, 0, 0, 0, + 69, 1, 0, 0, 70, 1,128, 2,133, 65, 0, 0,192, 1,128, 2,156, 65, 0, 1, +133, 1, 0, 0,192, 1, 0, 0, 1,130, 0, 0,213, 1,130, 3, 36, 2, 0, 0, + 0, 0,128, 0, 0, 0, 0, 1, 0, 0,128, 1, 0, 0, 0, 2, 0, 0,128, 2, +137, 1,130, 3, 30, 0,128, 0, 3, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, + 0,105,109, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0, 97,115,115,101,114,116, 0, + 4, 4, 0, 0, 0, 0, 0, 0, 0, 78,101,119, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 13, 0, 0, 0, 24, 0, 0, 0, 5, 1, 7, 8, 23, 0, 0, + 0,133, 0, 0, 0,134, 64, 64, 1,192, 0, 0, 0, 4, 1, 0, 0, 68, 1,128, + 0,132, 1, 0, 1,196, 1,128, 1,156,128, 0, 3,196, 0, 0, 2, 0, 1, 0, + 0, 64, 1, 0, 1,133,129, 0, 0,192, 1,128, 0,156, 1, 0, 1,220,128, 0, + 0,218, 0, 0, 0, 22,192, 0,128, 0, 1,128, 1, 64, 1, 0, 1, 30, 1,128, + 1, 22, 0, 0,128,158, 0, 0, 1, 30, 0,128, 0, 3, 0, 0, 0, 4, 3, 0, + 0, 0, 0, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 73,109, + 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 4, 7, 0, 0, 0, + 0, 0, 0, 0,117,110,112, 97, 99,107, 0, 0, 0, 0, 0, 23, 0, 0, 0, 15, + 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, + 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 18, 0, 0, 0, 18, 0, 0, 0, 18, + 0, 0, 0, 18, 0, 0, 0, 18, 0, 0, 0, 18, 0, 0, 0, 18, 0, 0, 0, 19, + 0, 0, 0, 19, 0, 0, 0, 20, 0, 0, 0, 20, 0, 0, 0, 20, 0, 0, 0, 20, + 0, 0, 0, 22, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 10, 0, 0, 0, 0, + 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 22, 0, 0, + 0, 4, 0, 0, 0, 0, 0, 0, 0, 97,114,103, 0, 0, 0, 0, 0, 22, 0, 0, + 0, 10, 0, 0, 0, 0, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 0, 8, + 0, 0, 0, 22, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0,114,101,116, 0, 15, + 0, 0, 0, 22, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119, +105,100,116,104, 0, 7, 0, 0, 0, 0, 0, 0, 0,104,101,105,103,104,116, 0, + 12, 0, 0, 0, 0, 0, 0, 0, 99,111,108,111,114, 95,115,112, 97, 99,101, 0, + 10, 0, 0, 0, 0, 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, 0, 5, 0, + 0, 0, 0, 0, 0, 0,102,117,110, 99, 0, 17, 0, 0, 0, 9, 0, 0, 0, 9, + 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 13, 0, 0, 0, 13, + 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, + 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 25, + 0, 0, 0, 6, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,102,117,110, 99,110, + 97,109,101, 0, 0, 0, 0, 0, 16, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, +119,105,100,116,104, 0, 0, 0, 0, 0, 16, 0, 0, 0, 7, 0, 0, 0, 0, 0, + 0, 0,104,101,105,103,104,116, 0, 0, 0, 0, 0, 16, 0, 0, 0, 12, 0, 0, + 0, 0, 0, 0, 0, 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 0, 0, 0, + 0, 16, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,100, 97,116, 97, 95,116,121, +112,101, 0, 0, 0, 0, 0, 16, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,102, +117,110, 99, 0, 2, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 31, 0, 0, 0, 50, 0, 0, 0, 0, 5, 0, 11, 22, 0, 0, 0, + 69, 1, 0, 0, 70, 1,128, 2,133, 65, 0, 0,192, 1,128, 2, 5,130, 0, 0, + 6,194, 64, 4, 65, 2, 1, 0,128, 2, 0, 0, 28, 2,128, 1,156, 65, 0, 0, +133, 1, 0, 0,192, 1, 0, 0, 1, 66, 1, 0,213, 1,130, 3, 36, 2, 0, 0, + 0, 0,128, 0, 0, 0, 0, 1, 0, 0,128, 1, 0, 0, 0, 2, 0, 0,128, 2, +137, 1,130, 3, 30, 0,128, 0, 6, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, + 0,105,109, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0, 97,115,115,101,114,116, 0, + 4, 7, 0, 0, 0, 0, 0, 0, 0,115,116,114,105,110,103, 0, 4, 7, 0, 0, + 0, 0, 0, 0, 0,102,111,114,109, 97,116, 0, 4, 24, 0, 0, 0, 0, 0, 0, + 0,117,110,100,101,102,105,110,101,100, 32,102,117,110, 99,116,105,111,110, 32, + 96, 37,115, 39, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 78,101,119, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, 49, 0, 0, 0, 5, 2, + 7, 10, 24, 0, 0, 0,197, 0, 0, 0,198, 64,192, 1, 0, 1, 0, 0, 68, 1, + 0, 0,132, 1,128, 0,196, 1, 0, 1, 4, 2,128, 1,220,128, 0, 3, 4, 1, + 0, 2, 64, 1, 0, 0,128, 1,128, 0,192, 1,128, 1, 5,130, 0, 0, 64, 2, + 0, 1, 28, 2, 0, 1, 28,129, 0, 0, 26, 1, 0, 0, 22,192, 0,128, 64, 1, + 0, 2,128, 1,128, 1, 94, 1,128, 1, 22, 0, 0,128,222, 0, 0, 1, 30, 0, +128, 0, 3, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 17, + 0, 0, 0, 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97, +115,101,100, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0,117,110,112, 97, 99,107, 0, + 0, 0, 0, 0, 24, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, + 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, + 43, 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, + 43, 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, 44, 0, 0, 0, 44, 0, 0, 0, + 45, 0, 0, 0, 45, 0, 0, 0, 45, 0, 0, 0, 45, 0, 0, 0, 47, 0, 0, 0, + 49, 0, 0, 0, 5, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0,115,114, 99, 95, +105,109, 97,103,101, 49, 0, 0, 0, 0, 0, 23, 0, 0, 0, 11, 0, 0, 0, 0, + 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 50, 0, 0, 0, 0, 0, 23, 0, + 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 97,114,103, 0, 0, 0, 0, 0, 23, 0, + 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 0, + 8, 0, 0, 0, 23, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0,114,101,116, 0, + 16, 0, 0, 0, 23, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, +119,105,100,116,104, 0, 7, 0, 0, 0, 0, 0, 0, 0,104,101,105,103,104,116, + 0, 12, 0, 0, 0, 0, 0, 0, 0, 99,111,108,111,114, 95,115,112, 97, 99,101, + 0, 10, 0, 0, 0, 0, 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, 0, 5, + 0, 0, 0, 0, 0, 0, 0,102,117,110, 99, 0, 22, 0, 0, 0, 32, 0, 0, 0, + 32, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, + 35, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, 38, 0, 0, 0, + 38, 0, 0, 0, 38, 0, 0, 0, 38, 0, 0, 0, 49, 0, 0, 0, 49, 0, 0, 0, + 49, 0, 0, 0, 49, 0, 0, 0, 49, 0, 0, 0, 49, 0, 0, 0, 49, 0, 0, 0, + 50, 0, 0, 0, 6, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,102,117,110, 99, +110, 97,109,101, 0, 0, 0, 0, 0, 21, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, + 0,119,105,100,116,104, 0, 0, 0, 0, 0, 21, 0, 0, 0, 7, 0, 0, 0, 0, + 0, 0, 0,104,101,105,103,104,116, 0, 0, 0, 0, 0, 21, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 0, 0, + 0, 0, 21, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,100, 97,116, 97, 95,116, +121,112,101, 0, 0, 0, 0, 0, 21, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, +102,117,110, 99, 0, 2, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 56, 0, 0, 0, 73, 0, 0, 0, 0, 5, 0, 9, 17, 0, 0, + 0, 69, 1, 0, 0, 70, 1,128, 2,133, 65, 0, 0,192, 1,128, 2,156, 65, 0, + 1,133, 1, 0, 0,192, 1, 0, 0, 1,130, 0, 0,213, 1,130, 3, 36, 2, 0, + 0, 0, 0,128, 0, 0, 0, 0, 1, 0, 0,128, 1, 0, 0, 0, 2, 0, 0,128, + 2,137, 1,130, 3, 30, 0,128, 0, 3, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, + 0, 0,105,109, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0, 97,115,115,101,114,116, + 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 78,101,119, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 61, 0, 0, 0, 72, 0, 0, 0, 5, 3, 7, 12, 25, 0, + 0, 0, 5, 1, 0, 0, 6, 65, 64, 2, 64, 1, 0, 0,132, 1, 0, 0,196, 1, +128, 0, 4, 2, 0, 1, 68, 2,128, 1, 28,129, 0, 3, 68, 1, 0, 2,128, 1, + 0, 0,192, 1,128, 0, 0, 2, 0, 1, 64, 2, 0, 2,133,130, 0, 0,192, 2, +128, 1,156, 2, 0, 1, 92,129, 0, 0, 90, 1, 0, 0, 22,192, 0,128,128, 1, +128, 2,192, 1, 0, 2,158, 1,128, 1, 22, 0, 0,128, 30, 1, 0, 1, 30, 0, +128, 0, 3, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 17, + 0, 0, 0, 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97, +115,101,100, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0,117,110,112, 97, 99,107, 0, + 0, 0, 0, 0, 25, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, + 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, + 66, 0, 0, 0, 66, 0, 0, 0, 66, 0, 0, 0, 66, 0, 0, 0, 66, 0, 0, 0, + 66, 0, 0, 0, 66, 0, 0, 0, 66, 0, 0, 0, 66, 0, 0, 0, 67, 0, 0, 0, + 67, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, + 70, 0, 0, 0, 72, 0, 0, 0, 6, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, +115,114, 99, 95,105,109, 97,103,101, 49, 0, 0, 0, 0, 0, 24, 0, 0, 0, 11, + 0, 0, 0, 0, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 50, 0, 0, 0, + 0, 0, 24, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0,115,114, 99, 95,105,109, + 97,103,101, 51, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, + 0, 97,114,103, 0, 0, 0, 0, 0, 24, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, + 0,100,115,116, 95,105,109, 97,103,101, 0, 8, 0, 0, 0, 24, 0, 0, 0, 4, + 0, 0, 0, 0, 0, 0, 0,114,101,116, 0, 17, 0, 0, 0, 24, 0, 0, 0, 5, + 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119,105,100,116,104, 0, 7, 0, 0, + 0, 0, 0, 0, 0,104,101,105,103,104,116, 0, 12, 0, 0, 0, 0, 0, 0, 0, + 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 10, 0, 0, 0, 0, 0, 0, 0, +100, 97,116, 97, 95,116,121,112,101, 0, 5, 0, 0, 0, 0, 0, 0, 0,102,117, +110, 99, 0, 17, 0, 0, 0, 57, 0, 0, 0, 57, 0, 0, 0, 58, 0, 0, 0, 58, + 0, 0, 0, 58, 0, 0, 0, 61, 0, 0, 0, 61, 0, 0, 0, 61, 0, 0, 0, 61, + 0, 0, 0, 72, 0, 0, 0, 72, 0, 0, 0, 72, 0, 0, 0, 72, 0, 0, 0, 72, + 0, 0, 0, 72, 0, 0, 0, 72, 0, 0, 0, 73, 0, 0, 0, 6, 0, 0, 0, 9, + 0, 0, 0, 0, 0, 0, 0,102,117,110, 99,110, 97,109,101, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119,105,100,116,104, 0, 0, 0, + 0, 0, 16, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0,104,101,105,103,104,116, + 0, 0, 0, 0, 0, 16, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 99,111,108, +111,114, 95,115,112, 97, 99,101, 0, 0, 0, 0, 0, 16, 0, 0, 0, 10, 0, 0, + 0, 0, 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, 0, 0, 0, 0, 0, 16, + 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,102,117,110, 99, 0, 2, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 0, 0, 0, + 97, 0, 0, 0, 0, 5, 0, 9, 17, 0, 0, 0, 69, 1, 0, 0, 70, 1,128, 2, +133, 65, 0, 0,192, 1,128, 2,156, 65, 0, 1,133, 1, 0, 0,192, 1, 0, 0, + 1,130, 0, 0,213, 1,130, 3, 36, 2, 0, 0, 0, 0,128, 0, 0, 0, 0, 1, + 0, 0,128, 1, 0, 0, 0, 2, 0, 0,128, 2,137, 1,130, 3, 30, 0,128, 0, + 3, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 7, 0, 0, + 0, 0, 0, 0, 0, 97,115,115,101,114,116, 0, 4, 4, 0, 0, 0, 0, 0, 0, + 0, 78,101,119, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 0, 0, + 0, 96, 0, 0, 0, 5, 1, 7, 10, 35, 0, 0, 0,133, 0, 0, 0,134, 64, 64, + 1,192, 0, 0, 0, 4, 1, 0, 0, 68, 1,128, 0,132, 1, 0, 1,196, 1,128, + 1,156,128, 0, 3,197, 0, 0, 0,198, 64,192, 1, 0, 1, 0, 0, 68, 1, 0, + 0,132, 1,128, 0,196, 1, 0, 1, 4, 2,128, 1,220,128, 0, 3, 4, 1, 0, + 2, 64, 1, 0, 0,128, 1, 0, 1,192, 1,128, 1, 5,130, 0, 0, 64, 2,128, + 0, 28, 2, 0, 1, 28,129, 0, 0, 26, 1, 0, 0, 22, 0, 1,128, 64, 1, 0, + 2,128, 1, 0, 1,192, 1,128, 1, 94, 1, 0, 2, 22,128, 0,128, 64, 1, 0, + 1,128, 1,128, 1, 94, 1,128, 1, 30, 0,128, 0, 3, 0, 0, 0, 4, 3, 0, + 0, 0, 0, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 73,109, + 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 4, 7, 0, 0, 0, + 0, 0, 0, 0,117,110,112, 97, 99,107, 0, 0, 0, 0, 0, 35, 0, 0, 0, 86, + 0, 0, 0, 86, 0, 0, 0, 86, 0, 0, 0, 86, 0, 0, 0, 86, 0, 0, 0, 86, + 0, 0, 0, 86, 0, 0, 0, 86, 0, 0, 0, 87, 0, 0, 0, 87, 0, 0, 0, 87, + 0, 0, 0, 87, 0, 0, 0, 87, 0, 0, 0, 87, 0, 0, 0, 87, 0, 0, 0, 87, + 0, 0, 0, 90, 0, 0, 0, 90, 0, 0, 0, 90, 0, 0, 0, 90, 0, 0, 0, 90, + 0, 0, 0, 90, 0, 0, 0, 90, 0, 0, 0, 90, 0, 0, 0, 91, 0, 0, 0, 91, + 0, 0, 0, 92, 0, 0, 0, 92, 0, 0, 0, 92, 0, 0, 0, 92, 0, 0, 0, 92, + 0, 0, 0, 94, 0, 0, 0, 94, 0, 0, 0, 94, 0, 0, 0, 96, 0, 0, 0, 5, + 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, + 0, 0, 0, 0, 0, 34, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 97,114,103, + 0, 0, 0, 0, 0, 34, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0,100,115,116, + 95,105,109, 97,103,101, 49, 0, 8, 0, 0, 0, 34, 0, 0, 0, 11, 0, 0, 0, + 0, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 50, 0, 16, 0, 0, 0, 34, + 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0,114,101,116, 0, 24, 0, 0, 0, 34, + 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119,105,100,116,104, + 0, 7, 0, 0, 0, 0, 0, 0, 0,104,101,105,103,104,116, 0, 12, 0, 0, 0, + 0, 0, 0, 0, 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 10, 0, 0, 0, + 0, 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, 0, 5, 0, 0, 0, 0, 0, + 0, 0,102,117,110, 99, 0, 17, 0, 0, 0, 80, 0, 0, 0, 80, 0, 0, 0, 81, + 0, 0, 0, 81, 0, 0, 0, 81, 0, 0, 0, 84, 0, 0, 0, 84, 0, 0, 0, 84, + 0, 0, 0, 84, 0, 0, 0, 96, 0, 0, 0, 96, 0, 0, 0, 96, 0, 0, 0, 96, + 0, 0, 0, 96, 0, 0, 0, 96, 0, 0, 0, 96, 0, 0, 0, 97, 0, 0, 0, 6, + 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,102,117,110, 99,110, 97,109,101, 0, + 0, 0, 0, 0, 16, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119,105,100,116, +104, 0, 0, 0, 0, 0, 16, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0,104,101, +105,103,104,116, 0, 0, 0, 0, 0, 16, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, + 0, 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 0, 0, 0, 0, 16, 0, 0, + 0, 10, 0, 0, 0, 0, 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, 0, 0, + 0, 0, 0, 16, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,102,117,110, 99, 0, + 2, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +103, 0, 0, 0,122, 0, 0, 0, 0, 5, 0, 9, 17, 0, 0, 0, 69, 1, 0, 0, + 70, 1,128, 2,133, 65, 0, 0,192, 1,128, 2,156, 65, 0, 1,133, 1, 0, 0, +192, 1, 0, 0, 1,130, 0, 0,213, 1,130, 3, 36, 2, 0, 0, 0, 0,128, 0, + 0, 0, 0, 1, 0, 0,128, 1, 0, 0, 0, 2, 0, 0,128, 2,137, 1,130, 3, + 30, 0,128, 0, 3, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, + 4, 7, 0, 0, 0, 0, 0, 0, 0, 97,115,115,101,114,116, 0, 4, 4, 0, 0, + 0, 0, 0, 0, 0, 78,101,119, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0,108, 0, 0, 0,121, 0, 0, 0, 5, 1, 7, 12, 46, 0, 0, 0,133, 0, 0, + 0,134, 64, 64, 1,192, 0, 0, 0, 4, 1, 0, 0, 68, 1,128, 0,132, 1, 0, + 1,196, 1,128, 1,156,128, 0, 3,197, 0, 0, 0,198, 64,192, 1, 0, 1, 0, + 0, 68, 1, 0, 0,132, 1,128, 0,196, 1, 0, 1, 4, 2,128, 1,220,128, 0, + 3, 5, 1, 0, 0, 6, 65, 64, 2, 64, 1, 0, 0,132, 1, 0, 0,196, 1,128, + 0, 4, 2, 0, 1, 68, 2,128, 1, 28,129, 0, 3, 68, 1, 0, 2,128, 1, 0, + 0,192, 1, 0, 1, 0, 2,128, 1, 64, 2, 0, 2,133,130, 0, 0,192, 2,128, + 0,156, 2, 0, 1, 92,129, 0, 0, 90, 1, 0, 0, 22, 64, 1,128,128, 1,128, + 2,192, 1, 0, 1, 0, 2,128, 1, 64, 2, 0, 2,158, 1,128, 2, 22,192, 0, +128,128, 1, 0, 1,192, 1,128, 1, 0, 2, 0, 2,158, 1, 0, 2, 30, 0,128, + 0, 3, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 17, 0, + 0, 0, 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115, +101,100, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0,117,110,112, 97, 99,107, 0, 0, + 0, 0, 0, 46, 0, 0, 0,110, 0, 0, 0,110, 0, 0, 0,110, 0, 0, 0,110, + 0, 0, 0,110, 0, 0, 0,110, 0, 0, 0,110, 0, 0, 0,110, 0, 0, 0,111, + 0, 0, 0,111, 0, 0, 0,111, 0, 0, 0,111, 0, 0, 0,111, 0, 0, 0,111, + 0, 0, 0,111, 0, 0, 0,111, 0, 0, 0,112, 0, 0, 0,112, 0, 0, 0,112, + 0, 0, 0,112, 0, 0, 0,112, 0, 0, 0,112, 0, 0, 0,112, 0, 0, 0,112, + 0, 0, 0,115, 0, 0, 0,115, 0, 0, 0,115, 0, 0, 0,115, 0, 0, 0,115, + 0, 0, 0,115, 0, 0, 0,115, 0, 0, 0,115, 0, 0, 0,115, 0, 0, 0,116, + 0, 0, 0,116, 0, 0, 0,117, 0, 0, 0,117, 0, 0, 0,117, 0, 0, 0,117, + 0, 0, 0,117, 0, 0, 0,117, 0, 0, 0,119, 0, 0, 0,119, 0, 0, 0,119, + 0, 0, 0,119, 0, 0, 0,121, 0, 0, 0, 6, 0, 0, 0, 10, 0, 0, 0, 0, + 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 45, 0, 0, + 0, 4, 0, 0, 0, 0, 0, 0, 0, 97,114,103, 0, 0, 0, 0, 0, 45, 0, 0, + 0, 11, 0, 0, 0, 0, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 49, 0, + 8, 0, 0, 0, 45, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0,100,115,116, 95, +105,109, 97,103,101, 50, 0, 16, 0, 0, 0, 45, 0, 0, 0, 11, 0, 0, 0, 0, + 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 51, 0, 24, 0, 0, 0, 45, 0, + 0, 0, 4, 0, 0, 0, 0, 0, 0, 0,114,101,116, 0, 33, 0, 0, 0, 45, 0, + 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119,105,100,116,104, 0, + 7, 0, 0, 0, 0, 0, 0, 0,104,101,105,103,104,116, 0, 12, 0, 0, 0, 0, + 0, 0, 0, 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 10, 0, 0, 0, 0, + 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, 0, 5, 0, 0, 0, 0, 0, 0, + 0,102,117,110, 99, 0, 17, 0, 0, 0,104, 0, 0, 0,104, 0, 0, 0,105, 0, + 0, 0,105, 0, 0, 0,105, 0, 0, 0,108, 0, 0, 0,108, 0, 0, 0,108, 0, + 0, 0,108, 0, 0, 0,121, 0, 0, 0,121, 0, 0, 0,121, 0, 0, 0,121, 0, + 0, 0,121, 0, 0, 0,121, 0, 0, 0,121, 0, 0, 0,122, 0, 0, 0, 6, 0, + 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,102,117,110, 99,110, 97,109,101, 0, 0, + 0, 0, 0, 16, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119,105,100,116,104, + 0, 0, 0, 0, 0, 16, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0,104,101,105, +103,104,116, 0, 0, 0, 0, 0, 16, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, + 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 0, 0, 0, 0, 16, 0, 0, 0, + 10, 0, 0, 0, 0, 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, 0, 0, 0, + 0, 0, 16, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,102,117,110, 99, 0, 2, + 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, + 0, 0, 0,130, 0, 0, 0, 0, 1, 0, 7, 18, 0, 0, 0,100, 0, 0, 0,133, + 0, 0, 0,134, 64, 64, 1,192, 0,128, 0, 11,129, 64, 0, 28, 1, 0, 1,220, +128, 0, 0, 0, 1,128, 0, 75,193, 64, 0, 92, 1, 0, 1, 28,129, 0, 0,204, + 0,129, 1,156,128, 0, 1,143, 0, 65, 1,206,128, 0,130,204, 64,193, 1,222, + 0, 0, 1, 30, 0,128, 0, 6, 0, 0, 0, 4, 5, 0, 0, 0, 0, 0, 0, 0, +109, 97,116,104, 0, 4, 5, 0, 0, 0, 0, 0, 0, 0,115,113,114,116, 0, 4, + 6, 0, 0, 0, 0, 0, 0, 0, 87,105,100,116,104, 0, 4, 7, 0, 0, 0, 0, + 0, 0, 0, 72,101,105,103,104,116, 0, 3, 0, 0, 0, 0, 0, 0, 0, 64, 3, + 0, 0, 0, 0, 0, 0,240, 63, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +127, 0, 0, 0,127, 0, 0, 0, 0, 1, 0, 2, 3, 0, 0, 0, 78, 0, 0, 0, + 94, 0, 0, 1, 30, 0,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, +127, 0, 0, 0,127, 0, 0, 0,127, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0,120, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 18, 0, + 0, 0,127, 0, 0, 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, + 0, 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, + 0, 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, 0, 0,129, 0, + 0, 0,129, 0, 0, 0,129, 0, 0, 0,130, 0, 0, 0, 3, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0,105,109, 97,103,101, 0, 0, 0, 0, 0, 17, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0,115,113,114, 0, 1, 0, 0, 0, 17, 0, 0, 0, + 5, 0, 0, 0, 0, 0, 0, 0,114,109, 97,120, 0, 14, 0, 0, 0, 17, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,141, 0, 0, 0,144, 0, 0, + 0, 0, 3, 0, 7, 14, 0, 0, 0,197, 0, 0, 0,198, 64,192, 1, 0, 1, 0, + 0, 64, 1,128, 0,128, 1, 0, 1,220,128, 0, 2, 5, 1, 0, 0, 6,129, 64, + 2, 64, 1, 0, 0,128, 1,128, 1, 28,129,128, 1, 64, 1,128, 1, 30, 1,128, + 1, 30, 0,128, 0, 3, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, + 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116, +101, 66, 97,115,101,100, 0, 4, 14, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99, +101,115,115, 82,101,100,117, 99,101, 0, 0, 0, 0, 0, 14, 0, 0, 0,142, 0, + 0, 0,142, 0, 0, 0,142, 0, 0, 0,142, 0, 0, 0,142, 0, 0, 0,142, 0, + 0, 0,143, 0, 0, 0,143, 0, 0, 0,143, 0, 0, 0,143, 0, 0, 0,143, 0, + 0, 0,143, 0, 0, 0,143, 0, 0, 0,144, 0, 0, 0, 4, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, + 13, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119,105,100,116,104, 0, 0, 0, + 0, 0, 13, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0,104,101,105,103,104,116, + 0, 0, 0, 0, 0, 13, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,100,115,116, + 95,105,109, 97,103,101, 0, 6, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,146, 0, 0, 0,149, 0, 0, 0, 0, 3, 0, 7, 14, + 0, 0, 0,197, 0, 0, 0,198, 64,192, 1, 0, 1, 0, 0, 64, 1,128, 0,128, + 1, 0, 1,220,128, 0, 2, 5, 1, 0, 0, 6,129, 64, 2, 64, 1, 0, 0,128, + 1,128, 1, 28,129,128, 1, 64, 1,128, 1, 30, 1,128, 1, 30, 0,128, 0, 3, + 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, + 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, + 0, 4, 14, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 82,101,115, +105,122,101, 0, 0, 0, 0, 0, 14, 0, 0, 0,147, 0, 0, 0,147, 0, 0, 0, +147, 0, 0, 0,147, 0, 0, 0,147, 0, 0, 0,147, 0, 0, 0,148, 0, 0, 0, +148, 0, 0, 0,148, 0, 0, 0,148, 0, 0, 0,148, 0, 0, 0,148, 0, 0, 0, +148, 0, 0, 0,149, 0, 0, 0, 4, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, +115,114, 99, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 13, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0,119,105,100,116,104, 0, 0, 0, 0, 0, 13, 0, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0,104,101,105,103,104,116, 0, 0, 0, 0, 0, 13, + 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, + 0, 6, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0,151, 0, 0, 0,151, 0, 0, 0, 0, 1, 0, 3, 5, 0, 0, 0, 75, 0, 64, + 0, 92,128, 0, 1, 79, 64,192, 0, 94, 0, 0, 1, 30, 0,128, 0, 2, 0, 0, + 0, 4, 6, 0, 0, 0, 0, 0, 0, 0, 87,105,100,116,104, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 64, 0, 0, 0, 0, 5, 0, 0, 0,151, 0, 0, 0,151, 0, 0, + 0,151, 0, 0, 0,151, 0, 0, 0,151, 0, 0, 0, 1, 0, 0, 0, 6, 0, 0, + 0, 0, 0, 0, 0,105,109, 97,103,101, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,152, 0, 0, 0,152, 0, 0, 0, 0, + 1, 0, 3, 5, 0, 0, 0, 75, 0, 64, 0, 92,128, 0, 1, 79, 64,192, 0, 94, + 0, 0, 1, 30, 0,128, 0, 2, 0, 0, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0, + 72,101,105,103,104,116, 0, 3, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, + 5, 0, 0, 0,152, 0, 0, 0,152, 0, 0, 0,152, 0, 0, 0,152, 0, 0, 0, +152, 0, 0, 0, 1, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,105,109, 97,103, +101, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,154, 0, 0, 0,160, 0, 0, 0, 0, 5, 0, 13, 19, 0, 0, 0, 77, 65, + 0, 1, 76, 1,192, 2,141,193, 0, 2,140, 1, 64, 3,197, 65, 0, 0,198,129, +192, 3, 0, 2, 0, 0, 64, 2,128, 2,128, 2, 0, 3,220,129, 0, 2, 5, 66, + 0, 0, 6,194, 64, 4, 64, 2, 0, 0,128, 2,128, 3,192, 2,128, 0, 0, 3, +128, 1, 28, 66,128, 2,222, 1, 0, 1, 30, 0,128, 0, 4, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0,240, 63, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, + 17, 0, 0, 0, 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, + 97,115,101,100, 0, 4, 12, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115, +115, 67,114,111,112, 0, 0, 0, 0, 0, 19, 0, 0, 0,155, 0, 0, 0,155, 0, + 0, 0,156, 0, 0, 0,156, 0, 0, 0,157, 0, 0, 0,157, 0, 0, 0,157, 0, + 0, 0,157, 0, 0, 0,157, 0, 0, 0,157, 0, 0, 0,158, 0, 0, 0,158, 0, + 0, 0,158, 0, 0, 0,158, 0, 0, 0,158, 0, 0, 0,158, 0, 0, 0,158, 0, + 0, 0,159, 0, 0, 0,160, 0, 0, 0, 8, 0, 0, 0, 10, 0, 0, 0, 0, 0, + 0, 0,115,114, 99, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 18, 0, 0, 0, + 5, 0, 0, 0, 0, 0, 0, 0,120,109,105,110, 0, 0, 0, 0, 0, 18, 0, 0, + 0, 5, 0, 0, 0, 0, 0, 0, 0,120,109, 97,120, 0, 0, 0, 0, 0, 18, 0, + 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,121,109,105,110, 0, 0, 0, 0, 0, 18, + 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,121,109, 97,120, 0, 0, 0, 0, 0, + 18, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119,105,100,116,104, 0, 2, 0, + 0, 0, 18, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0,104,101,105,103,104,116, + 0, 4, 0, 0, 0, 18, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,100,115,116, + 95,105,109, 97,103,101, 0, 10, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,164, 0, 0, 0,170, 0, 0, 0, 0, 5, 0, 13, 19, + 0, 0, 0, 77, 65, 0, 1, 76, 1,192, 2,141,193, 0, 2,140, 1, 64, 3,197, + 65, 0, 0,198,129,192, 3, 0, 2, 0, 0, 64, 2,128, 2,128, 2, 0, 3,220, +129, 0, 2, 5, 66, 0, 0, 6,194, 64, 4, 64, 2, 0, 0,128, 2,128, 3,192, + 2,128, 0, 0, 3,128, 1, 28, 66,128, 2,222, 1, 0, 1, 30, 0,128, 0, 4, + 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,240, 63, 4, 3, 0, 0, 0, 0, 0, 0, + 0,105,109, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 73,109, 97,103,101, 67,114, +101, 97,116,101, 66, 97,115,101,100, 0, 4, 18, 0, 0, 0, 0, 0, 0, 0, 80, +114,111, 99,101,115,115, 65,100,100, 77, 97,114,103,105,110,115, 0, 0, 0, 0, + 0, 19, 0, 0, 0,165, 0, 0, 0,165, 0, 0, 0,166, 0, 0, 0,166, 0, 0, + 0,167, 0, 0, 0,167, 0, 0, 0,167, 0, 0, 0,167, 0, 0, 0,167, 0, 0, + 0,167, 0, 0, 0,168, 0, 0, 0,168, 0, 0, 0,168, 0, 0, 0,168, 0, 0, + 0,168, 0, 0, 0,168, 0, 0, 0,168, 0, 0, 0,169, 0, 0, 0,170, 0, 0, + 0, 8, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,115,114, 99, 95,105,109, 97, +103,101, 0, 0, 0, 0, 0, 18, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,120, +109,105,110, 0, 0, 0, 0, 0, 18, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, +120,109, 97,120, 0, 0, 0, 0, 0, 18, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, + 0,121,109,105,110, 0, 0, 0, 0, 0, 18, 0, 0, 0, 5, 0, 0, 0, 0, 0, + 0, 0,121,109, 97,120, 0, 0, 0, 0, 0, 18, 0, 0, 0, 6, 0, 0, 0, 0, + 0, 0, 0,119,105,100,116,104, 0, 2, 0, 0, 0, 18, 0, 0, 0, 7, 0, 0, + 0, 0, 0, 0, 0,104,101,105,103,104,116, 0, 4, 0, 0, 0, 18, 0, 0, 0, + 10, 0, 0, 0, 0, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 0, 10, 0, + 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,172, 0, + 0, 0,176, 0, 0, 0, 0, 4, 0, 13, 26, 0, 0, 0, 5, 1, 0, 0, 6, 65, + 64, 2, 75,129, 64, 0, 92,129, 0, 1,139,193, 64, 0,156,129, 0, 1,192, 1, +128, 0, 0, 2, 0, 1, 28,193,128, 2,133, 1, 0, 0,134, 1, 65, 3,192, 1, + 0, 0, 0, 2, 0, 2, 64, 2,128, 2,156,129, 0, 2,197, 1, 0, 0,198, 65, +193, 3, 0, 2, 0, 0, 64, 2, 0, 3,128, 2,128, 0,192, 2, 0, 1, 0, 3, +128, 1,220,129, 0, 3, 0, 2, 0, 3,222, 1,128, 1, 30, 0,128, 0, 6, 0, + 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 22, 0, 0, 0, 0, + 0, 0, 0, 80,114,111, 99,101,115,115, 67, 97,108, 99, 82,111,116, 97,116,101, + 83,105,122,101, 0, 4, 6, 0, 0, 0, 0, 0, 0, 0, 87,105,100,116,104, 0, + 4, 7, 0, 0, 0, 0, 0, 0, 0, 72,101,105,103,104,116, 0, 4, 17, 0, 0, + 0, 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101, +100, 0, 4, 14, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 82,111, +116, 97,116,101, 0, 0, 0, 0, 0, 26, 0, 0, 0,173, 0, 0, 0,173, 0, 0, + 0,173, 0, 0, 0,173, 0, 0, 0,173, 0, 0, 0,173, 0, 0, 0,173, 0, 0, + 0,173, 0, 0, 0,173, 0, 0, 0,174, 0, 0, 0,174, 0, 0, 0,174, 0, 0, + 0,174, 0, 0, 0,174, 0, 0, 0,174, 0, 0, 0,175, 0, 0, 0,175, 0, 0, + 0,175, 0, 0, 0,175, 0, 0, 0,175, 0, 0, 0,175, 0, 0, 0,175, 0, 0, + 0,175, 0, 0, 0,175, 0, 0, 0,175, 0, 0, 0,176, 0, 0, 0, 7, 0, 0, + 0, 10, 0, 0, 0, 0, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 0, 0, + 0, 0, 0, 25, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 99,111,115, 48, 0, + 0, 0, 0, 0, 25, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,115,105,110, 48, + 0, 0, 0, 0, 0, 25, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,111,114,100, +101,114, 0, 0, 0, 0, 0, 25, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119, +105,100,116,104, 0, 9, 0, 0, 0, 25, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, + 0,104,101,105,103,104,116, 0, 9, 0, 0, 0, 25, 0, 0, 0, 10, 0, 0, 0, + 0, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 0, 15, 0, 0, 0, 25, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,179, 0, 0, 0,179, 0, + 0, 0, 0, 1, 0, 3, 4, 0, 0, 0, 75, 0, 64, 0, 93, 0, 0, 1, 94, 0, + 0, 0, 30, 0,128, 0, 1, 0, 0, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0, 72, +101,105,103,104,116, 0, 0, 0, 0, 0, 4, 0, 0, 0,179, 0, 0, 0,179, 0, + 0, 0,179, 0, 0, 0,179, 0, 0, 0, 1, 0, 0, 0, 6, 0, 0, 0, 0, 0, + 0, 0,105,109, 97,103,101, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,179, 0, 0, 0,179, 0, 0, 0, 0, 1, 0, 3, + 4, 0, 0, 0, 75, 0, 64, 0, 93, 0, 0, 1, 94, 0, 0, 0, 30, 0,128, 0, + 1, 0, 0, 0, 4, 6, 0, 0, 0, 0, 0, 0, 0, 87,105,100,116,104, 0, 0, + 0, 0, 0, 4, 0, 0, 0,179, 0, 0, 0,179, 0, 0, 0,179, 0, 0, 0,179, + 0, 0, 0, 1, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,105,109, 97,103,101, + 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0,212, 0, 0, 0,212, 0, 0, 0, 0, 1, 0, 3, 13, 0, 0, 0, 75, 0, 64, + 0, 92,128, 0, 1, 90, 0, 0, 0, 22,192, 0,128, 75, 0, 64, 0, 93, 0, 0, + 1, 94, 0, 0, 0, 22,192, 0,128, 75, 0, 64, 0, 92,128, 0, 1, 79, 64,192, + 0, 94, 0, 0, 1, 30, 0,128, 0, 2, 0, 0, 0, 4, 7, 0, 0, 0, 0, 0, + 0, 0, 72,101,105,103,104,116, 0, 3, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, + 0, 0, 13, 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, + 0, 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, + 0, 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0, 1, 0, + 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,105,109, 97,103,101, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,214, 0, 0, 0, +227, 0, 0, 0, 0, 1, 0, 8, 36, 0, 0, 0, 75, 0, 64, 0, 92,128, 0, 1, + 79, 64,192, 0,133,128, 0, 0,134,192, 64, 1,203, 0, 64, 0,220,128, 0, 1, + 1, 65, 0, 0,156,128,128, 1,154, 0, 0, 0, 22, 0, 0,128, 76, 0,193, 0, +133, 64, 1, 0,134,128, 65, 1,192, 0, 0, 0, 3, 1, 0, 2, 64, 1,128, 0, +156,128, 0, 2,197, 64, 1, 0,198,128,193, 1, 0, 1, 0, 0, 67, 1,128, 2, +139, 1, 64, 0,156,129, 0, 1,143, 65, 64, 3,220,128, 0, 2, 5, 65, 1, 0, + 6,193, 65, 2, 64, 1, 0, 0,128, 1, 0, 1,192, 1,128, 1, 28, 65, 0, 2, + 0, 1, 0, 1, 64, 1,128, 1, 30, 1,128, 1, 30, 0,128, 0, 8, 0, 0, 0, + 4, 7, 0, 0, 0, 0, 0, 0, 0, 72,101,105,103,104,116, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 64, 4, 5, 0, 0, 0, 0, 0, 0, 0,109, 97,116,104, 0, 4, + 4, 0, 0, 0, 0, 0, 0, 0,109,111,100, 0, 3, 0, 0, 0, 0, 0, 0,240, + 63, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, 0, 0, + 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 4, + 22, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 73,110,116,101,114, +108, 97, 99,101, 83,112,108,105,116, 0, 0, 0, 0, 0, 36, 0, 0, 0,216, 0, + 0, 0,216, 0, 0, 0,216, 0, 0, 0,217, 0, 0, 0,217, 0, 0, 0,217, 0, + 0, 0,217, 0, 0, 0,217, 0, 0, 0,217, 0, 0, 0,217, 0, 0, 0,217, 0, + 0, 0,218, 0, 0, 0,221, 0, 0, 0,221, 0, 0, 0,221, 0, 0, 0,221, 0, + 0, 0,221, 0, 0, 0,221, 0, 0, 0,222, 0, 0, 0,222, 0, 0, 0,222, 0, + 0, 0,222, 0, 0, 0,222, 0, 0, 0,222, 0, 0, 0,222, 0, 0, 0,222, 0, + 0, 0,225, 0, 0, 0,225, 0, 0, 0,225, 0, 0, 0,225, 0, 0, 0,225, 0, + 0, 0,225, 0, 0, 0,226, 0, 0, 0,226, 0, 0, 0,226, 0, 0, 0,227, 0, + 0, 0, 4, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,115,114, 99, 95,105,109, + 97,103,101, 0, 0, 0, 0, 0, 35, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, +100,115,116, 95,104,101,105,103,104,116, 49, 0, 3, 0, 0, 0, 35, 0, 0, 0, + 11, 0, 0, 0, 0, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 49, 0, 18, + 0, 0, 0, 35, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0,100,115,116, 95,105, +109, 97,103,101, 50, 0, 26, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,229, 0, 0, 0,235, 0, 0, 0, 0, 1, 0, 3, 14, 0, + 0, 0, 75, 0, 64, 0, 92,128, 0, 1,133, 64, 0, 0,134,128, 64, 1, 87,128, +128, 0, 22,192, 0,128,133, 64, 0, 0,134,192, 64, 1, 23,128,128, 0, 22, 64, + 0,128,133, 64, 0, 0, 70, 0, 65, 1, 94, 0, 0, 1, 30, 0,128, 0, 5, 0, + 0, 0, 4, 9, 0, 0, 0, 0, 0, 0, 0, 68, 97,116, 97, 84,121,112,101, 0, + 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 5, 0, 0, 0, 0, 0, 0, + 0, 66, 89, 84, 69, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0, 85, 83, 72, 79, 82, + 84, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 73, 78, 84, 0, 0, 0, 0, 0, 14, + 0, 0, 0,230, 0, 0, 0,230, 0, 0, 0,231, 0, 0, 0,231, 0, 0, 0,231, + 0, 0, 0,231, 0, 0, 0,231, 0, 0, 0,231, 0, 0, 0,231, 0, 0, 0,231, + 0, 0, 0,232, 0, 0, 0,232, 0, 0, 0,234, 0, 0, 0,235, 0, 0, 0, 2, + 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,105,109, 97,103,101, 0, 0, 0, 0, + 0, 13, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,100, 97,116, 97, 95,116,121, +112,101, 0, 2, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,250, 0, 0, 0,254, 0, 0, 0, 0, 3, 0, 9, 13, 0, 0, 0,197, + 0, 0, 0,198, 64,192, 1, 0, 1, 0, 0,220,128, 0, 1, 5, 1, 0, 0, 6, +129, 64, 2, 64, 1, 0, 0,128, 1,128, 0,192, 1,128, 1, 0, 2, 0, 1, 28, + 65,128, 2,222, 0, 0, 1, 30, 0,128, 0, 3, 0, 0, 0, 4, 3, 0, 0, 0, + 0, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 73,109, 97,103, +101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 4, 25, 0, 0, 0, 0, 0, + 0, 0, 80,114,111, 99,101,115,115, 65,114,105,116,104,109,101,116,105, 99, 67, +111,110,115,116, 79,112, 0, 0, 0, 0, 0, 13, 0, 0, 0,251, 0, 0, 0,251, + 0, 0, 0,251, 0, 0, 0,251, 0, 0, 0,252, 0, 0, 0,252, 0, 0, 0,252, + 0, 0, 0,252, 0, 0, 0,252, 0, 0, 0,252, 0, 0, 0,252, 0, 0, 0,253, + 0, 0, 0,254, 0, 0, 0, 4, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,115, +114, 99, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 12, 0, 0, 0, 10, 0, 0, + 0, 0, 0, 0, 0,115,114, 99, 95, 99,111,110,115,116, 0, 0, 0, 0, 0, 12, + 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0,111,112, 0, 0, 0, 0, 0, 12, 0, + 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 0, + 4, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 1, 0, 0, 9, 1, 0, 0, 0, 2, 0, 6, 11, 0, 0, 0,133, 0, 0, 0, +134, 64, 64, 1,198,128, 64, 0,156,128, 0, 1,197, 0, 0, 0,198,192,192, 1, + 0, 1, 0, 0, 64, 1, 0, 1,220, 64,128, 1,158, 0, 0, 1, 30, 0,128, 0, + 4, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 17, 0, 0, + 0, 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101, +100, 0, 3, 0, 0, 0, 0, 0, 0,240, 63, 4, 20, 0, 0, 0, 0, 0, 0, 0, + 80,114,111, 99,101,115,115, 77,117,108,116,105,112,108,101, 77,101, 97,110, 0, + 0, 0, 0, 0, 11, 0, 0, 0, 6, 1, 0, 0, 6, 1, 0, 0, 6, 1, 0, 0, + 6, 1, 0, 0, 7, 1, 0, 0, 7, 1, 0, 0, 7, 1, 0, 0, 7, 1, 0, 0, + 7, 1, 0, 0, 8, 1, 0, 0, 9, 1, 0, 0, 3, 0, 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 95,108,105,115,116, 0, 0, + 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,100,115,116, 95,105, +109, 97,103,101, 0, 0, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, + 0,100,115,116, 95,105,109, 97,103,101, 0, 4, 0, 0, 0, 10, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 1, 0, 0, 15, 1, 0, 0, 0, + 2, 0, 7, 12, 0, 0, 0,133, 0, 0, 0,134, 64, 64, 1,198,128, 64, 0,156, +128, 0, 1,197, 0, 0, 0,198,192,192, 1, 0, 1, 0, 0, 64, 1,128, 0,128, + 1, 0, 1,220, 64, 0, 2,158, 0, 0, 1, 30, 0,128, 0, 4, 0, 0, 0, 4, + 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, + 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 3, 0, 0, + 0, 0, 0, 0,240, 63, 4, 22, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101, +115,115, 77,117,108,116,105,112,108,101, 83,116,100, 68,101,118, 0, 0, 0, 0, + 0, 12, 0, 0, 0, 12, 1, 0, 0, 12, 1, 0, 0, 12, 1, 0, 0, 12, 1, 0, + 0, 13, 1, 0, 0, 13, 1, 0, 0, 13, 1, 0, 0, 13, 1, 0, 0, 13, 1, 0, + 0, 13, 1, 0, 0, 14, 1, 0, 0, 15, 1, 0, 0, 3, 0, 0, 0, 15, 0, 0, + 0, 0, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 95,108,105,115,116, 0, + 0, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0,109,101, 97,110, + 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 11, 0, 0, 0, 10, 0, 0, 0, 0, + 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 0, 4, 0, 0, 0, 11, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 1, 0, 0, 29, 1, 0, + 0, 0, 1, 0, 8, 28, 0, 0, 0, 69, 0, 0, 0, 70, 64,192, 0,128, 0, 0, + 0,195, 0, 0, 2, 69, 1, 0, 0, 70,129,192, 2,133, 1, 0, 0,134,193, 64, + 3, 92,128, 0, 3,133, 0, 0, 0,134, 64, 64, 1,192, 0, 0, 0, 3, 1,128, + 2,133, 1, 0, 0,134, 1, 65, 3,197, 1, 0, 0,198,193,192, 3,156,128, 0, + 3,197, 0, 0, 0,198, 64,193, 1, 0, 1, 0, 0, 64, 1,128, 0,128, 1, 0, + 1,220, 64, 0, 2,192, 0,128, 0, 0, 1, 0, 1,222, 0,128, 1, 30, 0,128, + 0, 6, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 17, 0, + 0, 0, 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115, +101,100, 0, 4, 5, 0, 0, 0, 0, 0, 0, 0, 71, 82, 65, 89, 0, 4, 5, 0, + 0, 0, 0, 0, 0, 0, 66, 89, 84, 69, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, + 82, 71, 66, 0, 4, 20, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, + 83,112,108,105,116, 89, 67,104,114,111,109, 97, 0, 0, 0, 0, 0, 28, 0, 0, + 0, 25, 1, 0, 0, 25, 1, 0, 0, 25, 1, 0, 0, 25, 1, 0, 0, 25, 1, 0, + 0, 25, 1, 0, 0, 25, 1, 0, 0, 25, 1, 0, 0, 25, 1, 0, 0, 26, 1, 0, + 0, 26, 1, 0, 0, 26, 1, 0, 0, 26, 1, 0, 0, 26, 1, 0, 0, 26, 1, 0, + 0, 26, 1, 0, 0, 26, 1, 0, 0, 26, 1, 0, 0, 27, 1, 0, 0, 27, 1, 0, + 0, 27, 1, 0, 0, 27, 1, 0, 0, 27, 1, 0, 0, 27, 1, 0, 0, 28, 1, 0, + 0, 28, 1, 0, 0, 28, 1, 0, 0, 29, 1, 0, 0, 3, 0, 0, 0, 10, 0, 0, + 0, 0, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 27, + 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0,121, 95,105,109, 97,103,101, 0, 9, + 0, 0, 0, 27, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 99,104,114,111,109, + 97, 95,105,109, 97,103,101, 0, 18, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 34, 1, 0, 0, 42, 1, 0, 0, 0, 1, 0, 14, + 29, 0, 0, 0, 75, 0, 64, 0, 92,128, 0, 1,138, 0, 0, 0,193, 64, 0, 0, + 0, 1,128, 0, 65, 65, 0, 0,224,128, 2,128,197,129, 0, 0,198,193,192, 3, + 0, 2, 0, 1, 69, 2, 1, 0, 70, 66,193, 4,128, 2, 0, 0,195, 2, 0, 6, + 69, 3, 1, 0, 70,131,193, 6, 92, 2,128, 2,220, 65, 0, 0,223,192,252,127, +197, 0, 1, 0,198,192,193, 1, 0, 1, 0, 0, 64, 1, 0, 1,220, 64,128, 1, +197, 0, 2, 0, 0, 1, 0, 1,221, 0, 0, 1,222, 0, 0, 0, 30, 0,128, 0, + 9, 0, 0, 0, 4, 6, 0, 0, 0, 0, 0, 0, 0, 68,101,112,116,104, 0, 3, + 0, 0, 0, 0, 0, 0,240, 63, 4, 6, 0, 0, 0, 0, 0, 0, 0,116, 97, 98, +108,101, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0,105,110,115,101,114,116, 0, 4, + 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, + 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 4, 5, 0, + 0, 0, 0, 0, 0, 0, 71, 82, 65, 89, 0, 4, 23, 0, 0, 0, 0, 0, 0, 0, + 80,114,111, 99,101,115,115, 83,112,108,105,116, 67,111,109,112,111,110,101,110, +116,115, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0,117,110,112, 97, 99,107, 0, 0, + 0, 0, 0, 29, 0, 0, 0, 35, 1, 0, 0, 35, 1, 0, 0, 36, 1, 0, 0, 37, + 1, 0, 0, 37, 1, 0, 0, 37, 1, 0, 0, 37, 1, 0, 0, 38, 1, 0, 0, 38, + 1, 0, 0, 38, 1, 0, 0, 38, 1, 0, 0, 38, 1, 0, 0, 38, 1, 0, 0, 38, + 1, 0, 0, 38, 1, 0, 0, 38, 1, 0, 0, 38, 1, 0, 0, 38, 1, 0, 0, 37, + 1, 0, 0, 40, 1, 0, 0, 40, 1, 0, 0, 40, 1, 0, 0, 40, 1, 0, 0, 40, + 1, 0, 0, 41, 1, 0, 0, 41, 1, 0, 0, 41, 1, 0, 0, 41, 1, 0, 0, 42, + 1, 0, 0, 7, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,115,114, 99, 95,105, +109, 97,103,101, 0, 0, 0, 0, 0, 28, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, + 0,100,101,112,116,104, 0, 2, 0, 0, 0, 28, 0, 0, 0, 11, 0, 0, 0, 0, + 0, 0, 0,100,115,116, 95,105,109, 97,103,101,115, 0, 3, 0, 0, 0, 28, 0, + 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 40,102,111,114, 32,105,110,100,101,120, + 41, 0, 6, 0, 0, 0, 19, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 40,102, +111,114, 32,108,105,109,105,116, 41, 0, 6, 0, 0, 0, 19, 0, 0, 0, 11, 0, + 0, 0, 0, 0, 0, 0, 40,102,111,114, 32,115,116,101,112, 41, 0, 6, 0, 0, + 0, 19, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,105, 0, 7, 0, 0, 0, 18, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 1, 0, 0, 48, + 1, 0, 0, 0, 1, 0, 6, 14, 0, 0, 0, 69, 0, 0, 0, 70, 64,192, 0,134, +128, 64, 0,195, 0, 0, 2, 69, 1, 0, 0, 70,193,192, 2, 92,128,128, 2,133, + 0, 0, 0,134, 0, 65, 1,192, 0, 0, 0, 0, 1,128, 0,156, 64,128, 1, 94, + 0, 0, 1, 30, 0,128, 0, 5, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0, +105,109, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, + 97,116,101, 66, 97,115,101,100, 0, 3, 0, 0, 0, 0, 0, 0,240, 63, 4, 4, + 0, 0, 0, 0, 0, 0, 0, 82, 71, 66, 0, 4, 23, 0, 0, 0, 0, 0, 0, 0, + 80,114,111, 99,101,115,115, 77,101,114,103,101, 67,111,109,112,111,110,101,110, +116,115, 0, 0, 0, 0, 0, 14, 0, 0, 0, 45, 1, 0, 0, 45, 1, 0, 0, 45, + 1, 0, 0, 45, 1, 0, 0, 45, 1, 0, 0, 45, 1, 0, 0, 45, 1, 0, 0, 46, + 1, 0, 0, 46, 1, 0, 0, 46, 1, 0, 0, 46, 1, 0, 0, 46, 1, 0, 0, 47, + 1, 0, 0, 48, 1, 0, 0, 2, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0,115, +114, 99, 95,105,109, 97,103,101, 95,108,105,115,116, 0, 0, 0, 0, 0, 13, 0, + 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 0, + 7, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0,144, 1, 0, 0, 25, 0, 0, 0, + 50, 0, 0, 0, 73, 0, 0, 0, 97, 0, 0, 0,122, 0, 0, 0,130, 0, 0, 0, +132, 0, 0, 0,132, 0, 0, 0,132, 0, 0, 0,132, 0, 0, 0,132, 0, 0, 0, +132, 0, 0, 0,133, 0, 0, 0,133, 0, 0, 0,133, 0, 0, 0,134, 0, 0, 0, +134, 0, 0, 0,134, 0, 0, 0,135, 0, 0, 0,135, 0, 0, 0,135, 0, 0, 0, +136, 0, 0, 0,136, 0, 0, 0,136, 0, 0, 0,136, 0, 0, 0,136, 0, 0, 0, +136, 0, 0, 0,136, 0, 0, 0,136, 0, 0, 0,136, 0, 0, 0,137, 0, 0, 0, +137, 0, 0, 0,137, 0, 0, 0,138, 0, 0, 0,138, 0, 0, 0,138, 0, 0, 0, +138, 0, 0, 0,138, 0, 0, 0,138, 0, 0, 0,139, 0, 0, 0,139, 0, 0, 0, +139, 0, 0, 0,139, 0, 0, 0,139, 0, 0, 0,139, 0, 0, 0,139, 0, 0, 0, +141, 0, 0, 0,144, 0, 0, 0,141, 0, 0, 0,146, 0, 0, 0,149, 0, 0, 0, +146, 0, 0, 0,151, 0, 0, 0,151, 0, 0, 0,151, 0, 0, 0,152, 0, 0, 0, +151, 0, 0, 0,154, 0, 0, 0,160, 0, 0, 0,154, 0, 0, 0,162, 0, 0, 0, +162, 0, 0, 0,162, 0, 0, 0,164, 0, 0, 0,170, 0, 0, 0,164, 0, 0, 0, +172, 0, 0, 0,176, 0, 0, 0,172, 0, 0, 0,178, 0, 0, 0,178, 0, 0, 0, +178, 0, 0, 0,179, 0, 0, 0,179, 0, 0, 0,179, 0, 0, 0,179, 0, 0, 0, +179, 0, 0, 0,180, 0, 0, 0,180, 0, 0, 0,180, 0, 0, 0,181, 0, 0, 0, +181, 0, 0, 0,181, 0, 0, 0,182, 0, 0, 0,182, 0, 0, 0,182, 0, 0, 0, +183, 0, 0, 0,183, 0, 0, 0,183, 0, 0, 0,184, 0, 0, 0,184, 0, 0, 0, +184, 0, 0, 0,185, 0, 0, 0,185, 0, 0, 0,185, 0, 0, 0,186, 0, 0, 0, +186, 0, 0, 0,186, 0, 0, 0,187, 0, 0, 0,187, 0, 0, 0,187, 0, 0, 0, +188, 0, 0, 0,188, 0, 0, 0,188, 0, 0, 0,189, 0, 0, 0,189, 0, 0, 0, +189, 0, 0, 0,190, 0, 0, 0,190, 0, 0, 0,190, 0, 0, 0,191, 0, 0, 0, +191, 0, 0, 0,191, 0, 0, 0,192, 0, 0, 0,192, 0, 0, 0,192, 0, 0, 0, +193, 0, 0, 0,193, 0, 0, 0,193, 0, 0, 0,194, 0, 0, 0,194, 0, 0, 0, +194, 0, 0, 0,195, 0, 0, 0,195, 0, 0, 0,195, 0, 0, 0,196, 0, 0, 0, +196, 0, 0, 0,196, 0, 0, 0,197, 0, 0, 0,197, 0, 0, 0,197, 0, 0, 0, +198, 0, 0, 0,198, 0, 0, 0,198, 0, 0, 0,199, 0, 0, 0,199, 0, 0, 0, +199, 0, 0, 0,200, 0, 0, 0,200, 0, 0, 0,200, 0, 0, 0,201, 0, 0, 0, +201, 0, 0, 0,201, 0, 0, 0,202, 0, 0, 0,202, 0, 0, 0,202, 0, 0, 0, +203, 0, 0, 0,203, 0, 0, 0,203, 0, 0, 0,204, 0, 0, 0,204, 0, 0, 0, +204, 0, 0, 0,205, 0, 0, 0,205, 0, 0, 0,205, 0, 0, 0,206, 0, 0, 0, +206, 0, 0, 0,206, 0, 0, 0,207, 0, 0, 0,207, 0, 0, 0,207, 0, 0, 0, +208, 0, 0, 0,208, 0, 0, 0,208, 0, 0, 0,209, 0, 0, 0,209, 0, 0, 0, +209, 0, 0, 0,210, 0, 0, 0,210, 0, 0, 0,210, 0, 0, 0,211, 0, 0, 0, +211, 0, 0, 0,211, 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0, +212, 0, 0, 0,212, 0, 0, 0,214, 0, 0, 0,227, 0, 0, 0,214, 0, 0, 0, +235, 0, 0, 0,237, 0, 0, 0,237, 0, 0, 0,237, 0, 0, 0,237, 0, 0, 0, +237, 0, 0, 0,238, 0, 0, 0,238, 0, 0, 0,238, 0, 0, 0,238, 0, 0, 0, +238, 0, 0, 0,239, 0, 0, 0,239, 0, 0, 0,239, 0, 0, 0,240, 0, 0, 0, +240, 0, 0, 0,240, 0, 0, 0,241, 0, 0, 0,241, 0, 0, 0,241, 0, 0, 0, +242, 0, 0, 0,242, 0, 0, 0,242, 0, 0, 0,243, 0, 0, 0,243, 0, 0, 0, +243, 0, 0, 0,244, 0, 0, 0,244, 0, 0, 0,244, 0, 0, 0,245, 0, 0, 0, +245, 0, 0, 0,245, 0, 0, 0,246, 0, 0, 0,246, 0, 0, 0,246, 0, 0, 0, +247, 0, 0, 0,247, 0, 0, 0,247, 0, 0, 0,248, 0, 0, 0,248, 0, 0, 0, +248, 0, 0, 0,250, 0, 0, 0,254, 0, 0, 0,250, 0, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, + 2, 1, 0, 0, 2, 1, 0, 0, 2, 1, 0, 0, 3, 1, 0, 0, 3, 1, 0, 0, + 3, 1, 0, 0, 3, 1, 0, 0, 3, 1, 0, 0, 3, 1, 0, 0, 5, 1, 0, 0, + 9, 1, 0, 0, 5, 1, 0, 0, 11, 1, 0, 0, 15, 1, 0, 0, 11, 1, 0, 0, + 17, 1, 0, 0, 17, 1, 0, 0, 17, 1, 0, 0, 18, 1, 0, 0, 18, 1, 0, 0, + 18, 1, 0, 0, 19, 1, 0, 0, 19, 1, 0, 0, 19, 1, 0, 0, 19, 1, 0, 0, + 19, 1, 0, 0, 19, 1, 0, 0, 19, 1, 0, 0, 20, 1, 0, 0, 20, 1, 0, 0, + 20, 1, 0, 0, 21, 1, 0, 0, 21, 1, 0, 0, 21, 1, 0, 0, 22, 1, 0, 0, + 22, 1, 0, 0, 22, 1, 0, 0, 24, 1, 0, 0, 29, 1, 0, 0, 24, 1, 0, 0, + 31, 1, 0, 0, 31, 1, 0, 0, 31, 1, 0, 0, 31, 1, 0, 0, 31, 1, 0, 0, + 31, 1, 0, 0, 31, 1, 0, 0, 31, 1, 0, 0, 32, 1, 0, 0, 32, 1, 0, 0, + 32, 1, 0, 0, 32, 1, 0, 0, 32, 1, 0, 0, 32, 1, 0, 0, 32, 1, 0, 0, + 32, 1, 0, 0, 34, 1, 0, 0, 42, 1, 0, 0, 34, 1, 0, 0, 44, 1, 0, 0, + 48, 1, 0, 0, 44, 1, 0, 0, 50, 1, 0, 0, 50, 1, 0, 0, 50, 1, 0, 0, + 50, 1, 0, 0, 50, 1, 0, 0, 50, 1, 0, 0, 51, 1, 0, 0, 51, 1, 0, 0, + 51, 1, 0, 0, 52, 1, 0, 0, 52, 1, 0, 0, 52, 1, 0, 0, 53, 1, 0, 0, + 53, 1, 0, 0, 53, 1, 0, 0, 54, 1, 0, 0, 54, 1, 0, 0, 54, 1, 0, 0, + 55, 1, 0, 0, 55, 1, 0, 0, 55, 1, 0, 0, 56, 1, 0, 0, 56, 1, 0, 0, + 56, 1, 0, 0, 57, 1, 0, 0, 57, 1, 0, 0, 57, 1, 0, 0, 57, 1, 0, 0, + 57, 1, 0, 0, 57, 1, 0, 0, 58, 1, 0, 0, 58, 1, 0, 0, 58, 1, 0, 0, + 58, 1, 0, 0, 58, 1, 0, 0, 58, 1, 0, 0, 59, 1, 0, 0, 59, 1, 0, 0, + 59, 1, 0, 0, 60, 1, 0, 0, 60, 1, 0, 0, 60, 1, 0, 0, 60, 1, 0, 0, + 60, 1, 0, 0, 60, 1, 0, 0, 60, 1, 0, 0, 61, 1, 0, 0, 61, 1, 0, 0, + 61, 1, 0, 0, 61, 1, 0, 0, 61, 1, 0, 0, 61, 1, 0, 0, 61, 1, 0, 0, + 62, 1, 0, 0, 62, 1, 0, 0, 62, 1, 0, 0, 62, 1, 0, 0, 62, 1, 0, 0, + 62, 1, 0, 0, 62, 1, 0, 0, 63, 1, 0, 0, 63, 1, 0, 0, 63, 1, 0, 0, + 64, 1, 0, 0, 64, 1, 0, 0, 64, 1, 0, 0, 64, 1, 0, 0, 64, 1, 0, 0, + 64, 1, 0, 0, 64, 1, 0, 0, 65, 1, 0, 0, 65, 1, 0, 0, 65, 1, 0, 0, + 65, 1, 0, 0, 65, 1, 0, 0, 65, 1, 0, 0, 65, 1, 0, 0, 66, 1, 0, 0, + 66, 1, 0, 0, 66, 1, 0, 0, 67, 1, 0, 0, 67, 1, 0, 0, 67, 1, 0, 0, + 68, 1, 0, 0, 68, 1, 0, 0, 68, 1, 0, 0, 69, 1, 0, 0, 69, 1, 0, 0, + 69, 1, 0, 0, 69, 1, 0, 0, 69, 1, 0, 0, 69, 1, 0, 0, 69, 1, 0, 0, + 70, 1, 0, 0, 70, 1, 0, 0, 70, 1, 0, 0, 70, 1, 0, 0, 70, 1, 0, 0, + 70, 1, 0, 0, 70, 1, 0, 0, 71, 1, 0, 0, 71, 1, 0, 0, 71, 1, 0, 0, + 72, 1, 0, 0, 72, 1, 0, 0, 72, 1, 0, 0, 72, 1, 0, 0, 7, 0, 0, 0, + 17, 0, 0, 0, 0, 0, 0, 0, 79,110,101, 83,111,117,114, 99,101, 79,110,101, + 68,101,115,116, 0, 1, 0, 0, 0,143, 1, 0, 0, 18, 0, 0, 0, 0, 0, 0, + 0, 84,119,111, 83,111,117,114, 99,101,115, 79,110,101, 68,101,115,116, 0, 2, + 0, 0, 0,143, 1, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 84,104,114,101,101, + 83,111,117,114, 99,101,115, 79,110,101, 68,101,115,116, 0, 3, 0, 0, 0,143, + 1, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 79,110,101, 83,111,117,114, 99,101, + 84,119,111, 68,101,115,116,115, 0, 4, 0, 0, 0,143, 1, 0, 0, 20, 0, 0, + 0, 0, 0, 0, 0, 79,110,101, 83,111,117,114, 99,101, 84,104,114,101,101, 68, +101,115,116,115, 0, 5, 0, 0, 0,143, 1, 0, 0, 13, 0, 0, 0, 0, 0, 0, + 0,104,111,117,103,104, 95,104,101,105,103,104,116, 0, 6, 0, 0, 0,143, 1, + 0, 0, 13, 0, 0, 0, 0, 0, 0, 0,105,110,116, 95,100, 97,116, 97,116,121, +112,101, 0,182, 0, 0, 0,143, 1, 0, 0, 0, 0, 0, 0, +}; + + if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"../obj/imlua_process51/im_process_le64.lo")==0) lua_call(L, 0, 0); +} diff --git a/im/src/lua5/loh/im_process_le64w.loh b/im/src/lua5/loh/im_process_le64w.loh new file mode 100755 index 0000000..b94506a --- /dev/null +++ b/im/src/lua5/loh/im_process_le64w.loh @@ -0,0 +1,890 @@ +/* code automatically generated by bin2c -- DO NOT EDIT */ +{ +/* #include'ing this file in a C program is equivalent to calling + if (luaL_loadfile(L,"../obj/imlua_process51/im_process_le64w.lo")==0) lua_pcall(L, 0, 0, 0); +*/ +/* ../obj/imlua_process51/im_process_le64w.lo */ +static const unsigned char B1[]={ + 27, 76,117, 97, 81, 0, 1, 4, 8, 4, 8, 0, 21, 0, 0, 0, 0, 0, 0, 0, + 64,108,117, 97, 53, 47,105,109, 95,112,114,111, 99,101,115,115, 46,108,117, 97, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 13,135, 1, 0, 0, 36, 0, 0, + 0,100, 64, 0, 0,164,128, 0, 0,228,192, 0, 0, 36, 1, 1, 0,100, 65, 1, + 0,128, 1, 0, 0,193, 1, 0, 0, 3, 2, 0, 5,197, 66, 0, 0,198,130,192, + 5,156, 65, 0, 3,128, 1, 0, 0,193,193, 0, 0,156, 65, 0, 1,128, 1, 0, + 0,193, 1, 1, 0,156, 65, 0, 1,128, 1, 0, 0,193, 65, 1, 0,156, 65, 0, + 1,128, 1, 0, 0,193,129, 1, 0, 1,194, 1, 0, 64, 2,128, 2,133, 66, 0, + 0,134, 2, 66, 5,197, 66, 0, 0,198, 66,194, 5,156, 65, 0, 3,128, 1, 0, + 0,193,129, 2, 0,156, 65, 0, 1,128, 1, 0, 0,193,193, 2, 0, 3, 2, 0, + 5,197, 66, 0, 0,198, 2,195, 5,156, 65, 0, 3,128, 1, 0, 0,193, 65, 3, + 0, 3, 2,128, 4,133, 66, 0, 0,134,130, 67, 5,195, 2,128, 5,156, 65, 0, + 3,133, 65, 0, 0,228,129, 1, 0,137,193,129,135,133, 65, 0, 0,228,193, 1, + 0,137,193, 1,136,128, 1, 0, 0,193, 65, 4, 0, 36, 2, 2, 0,100, 66, 2, + 0,156, 65, 0, 2,133, 65, 0, 0,228,129, 2, 0,137,193, 1,137,128, 1,128, + 0,193,193, 4, 0,156, 65, 0, 1,133, 65, 0, 0,228,193, 2, 0,137,193, 1, +138,133, 65, 0, 0,228, 1, 3, 0,137,193,129,138,128, 1, 0, 0,193,129, 5, + 0,156, 65, 0, 1,128, 1, 0, 0,193,193, 5, 0, 36, 66, 3, 0,100,130, 3, + 0,156, 65, 0, 2,128, 1, 0, 0,193, 1, 6, 0,156, 65, 0, 1,128, 1, 0, + 0,193, 65, 6, 0,156, 65, 0, 1,128, 1, 0, 0,193,129, 6, 0,156, 65, 0, + 1,128, 1, 0, 0,193,193, 6, 0,156, 65, 0, 1,128, 1, 0, 0,193, 1, 7, + 0,156, 65, 0, 1,128, 1, 0, 0,193, 65, 7, 0,156, 65, 0, 1,128, 1, 0, + 0,193,129, 7, 0,156, 65, 0, 1,128, 1, 0, 0,193,193, 7, 0,156, 65, 0, + 1,128, 1, 0, 0,193, 1, 8, 0,156, 65, 0, 1,128, 1, 0, 0,193, 65, 8, + 0,156, 65, 0, 1,128, 1, 0, 0,193,129, 8, 0,156, 65, 0, 1,128, 1, 0, + 0,193,193, 8, 0,156, 65, 0, 1,128, 1, 0, 0,193, 1, 9, 0,156, 65, 0, + 1,128, 1, 0, 0,193, 65, 9, 0,156, 65, 0, 1,128, 1, 0, 0,193,129, 9, + 0,156, 65, 0, 1,128, 1, 0, 0,193,193, 9, 0,156, 65, 0, 1,128, 1, 0, + 0,193, 1, 10, 0,156, 65, 0, 1,128, 1, 0, 0,193, 65, 10, 0,156, 65, 0, + 1,128, 1, 0, 0,193,129, 10, 0,156, 65, 0, 1,128, 1, 0, 0,193,193, 10, + 0,156, 65, 0, 1,128, 1, 0, 0,193, 1, 11, 0,156, 65, 0, 1,128, 1, 0, + 0,193, 65, 11, 0,156, 65, 0, 1,128, 1, 0, 0,193,129, 11, 0,156, 65, 0, + 1,128, 1, 0, 0,193,193, 11, 0,156, 65, 0, 1,128, 1, 0, 0,193, 1, 12, + 0,156, 65, 0, 1,128, 1, 0, 0,193, 65, 12, 0,156, 65, 0, 1,128, 1, 0, + 0,193,129, 12, 0,156, 65, 0, 1,128, 1, 0, 0,193,193, 12, 0,156, 65, 0, + 1,128, 1, 0, 0,193, 1, 13, 0,156, 65, 0, 1,128, 1, 0, 0,193, 65, 13, + 0,156, 65, 0, 1,128, 1, 0, 0,193,129, 13, 0,156, 65, 0, 1,128, 1, 0, + 0,193,193, 13, 0,156, 65, 0, 1,128, 1,128, 1,193, 1, 14, 0, 3, 2, 0, + 4,100,194, 3, 0,156, 65, 0, 2,133, 65, 0, 0,228, 1, 4, 0,137,193,129, +156,164, 65, 4, 0,192, 1, 0, 0, 1,130, 14, 0, 67, 2,128, 5, 0, 3, 0, + 3,220, 65, 0, 3,192, 1, 0, 0, 1,194, 14, 0, 67, 2,128, 5, 0, 3, 0, + 3,220, 65, 0, 3,192, 1, 0, 0, 1, 2, 15, 0,220, 65, 0, 1,192, 1, 0, + 0, 1, 66, 15, 0,220, 65, 0, 1,192, 1, 0, 0, 1,130, 15, 0,220, 65, 0, + 1,192, 1, 0, 0, 1,194, 15, 0,220, 65, 0, 1,192, 1, 0, 0, 1, 2, 16, + 0,220, 65, 0, 1,192, 1, 0, 0, 1, 66, 16, 0,220, 65, 0, 1,192, 1,128, + 0, 1,130, 16, 0,220, 65, 0, 1,197, 65, 0, 0, 36,130, 4, 0,201, 1,130, +161,192, 1,128, 0, 1, 2, 17, 0,220, 65, 0, 1,192, 1, 0, 1, 1, 66, 17, + 0,220, 65, 0, 1,192, 1,128, 1, 1,130, 17, 0,220, 65, 0, 1,192, 1,128, + 0, 1,194, 17, 0, 67, 2,128, 5, 5, 67, 0, 0, 6, 3, 82, 6,220, 65, 0, + 3,197, 65, 0, 0, 36,194, 4, 0,201, 1,130,164,197, 65, 0, 0, 36, 2, 5, + 0,201, 1, 2,165,192, 1,128, 0, 1,194, 18, 0,220, 65, 0, 1,192, 1, 0, + 0, 1, 2, 19, 0,220, 65, 0, 1,192, 1, 0, 0, 1, 66, 19, 0, 67, 2, 0, + 5,197, 66, 0, 0,198,130,211, 5, 3, 3, 0, 6,220, 65, 0, 3,192, 1, 0, + 0, 1,194, 19, 0,220, 65, 0, 1,192, 1, 0, 0, 1, 2, 20, 0,220, 65, 0, + 1,192, 1, 0, 0, 1, 66, 20, 0,220, 65, 0, 1,197, 65, 0, 0, 36, 66, 5, + 0,201, 1, 2,169,192, 1, 0, 2, 1,194, 20, 0, 67, 2, 0, 5,197, 66, 0, + 0,198, 2,194, 5, 5, 67, 0, 0, 6, 3, 67, 6,220, 65, 0, 3,192, 1, 0, + 1, 1, 2, 21, 0, 67, 2, 0, 5,197, 66, 0, 0,198, 66,213, 5, 5, 67, 0, + 0, 6,131, 85, 6,220, 65, 0, 3,197, 65, 0, 0, 36,130, 5, 0,201, 1,130, +171,197, 65, 0, 0, 36,194, 5, 0,201, 1, 2,172,192, 1, 0, 0, 1, 66, 22, + 0, 67, 2,128, 5, 5, 67, 0, 0, 6, 3, 67, 6,220, 65, 0, 3,192, 1, 0, + 0, 1,130, 22, 0,220, 65, 0, 1,192, 1,128, 0, 1,194, 22, 0,220, 65, 0, + 1,192, 1, 0, 0, 1, 2, 23, 0,220, 65, 0, 1,192, 1, 0, 0, 1, 66, 23, + 0,220, 65, 0, 1,192, 1, 0, 0, 1,130, 23, 0,220, 65, 0, 1,192, 1, 0, + 0, 1,194, 23, 0,220, 65, 0, 1,192, 1, 0, 0, 1, 2, 24, 0, 67, 2,128, + 5, 5, 67, 0, 0, 6,131, 85, 6,220, 65, 0, 3,192, 1, 0, 0, 1, 66, 24, + 0, 67, 2,128, 5, 5, 67, 0, 0, 6,131, 85, 6,220, 65, 0, 3,192, 1, 0, + 0, 1,130, 24, 0,220, 65, 0, 1,192, 1, 0, 0, 1,194, 24, 0, 67, 2, 0, + 5,197, 66, 0, 0,198,130,195, 5, 3, 3, 0, 6,220, 65, 0, 3,192, 1, 0, + 0, 1, 2, 25, 0, 67, 2, 0, 5,197, 66, 0, 0,198,130,195, 5, 3, 3, 0, + 6,220, 65, 0, 3,192, 1, 0, 0, 1, 66, 25, 0, 67, 2, 0, 5,197, 66, 0, + 0,198,130,195, 5, 3, 3, 0, 6,220, 65, 0, 3,192, 1,128, 0, 1,130, 25, + 0,220, 65, 0, 1,192, 1, 0, 0, 1,194, 25, 0, 67, 2, 0, 5,197, 66, 0, + 0,198,130,195, 5, 3, 3, 0, 6,220, 65, 0, 3,192, 1, 0, 0, 1, 2, 26, + 0, 67, 2, 0, 5,197, 66, 0, 0,198,130,195, 5, 3, 3, 0, 6,220, 65, 0, + 3,192, 1, 0, 0, 1, 66, 26, 0,220, 65, 0, 1,192, 1, 0, 0, 1,130, 26, + 0,220, 65, 0, 1,192, 1, 0, 0, 1,194, 26, 0,220, 65, 0, 1,192, 1, 0, + 0, 1, 2, 27, 0, 67, 2, 0, 5,197, 66, 0, 0,198,130,195, 5, 3, 3, 0, + 6,220, 65, 0, 3,192, 1, 0, 0, 1, 66, 27, 0, 67, 2, 0, 5,197, 66, 0, + 0,198,130,195, 5, 3, 3, 0, 6,220, 65, 0, 3,192, 1, 0, 0, 1,130, 27, + 0,220, 65, 0, 1,192, 1, 0, 0, 1,194, 27, 0,220, 65, 0, 1, 30, 0,128, + 0,112, 0, 0, 0, 4, 19, 0, 0, 0, 0, 0, 0, 0, 65,110, 97,108,121,122, +101, 70,105,110,100, 82,101,103,105,111,110,115, 0, 4, 3, 0, 0, 0, 0, 0, + 0, 0,105,109, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0, 85, 83, 72, 79, 82, 84, + 0, 4, 21, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 80,101,114, +105,109,101,116,101,114, 76,105,110,101, 0, 4, 13, 0, 0, 0, 0, 0, 0, 0, + 80,114,111, 99,101,115,115, 80,114,117,110,101, 0, 4, 17, 0, 0, 0, 0, 0, + 0, 0, 80,114,111, 99,101,115,115, 70,105,108,108, 72,111,108,101,115, 0, 4, + 18, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 72,111,117,103,104, + 76,105,110,101,115, 0, 3, 0, 0, 0, 0, 0,128,102, 64, 4, 5, 0, 0, 0, + 0, 0, 0, 0, 71, 82, 65, 89, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 73, 78, + 84, 0, 4, 22, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 72,111, +117,103,104, 76,105,110,101,115, 68,114, 97,119, 0, 4, 25, 0, 0, 0, 0, 0, + 0, 0, 80,114,111, 99,101,115,115, 68,105,115,116, 97,110, 99,101, 84,114, 97, +110,115,102,111,114,109, 0, 4, 6, 0, 0, 0, 0, 0, 0, 0, 70, 76, 79, 65, + 84, 0, 4, 23, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 82,101, +103,105,111,110, 97,108, 77, 97,120,105,109,117,109, 0, 4, 7, 0, 0, 0, 0, + 0, 0, 0, 66, 73, 78, 65, 82, 89, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 80, +114,111, 99,101,115,115, 82,101,100,117, 99,101, 78,101,119, 0, 4, 17, 0, 0, + 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 82,101,115,105,122,101, 78,101, +119, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 82,101, +100,117, 99,101, 66,121, 52, 0, 4, 15, 0, 0, 0, 0, 0, 0, 0, 80,114,111, + 99,101,115,115, 67,114,111,112, 78,101,119, 0, 4, 14, 0, 0, 0, 0, 0, 0, + 0, 80,114,111, 99,101,115,115, 73,110,115,101,114,116, 0, 4, 21, 0, 0, 0, + 0, 0, 0, 0, 80,114,111, 99,101,115,115, 65,100,100, 77, 97,114,103,105,110, +115, 78,101,119, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115, +115, 82,111,116, 97,116,101, 78,101,119, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, + 80,114,111, 99,101,115,115, 82,111,116, 97,116,101, 82,101,102, 0, 4, 16, 0, + 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 82,111,116, 97,116,101, 57, + 48, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 82,111, +116, 97,116,101, 49, 56, 48, 0, 4, 14, 0, 0, 0, 0, 0, 0, 0, 80,114,111, + 99,101,115,115, 77,105,114,114,111,114, 0, 4, 12, 0, 0, 0, 0, 0, 0, 0, + 80,114,111, 99,101,115,115, 70,108,105,112, 0, 4, 14, 0, 0, 0, 0, 0, 0, + 0, 80,114,111, 99,101,115,115, 82, 97,100,105, 97,108, 0, 4, 25, 0, 0, 0, + 0, 0, 0, 0, 80,114,111, 99,101,115,115, 71,114, 97,121, 77,111,114,112,104, + 67,111,110,118,111,108,118,101, 0, 4, 22, 0, 0, 0, 0, 0, 0, 0, 80,114, +111, 99,101,115,115, 71,114, 97,121, 77,111,114,112,104, 69,114,111,100,101, 0, + 4, 23, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 71,114, 97,121, + 77,111,114,112,104, 68,105,108, 97,116,101, 0, 4, 21, 0, 0, 0, 0, 0, 0, + 0, 80,114,111, 99,101,115,115, 71,114, 97,121, 77,111,114,112,104, 79,112,101, +110, 0, 4, 22, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 71,114, + 97,121, 77,111,114,112,104, 67,108,111,115,101, 0, 4, 23, 0, 0, 0, 0, 0, + 0, 0, 80,114,111, 99,101,115,115, 71,114, 97,121, 77,111,114,112,104, 84,111, +112, 72, 97,116, 0, 4, 21, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115, +115, 71,114, 97,121, 77,111,114,112,104, 87,101,108,108, 0, 4, 25, 0, 0, 0, + 0, 0, 0, 0, 80,114,111, 99,101,115,115, 71,114, 97,121, 77,111,114,112,104, + 71,114, 97,100,105,101,110,116, 0, 4, 24, 0, 0, 0, 0, 0, 0, 0, 80,114, +111, 99,101,115,115, 66,105,110, 77,111,114,112,104, 67,111,110,118,111,108,118, +101, 0, 4, 21, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 66,105, +110, 77,111,114,112,104, 69,114,111,100,101, 0, 4, 22, 0, 0, 0, 0, 0, 0, + 0, 80,114,111, 99,101,115,115, 66,105,110, 77,111,114,112,104, 68,105,108, 97, +116,101, 0, 4, 20, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 66, +105,110, 77,111,114,112,104, 79,112,101,110, 0, 4, 21, 0, 0, 0, 0, 0, 0, + 0, 80,114,111, 99,101,115,115, 66,105,110, 77,111,114,112,104, 67,108,111,115, +101, 0, 4, 23, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 66,105, +110, 77,111,114,112,104, 79,117,116,108,105,110,101, 0, 4, 20, 0, 0, 0, 0, + 0, 0, 0, 80,114,111, 99,101,115,115, 66,105,110, 77,111,114,112,104, 84,104, +105,110, 0, 4, 22, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 77, +101,100,105, 97,110, 67,111,110,118,111,108,118,101, 0, 4, 21, 0, 0, 0, 0, + 0, 0, 0, 80,114,111, 99,101,115,115, 82, 97,110,103,101, 67,111,110,118,111, +108,118,101, 0, 4, 27, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, + 82, 97,110,107, 67,108,111,115,101,115,116, 67,111,110,118,111,108,118,101, 0, + 4, 23, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 82, 97,110,107, + 77, 97,120, 67,111,110,118,111,108,118,101, 0, 4, 23, 0, 0, 0, 0, 0, 0, + 0, 80,114,111, 99,101,115,115, 82, 97,110,107, 77,105,110, 67,111,110,118,111, +108,118,101, 0, 4, 16, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, + 67,111,110,118,111,108,118,101, 0, 4, 19, 0, 0, 0, 0, 0, 0, 0, 80,114, +111, 99,101,115,115, 67,111,110,118,111,108,118,101, 83,101,112, 0, 4, 19, 0, + 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 67,111,110,118,111,108,118, +101, 82,101,112, 0, 4, 20, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115, +115, 67,111,110,118,111,108,118,101, 68,117, 97,108, 0, 4, 23, 0, 0, 0, 0, + 0, 0, 0, 80,114,111, 99,101,115,115, 67,111,109,112, 97,115,115, 67,111,110, +118,111,108,118,101, 0, 4, 20, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101, +115,115, 77,101, 97,110, 67,111,110,118,111,108,118,101, 0, 4, 24, 0, 0, 0, + 0, 0, 0, 0, 80,114,111, 99,101,115,115, 71, 97,117,115,115,105, 97,110, 67, +111,110,118,111,108,118,101, 0, 4, 23, 0, 0, 0, 0, 0, 0, 0, 80,114,111, + 99,101,115,115, 66, 97,114,108,101,116,116, 67,111,110,118,111,108,118,101, 0, + 4, 22, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 73,110,116,101, +114,108, 97, 99,101, 83,112,108,105,116, 0, 4, 25, 0, 0, 0, 0, 0, 0, 0, + 80,114,111, 99,101,115,115, 73,110,116,101,114,108, 97, 99,101, 83,112,108,105, +116, 78,101,119, 0, 4, 30, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115, +115, 68,105,102,102, 79,102, 71, 97,117,115,115,105, 97,110, 67,111,110,118,111, +108,118,101, 0, 4, 29, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, + 76, 97,112, 79,102, 71, 97,117,115,115,105, 97,110, 67,111,110,118,111,108,118, +101, 0, 4, 21, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 83,111, + 98,101,108, 67,111,110,118,111,108,118,101, 0, 4, 26, 0, 0, 0, 0, 0, 0, + 0, 80,114,111, 99,101,115,115, 83,112,108,105,110,101, 69,100,103,101, 67,111, +110,118,111,108,118,101, 0, 4, 23, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99, +101,115,115, 80,114,101,119,105,116,116, 67,111,110,118,111,108,118,101, 0, 4, + 20, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 90,101,114,111, 67, +114,111,115,115,105,110,103, 0, 4, 13, 0, 0, 0, 0, 0, 0, 0, 80,114,111, + 99,101,115,115, 67, 97,110,110,121, 0, 4, 22, 0, 0, 0, 0, 0, 0, 0, 80, +114,111, 99,101,115,115, 85,110, 65,114,105,116,104,109,101,116,105, 99, 79,112, + 0, 4, 20, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 65,114,105, +116,104,109,101,116,105, 99, 79,112, 0, 4, 28, 0, 0, 0, 0, 0, 0, 0, 80, +114,111, 99,101,115,115, 65,114,105,116,104,109,101,116,105, 99, 67,111,110,115, +116, 79,112, 78,101,119, 0, 4, 18, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99, +101,115,115, 66,108,101,110,100, 67,111,110,115,116, 0, 4, 13, 0, 0, 0, 0, + 0, 0, 0, 80,114,111, 99,101,115,115, 66,108,101,110,100, 0, 4, 20, 0, 0, + 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 83,112,108,105,116, 67,111,109, +112,108,101,120, 0, 4, 20, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115, +115, 77,101,114,103,101, 67,111,109,112,108,101,120, 0, 4, 7, 0, 0, 0, 0, + 0, 0, 0, 67, 70, 76, 79, 65, 84, 0, 4, 23, 0, 0, 0, 0, 0, 0, 0, 80, +114,111, 99,101,115,115, 77,117,108,116,105,112,108,101, 77,101, 97,110, 78,101, +119, 0, 4, 25, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 77,117, +108,116,105,112,108,101, 83,116,100, 68,101,118, 78,101,119, 0, 4, 22, 0, 0, + 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 65,117,116,111, 67,111,118, 97, +114,105, 97,110, 99,101, 0, 4, 20, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99, +101,115,115, 77,117,108,116,105,112,108,121, 67,111,110,106, 0, 4, 26, 0, 0, + 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 81,117, 97,110,116,105,122,101, + 82, 71, 66, 85,110,105,102,111,114,109, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, + 77, 65, 80, 0, 4, 27, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, + 81,117, 97,110,116,105,122,101, 71,114, 97,121, 85,110,105,102,111,114,109, 0, + 4, 23, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 69,120,112, 97, +110,100, 72,105,115,116,111,103,114, 97,109, 0, 4, 25, 0, 0, 0, 0, 0, 0, + 0, 80,114,111, 99,101,115,115, 69,113,117, 97,108,105,122,101, 72,105,115,116, +111,103,114, 97,109, 0, 4, 23, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101, +115,115, 83,112,108,105,116, 89, 67,104,114,111,109, 97, 78,101,119, 0, 4, 16, + 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 83,112,108,105,116, 72, + 83, 73, 0, 4, 16, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 77, +101,114,103,101, 72, 83, 73, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 82, 71, 66, + 0, 4, 5, 0, 0, 0, 0, 0, 0, 0, 66, 89, 84, 69, 0, 4, 26, 0, 0, 0, + 0, 0, 0, 0, 80,114,111, 99,101,115,115, 83,112,108,105,116, 67,111,109,112, +111,110,101,110,116,115, 78,101,119, 0, 4, 26, 0, 0, 0, 0, 0, 0, 0, 80, +114,111, 99,101,115,115, 77,101,114,103,101, 67,111,109,112,111,110,101,110,116, +115, 78,101,119, 0, 4, 27, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115, +115, 78,111,114,109, 97,108,105,122,101, 67,111,109,112,111,110,101,110,116,115, + 0, 4, 20, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 82,101,112, +108, 97, 99,101, 67,111,108,111,114, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 80, +114,111, 99,101,115,115, 66,105,116,119,105,115,101, 79,112, 0, 4, 18, 0, 0, + 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 66,105,116,119,105,115,101, 78, +111,116, 0, 4, 15, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 66, +105,116, 77, 97,115,107, 0, 4, 16, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99, +101,115,115, 66,105,116, 80,108, 97,110,101, 0, 4, 17, 0, 0, 0, 0, 0, 0, + 0, 80,114,111, 99,101,115,115, 84,111,110,101, 71, 97,109,117,116, 0, 4, 19, + 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 85,110, 78,111,114,109, + 97,108,105,122,101, 0, 4, 18, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101, +115,115, 68,105,114,101, 99,116, 67,111,110,118, 0, 4, 16, 0, 0, 0, 0, 0, + 0, 0, 80,114,111, 99,101,115,115, 78,101,103, 97,116,105,118,101, 0, 4, 30, + 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 82, 97,110,103,101, 67, +111,110,116,114, 97,115,116, 84,104,114,101,115,104,111,108,100, 0, 4, 25, 0, + 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 76,111, 99, 97,108, 77, 97, +120, 84,104,114,101,115,104,111,108,100, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, + 80,114,111, 99,101,115,115, 84,104,114,101,115,104,111,108,100, 0, 4, 23, 0, + 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 84,104,114,101,115,104,111, +108,100, 66,121, 68,105,102,102, 0, 4, 27, 0, 0, 0, 0, 0, 0, 0, 80,114, +111, 99,101,115,115, 72,121,115,116,101,114,101,115,105,115, 84,104,114,101,115, +104,111,108,100, 0, 4, 27, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115, +115, 85,110,105,102,111,114,109, 69,114,114, 84,104,114,101,115,104,111,108,100, + 0, 4, 28, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 68,105,102, +117,115,105,111,110, 69,114,114, 84,104,114,101,115,104,111,108,100, 0, 4, 24, + 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 80,101,114, 99,101,110, +116, 84,104,114,101,115,104,111,108,100, 0, 4, 21, 0, 0, 0, 0, 0, 0, 0, + 80,114,111, 99,101,115,115, 79,116,115,117, 84,104,114,101,115,104,111,108,100, + 0, 4, 23, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 77,105,110, + 77, 97,120, 84,104,114,101,115,104,111,108,100, 0, 4, 22, 0, 0, 0, 0, 0, + 0, 0, 80,114,111, 99,101,115,115, 83,108,105, 99,101, 84,104,114,101,115,104, +111,108,100, 0, 4, 16, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, + 80,105,120,101,108, 97,116,101, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 80,114, +111, 99,101,115,115, 80,111,115,116,101,114,105,122,101, 0, 24, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 25, 0, 0, 0, 0, 5, 0, 9, 17, + 0, 0, 0, 69, 1, 0, 0, 70, 1,128, 2,133, 65, 0, 0,192, 1,128, 2,156, + 65, 0, 1,133, 1, 0, 0,192, 1, 0, 0, 1,130, 0, 0,213, 1,130, 3, 36, + 2, 0, 0, 0, 0,128, 0, 0, 0, 0, 1, 0, 0,128, 1, 0, 0, 0, 2, 0, + 0,128, 2,137, 1,130, 3, 30, 0,128, 0, 3, 0, 0, 0, 4, 3, 0, 0, 0, + 0, 0, 0, 0,105,109, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0, 97,115,115,101, +114,116, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 78,101,119, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 24, 0, 0, 0, 5, 1, 7, 8, + 23, 0, 0, 0,133, 0, 0, 0,134, 64, 64, 1,192, 0, 0, 0, 4, 1, 0, 0, + 68, 1,128, 0,132, 1, 0, 1,196, 1,128, 1,156,128, 0, 3,196, 0, 0, 2, + 0, 1, 0, 0, 64, 1, 0, 1,133,129, 0, 0,192, 1,128, 0,156, 1, 0, 1, +220,128, 0, 0,218, 0, 0, 0, 22,192, 0,128, 0, 1,128, 1, 64, 1, 0, 1, + 30, 1,128, 1, 22, 0, 0,128,158, 0, 0, 1, 30, 0,128, 0, 3, 0, 0, 0, + 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, 0, 0, 0, + 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 4, 7, + 0, 0, 0, 0, 0, 0, 0,117,110,112, 97, 99,107, 0, 0, 0, 0, 0, 23, 0, + 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, + 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, 18, 0, 0, 0, 18, 0, + 0, 0, 18, 0, 0, 0, 18, 0, 0, 0, 18, 0, 0, 0, 18, 0, 0, 0, 18, 0, + 0, 0, 19, 0, 0, 0, 19, 0, 0, 0, 20, 0, 0, 0, 20, 0, 0, 0, 20, 0, + 0, 0, 20, 0, 0, 0, 22, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, + 22, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 97,114,103, 0, 0, 0, 0, 0, + 22, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,100,115,116, 95,105,109, 97,103, +101, 0, 8, 0, 0, 0, 22, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0,114,101, +116, 0, 15, 0, 0, 0, 22, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, 0, + 0, 0,119,105,100,116,104, 0, 7, 0, 0, 0, 0, 0, 0, 0,104,101,105,103, +104,116, 0, 12, 0, 0, 0, 0, 0, 0, 0, 99,111,108,111,114, 95,115,112, 97, + 99,101, 0, 10, 0, 0, 0, 0, 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, + 0, 5, 0, 0, 0, 0, 0, 0, 0,102,117,110, 99, 0, 17, 0, 0, 0, 9, 0, + 0, 0, 9, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 13, 0, + 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 24, 0, 0, 0, 24, 0, + 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, + 0, 0, 25, 0, 0, 0, 6, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,102,117, +110, 99,110, 97,109,101, 0, 0, 0, 0, 0, 16, 0, 0, 0, 6, 0, 0, 0, 0, + 0, 0, 0,119,105,100,116,104, 0, 0, 0, 0, 0, 16, 0, 0, 0, 7, 0, 0, + 0, 0, 0, 0, 0,104,101,105,103,104,116, 0, 0, 0, 0, 0, 16, 0, 0, 0, + 12, 0, 0, 0, 0, 0, 0, 0, 99,111,108,111,114, 95,115,112, 97, 99,101, 0, + 0, 0, 0, 0, 16, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,100, 97,116, 97, + 95,116,121,112,101, 0, 0, 0, 0, 0, 16, 0, 0, 0, 5, 0, 0, 0, 0, 0, + 0, 0,102,117,110, 99, 0, 2, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, 50, 0, 0, 0, 0, 5, 0, 11, 22, + 0, 0, 0, 69, 1, 0, 0, 70, 1,128, 2,133, 65, 0, 0,192, 1,128, 2, 5, +130, 0, 0, 6,194, 64, 4, 65, 2, 1, 0,128, 2, 0, 0, 28, 2,128, 1,156, + 65, 0, 0,133, 1, 0, 0,192, 1, 0, 0, 1, 66, 1, 0,213, 1,130, 3, 36, + 2, 0, 0, 0, 0,128, 0, 0, 0, 0, 1, 0, 0,128, 1, 0, 0, 0, 2, 0, + 0,128, 2,137, 1,130, 3, 30, 0,128, 0, 6, 0, 0, 0, 4, 3, 0, 0, 0, + 0, 0, 0, 0,105,109, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0, 97,115,115,101, +114,116, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0,115,116,114,105,110,103, 0, 4, + 7, 0, 0, 0, 0, 0, 0, 0,102,111,114,109, 97,116, 0, 4, 24, 0, 0, 0, + 0, 0, 0, 0,117,110,100,101,102,105,110,101,100, 32,102,117,110, 99,116,105, +111,110, 32, 96, 37,115, 39, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 78,101,119, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, 49, 0, 0, + 0, 5, 2, 7, 10, 24, 0, 0, 0,197, 0, 0, 0,198, 64,192, 1, 0, 1, 0, + 0, 68, 1, 0, 0,132, 1,128, 0,196, 1, 0, 1, 4, 2,128, 1,220,128, 0, + 3, 4, 1, 0, 2, 64, 1, 0, 0,128, 1,128, 0,192, 1,128, 1, 5,130, 0, + 0, 64, 2, 0, 1, 28, 2, 0, 1, 28,129, 0, 0, 26, 1, 0, 0, 22,192, 0, +128, 64, 1, 0, 2,128, 1,128, 1, 94, 1,128, 1, 22, 0, 0,128,222, 0, 0, + 1, 30, 0,128, 0, 3, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, + 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116, +101, 66, 97,115,101,100, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0,117,110,112, 97, + 99,107, 0, 0, 0, 0, 0, 24, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, + 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, + 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, 43, + 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, 43, 0, 0, 0, 44, 0, 0, 0, 44, + 0, 0, 0, 45, 0, 0, 0, 45, 0, 0, 0, 45, 0, 0, 0, 45, 0, 0, 0, 47, + 0, 0, 0, 49, 0, 0, 0, 5, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0,115, +114, 99, 95,105,109, 97,103,101, 49, 0, 0, 0, 0, 0, 23, 0, 0, 0, 11, 0, + 0, 0, 0, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 50, 0, 0, 0, 0, + 0, 23, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 97,114,103, 0, 0, 0, 0, + 0, 23, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,100,115,116, 95,105,109, 97, +103,101, 0, 8, 0, 0, 0, 23, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0,114, +101,116, 0, 16, 0, 0, 0, 23, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, + 0, 0, 0,119,105,100,116,104, 0, 7, 0, 0, 0, 0, 0, 0, 0,104,101,105, +103,104,116, 0, 12, 0, 0, 0, 0, 0, 0, 0, 99,111,108,111,114, 95,115,112, + 97, 99,101, 0, 10, 0, 0, 0, 0, 0, 0, 0,100, 97,116, 97, 95,116,121,112, +101, 0, 5, 0, 0, 0, 0, 0, 0, 0,102,117,110, 99, 0, 22, 0, 0, 0, 32, + 0, 0, 0, 32, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, 35, + 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, 35, 0, 0, 0, 38, + 0, 0, 0, 38, 0, 0, 0, 38, 0, 0, 0, 38, 0, 0, 0, 49, 0, 0, 0, 49, + 0, 0, 0, 49, 0, 0, 0, 49, 0, 0, 0, 49, 0, 0, 0, 49, 0, 0, 0, 49, + 0, 0, 0, 50, 0, 0, 0, 6, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,102, +117,110, 99,110, 97,109,101, 0, 0, 0, 0, 0, 21, 0, 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0,119,105,100,116,104, 0, 0, 0, 0, 0, 21, 0, 0, 0, 7, 0, + 0, 0, 0, 0, 0, 0,104,101,105,103,104,116, 0, 0, 0, 0, 0, 21, 0, 0, + 0, 12, 0, 0, 0, 0, 0, 0, 0, 99,111,108,111,114, 95,115,112, 97, 99,101, + 0, 0, 0, 0, 0, 21, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,100, 97,116, + 97, 95,116,121,112,101, 0, 0, 0, 0, 0, 21, 0, 0, 0, 5, 0, 0, 0, 0, + 0, 0, 0,102,117,110, 99, 0, 2, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 73, 0, 0, 0, 0, 5, 0, 9, + 17, 0, 0, 0, 69, 1, 0, 0, 70, 1,128, 2,133, 65, 0, 0,192, 1,128, 2, +156, 65, 0, 1,133, 1, 0, 0,192, 1, 0, 0, 1,130, 0, 0,213, 1,130, 3, + 36, 2, 0, 0, 0, 0,128, 0, 0, 0, 0, 1, 0, 0,128, 1, 0, 0, 0, 2, + 0, 0,128, 2,137, 1,130, 3, 30, 0,128, 0, 3, 0, 0, 0, 4, 3, 0, 0, + 0, 0, 0, 0, 0,105,109, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0, 97,115,115, +101,114,116, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 78,101,119, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 0, 0, 72, 0, 0, 0, 5, 3, 7, + 12, 25, 0, 0, 0, 5, 1, 0, 0, 6, 65, 64, 2, 64, 1, 0, 0,132, 1, 0, + 0,196, 1,128, 0, 4, 2, 0, 1, 68, 2,128, 1, 28,129, 0, 3, 68, 1, 0, + 2,128, 1, 0, 0,192, 1,128, 0, 0, 2, 0, 1, 64, 2, 0, 2,133,130, 0, + 0,192, 2,128, 1,156, 2, 0, 1, 92,129, 0, 0, 90, 1, 0, 0, 22,192, 0, +128,128, 1,128, 2,192, 1, 0, 2,158, 1,128, 1, 22, 0, 0,128, 30, 1, 0, + 1, 30, 0,128, 0, 3, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, + 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116, +101, 66, 97,115,101,100, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0,117,110,112, 97, + 99,107, 0, 0, 0, 0, 0, 25, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, + 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 63, + 0, 0, 0, 66, 0, 0, 0, 66, 0, 0, 0, 66, 0, 0, 0, 66, 0, 0, 0, 66, + 0, 0, 0, 66, 0, 0, 0, 66, 0, 0, 0, 66, 0, 0, 0, 66, 0, 0, 0, 67, + 0, 0, 0, 67, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, + 0, 0, 0, 70, 0, 0, 0, 72, 0, 0, 0, 6, 0, 0, 0, 11, 0, 0, 0, 0, + 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 49, 0, 0, 0, 0, 0, 24, 0, + 0, 0, 11, 0, 0, 0, 0, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 50, + 0, 0, 0, 0, 0, 24, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0,115,114, 99, + 95,105,109, 97,103,101, 51, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 97,114,103, 0, 0, 0, 0, 0, 24, 0, 0, 0, 10, 0, 0, 0, + 0, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 0, 8, 0, 0, 0, 24, 0, + 0, 0, 4, 0, 0, 0, 0, 0, 0, 0,114,101,116, 0, 17, 0, 0, 0, 24, 0, + 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119,105,100,116,104, 0, + 7, 0, 0, 0, 0, 0, 0, 0,104,101,105,103,104,116, 0, 12, 0, 0, 0, 0, + 0, 0, 0, 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 10, 0, 0, 0, 0, + 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, 0, 5, 0, 0, 0, 0, 0, 0, + 0,102,117,110, 99, 0, 17, 0, 0, 0, 57, 0, 0, 0, 57, 0, 0, 0, 58, 0, + 0, 0, 58, 0, 0, 0, 58, 0, 0, 0, 61, 0, 0, 0, 61, 0, 0, 0, 61, 0, + 0, 0, 61, 0, 0, 0, 72, 0, 0, 0, 72, 0, 0, 0, 72, 0, 0, 0, 72, 0, + 0, 0, 72, 0, 0, 0, 72, 0, 0, 0, 72, 0, 0, 0, 73, 0, 0, 0, 6, 0, + 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,102,117,110, 99,110, 97,109,101, 0, 0, + 0, 0, 0, 16, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119,105,100,116,104, + 0, 0, 0, 0, 0, 16, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0,104,101,105, +103,104,116, 0, 0, 0, 0, 0, 16, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, + 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 0, 0, 0, 0, 16, 0, 0, 0, + 10, 0, 0, 0, 0, 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, 0, 0, 0, + 0, 0, 16, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,102,117,110, 99, 0, 2, + 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, + 0, 0, 0, 97, 0, 0, 0, 0, 5, 0, 9, 17, 0, 0, 0, 69, 1, 0, 0, 70, + 1,128, 2,133, 65, 0, 0,192, 1,128, 2,156, 65, 0, 1,133, 1, 0, 0,192, + 1, 0, 0, 1,130, 0, 0,213, 1,130, 3, 36, 2, 0, 0, 0, 0,128, 0, 0, + 0, 0, 1, 0, 0,128, 1, 0, 0, 0, 2, 0, 0,128, 2,137, 1,130, 3, 30, + 0,128, 0, 3, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, + 7, 0, 0, 0, 0, 0, 0, 0, 97,115,115,101,114,116, 0, 4, 4, 0, 0, 0, + 0, 0, 0, 0, 78,101,119, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 84, 0, 0, 0, 96, 0, 0, 0, 5, 1, 7, 10, 35, 0, 0, 0,133, 0, 0, 0, +134, 64, 64, 1,192, 0, 0, 0, 4, 1, 0, 0, 68, 1,128, 0,132, 1, 0, 1, +196, 1,128, 1,156,128, 0, 3,197, 0, 0, 0,198, 64,192, 1, 0, 1, 0, 0, + 68, 1, 0, 0,132, 1,128, 0,196, 1, 0, 1, 4, 2,128, 1,220,128, 0, 3, + 4, 1, 0, 2, 64, 1, 0, 0,128, 1, 0, 1,192, 1,128, 1, 5,130, 0, 0, + 64, 2,128, 0, 28, 2, 0, 1, 28,129, 0, 0, 26, 1, 0, 0, 22, 0, 1,128, + 64, 1, 0, 2,128, 1, 0, 1,192, 1,128, 1, 94, 1, 0, 2, 22,128, 0,128, + 64, 1, 0, 1,128, 1,128, 1, 94, 1,128, 1, 30, 0,128, 0, 3, 0, 0, 0, + 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, 0, 0, 0, + 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 4, 7, + 0, 0, 0, 0, 0, 0, 0,117,110,112, 97, 99,107, 0, 0, 0, 0, 0, 35, 0, + 0, 0, 86, 0, 0, 0, 86, 0, 0, 0, 86, 0, 0, 0, 86, 0, 0, 0, 86, 0, + 0, 0, 86, 0, 0, 0, 86, 0, 0, 0, 86, 0, 0, 0, 87, 0, 0, 0, 87, 0, + 0, 0, 87, 0, 0, 0, 87, 0, 0, 0, 87, 0, 0, 0, 87, 0, 0, 0, 87, 0, + 0, 0, 87, 0, 0, 0, 90, 0, 0, 0, 90, 0, 0, 0, 90, 0, 0, 0, 90, 0, + 0, 0, 90, 0, 0, 0, 90, 0, 0, 0, 90, 0, 0, 0, 90, 0, 0, 0, 91, 0, + 0, 0, 91, 0, 0, 0, 92, 0, 0, 0, 92, 0, 0, 0, 92, 0, 0, 0, 92, 0, + 0, 0, 92, 0, 0, 0, 94, 0, 0, 0, 94, 0, 0, 0, 94, 0, 0, 0, 96, 0, + 0, 0, 5, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,115,114, 99, 95,105,109, + 97,103,101, 0, 0, 0, 0, 0, 34, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, + 97,114,103, 0, 0, 0, 0, 0, 34, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, +100,115,116, 95,105,109, 97,103,101, 49, 0, 8, 0, 0, 0, 34, 0, 0, 0, 11, + 0, 0, 0, 0, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 50, 0, 16, 0, + 0, 0, 34, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0,114,101,116, 0, 24, 0, + 0, 0, 34, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119,105, +100,116,104, 0, 7, 0, 0, 0, 0, 0, 0, 0,104,101,105,103,104,116, 0, 12, + 0, 0, 0, 0, 0, 0, 0, 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 10, + 0, 0, 0, 0, 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, 0, 5, 0, 0, + 0, 0, 0, 0, 0,102,117,110, 99, 0, 17, 0, 0, 0, 80, 0, 0, 0, 80, 0, + 0, 0, 81, 0, 0, 0, 81, 0, 0, 0, 81, 0, 0, 0, 84, 0, 0, 0, 84, 0, + 0, 0, 84, 0, 0, 0, 84, 0, 0, 0, 96, 0, 0, 0, 96, 0, 0, 0, 96, 0, + 0, 0, 96, 0, 0, 0, 96, 0, 0, 0, 96, 0, 0, 0, 96, 0, 0, 0, 97, 0, + 0, 0, 6, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,102,117,110, 99,110, 97, +109,101, 0, 0, 0, 0, 0, 16, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119, +105,100,116,104, 0, 0, 0, 0, 0, 16, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, + 0,104,101,105,103,104,116, 0, 0, 0, 0, 0, 16, 0, 0, 0, 12, 0, 0, 0, + 0, 0, 0, 0, 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,100, 97,116, 97, 95,116,121,112, +101, 0, 0, 0, 0, 0, 16, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,102,117, +110, 99, 0, 2, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,103, 0, 0, 0,122, 0, 0, 0, 0, 5, 0, 9, 17, 0, 0, 0, 69, + 1, 0, 0, 70, 1,128, 2,133, 65, 0, 0,192, 1,128, 2,156, 65, 0, 1,133, + 1, 0, 0,192, 1, 0, 0, 1,130, 0, 0,213, 1,130, 3, 36, 2, 0, 0, 0, + 0,128, 0, 0, 0, 0, 1, 0, 0,128, 1, 0, 0, 0, 2, 0, 0,128, 2,137, + 1,130, 3, 30, 0,128, 0, 3, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0, +105,109, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0, 97,115,115,101,114,116, 0, 4, + 4, 0, 0, 0, 0, 0, 0, 0, 78,101,119, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,108, 0, 0, 0,121, 0, 0, 0, 5, 1, 7, 12, 46, 0, 0, 0, +133, 0, 0, 0,134, 64, 64, 1,192, 0, 0, 0, 4, 1, 0, 0, 68, 1,128, 0, +132, 1, 0, 1,196, 1,128, 1,156,128, 0, 3,197, 0, 0, 0,198, 64,192, 1, + 0, 1, 0, 0, 68, 1, 0, 0,132, 1,128, 0,196, 1, 0, 1, 4, 2,128, 1, +220,128, 0, 3, 5, 1, 0, 0, 6, 65, 64, 2, 64, 1, 0, 0,132, 1, 0, 0, +196, 1,128, 0, 4, 2, 0, 1, 68, 2,128, 1, 28,129, 0, 3, 68, 1, 0, 2, +128, 1, 0, 0,192, 1, 0, 1, 0, 2,128, 1, 64, 2, 0, 2,133,130, 0, 0, +192, 2,128, 0,156, 2, 0, 1, 92,129, 0, 0, 90, 1, 0, 0, 22, 64, 1,128, +128, 1,128, 2,192, 1, 0, 1, 0, 2,128, 1, 64, 2, 0, 2,158, 1,128, 2, + 22,192, 0,128,128, 1, 0, 1,192, 1,128, 1, 0, 2, 0, 2,158, 1, 0, 2, + 30, 0,128, 0, 3, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, + 4, 17, 0, 0, 0, 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, + 66, 97,115,101,100, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0,117,110,112, 97, 99, +107, 0, 0, 0, 0, 0, 46, 0, 0, 0,110, 0, 0, 0,110, 0, 0, 0,110, 0, + 0, 0,110, 0, 0, 0,110, 0, 0, 0,110, 0, 0, 0,110, 0, 0, 0,110, 0, + 0, 0,111, 0, 0, 0,111, 0, 0, 0,111, 0, 0, 0,111, 0, 0, 0,111, 0, + 0, 0,111, 0, 0, 0,111, 0, 0, 0,111, 0, 0, 0,112, 0, 0, 0,112, 0, + 0, 0,112, 0, 0, 0,112, 0, 0, 0,112, 0, 0, 0,112, 0, 0, 0,112, 0, + 0, 0,112, 0, 0, 0,115, 0, 0, 0,115, 0, 0, 0,115, 0, 0, 0,115, 0, + 0, 0,115, 0, 0, 0,115, 0, 0, 0,115, 0, 0, 0,115, 0, 0, 0,115, 0, + 0, 0,116, 0, 0, 0,116, 0, 0, 0,117, 0, 0, 0,117, 0, 0, 0,117, 0, + 0, 0,117, 0, 0, 0,117, 0, 0, 0,117, 0, 0, 0,119, 0, 0, 0,119, 0, + 0, 0,119, 0, 0, 0,119, 0, 0, 0,121, 0, 0, 0, 6, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, + 45, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 97,114,103, 0, 0, 0, 0, 0, + 45, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0,100,115,116, 95,105,109, 97,103, +101, 49, 0, 8, 0, 0, 0, 45, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0,100, +115,116, 95,105,109, 97,103,101, 50, 0, 16, 0, 0, 0, 45, 0, 0, 0, 11, 0, + 0, 0, 0, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 51, 0, 24, 0, 0, + 0, 45, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0,114,101,116, 0, 33, 0, 0, + 0, 45, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119,105,100, +116,104, 0, 7, 0, 0, 0, 0, 0, 0, 0,104,101,105,103,104,116, 0, 12, 0, + 0, 0, 0, 0, 0, 0, 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 10, 0, + 0, 0, 0, 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, 0, 5, 0, 0, 0, + 0, 0, 0, 0,102,117,110, 99, 0, 17, 0, 0, 0,104, 0, 0, 0,104, 0, 0, + 0,105, 0, 0, 0,105, 0, 0, 0,105, 0, 0, 0,108, 0, 0, 0,108, 0, 0, + 0,108, 0, 0, 0,108, 0, 0, 0,121, 0, 0, 0,121, 0, 0, 0,121, 0, 0, + 0,121, 0, 0, 0,121, 0, 0, 0,121, 0, 0, 0,121, 0, 0, 0,122, 0, 0, + 0, 6, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,102,117,110, 99,110, 97,109, +101, 0, 0, 0, 0, 0, 16, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119,105, +100,116,104, 0, 0, 0, 0, 0, 16, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, +104,101,105,103,104,116, 0, 0, 0, 0, 0, 16, 0, 0, 0, 12, 0, 0, 0, 0, + 0, 0, 0, 99,111,108,111,114, 95,115,112, 97, 99,101, 0, 0, 0, 0, 0, 16, + 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,100, 97,116, 97, 95,116,121,112,101, + 0, 0, 0, 0, 0, 16, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,102,117,110, + 99, 0, 2, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,126, 0, 0, 0,130, 0, 0, 0, 0, 1, 0, 7, 18, 0, 0, 0,100, 0, + 0, 0,133, 0, 0, 0,134, 64, 64, 1,192, 0,128, 0, 11,129, 64, 0, 28, 1, + 0, 1,220,128, 0, 0, 0, 1,128, 0, 75,193, 64, 0, 92, 1, 0, 1, 28,129, + 0, 0,204, 0,129, 1,156,128, 0, 1,143, 0, 65, 1,206,128, 0,130,204, 64, +193, 1,222, 0, 0, 1, 30, 0,128, 0, 6, 0, 0, 0, 4, 5, 0, 0, 0, 0, + 0, 0, 0,109, 97,116,104, 0, 4, 5, 0, 0, 0, 0, 0, 0, 0,115,113,114, +116, 0, 4, 6, 0, 0, 0, 0, 0, 0, 0, 87,105,100,116,104, 0, 4, 7, 0, + 0, 0, 0, 0, 0, 0, 72,101,105,103,104,116, 0, 3, 0, 0, 0, 0, 0, 0, + 0, 64, 3, 0, 0, 0, 0, 0, 0,240, 63, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,127, 0, 0, 0,127, 0, 0, 0, 0, 1, 0, 2, 3, 0, 0, 0, 78, + 0, 0, 0, 94, 0, 0, 1, 30, 0,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, + 0, 0, 0,127, 0, 0, 0,127, 0, 0, 0,127, 0, 0, 0, 1, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 0, 0,120, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, + 0, 18, 0, 0, 0,127, 0, 0, 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, 0, + 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, 0, + 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, 0, 0,128, 0, 0, + 0,129, 0, 0, 0,129, 0, 0, 0,129, 0, 0, 0,130, 0, 0, 0, 3, 0, 0, + 0, 6, 0, 0, 0, 0, 0, 0, 0,105,109, 97,103,101, 0, 0, 0, 0, 0, 17, + 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0,115,113,114, 0, 1, 0, 0, 0, 17, + 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,114,109, 97,120, 0, 14, 0, 0, 0, + 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,141, 0, 0, 0, +144, 0, 0, 0, 0, 3, 0, 7, 14, 0, 0, 0,197, 0, 0, 0,198, 64,192, 1, + 0, 1, 0, 0, 64, 1,128, 0,128, 1, 0, 1,220,128, 0, 2, 5, 1, 0, 0, + 6,129, 64, 2, 64, 1, 0, 0,128, 1,128, 1, 28,129,128, 1, 64, 1,128, 1, + 30, 1,128, 1, 30, 0,128, 0, 3, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, + 0,105,109, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 73,109, 97,103,101, 67,114, +101, 97,116,101, 66, 97,115,101,100, 0, 4, 14, 0, 0, 0, 0, 0, 0, 0, 80, +114,111, 99,101,115,115, 82,101,100,117, 99,101, 0, 0, 0, 0, 0, 14, 0, 0, + 0,142, 0, 0, 0,142, 0, 0, 0,142, 0, 0, 0,142, 0, 0, 0,142, 0, 0, + 0,142, 0, 0, 0,143, 0, 0, 0,143, 0, 0, 0,143, 0, 0, 0,143, 0, 0, + 0,143, 0, 0, 0,143, 0, 0, 0,143, 0, 0, 0,144, 0, 0, 0, 4, 0, 0, + 0, 10, 0, 0, 0, 0, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 0, 0, + 0, 0, 0, 13, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119,105,100,116,104, + 0, 0, 0, 0, 0, 13, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0,104,101,105, +103,104,116, 0, 0, 0, 0, 0, 13, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, +100,115,116, 95,105,109, 97,103,101, 0, 6, 0, 0, 0, 13, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,146, 0, 0, 0,149, 0, 0, 0, 0, 3, + 0, 7, 14, 0, 0, 0,197, 0, 0, 0,198, 64,192, 1, 0, 1, 0, 0, 64, 1, +128, 0,128, 1, 0, 1,220,128, 0, 2, 5, 1, 0, 0, 6,129, 64, 2, 64, 1, + 0, 0,128, 1,128, 1, 28,129,128, 1, 64, 1,128, 1, 30, 1,128, 1, 30, 0, +128, 0, 3, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 17, + 0, 0, 0, 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97, +115,101,100, 0, 4, 14, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, + 82,101,115,105,122,101, 0, 0, 0, 0, 0, 14, 0, 0, 0,147, 0, 0, 0,147, + 0, 0, 0,147, 0, 0, 0,147, 0, 0, 0,147, 0, 0, 0,147, 0, 0, 0,148, + 0, 0, 0,148, 0, 0, 0,148, 0, 0, 0,148, 0, 0, 0,148, 0, 0, 0,148, + 0, 0, 0,148, 0, 0, 0,149, 0, 0, 0, 4, 0, 0, 0, 10, 0, 0, 0, 0, + 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 13, 0, 0, + 0, 6, 0, 0, 0, 0, 0, 0, 0,119,105,100,116,104, 0, 0, 0, 0, 0, 13, + 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0,104,101,105,103,104,116, 0, 0, 0, + 0, 0, 13, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,100,115,116, 95,105,109, + 97,103,101, 0, 6, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,151, 0, 0, 0,151, 0, 0, 0, 0, 1, 0, 3, 5, 0, 0, 0, + 75, 0, 64, 0, 92,128, 0, 1, 79, 64,192, 0, 94, 0, 0, 1, 30, 0,128, 0, + 2, 0, 0, 0, 4, 6, 0, 0, 0, 0, 0, 0, 0, 87,105,100,116,104, 0, 3, + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 5, 0, 0, 0,151, 0, 0, 0, +151, 0, 0, 0,151, 0, 0, 0,151, 0, 0, 0,151, 0, 0, 0, 1, 0, 0, 0, + 6, 0, 0, 0, 0, 0, 0, 0,105,109, 97,103,101, 0, 0, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,152, 0, 0, 0,152, 0, + 0, 0, 0, 1, 0, 3, 5, 0, 0, 0, 75, 0, 64, 0, 92,128, 0, 1, 79, 64, +192, 0, 94, 0, 0, 1, 30, 0,128, 0, 2, 0, 0, 0, 4, 7, 0, 0, 0, 0, + 0, 0, 0, 72,101,105,103,104,116, 0, 3, 0, 0, 0, 0, 0, 0, 0, 64, 0, + 0, 0, 0, 5, 0, 0, 0,152, 0, 0, 0,152, 0, 0, 0,152, 0, 0, 0,152, + 0, 0, 0,152, 0, 0, 0, 1, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,105, +109, 97,103,101, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0,154, 0, 0, 0,160, 0, 0, 0, 0, 5, 0, 13, 19, 0, 0, + 0, 77, 65, 0, 1, 76, 1,192, 2,141,193, 0, 1,140, 1, 64, 3,197, 65, 0, + 0,198,129,192, 3, 0, 2, 0, 0, 64, 2,128, 2,128, 2, 0, 3,220,129, 0, + 2, 5, 66, 0, 0, 6,194, 64, 4, 64, 2, 0, 0,128, 2,128, 3,192, 2,128, + 0, 0, 3,128, 1, 28, 66,128, 2,222, 1, 0, 1, 30, 0,128, 0, 4, 0, 0, + 0, 3, 0, 0, 0, 0, 0, 0,240, 63, 4, 3, 0, 0, 0, 0, 0, 0, 0,105, +109, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97, +116,101, 66, 97,115,101,100, 0, 4, 12, 0, 0, 0, 0, 0, 0, 0, 80,114,111, + 99,101,115,115, 67,114,111,112, 0, 0, 0, 0, 0, 19, 0, 0, 0,155, 0, 0, + 0,155, 0, 0, 0,156, 0, 0, 0,156, 0, 0, 0,157, 0, 0, 0,157, 0, 0, + 0,157, 0, 0, 0,157, 0, 0, 0,157, 0, 0, 0,157, 0, 0, 0,158, 0, 0, + 0,158, 0, 0, 0,158, 0, 0, 0,158, 0, 0, 0,158, 0, 0, 0,158, 0, 0, + 0,158, 0, 0, 0,159, 0, 0, 0,160, 0, 0, 0, 8, 0, 0, 0, 10, 0, 0, + 0, 0, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 18, + 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,120,109,105,110, 0, 0, 0, 0, 0, + 18, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,120,109, 97,120, 0, 0, 0, 0, + 0, 18, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,121,109,105,110, 0, 0, 0, + 0, 0, 18, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,121,109, 97,120, 0, 0, + 0, 0, 0, 18, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,119,105,100,116,104, + 0, 2, 0, 0, 0, 18, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0,104,101,105, +103,104,116, 0, 4, 0, 0, 0, 18, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, +100,115,116, 95,105,109, 97,103,101, 0, 10, 0, 0, 0, 18, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,164, 0, 0, 0,170, 0, 0, 0, 0, 5, + 0, 13, 19, 0, 0, 0, 77, 65, 0, 1, 76, 1,192, 2,141,193, 0, 1,140, 1, + 64, 3,197, 65, 0, 0,198,129,192, 3, 0, 2, 0, 0, 64, 2,128, 2,128, 2, + 0, 3,220,129, 0, 2, 5, 66, 0, 0, 6,194, 64, 4, 64, 2, 0, 0,128, 2, +128, 3,192, 2,128, 0, 0, 3,128, 1, 28, 66,128, 2,222, 1, 0, 1, 30, 0, +128, 0, 4, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,240, 63, 4, 3, 0, 0, 0, + 0, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 73,109, 97,103, +101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 4, 18, 0, 0, 0, 0, 0, + 0, 0, 80,114,111, 99,101,115,115, 65,100,100, 77, 97,114,103,105,110,115, 0, + 0, 0, 0, 0, 19, 0, 0, 0,165, 0, 0, 0,165, 0, 0, 0,166, 0, 0, 0, +166, 0, 0, 0,167, 0, 0, 0,167, 0, 0, 0,167, 0, 0, 0,167, 0, 0, 0, +167, 0, 0, 0,167, 0, 0, 0,168, 0, 0, 0,168, 0, 0, 0,168, 0, 0, 0, +168, 0, 0, 0,168, 0, 0, 0,168, 0, 0, 0,168, 0, 0, 0,169, 0, 0, 0, +170, 0, 0, 0, 8, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,115,114, 99, 95, +105,109, 97,103,101, 0, 0, 0, 0, 0, 18, 0, 0, 0, 5, 0, 0, 0, 0, 0, + 0, 0,120,109,105,110, 0, 0, 0, 0, 0, 18, 0, 0, 0, 5, 0, 0, 0, 0, + 0, 0, 0,120,109, 97,120, 0, 0, 0, 0, 0, 18, 0, 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0,121,109,105,110, 0, 0, 0, 0, 0, 18, 0, 0, 0, 5, 0, 0, + 0, 0, 0, 0, 0,121,109, 97,120, 0, 0, 0, 0, 0, 18, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0,119,105,100,116,104, 0, 2, 0, 0, 0, 18, 0, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0,104,101,105,103,104,116, 0, 4, 0, 0, 0, 18, + 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, + 0, 10, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0,172, 0, 0, 0,176, 0, 0, 0, 0, 4, 0, 13, 26, 0, 0, 0, 5, 1, 0, + 0, 6, 65, 64, 2, 75,129, 64, 0, 92,129, 0, 1,139,193, 64, 0,156,129, 0, + 1,192, 1,128, 0, 0, 2, 0, 1, 28,193,128, 2,133, 1, 0, 0,134, 1, 65, + 3,192, 1, 0, 0, 0, 2, 0, 2, 64, 2,128, 2,156,129, 0, 2,197, 1, 0, + 0,198, 65,193, 3, 0, 2, 0, 0, 64, 2, 0, 3,128, 2,128, 0,192, 2, 0, + 1, 0, 3,128, 1,220,129, 0, 3, 0, 2, 0, 3,222, 1,128, 1, 30, 0,128, + 0, 6, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 22, 0, + 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 67, 97,108, 99, 82,111,116, + 97,116,101, 83,105,122,101, 0, 4, 6, 0, 0, 0, 0, 0, 0, 0, 87,105,100, +116,104, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0, 72,101,105,103,104,116, 0, 4, + 17, 0, 0, 0, 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, + 97,115,101,100, 0, 4, 14, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115, +115, 82,111,116, 97,116,101, 0, 0, 0, 0, 0, 26, 0, 0, 0,173, 0, 0, 0, +173, 0, 0, 0,173, 0, 0, 0,173, 0, 0, 0,173, 0, 0, 0,173, 0, 0, 0, +173, 0, 0, 0,173, 0, 0, 0,173, 0, 0, 0,174, 0, 0, 0,174, 0, 0, 0, +174, 0, 0, 0,174, 0, 0, 0,174, 0, 0, 0,174, 0, 0, 0,175, 0, 0, 0, +175, 0, 0, 0,175, 0, 0, 0,175, 0, 0, 0,175, 0, 0, 0,175, 0, 0, 0, +175, 0, 0, 0,175, 0, 0, 0,175, 0, 0, 0,175, 0, 0, 0,176, 0, 0, 0, + 7, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,115,114, 99, 95,105,109, 97,103, +101, 0, 0, 0, 0, 0, 25, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 99,111, +115, 48, 0, 0, 0, 0, 0, 25, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,115, +105,110, 48, 0, 0, 0, 0, 0, 25, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, +111,114,100,101,114, 0, 0, 0, 0, 0, 25, 0, 0, 0, 6, 0, 0, 0, 0, 0, + 0, 0,119,105,100,116,104, 0, 9, 0, 0, 0, 25, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0,104,101,105,103,104,116, 0, 9, 0, 0, 0, 25, 0, 0, 0, 10, + 0, 0, 0, 0, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 0, 15, 0, 0, + 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,179, 0, 0, + 0,179, 0, 0, 0, 0, 1, 0, 3, 4, 0, 0, 0, 75, 0, 64, 0, 93, 0, 0, + 1, 94, 0, 0, 0, 30, 0,128, 0, 1, 0, 0, 0, 4, 7, 0, 0, 0, 0, 0, + 0, 0, 72,101,105,103,104,116, 0, 0, 0, 0, 0, 4, 0, 0, 0,179, 0, 0, + 0,179, 0, 0, 0,179, 0, 0, 0,179, 0, 0, 0, 1, 0, 0, 0, 6, 0, 0, + 0, 0, 0, 0, 0,105,109, 97,103,101, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,179, 0, 0, 0,179, 0, 0, 0, 0, + 1, 0, 3, 4, 0, 0, 0, 75, 0, 64, 0, 93, 0, 0, 1, 94, 0, 0, 0, 30, + 0,128, 0, 1, 0, 0, 0, 4, 6, 0, 0, 0, 0, 0, 0, 0, 87,105,100,116, +104, 0, 0, 0, 0, 0, 4, 0, 0, 0,179, 0, 0, 0,179, 0, 0, 0,179, 0, + 0, 0,179, 0, 0, 0, 1, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,105,109, + 97,103,101, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0, 0, 1, 0, 3, 13, 0, 0, 0, + 75, 0, 64, 0, 92,128, 0, 1, 90, 0, 0, 0, 22,192, 0,128, 75, 0, 64, 0, + 93, 0, 0, 1, 94, 0, 0, 0, 22,192, 0,128, 75, 0, 64, 0, 92,128, 0, 1, + 79, 64,192, 0, 94, 0, 0, 1, 30, 0,128, 0, 2, 0, 0, 0, 4, 7, 0, 0, + 0, 0, 0, 0, 0, 72,101,105,103,104,116, 0, 3, 0, 0, 0, 0, 0, 0, 0, + 64, 0, 0, 0, 0, 13, 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, 0, + 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, 0, + 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0,212, 0, 0, + 0, 1, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,105,109, 97,103,101, 0, 0, + 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,214, + 0, 0, 0,227, 0, 0, 0, 0, 1, 0, 8, 36, 0, 0, 0, 75, 0, 64, 0, 92, +128, 0, 1, 79, 64,192, 0,133,128, 0, 0,134,192, 64, 1,203, 0, 64, 0,220, +128, 0, 1, 1, 65, 0, 0,156,128,128, 1,154, 0, 0, 0, 22, 0, 0,128, 76, + 0,193, 0,133, 64, 1, 0,134,128, 65, 1,192, 0, 0, 0, 3, 1, 0, 2, 64, + 1,128, 0,156,128, 0, 2,197, 64, 1, 0,198,128,193, 1, 0, 1, 0, 0, 67, + 1,128, 2,139, 1, 64, 0,156,129, 0, 1,143, 65, 64, 3,220,128, 0, 2, 5, + 65, 1, 0, 6,193, 65, 2, 64, 1, 0, 0,128, 1, 0, 1,192, 1,128, 1, 28, + 65, 0, 2, 0, 1, 0, 1, 64, 1,128, 1, 30, 1,128, 1, 30, 0,128, 0, 8, + 0, 0, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0, 72,101,105,103,104,116, 0, 3, + 0, 0, 0, 0, 0, 0, 0, 64, 4, 5, 0, 0, 0, 0, 0, 0, 0,109, 97,116, +104, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0,109,111,100, 0, 3, 0, 0, 0, 0, + 0, 0,240, 63, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 17, 0, 0, + 0, 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101, +100, 0, 4, 22, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 73,110, +116,101,114,108, 97, 99,101, 83,112,108,105,116, 0, 0, 0, 0, 0, 36, 0, 0, + 0,216, 0, 0, 0,216, 0, 0, 0,216, 0, 0, 0,217, 0, 0, 0,217, 0, 0, + 0,217, 0, 0, 0,217, 0, 0, 0,217, 0, 0, 0,217, 0, 0, 0,217, 0, 0, + 0,217, 0, 0, 0,218, 0, 0, 0,221, 0, 0, 0,221, 0, 0, 0,221, 0, 0, + 0,221, 0, 0, 0,221, 0, 0, 0,221, 0, 0, 0,222, 0, 0, 0,222, 0, 0, + 0,222, 0, 0, 0,222, 0, 0, 0,222, 0, 0, 0,222, 0, 0, 0,222, 0, 0, + 0,222, 0, 0, 0,225, 0, 0, 0,225, 0, 0, 0,225, 0, 0, 0,225, 0, 0, + 0,225, 0, 0, 0,225, 0, 0, 0,226, 0, 0, 0,226, 0, 0, 0,226, 0, 0, + 0,227, 0, 0, 0, 4, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,115,114, 99, + 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 35, 0, 0, 0, 12, 0, 0, 0, 0, + 0, 0, 0,100,115,116, 95,104,101,105,103,104,116, 49, 0, 3, 0, 0, 0, 35, + 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, + 49, 0, 18, 0, 0, 0, 35, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0,100,115, +116, 95,105,109, 97,103,101, 50, 0, 26, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0,229, 0, 0, 0,235, 0, 0, 0, 0, 1, 0, + 3, 14, 0, 0, 0, 75, 0, 64, 0, 92,128, 0, 1,133, 64, 0, 0,134,128, 64, + 1, 87,128,128, 0, 22,192, 0,128,133, 64, 0, 0,134,192, 64, 1, 23,128,128, + 0, 22, 64, 0,128,133, 64, 0, 0, 70, 0, 65, 1, 94, 0, 0, 1, 30, 0,128, + 0, 5, 0, 0, 0, 4, 9, 0, 0, 0, 0, 0, 0, 0, 68, 97,116, 97, 84,121, +112,101, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 5, 0, 0, 0, + 0, 0, 0, 0, 66, 89, 84, 69, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0, 85, 83, + 72, 79, 82, 84, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 73, 78, 84, 0, 0, 0, + 0, 0, 14, 0, 0, 0,230, 0, 0, 0,230, 0, 0, 0,231, 0, 0, 0,231, 0, + 0, 0,231, 0, 0, 0,231, 0, 0, 0,231, 0, 0, 0,231, 0, 0, 0,231, 0, + 0, 0,231, 0, 0, 0,232, 0, 0, 0,232, 0, 0, 0,234, 0, 0, 0,235, 0, + 0, 0, 2, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,105,109, 97,103,101, 0, + 0, 0, 0, 0, 13, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,100, 97,116, 97, + 95,116,121,112,101, 0, 2, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,247, 0, 0, 0,251, 0, 0, 0, 0, 3, 0, 9, 13, 0, + 0, 0,197, 0, 0, 0,198, 64,192, 1, 0, 1, 0, 0,220,128, 0, 1, 5, 1, + 0, 0, 6,129, 64, 2, 64, 1, 0, 0,128, 1,128, 0,192, 1,128, 1, 0, 2, + 0, 1, 28, 65,128, 2,222, 0, 0, 1, 30, 0,128, 0, 3, 0, 0, 0, 4, 3, + 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 73, +109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 4, 25, 0, 0, + 0, 0, 0, 0, 0, 80,114,111, 99,101,115,115, 65,114,105,116,104,109,101,116, +105, 99, 67,111,110,115,116, 79,112, 0, 0, 0, 0, 0, 13, 0, 0, 0,248, 0, + 0, 0,248, 0, 0, 0,248, 0, 0, 0,248, 0, 0, 0,249, 0, 0, 0,249, 0, + 0, 0,249, 0, 0, 0,249, 0, 0, 0,249, 0, 0, 0,249, 0, 0, 0,249, 0, + 0, 0,250, 0, 0, 0,251, 0, 0, 0, 4, 0, 0, 0, 10, 0, 0, 0, 0, 0, + 0, 0,115,114, 99, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 12, 0, 0, 0, + 10, 0, 0, 0, 0, 0, 0, 0,115,114, 99, 95, 99,111,110,115,116, 0, 0, 0, + 0, 0, 12, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0,111,112, 0, 0, 0, 0, + 0, 12, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,100,115,116, 95,105,109, 97, +103,101, 0, 4, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2, 1, 0, 0, 6, 1, 0, 0, 0, 2, 0, 6, 11, 0, 0, 0,133, + 0, 0, 0,134, 64, 64, 1,198,128, 64, 0,156,128, 0, 1,197, 0, 0, 0,198, +192,192, 1, 0, 1, 0, 0, 64, 1, 0, 1,220, 64,128, 1,158, 0, 0, 1, 30, + 0,128, 0, 4, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, + 17, 0, 0, 0, 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, + 97,115,101,100, 0, 3, 0, 0, 0, 0, 0, 0,240, 63, 4, 20, 0, 0, 0, 0, + 0, 0, 0, 80,114,111, 99,101,115,115, 77,117,108,116,105,112,108,101, 77,101, + 97,110, 0, 0, 0, 0, 0, 11, 0, 0, 0, 3, 1, 0, 0, 3, 1, 0, 0, 3, + 1, 0, 0, 3, 1, 0, 0, 4, 1, 0, 0, 4, 1, 0, 0, 4, 1, 0, 0, 4, + 1, 0, 0, 4, 1, 0, 0, 5, 1, 0, 0, 6, 1, 0, 0, 3, 0, 0, 0, 15, + 0, 0, 0, 0, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 95,108,105,115, +116, 0, 0, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,100,115, +116, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, + 0, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 0, 4, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 1, 0, 0, 12, 1, + 0, 0, 0, 2, 0, 7, 12, 0, 0, 0,133, 0, 0, 0,134, 64, 64, 1,198,128, + 64, 0,156,128, 0, 1,197, 0, 0, 0,198,192,192, 1, 0, 1, 0, 0, 64, 1, +128, 0,128, 1, 0, 1,220, 64, 0, 2,158, 0, 0, 1, 30, 0,128, 0, 4, 0, + 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, 0, + 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, + 3, 0, 0, 0, 0, 0, 0,240, 63, 4, 22, 0, 0, 0, 0, 0, 0, 0, 80,114, +111, 99,101,115,115, 77,117,108,116,105,112,108,101, 83,116,100, 68,101,118, 0, + 0, 0, 0, 0, 12, 0, 0, 0, 9, 1, 0, 0, 9, 1, 0, 0, 9, 1, 0, 0, + 9, 1, 0, 0, 10, 1, 0, 0, 10, 1, 0, 0, 10, 1, 0, 0, 10, 1, 0, 0, + 10, 1, 0, 0, 10, 1, 0, 0, 11, 1, 0, 0, 12, 1, 0, 0, 3, 0, 0, 0, + 15, 0, 0, 0, 0, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 95,108,105, +115,116, 0, 0, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0,109, +101, 97,110, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 11, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 0, 0,100,115,116, 95,105,109, 97,103,101, 0, 4, 0, 0, 0, + 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 1, 0, 0, + 26, 1, 0, 0, 0, 1, 0, 8, 28, 0, 0, 0, 69, 0, 0, 0, 70, 64,192, 0, +128, 0, 0, 0,195, 0, 0, 2, 69, 1, 0, 0, 70,129,192, 2,133, 1, 0, 0, +134,193, 64, 3, 92,128, 0, 3,133, 0, 0, 0,134, 64, 64, 1,192, 0, 0, 0, + 3, 1,128, 2,133, 1, 0, 0,134, 1, 65, 3,197, 1, 0, 0,198,193,192, 3, +156,128, 0, 3,197, 0, 0, 0,198, 64,193, 1, 0, 1, 0, 0, 64, 1,128, 0, +128, 1, 0, 1,220, 64, 0, 2,192, 0,128, 0, 0, 1, 0, 1,222, 0,128, 1, + 30, 0,128, 0, 6, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, + 4, 17, 0, 0, 0, 0, 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, + 66, 97,115,101,100, 0, 4, 5, 0, 0, 0, 0, 0, 0, 0, 71, 82, 65, 89, 0, + 4, 5, 0, 0, 0, 0, 0, 0, 0, 66, 89, 84, 69, 0, 4, 4, 0, 0, 0, 0, + 0, 0, 0, 82, 71, 66, 0, 4, 20, 0, 0, 0, 0, 0, 0, 0, 80,114,111, 99, +101,115,115, 83,112,108,105,116, 89, 67,104,114,111,109, 97, 0, 0, 0, 0, 0, + 28, 0, 0, 0, 22, 1, 0, 0, 22, 1, 0, 0, 22, 1, 0, 0, 22, 1, 0, 0, + 22, 1, 0, 0, 22, 1, 0, 0, 22, 1, 0, 0, 22, 1, 0, 0, 22, 1, 0, 0, + 23, 1, 0, 0, 23, 1, 0, 0, 23, 1, 0, 0, 23, 1, 0, 0, 23, 1, 0, 0, + 23, 1, 0, 0, 23, 1, 0, 0, 23, 1, 0, 0, 23, 1, 0, 0, 24, 1, 0, 0, + 24, 1, 0, 0, 24, 1, 0, 0, 24, 1, 0, 0, 24, 1, 0, 0, 24, 1, 0, 0, + 25, 1, 0, 0, 25, 1, 0, 0, 25, 1, 0, 0, 26, 1, 0, 0, 3, 0, 0, 0, + 10, 0, 0, 0, 0, 0, 0, 0,115,114, 99, 95,105,109, 97,103,101, 0, 0, 0, + 0, 0, 27, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0,121, 95,105,109, 97,103, +101, 0, 9, 0, 0, 0, 27, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 99,104, +114,111,109, 97, 95,105,109, 97,103,101, 0, 18, 0, 0, 0, 27, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 1, 0, 0, 39, 1, 0, 0, 0, + 1, 0, 14, 29, 0, 0, 0, 75, 0, 64, 0, 92,128, 0, 1,138, 0, 0, 0,193, + 64, 0, 0, 0, 1,128, 0, 65, 65, 0, 0,224,128, 2,128,197,129, 0, 0,198, +193,192, 3, 0, 2, 0, 1, 69, 2, 1, 0, 70, 66,193, 4,128, 2, 0, 0,195, + 2, 0, 6, 69, 3, 1, 0, 70,131,193, 6, 92, 2,128, 2,220, 65, 0, 0,223, +192,252,127,197, 0, 1, 0,198,192,193, 1, 0, 1, 0, 0, 64, 1, 0, 1,220, + 64,128, 1,197, 0, 2, 0, 0, 1, 0, 1,221, 0, 0, 1,222, 0, 0, 0, 30, + 0,128, 0, 9, 0, 0, 0, 4, 6, 0, 0, 0, 0, 0, 0, 0, 68,101,112,116, +104, 0, 3, 0, 0, 0, 0, 0, 0,240, 63, 4, 6, 0, 0, 0, 0, 0, 0, 0, +116, 97, 98,108,101, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0,105,110,115,101,114, +116, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, 0, + 0, 0, 0, 73,109, 97,103,101, 67,114,101, 97,116,101, 66, 97,115,101,100, 0, + 4, 5, 0, 0, 0, 0, 0, 0, 0, 71, 82, 65, 89, 0, 4, 23, 0, 0, 0, 0, + 0, 0, 0, 80,114,111, 99,101,115,115, 83,112,108,105,116, 67,111,109,112,111, +110,101,110,116,115, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0,117,110,112, 97, 99, +107, 0, 0, 0, 0, 0, 29, 0, 0, 0, 32, 1, 0, 0, 32, 1, 0, 0, 33, 1, + 0, 0, 34, 1, 0, 0, 34, 1, 0, 0, 34, 1, 0, 0, 34, 1, 0, 0, 35, 1, + 0, 0, 35, 1, 0, 0, 35, 1, 0, 0, 35, 1, 0, 0, 35, 1, 0, 0, 35, 1, + 0, 0, 35, 1, 0, 0, 35, 1, 0, 0, 35, 1, 0, 0, 35, 1, 0, 0, 35, 1, + 0, 0, 34, 1, 0, 0, 37, 1, 0, 0, 37, 1, 0, 0, 37, 1, 0, 0, 37, 1, + 0, 0, 37, 1, 0, 0, 38, 1, 0, 0, 38, 1, 0, 0, 38, 1, 0, 0, 38, 1, + 0, 0, 39, 1, 0, 0, 7, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,115,114, + 99, 95,105,109, 97,103,101, 0, 0, 0, 0, 0, 28, 0, 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0,100,101,112,116,104, 0, 2, 0, 0, 0, 28, 0, 0, 0, 11, 0, + 0, 0, 0, 0, 0, 0,100,115,116, 95,105,109, 97,103,101,115, 0, 3, 0, 0, + 0, 28, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 40,102,111,114, 32,105,110, +100,101,120, 41, 0, 6, 0, 0, 0, 19, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, + 0, 40,102,111,114, 32,108,105,109,105,116, 41, 0, 6, 0, 0, 0, 19, 0, 0, + 0, 11, 0, 0, 0, 0, 0, 0, 0, 40,102,111,114, 32,115,116,101,112, 41, 0, + 6, 0, 0, 0, 19, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,105, 0, 7, 0, + 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 1, + 0, 0, 45, 1, 0, 0, 0, 1, 0, 6, 14, 0, 0, 0, 69, 0, 0, 0, 70, 64, +192, 0,134,128, 64, 0,195, 0, 0, 2, 69, 1, 0, 0, 70,193,192, 2, 92,128, +128, 2,133, 0, 0, 0,134, 0, 65, 1,192, 0, 0, 0, 0, 1,128, 0,156, 64, +128, 1, 94, 0, 0, 1, 30, 0,128, 0, 5, 0, 0, 0, 4, 3, 0, 0, 0, 0, + 0, 0, 0,105,109, 0, 4, 17, 0, 0, 0, 0, 0, 0, 0, 73,109, 97,103,101, + 67,114,101, 97,116,101, 66, 97,115,101,100, 0, 3, 0, 0, 0, 0, 0, 0,240, + 63, 4, 4, 0, 0, 0, 0, 0, 0, 0, 82, 71, 66, 0, 4, 23, 0, 0, 0, 0, + 0, 0, 0, 80,114,111, 99,101,115,115, 77,101,114,103,101, 67,111,109,112,111, +110,101,110,116,115, 0, 0, 0, 0, 0, 14, 0, 0, 0, 42, 1, 0, 0, 42, 1, + 0, 0, 42, 1, 0, 0, 42, 1, 0, 0, 42, 1, 0, 0, 42, 1, 0, 0, 42, 1, + 0, 0, 43, 1, 0, 0, 43, 1, 0, 0, 43, 1, 0, 0, 43, 1, 0, 0, 43, 1, + 0, 0, 44, 1, 0, 0, 45, 1, 0, 0, 2, 0, 0, 0, 15, 0, 0, 0, 0, 0, + 0, 0,115,114, 99, 95,105,109, 97,103,101, 95,108,105,115,116, 0, 0, 0, 0, + 0, 13, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,100,115,116, 95,105,109, 97, +103,101, 0, 7, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0,135, 1, 0, 0, 25, + 0, 0, 0, 50, 0, 0, 0, 73, 0, 0, 0, 97, 0, 0, 0,122, 0, 0, 0,130, + 0, 0, 0,132, 0, 0, 0,132, 0, 0, 0,132, 0, 0, 0,132, 0, 0, 0,132, + 0, 0, 0,132, 0, 0, 0,133, 0, 0, 0,133, 0, 0, 0,133, 0, 0, 0,134, + 0, 0, 0,134, 0, 0, 0,134, 0, 0, 0,135, 0, 0, 0,135, 0, 0, 0,135, + 0, 0, 0,136, 0, 0, 0,136, 0, 0, 0,136, 0, 0, 0,136, 0, 0, 0,136, + 0, 0, 0,136, 0, 0, 0,136, 0, 0, 0,136, 0, 0, 0,136, 0, 0, 0,137, + 0, 0, 0,137, 0, 0, 0,137, 0, 0, 0,138, 0, 0, 0,138, 0, 0, 0,138, + 0, 0, 0,138, 0, 0, 0,138, 0, 0, 0,138, 0, 0, 0,139, 0, 0, 0,139, + 0, 0, 0,139, 0, 0, 0,139, 0, 0, 0,139, 0, 0, 0,139, 0, 0, 0,139, + 0, 0, 0,141, 0, 0, 0,144, 0, 0, 0,141, 0, 0, 0,146, 0, 0, 0,149, + 0, 0, 0,146, 0, 0, 0,151, 0, 0, 0,151, 0, 0, 0,151, 0, 0, 0,152, + 0, 0, 0,151, 0, 0, 0,154, 0, 0, 0,160, 0, 0, 0,154, 0, 0, 0,162, + 0, 0, 0,162, 0, 0, 0,162, 0, 0, 0,164, 0, 0, 0,170, 0, 0, 0,164, + 0, 0, 0,172, 0, 0, 0,176, 0, 0, 0,172, 0, 0, 0,178, 0, 0, 0,178, + 0, 0, 0,178, 0, 0, 0,179, 0, 0, 0,179, 0, 0, 0,179, 0, 0, 0,179, + 0, 0, 0,179, 0, 0, 0,180, 0, 0, 0,180, 0, 0, 0,180, 0, 0, 0,181, + 0, 0, 0,181, 0, 0, 0,181, 0, 0, 0,182, 0, 0, 0,182, 0, 0, 0,182, + 0, 0, 0,183, 0, 0, 0,183, 0, 0, 0,183, 0, 0, 0,184, 0, 0, 0,184, + 0, 0, 0,184, 0, 0, 0,185, 0, 0, 0,185, 0, 0, 0,185, 0, 0, 0,186, + 0, 0, 0,186, 0, 0, 0,186, 0, 0, 0,187, 0, 0, 0,187, 0, 0, 0,187, + 0, 0, 0,188, 0, 0, 0,188, 0, 0, 0,188, 0, 0, 0,189, 0, 0, 0,189, + 0, 0, 0,189, 0, 0, 0,190, 0, 0, 0,190, 0, 0, 0,190, 0, 0, 0,191, + 0, 0, 0,191, 0, 0, 0,191, 0, 0, 0,192, 0, 0, 0,192, 0, 0, 0,192, + 0, 0, 0,193, 0, 0, 0,193, 0, 0, 0,193, 0, 0, 0,194, 0, 0, 0,194, + 0, 0, 0,194, 0, 0, 0,195, 0, 0, 0,195, 0, 0, 0,195, 0, 0, 0,196, + 0, 0, 0,196, 0, 0, 0,196, 0, 0, 0,197, 0, 0, 0,197, 0, 0, 0,197, + 0, 0, 0,198, 0, 0, 0,198, 0, 0, 0,198, 0, 0, 0,199, 0, 0, 0,199, + 0, 0, 0,199, 0, 0, 0,200, 0, 0, 0,200, 0, 0, 0,200, 0, 0, 0,201, + 0, 0, 0,201, 0, 0, 0,201, 0, 0, 0,202, 0, 0, 0,202, 0, 0, 0,202, + 0, 0, 0,203, 0, 0, 0,203, 0, 0, 0,203, 0, 0, 0,204, 0, 0, 0,204, + 0, 0, 0,204, 0, 0, 0,205, 0, 0, 0,205, 0, 0, 0,205, 0, 0, 0,206, + 0, 0, 0,206, 0, 0, 0,206, 0, 0, 0,207, 0, 0, 0,207, 0, 0, 0,207, + 0, 0, 0,208, 0, 0, 0,208, 0, 0, 0,208, 0, 0, 0,209, 0, 0, 0,209, + 0, 0, 0,209, 0, 0, 0,210, 0, 0, 0,210, 0, 0, 0,210, 0, 0, 0,211, + 0, 0, 0,211, 0, 0, 0,211, 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0,212, + 0, 0, 0,212, 0, 0, 0,212, 0, 0, 0,214, 0, 0, 0,227, 0, 0, 0,214, + 0, 0, 0,235, 0, 0, 0,237, 0, 0, 0,237, 0, 0, 0,237, 0, 0, 0,237, + 0, 0, 0,237, 0, 0, 0,238, 0, 0, 0,238, 0, 0, 0,238, 0, 0, 0,238, + 0, 0, 0,238, 0, 0, 0,239, 0, 0, 0,239, 0, 0, 0,239, 0, 0, 0,240, + 0, 0, 0,240, 0, 0, 0,240, 0, 0, 0,241, 0, 0, 0,241, 0, 0, 0,241, + 0, 0, 0,242, 0, 0, 0,242, 0, 0, 0,242, 0, 0, 0,243, 0, 0, 0,243, + 0, 0, 0,243, 0, 0, 0,244, 0, 0, 0,244, 0, 0, 0,244, 0, 0, 0,245, + 0, 0, 0,245, 0, 0, 0,245, 0, 0, 0,247, 0, 0, 0,251, 0, 0, 0,247, + 0, 0, 0,253, 0, 0, 0,253, 0, 0, 0,253, 0, 0, 0,254, 0, 0, 0,254, + 0, 0, 0,254, 0, 0, 0,255, 0, 0, 0,255, 0, 0, 0,255, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, + 1, 0, 0, 2, 1, 0, 0, 6, 1, 0, 0, 2, 1, 0, 0, 8, 1, 0, 0, 12, + 1, 0, 0, 8, 1, 0, 0, 14, 1, 0, 0, 14, 1, 0, 0, 14, 1, 0, 0, 15, + 1, 0, 0, 15, 1, 0, 0, 15, 1, 0, 0, 16, 1, 0, 0, 16, 1, 0, 0, 16, + 1, 0, 0, 16, 1, 0, 0, 16, 1, 0, 0, 16, 1, 0, 0, 16, 1, 0, 0, 17, + 1, 0, 0, 17, 1, 0, 0, 17, 1, 0, 0, 18, 1, 0, 0, 18, 1, 0, 0, 18, + 1, 0, 0, 19, 1, 0, 0, 19, 1, 0, 0, 19, 1, 0, 0, 21, 1, 0, 0, 26, + 1, 0, 0, 21, 1, 0, 0, 28, 1, 0, 0, 28, 1, 0, 0, 28, 1, 0, 0, 28, + 1, 0, 0, 28, 1, 0, 0, 28, 1, 0, 0, 28, 1, 0, 0, 28, 1, 0, 0, 29, + 1, 0, 0, 29, 1, 0, 0, 29, 1, 0, 0, 29, 1, 0, 0, 29, 1, 0, 0, 29, + 1, 0, 0, 29, 1, 0, 0, 29, 1, 0, 0, 31, 1, 0, 0, 39, 1, 0, 0, 31, + 1, 0, 0, 41, 1, 0, 0, 45, 1, 0, 0, 41, 1, 0, 0, 47, 1, 0, 0, 47, + 1, 0, 0, 47, 1, 0, 0, 47, 1, 0, 0, 47, 1, 0, 0, 47, 1, 0, 0, 48, + 1, 0, 0, 48, 1, 0, 0, 48, 1, 0, 0, 49, 1, 0, 0, 49, 1, 0, 0, 49, + 1, 0, 0, 50, 1, 0, 0, 50, 1, 0, 0, 50, 1, 0, 0, 51, 1, 0, 0, 51, + 1, 0, 0, 51, 1, 0, 0, 52, 1, 0, 0, 52, 1, 0, 0, 52, 1, 0, 0, 53, + 1, 0, 0, 53, 1, 0, 0, 53, 1, 0, 0, 54, 1, 0, 0, 54, 1, 0, 0, 54, + 1, 0, 0, 54, 1, 0, 0, 54, 1, 0, 0, 54, 1, 0, 0, 55, 1, 0, 0, 55, + 1, 0, 0, 55, 1, 0, 0, 55, 1, 0, 0, 55, 1, 0, 0, 55, 1, 0, 0, 56, + 1, 0, 0, 56, 1, 0, 0, 56, 1, 0, 0, 57, 1, 0, 0, 57, 1, 0, 0, 57, + 1, 0, 0, 57, 1, 0, 0, 57, 1, 0, 0, 57, 1, 0, 0, 57, 1, 0, 0, 58, + 1, 0, 0, 58, 1, 0, 0, 58, 1, 0, 0, 58, 1, 0, 0, 58, 1, 0, 0, 58, + 1, 0, 0, 58, 1, 0, 0, 59, 1, 0, 0, 59, 1, 0, 0, 59, 1, 0, 0, 59, + 1, 0, 0, 59, 1, 0, 0, 59, 1, 0, 0, 59, 1, 0, 0, 60, 1, 0, 0, 60, + 1, 0, 0, 60, 1, 0, 0, 61, 1, 0, 0, 61, 1, 0, 0, 61, 1, 0, 0, 61, + 1, 0, 0, 61, 1, 0, 0, 61, 1, 0, 0, 61, 1, 0, 0, 62, 1, 0, 0, 62, + 1, 0, 0, 62, 1, 0, 0, 62, 1, 0, 0, 62, 1, 0, 0, 62, 1, 0, 0, 62, + 1, 0, 0, 63, 1, 0, 0, 63, 1, 0, 0, 63, 1, 0, 0, 64, 1, 0, 0, 64, + 1, 0, 0, 64, 1, 0, 0, 65, 1, 0, 0, 65, 1, 0, 0, 65, 1, 0, 0, 66, + 1, 0, 0, 66, 1, 0, 0, 66, 1, 0, 0, 66, 1, 0, 0, 66, 1, 0, 0, 66, + 1, 0, 0, 66, 1, 0, 0, 67, 1, 0, 0, 67, 1, 0, 0, 67, 1, 0, 0, 67, + 1, 0, 0, 67, 1, 0, 0, 67, 1, 0, 0, 67, 1, 0, 0, 68, 1, 0, 0, 68, + 1, 0, 0, 68, 1, 0, 0, 69, 1, 0, 0, 69, 1, 0, 0, 69, 1, 0, 0, 69, + 1, 0, 0, 7, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 79,110,101, 83,111, +117,114, 99,101, 79,110,101, 68,101,115,116, 0, 1, 0, 0, 0,134, 1, 0, 0, + 18, 0, 0, 0, 0, 0, 0, 0, 84,119,111, 83,111,117,114, 99,101,115, 79,110, +101, 68,101,115,116, 0, 2, 0, 0, 0,134, 1, 0, 0, 20, 0, 0, 0, 0, 0, + 0, 0, 84,104,114,101,101, 83,111,117,114, 99,101,115, 79,110,101, 68,101,115, +116, 0, 3, 0, 0, 0,134, 1, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 79,110, +101, 83,111,117,114, 99,101, 84,119,111, 68,101,115,116,115, 0, 4, 0, 0, 0, +134, 1, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 79,110,101, 83,111,117,114, 99, +101, 84,104,114,101,101, 68,101,115,116,115, 0, 5, 0, 0, 0,134, 1, 0, 0, + 13, 0, 0, 0, 0, 0, 0, 0,104,111,117,103,104, 95,104,101,105,103,104,116, + 0, 6, 0, 0, 0,134, 1, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0,105,110,116, + 95,100, 97,116, 97,116,121,112,101, 0,182, 0, 0, 0,134, 1, 0, 0, 0, 0, + 0, 0, +}; + + if (luaL_loadbuffer(L,(const char*)B1,sizeof(B1),"../obj/imlua_process51/im_process_le64w.lo")==0) lua_pcall(L, 0, 0, 0); +} diff --git a/im/src/make_uname b/im/src/make_uname new file mode 100755 index 0000000..b104eac --- /dev/null +++ b/im/src/make_uname @@ -0,0 +1,13 @@ +# This builds all the libraries of the folder for 1 uname + +tecmake $1 $2 $3 $4 $5 $6 $7 $8 +tecmake $1 MF=im_process $2 $3 $4 $5 $6 $7 $8 +tecmake $1 MF=im_jp2 $2 $3 $4 $5 $6 $7 $8 +tecmake $1 MF=im_fftw $2 $3 $4 $5 $6 $7 $8 + +#tecmake $1 MF=imlua3 $2 $3 $4 $5 $6 $7 $8 + +tecmake $1 MF=imlua5 $2 $3 $4 $5 $6 $7 $8 +tecmake $1 MF=imlua_process5 $2 $3 $4 $5 $6 $7 $8 +tecmake $1 MF=imlua_jp2 $2 $3 $4 $5 $6 $7 $8 +tecmake $1 MF=imlua_fftw5 $2 $3 $4 $5 $6 $7 $8 diff --git a/im/src/make_uname.bat b/im/src/make_uname.bat new file mode 100755 index 0000000..0bfcec1 --- /dev/null +++ b/im/src/make_uname.bat @@ -0,0 +1,74 @@ +@echo off +REM This builds all the libraries of the folder for 1 uname + +if "%1"=="VCC" goto do-vcc +if "%1"=="vc-all" goto start-all-vc + +call tecmake %1 %2 %3 %4 %5 %6 %7 %8 +call tecmake %1 "MF=im_process" %2 %3 %4 %5 %6 %7 %8 +call tecmake %1 "MF=im_jp2" %2 %3 %4 %5 %6 %7 %8 +call tecmake %1 "MF=im_avi" %2 %3 %4 %5 %6 %7 %8 +call tecmake %1 "MF=im_fftw" %2 %3 %4 %5 %6 %7 %8 + +REM call tecmake %1 "MF=imlua3" %2 %3 %4 %5 %6 %7 %8 + +call tecmake %1 "MF=imlua5" %2 %3 %4 %5 %6 %7 %8 +call tecmake %1 "MF=imlua_process5" %2 %3 %4 %5 %6 %7 %8 +call tecmake %1 "MF=imlua_jp2" %2 %3 %4 %5 %6 %7 %8 +call tecmake %1 "MF=imlua_avi" %2 %3 %4 %5 %6 %7 %8 +call tecmake %1 "MF=imlua_fftw5" %2 %3 %4 %5 %6 %7 %8 + +if "%1"=="vc6" goto vc +if "%1"=="vc7" goto vc +if "%1"=="vc8" goto vc +if "%1"=="vc8_64" goto vc +if "%1"=="vc9" goto vc +if "%1"=="vc9_64" goto vc +if "%1"=="dll" goto vc +if "%1"=="dll7" goto vc +if "%1"=="dll8" goto vc +if "%1"=="dll8_64" goto vc +if "%1"=="dll9" goto vc +if "%1"=="dll9_64" goto vc +if "%1"=="all" goto start-all-vc +goto end + +:vc +call tecmake %1 "MF=im_wmv" %2 %3 %4 %5 %6 %7 %8 +call tecmake %1 "MF=imlua_wmv" %2 %3 %4 %5 %6 %7 %8 +call tecmake %1 "MF=im_capture" %2 %3 %4 %5 %6 %7 %8 +call tecmake %1 "MF=imlua_capture5" %2 %3 %4 %5 %6 %7 %8 +if "%1"=="dll" goto dll +goto end + +:dll +call tecmake mingw4 "MF=im_capture" mingw4-dll +call tecmake mingw3 "MF=im_capture" mingw3-dll +call tecmake bc56 "MF=im_capture" bc56-dll +REM call tecmake owc1 "MF=im_capture" owc1-dll +goto end + +:start-all-vc +call make_uname VCC vc6 %2 %3 %4 %5 %6 +call make_uname VCC vc7 %2 %3 %4 %5 %6 +call make_uname VCC vc8 %2 %3 %4 %5 %6 +call make_uname VCC vc8_64 %2 %3 %4 %5 %6 +call make_uname VCC vc9 %2 %3 %4 %5 %6 +call make_uname VCC vc9_64 %2 %3 %4 %5 %6 +call make_uname VCC dll %2 %3 %4 %5 %6 +call make_uname VCC dll7 %2 %3 %4 %5 %6 +call make_uname VCC dll8 %2 %3 %4 %5 %6 +call make_uname VCC dll8_64 %2 %3 %4 %5 %6 +call make_uname VCC dll9 %2 %3 %4 %5 %6 +call make_uname VCC dll9_64 %2 %3 %4 %5 %6 +goto end + +:do-vcc +call tecmake %2 "MF=im_wmv" %3 %4 %5 %6 %7 %8 +call tecmake %2 "MF=imlua_wmv" %3 %4 %5 %6 %7 %8 +call tecmake %2 "MF=im_capture" %3 %4 %5 %6 %7 %8 +call tecmake %2 "MF=imlua_capture5" %3 %4 %5 %6 %7 %8 +if "%2"=="dll" goto dll +goto end + +:end diff --git a/im/src/old_im.cpp b/im/src/old_im.cpp new file mode 100755 index 0000000..44a0e1c --- /dev/null +++ b/im/src/old_im.cpp @@ -0,0 +1,440 @@ +/** \file + * \brief Old API + * + * See Copyright Notice in im_lib.h + * $Id: old_im.cpp,v 1.2 2009/08/19 18:39:43 scuri Exp $ + */ + +#include +#include +#include + +#include "old_im.h" +#include "im.h" +#include "im_util.h" +#include "im_counter.h" + +long imEncodeColor(unsigned char Red, unsigned char Green, unsigned char Blue) +{ + return imColorEncode(Red, Green, Blue); +} + +void imDecodeColor(unsigned char* Red, unsigned char* Green, unsigned char* Blue, long Color) +{ + imColorDecode(Red, Green, Blue, Color); +} + +static int FormatNew2Old(const char* new_format, const char* compression) +{ + int format; + + if (!imStrEqual(new_format, "BMP")) + format = IM_BMP; + else if (!imStrEqual(new_format, "GIF")) + format = IM_GIF; + else if (!imStrEqual(new_format, "PCX")) + format = IM_PCX; + else if (!imStrEqual(new_format, "RAS")) + format = IM_RAS; + else if (!imStrEqual(new_format, "SGI")) + format = IM_SGI; + else if (!imStrEqual(new_format, "JPEG")) + format = IM_JPG; + else if (!imStrEqual(new_format, "LED")) + format = IM_LED; + else if (!imStrEqual(new_format, "TIFF")) + format = IM_TIF; + else if (!imStrEqual(new_format, "TGA")) + format = IM_TGA; + else + return -1; + + if (!imStrEqual(compression, "NONE")) + format |= IM_DEFAULT; + + return format; +} + +int imFileFormat(char *filename, int* format) +{ + char new_format[10], compression[10]; + int error, image_count; + + imFile* ifile = imFileOpen(filename, &error); + if (!ifile) return error; + + imFileGetInfo(ifile, new_format, compression, &image_count); + imFileClose(ifile); + + *format = FormatNew2Old(new_format, compression); + if (*format == -1) + return IM_ERR_FORMAT; + + return IM_ERR_NONE; +} + +static int ColorMode2Type(int color_mode) +{ + switch (imColorModeSpace(color_mode)) + { + case IM_BINARY: + case IM_GRAY: + case IM_MAP: + return IM_MAP; + default: + return IM_RGB; + } +} + +int imImageInfo(char *filename, int *width, int *height, int *type, int *palette_count) +{ + int error; + imFile* ifile = imFileOpen(filename, &error); + if (!ifile) return error; + + int data_type, color_mode; + error = imFileReadImageInfo(ifile, 0, width, height, &color_mode, &data_type); + if (error) + { + imFileClose(ifile); + return error; + } + + *type = ColorMode2Type(color_mode); + if (*type == -1) + { + imFileClose(ifile); + return IM_ERR_DATA; + } + + if (*type == IM_MAP) + { + long palette[256]; + imFileGetPalette(ifile, palette, palette_count); + } + + imFileClose(ifile); + return IM_ERR_NONE; +} + +static imTiffImageDesc iOldTiffImageDescCB = NULL; +static imGifTranspIndex iOldGifTranspIndexCB = NULL; +static imResolutionCallback iOldResolutionCB = NULL; +static imFileCounterCallback iOldCounterCB = NULL; + +static int iOldFileCounter(int counter, void* user_data, const char* name, int progress) +{ + (void)counter; + if (progress == -1 || progress == 1001) return 1; + return !iOldCounterCB((char*)user_data, progress/10, (name[4] == 'R')? 0: 1); +} + +int imRegisterCallback(imCallback cb, int cb_id, int format) +{ + if (format == IM_ALL) + { + switch(cb_id) + { + case IM_COUNTER_CB: + iOldCounterCB = (imFileCounterCallback)cb; + return 1; + case IM_RESOLUTION_CB: + iOldResolutionCB = (imResolutionCallback)cb; + return 1; + } + } + + if (format == IM_GIF && cb_id == IM_GIF_TRANSPARENT_COLOR_CB) + { + iOldGifTranspIndexCB = (imGifTranspIndex)cb; + return 1; + } + + if (format == IM_TIF && cb_id == IM_TIF_IMAGE_DESCRIPTION_CB) + { + iOldTiffImageDescCB = (imTiffImageDesc)cb; + return 1; + } + + return 0; +} + +static void iConvertMapToRGB(const imbyte* src_map, imbyte* red, imbyte* green, imbyte* blue, int count, const long* palette, const int palette_count) +{ + imbyte r[256], g[256], b[256]; + for (int c = 0; c < palette_count; c++) + imColorDecode(&r[c], &g[c], &b[c], palette[c]); + + for (int i = 0; i < count; i++) + { + int index = *src_map++; + *red++ = r[index]; + *green++ = g[index]; + *blue++ = b[index]; + } +} + +int imLoadRGB(char *filename, unsigned char *red, unsigned char *green, unsigned char *blue) +{ + int error; + imFile* ifile = imFileOpen(filename, &error); + if (!ifile) return error; + + int width, height, color_mode, data_type; + error = imFileReadImageInfo(ifile, 0, &width, &height, &color_mode, &data_type); + if (error) + { + imFileClose(ifile); + return error; + } + + if (iOldResolutionCB) + { + double xres = *(float*)imFileGetAttribute(ifile, "XResolution", NULL, NULL); + double yres = *(float*)imFileGetAttribute(ifile, "YResolution", NULL, NULL); + int res_unit = *(int*)imFileGetAttribute(ifile, "ResolutionUnit", NULL, NULL); + iOldResolutionCB(filename, &xres, &yres, &res_unit); + } + + if (iOldTiffImageDescCB) + { + char* img_desc = (char*)imFileGetAttribute(ifile, "Description", NULL, NULL); + iOldTiffImageDescCB(filename, img_desc); + } + + if (iOldGifTranspIndexCB) + { + unsigned char transp_index = *(unsigned char*)imFileGetAttribute(ifile, "TransparencyIndex", NULL, NULL); + iOldGifTranspIndexCB(filename, &transp_index); + } + + int count = width*height; + void* data; + if (green != red + count || blue != green + count) + data = malloc(imImageDataSize(width, height, IM_RGB, IM_BYTE)); + else + data = red; + + if (!data) + { + imFileClose(ifile); + return IM_ERR_MEM; + } + + if (iOldCounterCB) + imCounterSetCallback(filename, iOldFileCounter); + + error = imFileReadImageData(ifile, data, 1, 0); + if (error) + { + if (data != red) free(data); + imFileClose(ifile); + return error; + } + + if (imColorModeToBitmap(color_mode) != IM_RGB) + { + long palette[256]; + int palette_count; + imFileGetPalette(ifile, palette, &palette_count); + iConvertMapToRGB((imbyte*)data, red, green, blue, count, palette, palette_count); + } + else if (data != red) + { + memcpy(red, data, count); + memcpy(green, (unsigned char*)data+count, count); + memcpy(blue, (unsigned char*)data+2*count, count); + } + + imFileClose(ifile); + + if (data != red) free(data); + return IM_ERR_NONE; +} + +int imLoadMap(char *filename, unsigned char *map, long *palette) +{ + int error; + imFile* ifile = imFileOpen(filename, &error); + if (!ifile) return error; + + int width, height, color_mode, data_type; + error = imFileReadImageInfo(ifile, 0, &width, &height, &color_mode, &data_type); + if (error) + { + imFileClose(ifile); + return error; + } + + if (imColorModeSpace(color_mode) != IM_MAP && + imColorModeSpace(color_mode) != IM_GRAY && + imColorModeSpace(color_mode) != IM_BINARY) + return IM_ERR_DATA; + + if (iOldResolutionCB) + { + double xres = *(float*)imFileGetAttribute(ifile, "XResolution", NULL, NULL); + double yres = *(float*)imFileGetAttribute(ifile, "YResolution", NULL, NULL); + int res_unit = *(int*)imFileGetAttribute(ifile, "ResolutionUnit", NULL, NULL); + iOldResolutionCB(filename, &xres, &yres, &res_unit); + } + + if (iOldTiffImageDescCB) + { + char* img_desc = (char*)imFileGetAttribute(ifile, "Description", NULL, NULL); + iOldTiffImageDescCB(filename, img_desc); + } + + if (iOldGifTranspIndexCB) + { + unsigned char transp_index = *(unsigned char*)imFileGetAttribute(ifile, "TransparencyIndex", NULL, NULL); + iOldGifTranspIndexCB(filename, &transp_index); + } + + if (iOldCounterCB) + imCounterSetCallback(filename, iOldFileCounter); + + error = imFileReadImageData(ifile, map, 1, 0); + if (error) + { + imFileClose(ifile); + return error; + } + + int palette_count; + imFileGetPalette(ifile, palette, &palette_count); + + imFileClose(ifile); + + return IM_ERR_NONE; +} + +static char* i_format_old2new[] = {"BMP", "PCX", "GIF", "TIFF", "RAS", "SGI", "JPEG", "LED", "TGA"}; + +int imSaveRGB(int width, int height, int format, unsigned char *red, unsigned char *green, unsigned char *blue, char *filename) +{ + int error; + char* new_format = i_format_old2new[format & 0x00FF]; + + imFile* ifile = imFileNew(filename, new_format, &error); + if (!ifile) return error; + + if (format & 0xFF00) + imFileSetInfo(ifile, NULL); + else + imFileSetInfo(ifile, "NONE"); + + if (iOldResolutionCB) + { + double xres, yres; + int res_unit; + iOldResolutionCB(filename, &xres, &yres, &res_unit); + float fxres=(float)xres, fyres=(float)yres; + imFileSetAttribute(ifile, "XResolution", IM_FLOAT, 1, (void*)&fxres); + imFileSetAttribute(ifile, "YResolution", IM_FLOAT, 1, (void*)&fyres); + imFileSetAttribute(ifile, "ResolutionUnit", IM_INT, 1, (void*)&res_unit); + } + + if (iOldTiffImageDescCB) + { + char img_desc[50]; + iOldTiffImageDescCB(filename, img_desc); + imFileSetAttribute(ifile, "Description", IM_BYTE, -1, (void*)img_desc); + } + + if (iOldGifTranspIndexCB) + { + unsigned char transp_index; + iOldGifTranspIndexCB(filename, &transp_index); + imFileSetAttribute(ifile, "TransparencyIndex", IM_BYTE, 1, (void*)&transp_index); + } + + error = imFileWriteImageInfo(ifile, width, height, IM_RGB, IM_BYTE); + if (error) + { + imFileClose(ifile); + return error; + } + + if (iOldCounterCB) + imCounterSetCallback(filename, iOldFileCounter); + + int count = width*height; + void* data; + if (green != red + count || blue != green + count) + data = malloc(imImageDataSize(width, height, IM_RGB, IM_BYTE)); + else + data = red; + + if (!data) + { + imFileClose(ifile); + return IM_ERR_MEM; + } + + if (data != red) + { + memcpy(data, red, count); + memcpy((unsigned char*)data+count, green, count); + memcpy((unsigned char*)data+2*count, blue, count); + } + + error = imFileWriteImageData(ifile, data); + imFileClose(ifile); + if (data != red) free(data); + return error; +} + +int imSaveMap(int width, int height, int format, unsigned char *map, int palette_count, long *palette, char *filename) +{ + int error; + char* new_format = i_format_old2new[format & 0x00FF]; + imFile* ifile = imFileNew(filename, new_format, &error); + if (!ifile) return error; + + if (format & 0xFF00) + imFileSetInfo(ifile, NULL); + else + imFileSetInfo(ifile, "NONE"); + + imFileSetPalette(ifile, palette, palette_count); + + if (iOldResolutionCB) + { + double xres, yres; + int res_unit; + iOldResolutionCB(filename, &xres, &yres, &res_unit); + float fxres=(float)xres, fyres=(float)yres; + imFileSetAttribute(ifile, "XResolution", IM_FLOAT, 1, (void*)&fxres); + imFileSetAttribute(ifile, "YResolution", IM_FLOAT, 1, (void*)&fyres); + imFileSetAttribute(ifile, "ResolutionUnit", IM_INT, 1, (void*)&res_unit); + } + + if (iOldTiffImageDescCB) + { + char img_desc[50]; + iOldTiffImageDescCB(filename, img_desc); + imFileSetAttribute(ifile, "Description", IM_BYTE, -1, (void*)img_desc); + } + + if (iOldGifTranspIndexCB) + { + unsigned char transp_index; + iOldGifTranspIndexCB(filename, &transp_index); + imFileSetAttribute(ifile, "TransparencyIndex", IM_BYTE, 1, (void*)&transp_index); + } + + error = imFileWriteImageInfo(ifile, width, height, IM_MAP, IM_BYTE); + if (error) + { + imFileClose(ifile); + return error; + } + + if (iOldCounterCB) + imCounterSetCallback(filename, iOldFileCounter); + + error = imFileWriteImageData(ifile, map); + imFileClose(ifile); + return error; +} diff --git a/im/src/old_imcolor.c b/im/src/old_imcolor.c new file mode 100755 index 0000000..0c6b353 --- /dev/null +++ b/im/src/old_imcolor.c @@ -0,0 +1,75 @@ +/** \file + * \brief Old resize/stretch functions + * + * See Copyright Notice in im_lib.h + * $Id: old_imcolor.c,v 1.1 2008/10/17 06:10:16 scuri Exp $ + */ + +#include "old_im.h" +#include "im.h" +#include "im_util.h" +#include "im_image.h" +#include "im_convert.h" + +void imRGB2Map(int width, int height, + unsigned char *red, unsigned char *green, unsigned char *blue, + unsigned char *map, int palette_count, long *palette) +{ + imConvertRGB2Map(width, height, + red, green, blue, + map, palette, &palette_count); +} + +void imMap2RGB(int width, int height, unsigned char *map, int palette_count, long *palette, unsigned char *red, unsigned char *green, unsigned char *blue) +{ + int i, count, c, index; + unsigned char r[256], g[256], b[256]; + + for (c = 0; c < palette_count; c++) + imColorDecode(&r[c], &g[c], &b[c], palette[c]); + + count = width*height; + for (i = 0; i < count; i++) + { + index = *map++; + *red++ = r[index]; + *green++ = g[index]; + *blue++ = b[index]; + } +} + +void imRGB2Gray(int width, int height, unsigned char *red, unsigned char *green, unsigned char *blue, unsigned char *map, long *grays) +{ + int i, count, c; + + for (c = 0; c < 256; c++) + *grays++ = imColorEncode((unsigned char)c, (unsigned char)c, (unsigned char)c); + + count = width*height; + for (i = 0; i < count; i++) + { + *map++ = (unsigned char)((*red++ * 30 + *green++ * 59 + *blue++ * 11) / 100); + } +} + +void imMap2Gray(int width, int height, unsigned char *map, int palette_count, long *palette, unsigned char *gray_map, long *grays) +{ + int i, count, c; + unsigned char cnv_table[256]; + unsigned char r, g, b; + + for (c = 0; c < 256; c++) + *grays++ = imColorEncode((unsigned char)c, (unsigned char)c, (unsigned char)c); + + for (c = 0; c < palette_count; c++) + { + imColorDecode(&r, &g, &b, palette[c]); + cnv_table[c] = (unsigned char)((r * 30 + g * 59 + b * 11) / 100); + } + + count = width*height; + for (i = 0; i < count; i++) + { + *gray_map++ = cnv_table[*map++]; + } +} diff --git a/im/src/old_imresize.c b/im/src/old_imresize.c new file mode 100755 index 0000000..8191037 --- /dev/null +++ b/im/src/old_imresize.c @@ -0,0 +1,117 @@ +/** \file + * \brief Old resize/stretch functions + * + * See Copyright Notice in im_lib.h + * $Id: old_imresize.c,v 1.1 2008/10/17 06:10:16 scuri Exp $ + */ + +#include "old_im.h" + +#include +#include +#include + + +/* + BILINEAR INTERPOLATION: + + x' = floor(x) f(x' , y') = fll + y' = floor(y) f(x' , y'+ 1) = flh + f(x'+ 1, y') = fhl + t = x - x' f(x'+ 1, y'+ 1) = fhh + u = y - y' + + f(x,y) = (1-t) * (1-u) * f(x' , y'), + (1-t) * u * f(x' , y'+ 1), + t * (1-u) * f(x'+ 1, y'), + t * u * f(x'+ 1, y'+ 1) + + f(x,y) = fll + (re-arranging) + t * (fhl - fll), + u * (flh - fll), + u * t * (fhh - flh - fhl + fll) + +*/ + +void imResize(int src_width, int src_height, unsigned char *src_map, int dst_width, int dst_height, unsigned char *dst_map) +{ + /* Do bilinear interpolation */ + + unsigned char *line_mapl, *line_maph; + double t, u, src_x, src_y, factor; + int fhh, fll, fhl, flh, xl, yl, xh, yh, x, y; + + int *XL = (int*)malloc(dst_width * sizeof(int)); + double *T = (double*)malloc(dst_width * sizeof(double)); + + factor = (double)(src_width-1) / (double)(dst_width-1); + for (x = 0; x < dst_width; x++) + { + src_x = x * factor; + xl = (int)floor(src_x); + T[x] = src_x - xl; + XL[x] = xl; + } + + factor = (double)(src_height-1) / (double)(dst_height-1); + + for (y = 0; y < dst_height; y++) + { + src_y = y * factor; + yl = (int)floor(src_y); + yh = (yl == src_height-1)? yl: yl + 1; + u = src_y - yl; + + line_mapl = src_map + yl * src_width; + line_maph = src_map + yh * src_width; + + for (x = 0; x < dst_width; x++) + { + xl = XL[x]; + xh = (xl == src_width-1)? xl: xl + 1; + t = T[x]; + + fll = line_mapl[xl]; + fhl = line_mapl[xh]; + flh = line_maph[xl]; + fhh = line_maph[xh]; + + *(dst_map++) = (unsigned char)(u * t * (fhh - flh - fhl + fll) + t * (fhl - fll) + u * (flh - fll) + fll); + } + } + + free(XL); + free(T); +} + +void imStretch(int src_width, int src_height, unsigned char *src_map, int dst_width, int dst_height, unsigned char *dst_map) +{ + int x, y, offset; + double factor; + unsigned char *line_map; + int* XTab = (int*)malloc(dst_width*sizeof(int)); + + /* initialize convertion tables to speed up the stretch process */ + factor = (double)(src_width-1) / (double)(dst_width-1); + for(x = 0; x < dst_width; x++) + XTab[x] = (int)(factor * x + 0.5); + + factor = (double)(src_height-1) / (double)(dst_height-1); + + line_map = src_map; + + for (y = 0; y < dst_height; y++) + { + for (x = 0; x < dst_width; x++) + { + offset = XTab[x]; + *(dst_map++) = line_map[offset]; + } + + offset = ((int)(factor * y + 0.5)) * src_width; + line_map = src_map + offset; + } + + free(XTab); +} + diff --git a/im/src/process/im_analyze.cpp b/im/src/process/im_analyze.cpp new file mode 100755 index 0000000..6fa9405 --- /dev/null +++ b/im/src/process/im_analyze.cpp @@ -0,0 +1,1268 @@ +/** \file + * \brief Image Analysis + * + * See Copyright Notice in im_lib.h + * $Id: im_analyze.cpp,v 1.2 2009/09/28 20:19:09 scuri Exp $ + */ + + +#include +#include +#include + +#include "im_process_ana.h" +#include "im_process_pon.h" + +#include +#include +#include +#include + +#define MAX_COUNT 65536 // maximum number of regions + +/* ajust the alias table to be a remap table (final step) */ +static void alias_update(imushort* alias_table, int ®ion_count) +{ + int i, real_count = region_count; + + for (i = 0; i < region_count; i++) + { + if (alias_table[i]) + { + // search for the first alias + imushort prev = alias_table[i]; + while (alias_table[prev]) + prev = alias_table[prev]; + + alias_table[i] = prev; + real_count--; // decrement aliases from the region count + } + } + + // now all the aliases in the same group point to only one alias + // transform the alias table into a remap table + + alias_table[0] = 0; + alias_table[1] = 0; // border is mapped to background + + int r = 1; + for (i = 2; i < region_count; i++) + { + if (!alias_table[i]) + { + alias_table[i] = (imushort)r; // only non alias get real values + r++; + } + else + alias_table[i] = (imushort)(alias_table[alias_table[i]]); + } + + region_count = real_count-2; // remove the regions (background,border) from the count +} + +/* find the smallest region number to be set as alias. */ +static void alias_getmin(imushort* alias_table, imushort region, imushort &min) +{ + while (alias_table[region]) + { + if (min > alias_table[region]) + min = alias_table[region]; + + region = alias_table[region]; + } +} + +/* replace all the aliases of a region by its smallest value. */ +static void alias_setmin(imushort* alias_table, imushort region, imushort min) +{ + while (alias_table[region]) + { + imushort next_region = alias_table[region]; + alias_table[region] = min; + region = next_region; + } + + if (region != min) + alias_table[region] = min; +} + +/* set a region number to be an alias of another */ +static void alias_set(imushort* alias_table, imushort region1, imushort region2) +{ + if (region1 == region2) + return; + + imushort min = region1 MAX_COUNT) + { + delete [] alias_table; + return -1; + } + } + } + } + } + + pmap1 = pmap; + new_pmap1 = new_pmap; + pmap += width; + new_pmap += width; + } + + // now all pixels are marked, + // but some marks are aliases to others + + // ajust the alias table to be a remap table + // and return the real region count + alias_update(alias_table, region_count); + + int count = width*height; + for (i = 0; i < count; i++) + { + new_map[i] = alias_table[new_map[i]]; + } + + delete [] alias_table; + + return region_count; +} + +static int DoAnalyzeFindRegionsBorder(int width, int height, imbyte* map, imushort* new_map, int connect) +{ + int i, j; + + imbyte* pmap1 = map - width; // previous line (line -1 = invalid) + imushort* new_pmap1 = new_map - width; + + imbyte* pmap = map; // current line (line 0) + imushort* new_pmap = new_map; + + int region_count = 2; // still consider: 0- background, 1-border + imushort* alias_table = new imushort [MAX_COUNT]; + memset(alias_table, 0, MAX_COUNT); // aliases are all zero at start (not used) + + for (i = 0; i < height; i++) + { + for (j = 0; j < width; j++) + { + if (pmap[j]) + { + int b01 = j > 0? 1: 0; // valid for pmap[j-1] + int b10 = i > 0? 1: 0; // valid for pmap1[j] + int b11 = i > 0 && j > 0? 1: 0; // valid for pmap1[j-1] + int b12 = i > 0 && j < width-1? 1: 0; // valid for pmap1[j+1] + + if ((b01&&pmap[j-1]) || (b10&&pmap1[j]) || + (connect == 8 && ((b11&&pmap1[j-1]) || (b12&&pmap1[j+1])))) // 4 or 8 connected to the previous neighbors + { + imushort region = 0; + + if (b01&&pmap[j-1]) + { + if (!region) + region = new_pmap[j-1]; // horizontal neighbor -00 + else // X1 + { + // this is a right border pixel that connects to an horizontal neighbor + + // this pixel can connect two different regions + alias_set(alias_table, region, new_pmap[j-1]); + } + } + + if (b10&&pmap1[j]) // vertical neighbor + { + if (!region) + region = new_pmap1[j]; // isolated vertical neighbor -X- + else // 01 + { + // an horizontal neighbor connects to a vertical neighbor -X- + // X1 + + // this pixel can connect two different regions + alias_set(alias_table, region, new_pmap1[j]); + } + } + else if (region && connect == 8 && (b12&&pmap1[j+1])) + { + // an horizontal neighbor connects to a right corner neighbor 00X + // X1 + + // this pixel can connect two different regions + alias_set(alias_table, region, new_pmap1[j+1]); + } + + if (connect == 8 && ((b11&&pmap1[j-1]) || (b12&&pmap1[j+1])) && !region) // isolated corner + { + // a left corner neighbor or a right corner neighbor X0X + // 01 + + if (b11&&pmap1[j-1]) // left corner + region = new_pmap1[j-1]; + + if (b12&&pmap1[j+1]) // right corner + { + if (!region) // isolated right corner + region = new_pmap1[j+1]; + else + { + // this pixel can connect two different regions + alias_set(alias_table, new_pmap1[j-1], new_pmap1[j+1]); + } + } + } + + new_pmap[j] = region; + } + else + { + // this pixel touches no pixels + + // create a new region 000 + // 01 + new_pmap[j] = (imushort)region_count; + region_count++; + + if (region_count > MAX_COUNT) + { + delete [] alias_table; + return -1; + } + } + } + } + + pmap1 = pmap; + new_pmap1 = new_pmap; + pmap += width; + new_pmap += width; + } + + // now all pixels are marked, + // but some marks are aliases to others + + // ajust the alias table to be a remap table + // and return the real region count + alias_update(alias_table, region_count); + + int count = width*height; + for (i = 0; i < count; i++) + { + new_map[i] = alias_table[new_map[i]]; + } + + delete [] alias_table; + + return region_count; +} + +int imAnalyzeFindRegions(const imImage* image, imImage* NewImage, int connect, int touch_border) +{ + imImageSetAttribute(NewImage, "REGION_CONNECT", IM_BYTE, 1, connect==4?"4":"8"); + if (touch_border) + return DoAnalyzeFindRegionsBorder(image->width, image->height, (imbyte*)image->data[0], (imushort*)NewImage->data[0], connect); + else + return DoAnalyzeFindRegions(image->width, image->height, (imbyte*)image->data[0], (imushort*)NewImage->data[0], connect); +} + +void imAnalyzeMeasureArea(const imImage* image, int* data_area, int region_count) +{ + imushort* img_data = (imushort*)image->data[0]; + + memset(data_area, 0, region_count*sizeof(int)); + + for (int i = 0; i < image->count; i++) + { + if (*img_data) + data_area[(*img_data) - 1]++; + img_data++; + } +} + +void imAnalyzeMeasureCentroid(const imImage* image, const int* data_area, int region_count, float* data_cx, float* data_cy) +{ + imushort* img_data = (imushort*)image->data[0]; + int* local_data_area = 0; + + if (!data_area) + { + local_data_area = (int*)malloc(region_count*sizeof(int)); + imAnalyzeMeasureArea(image, local_data_area, region_count); + data_area = (const int*)local_data_area; + } + + if (data_cx) memset(data_cx, 0, region_count*sizeof(float)); + if (data_cy) memset(data_cy, 0, region_count*sizeof(float)); + + for (int y = 0; y < image->height; y++) + { + int offset = y*image->width; + + for (int x = 0; x < image->width; x++) + { + int region_index = img_data[offset+x]; + if (region_index) + { + if (data_cx) data_cx[region_index-1] += (float)x; + if (data_cy) data_cy[region_index-1] += (float)y; + } + } + } + + for (int i = 0; i < region_count; i++) + { + if (data_cx) data_cx[i] /= (float)data_area[i]; + if (data_cy) data_cy[i] /= (float)data_area[i]; + } + + if (local_data_area) + free(local_data_area); +} + +static inline double ipow(double x, int j) +{ + double r = 1.0; + for (int i = 0; i < j; i++) + r *= x; + return r; +} + +static void iCalcMoment(double* cm, int px, int py, const imImage* image, const float* cx, const float* cy, int region_count) +{ + imushort* img_data = (imushort*)image->data[0]; + + memset(cm, 0, region_count*sizeof(double)); + + for (int y = 0; y < image->height; y++) + { + int offset = y*image->width; + + for (int x = 0; x < image->width; x++) + { + int region_index = img_data[offset+x]; + if (region_index) + { + int i = region_index-1; + + if (px == 0) + cm[i] += ipow(y-cy[i],py); + else if (py == 0) + cm[i] += ipow(x-cx[i],px); + else + cm[i] += ipow(x-cx[i],px)*ipow(y-cy[i],py); + } + } + } +} + +template +static inline int IsPerimeterPoint(T* map, int width, int height, int x, int y) +{ + // map here points to the start of the line, even if its an invalid line. + + // if outside the image, then is not a perimeter line. + if (x == -1 || x == width || + y == -1 || y == height) + return 0; + + T v = map[x]; // here v is image(x,y) + if (!v) + return 0; + + // if touches the border, then is a perimeter line. + if (x == 0 || x == width-1 || + y == 0 || y == height-1) + return 1; + + // if has 4 connected neighbors, then is a perimeter line. + if (map[width+x] != v || + map[x+1] != v || + map[x-1] != v || + map[-width+x] != v) + return 1; + + return 0; +} + +void imAnalyzeMeasurePrincipalAxis(const imImage* image, const int* data_area, const float* data_cx, const float* data_cy, + const int region_count, float* major_slope, float* major_length, + float* minor_slope, float* minor_length) +{ + int i; + int *local_data_area = 0; + float *local_data_cx = 0, *local_data_cy = 0; + + if (!data_area) + { + local_data_area = (int*)malloc(region_count*sizeof(int)); + imAnalyzeMeasureArea(image, local_data_area, region_count); + data_area = (const int*)local_data_area; + } + + if (!data_cx || !data_cy) + { + if (!data_cx) + { + local_data_cx = (float*)malloc(region_count*sizeof(float)); + data_cx = (const float*)local_data_cx; + } + + if (!data_cy) + { + local_data_cy = (float*)malloc(region_count*sizeof(float)); + data_cy = (const float*)local_data_cy; + } + + if (local_data_cx && local_data_cy) + imAnalyzeMeasureCentroid(image, data_area, region_count, local_data_cx, local_data_cy); + else if (local_data_cx) + imAnalyzeMeasureCentroid(image, data_area, region_count, local_data_cx, NULL); + else if (local_data_cy) + imAnalyzeMeasureCentroid(image, data_area, region_count, NULL, local_data_cy); + } + + // additional moments + double* cm20 = (double*)malloc(region_count*sizeof(double)); + double* cm02 = (double*)malloc(region_count*sizeof(double)); + double* cm11 = (double*)malloc(region_count*sizeof(double)); + + iCalcMoment(cm20, 2, 0, image, data_cx, data_cy, region_count); + iCalcMoment(cm02, 0, 2, image, data_cx, data_cy, region_count); + iCalcMoment(cm11, 1, 1, image, data_cx, data_cy, region_count); + + float *local_major_slope = 0, *local_minor_slope = 0; + if (!major_slope) + { + local_major_slope = (float*)malloc(region_count*sizeof(float)); + major_slope = local_major_slope; + } + if (!minor_slope) + { + local_minor_slope = (float*)malloc(region_count*sizeof(float)); + minor_slope = local_minor_slope; + } + +#define RAD2DEG 57.296 + + // We are going to find 2 axis parameters. + // Axis 1 are located in quadrants 1-3 + // Axis 2 are located in quadrants 2-4 + + // Quadrants + // 2 | 1 + // ----- + // 3 | 4 + + // line coeficients for lines that belongs to axis 1 and 2 + float* A1 = (float*)malloc(region_count*sizeof(float)); + float* A2 = (float*)malloc(region_count*sizeof(float)); + float* C1 = (float*)malloc(region_count*sizeof(float)); + float* C2 = (float*)malloc(region_count*sizeof(float)); + + float *slope1 = major_slope; // Use major_slope as a storage place, + float *slope2 = minor_slope; // and create an alias to make code clear. + + for (i = 0; i < region_count; i++) + { + if (cm11[i] == 0) + { + slope1[i] = 0; + slope2[i] = 90; + + // These should not be used + A1[i] = 0; + A2[i] = 0; // infinite + C1[i] = 0; // data_cy[i] + C2[i] = 0; + } + else + { + double b = (cm20[i] - cm02[i])/cm11[i]; + double delta = sqrt(b*b + 4.0); + double r1 = (-b-delta)/2.0; + double r2 = (-b+delta)/2.0; + float a1 = (float)(atan(r1)*RAD2DEG + 90); // to avoid negative results + float a2 = (float)(atan(r2)*RAD2DEG + 90); + + if (a1 == 180) a1 = 0; + if (a2 == 180) a2 = 0; + + if (a1 < 90) // a1 is quadrants q1-q3 + { + slope1[i] = a1; + slope2[i] = a2; + A1[i] = (float)r1; + A2[i] = (float)r2; + } + else // a2 is quadrants q1-q3 + { + slope1[i] = a2; + slope2[i] = a1; + A1[i] = (float)r2; + A2[i] = (float)r1; + } + + C1[i] = data_cy[i] - A1[i] * data_cx[i]; + C2[i] = data_cy[i] - A2[i] * data_cx[i]; + } + } + + // moments are not necessary anymore + free(cm20); free(cm02); free(cm11); + cm20 = 0; cm02 = 0; cm11 = 0; + + // maximum distance from a point in the perimeter to an axis in each side of the axis + // D1 is distance to axis 1, a and b are sides + float* D1a = (float*)malloc(region_count*sizeof(float)); + float* D1b = (float*)malloc(region_count*sizeof(float)); + float* D2a = (float*)malloc(region_count*sizeof(float)); + float* D2b = (float*)malloc(region_count*sizeof(float)); + memset(D1a, 0, region_count*sizeof(float)); + memset(D1b, 0, region_count*sizeof(float)); + memset(D2a, 0, region_count*sizeof(float)); + memset(D2b, 0, region_count*sizeof(float)); + + imushort* img_data = (imushort*)image->data[0]; + int width = image->width; + int height = image->height; + for (int y = 0; y < height; y++) + { + int offset = y*width; + + for (int x = 0; x < width; x++) + { + if (IsPerimeterPoint(img_data+offset, width, height, x, y)) + { + i = img_data[offset+x] - 1; + + float d1, d2; + if (slope2[i] == 90) + { + d2 = y - data_cy[i]; // I ckecked this many times, looks odd but it is correct. + d1 = x - data_cx[i]; + } + else + { + d1 = A1[i]*x - y + C1[i]; + d2 = A2[i]*x - y + C2[i]; + } + + if (d1 < 0) + { + d1 = (float)fabs(d1); + if (d1 > D1a[i]) + D1a[i] = d1; + } + else + { + if (d1 > D1b[i]) + D1b[i] = d1; + } + + if (d2 < 0) + { + d2 = (float)fabs(d2); + if (d2 > D2a[i]) + D2a[i] = d2; + } + else + { + if (d2 > D2b[i]) + D2b[i] = d2; + } + } + } + } + + for (i = 0; i < region_count; i++) + { + float AB1 = (float)sqrt(A1[i]*A1[i] + 1); + float AB2 = (float)sqrt(A2[i]*A2[i] + 1); + + float D1 = (D1a[i] + D1b[i]) / AB1; + float D2 = (D2a[i] + D2b[i]) / AB2; + + if (D1 < D2) // Major Axis in 2-4 quadrants + { + // now remember that we did an alias before + // slope1 -> major_slope + // slope2 -> minor_slope + + float tmp = major_slope[i]; + major_slope[i] = minor_slope[i]; + minor_slope[i] = tmp; + + if (minor_length) minor_length[i] = D1; + if (major_length) major_length[i] = D2; + } + else + { + if (minor_length) minor_length[i] = D2; + if (major_length) major_length[i] = D1; + } + } + + if (local_major_slope) free(local_major_slope); + if (local_minor_slope) free(local_minor_slope); + if (local_data_area) free(local_data_area); + if (local_data_cx) free(local_data_cx); + if (local_data_cy) free(local_data_cy); + + free(A1); + free(A2); + free(C1); + free(C2); + + free(D1b); + free(D2b); + free(D1a); + free(D2a); +} + +void imAnalyzeMeasureHoles(const imImage* image, int connect, int* count_data, int* area_data, float* perim_data) +{ + int i; + imImage *inv_image = imImageCreate(image->width, image->height, IM_BINARY, IM_BYTE); + imbyte* inv_data = (imbyte*)inv_image->data[0]; + imushort* img_data = (imushort*)image->data[0]; + + // finds the holes in the inverted image + for (i = 0; i < image->count; i++) + { + if (*img_data) + *inv_data = 0; + else + *inv_data = 1; + + img_data++; + inv_data++; + } + + imImage *holes_image = imImageClone(image); + if (!holes_image) + return; + + int holes_count = imAnalyzeFindRegions(inv_image, holes_image, connect, 0); + imImageDestroy(inv_image); + + if (!holes_count) + { + imImageDestroy(holes_image); + return; + } + + // measure the holes area + int* holes_area = (int*)malloc(holes_count*sizeof(int)); + imAnalyzeMeasureArea(holes_image, holes_area, holes_count); + + float* holes_perim = 0; + if (perim_data) + { + holes_perim = (float*)malloc(holes_count*sizeof(int)); + imAnalyzeMeasurePerimeter(holes_image, holes_perim, holes_count); + } + + imushort* holes_data = (imushort*)holes_image->data[0]; + img_data = (imushort*)image->data[0]; + + // holes do not touch the border + for (int y = 1; y < image->height-1; y++) + { + int offset_up = (y+1)*image->width; + int offset = y*image->width; + int offset_dw = (y-1)*image->width; + + for (int x = 1; x < image->width-1; x++) + { + int hole_index = holes_data[offset+x]; + + if (hole_index && holes_area[hole_index-1]) // a hole not yet used + { + // if the hole has not been used, + // it is the first time we encounter a pixel of this hole. + // then it is a pixel from the hole border. + // now find which region this hole is inside. + // a 4 connected neighbour is necessarilly a valid region or 0. + + int region_index = 0; + if (img_data[offset_up + x]) region_index = img_data[offset_up + x]; + else if (img_data[offset + x+1]) region_index = img_data[offset + x+1]; + else if (img_data[offset + x-1]) region_index = img_data[offset + x-1]; + else if (img_data[offset_dw+x]) region_index = img_data[offset_dw+x]; + + if (!region_index) continue; + + if (count_data) count_data[region_index-1]++; + if (area_data) area_data[region_index-1] += holes_area[hole_index-1]; + if (perim_data) perim_data[region_index-1] += holes_perim[hole_index-1]; + holes_area[hole_index-1] = 0; // mark hole as used + } + } + } + + if (holes_perim) free(holes_perim); + free(holes_area); + imImageDestroy(holes_image); +} + +template +static void DoPerimeterLine(T* map, T* new_map, int width, int height) +{ + int x, y, offset; + + for (y = 0; y < height; y++) + { + offset = y*width; + + for (x = 0; x < width; x++) + { + if (IsPerimeterPoint(map+offset, width, height, x, y)) + new_map[offset+x] = map[offset+x]; + else + new_map[offset+x] = 0; + } + } +} + +void imProcessPerimeterLine(const imImage* src_image, imImage* dst_image) +{ + switch(src_image->data_type) + { + case IM_BYTE: + DoPerimeterLine((imbyte*)src_image->data[0], (imbyte*)dst_image->data[0], src_image->width, src_image->height); + break; + case IM_USHORT: + DoPerimeterLine((imushort*)src_image->data[0], (imushort*)dst_image->data[0], src_image->width, src_image->height); + break; + case IM_INT: + DoPerimeterLine((int*)src_image->data[0], (int*)dst_image->data[0], src_image->width, src_image->height); + break; + } +} + +/* Perimeter Templates idea based in + Parker, Pratical Computer Vision Using C + +For 1.414 (sqrt(2)/2 + sqrt(2)/2) [1]: + 1 0 0 0 0 1 1 0 0 0 0 1 0 0 0 1 0 1 + 0 x 0 0 x 0 0 x 0 0 x 0 0 x 0 0 x 0 + 0 0 1 1 0 0 1 0 0 0 0 1 1 0 1 0 0 0 + 129 36 132 33 5 160 + +For 1.207 (sqrt(2)/2 + 1.0/2) [2]: + 0 0 0 0 0 1 0 1 0 0 1 0 1 0 0 0 0 1 0 0 0 1 0 0 + 1 x 0 1 x 0 0 x 0 0 x 0 0 x 0 0 x 0 0 x 1 0 x 1 + 0 0 1 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 1 0 0 0 0 0 + 17 48 68 65 130 34 12 136 + + 0 0 0 1 0 0 1 1 0 0 1 1 0 0 1 0 0 0 0 0 0 0 0 0 + 1 x 0 1 x 0 0 x 0 0 x 0 0 x 1 0 x 1 0 x 0 0 x 0 + 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 1 1 0 + 20 144 192 96 40 9 3 6 + +For 1.0 (1.0/2 + 1.0/2) [0]: + 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 1 0 + 1 x 1 0 x 0 1 x 0 0 x 1 1 x 0 0 x 1 + 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 + 24 66 18 10 80 72 + +For 0.707 (sqrt(2)/2) [3]: + 1 0 0 0 0 1 0 0 0 0 0 0 + 0 x 0 0 x 0 0 x 0 0 x 0 (For Line Length) + 0 0 0 0 0 0 0 0 1 1 0 0 + 128 32 1 4 + +For 0.5 (1.0/2) [4]: + 0 1 0 0 0 0 0 0 0 0 0 0 + 0 x 0 0 x 1 0 x 0 1 x 0 (For Line Length) + 0 0 0 0 0 0 0 1 0 0 0 0 + 64 8 2 16 + +*/ +static void iInitPerimTemplate(imbyte *templ, float *v) +{ + memset(templ, 0, 256); + + templ[129] = 1; + templ[36] = 1; + templ[132] = 1; + templ[33] = 1; + templ[5] = 1; + templ[160] = 1; + + templ[17] = 2; + templ[48] = 2; + templ[68] = 2; + templ[65] = 2; + templ[130] = 2; + templ[34] = 2; + templ[12] = 2; + templ[136] = 2; + templ[20] = 2; + templ[144] = 2; + templ[192] = 2; + templ[96] = 2; + templ[40] = 2; + templ[9] = 2; + templ[3] = 2; + templ[6] = 2; + + templ[24] = 0; + templ[66] = 0; + templ[18] = 0; + templ[10] = 0; + templ[80] = 0; + templ[72] = 0; + + templ[128] = 3; + templ[32] = 3; + templ[1] = 3; + templ[4] = 3; + + templ[64] = 4; + templ[8] = 4; + templ[2] = 4; + templ[16] = 4; + +const float DT_SQRT2 = 1.414213562373f; +const float DT_SQRT2D2 = 0.707106781187f; + + v[1] = DT_SQRT2; + v[2] = DT_SQRT2D2 + 0.5f; + v[0] = 1.0f; + v[3] = DT_SQRT2D2; + v[4] = 0.5f; +} + +void imAnalyzeMeasurePerimeter(const imImage* image, float* perim_data, int region_count) +{ + static imbyte templ[256]; + static float vt[5]; + static int first = 1; + if (first) + { + iInitPerimTemplate(templ, vt); + first = 0; + } + + imushort* map = (imushort*)image->data[0]; + + memset(perim_data, 0, region_count*sizeof(int)); + + int width = image->width; + int height = image->height; + for (int y = 0; y < height; y++) + { + int offset = y*image->width; + + for (int x = 0; x < width; x++) + { + if (IsPerimeterPoint(map+offset, width, height, x, y)) + { + int T = 0; + + // check the 8 neighboors if they belong to the perimeter + if (IsPerimeterPoint(map+offset+width, width, height, x-1, y+1)) + T |= 0x01; + if (IsPerimeterPoint(map+offset+width, width, height, x, y+1)) + T |= 0x02; + if (IsPerimeterPoint(map+offset+width, width, height, x+1, y+1)) + T |= 0x04; + + if (IsPerimeterPoint(map+offset, width, height, x-1, y)) + T |= 0x08; + if (IsPerimeterPoint(map+offset, width, height, x+1, y)) + T |= 0x10; + + if (IsPerimeterPoint(map+offset-width, width, height, x-1, y-1)) + T |= 0x20; + if (IsPerimeterPoint(map+offset-width, width, height, x, y-1)) + T |= 0x40; + if (IsPerimeterPoint(map+offset-width, width, height, x+1, y-1)) + T |= 0x80; + + if (T) + perim_data[map[offset+x] - 1] += vt[templ[T]]; + } + } + } +} + +/* Perimeter Area Templates + +For "1.0" (0): + + 1 1 1 + 1 x 1 + 1 1 1 + 255 + +For "0.75" (1): + + 1 1 1 1 1 1 0 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 0 1 + 1 x 1 1 x 1 1 x 1 1 x 1 0 x 1 1 x 0 1 x 1 1 x 1 + 0 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 + 251 254 127 223 239 247 253 191 + +For "0.625" (2): + + 1 1 1 0 0 1 0 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 0 0 + 1 x 1 1 x 1 0 x 1 1 x 0 0 x 1 1 x 0 1 x 1 1 x 1 + 0 0 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 0 1 0 0 1 1 1 + 249 63 111 215 235 246 252 159 + +For "0.5" (3): + + 0 0 0 0 1 1 1 1 1 1 1 0 1 1 1 0 0 1 1 0 0 1 1 1 + 1 x 1 0 x 1 1 x 1 1 x 0 0 x 1 0 x 1 1 x 0 1 x 0 + 1 1 1 0 1 1 0 0 0 1 1 0 0 0 1 1 1 1 1 1 1 1 0 0 + 31 107 248 214 233 47 151 244 + +For "0.375" (4): + + 0 0 0 1 1 1 1 1 0 0 1 1 1 0 0 0 0 1 0 0 0 1 1 1 + 1 x 0 1 x 0 1 x 0 0 x 1 1 x 0 0 x 1 0 x 1 0 x 1 + 1 1 1 0 0 0 1 0 0 0 0 1 1 1 0 0 1 1 1 1 1 0 0 0 + 23 240 212 105 150 43 15 232 + +For "0.25" (5): + + 0 0 0 0 0 0 1 1 0 0 1 1 1 0 0 0 0 1 0 0 0 1 1 1 + 1 x 0 0 x 1 1 x 0 0 x 1 1 x 0 0 x 1 0 x 0 0 x 0 + 1 1 0 0 1 1 0 0 0 0 0 0 1 0 0 0 0 1 1 1 1 0 0 0 + 22 11 208 104 148 41 7 224 + +For "0.125" (6): + + 0 0 0 0 0 0 1 1 0 0 0 1 1 0 0 0 0 0 0 0 0 0 1 1 + 1 x 0 0 x 0 0 x 0 0 x 1 1 x 0 0 x 1 0 x 0 0 x 0 + 1 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 + 20 3 192 40 144 9 6 96 + +*/ +static void iInitPerimAreaTemplate(imbyte *templ, float *v) +{ + memset(templ, 0, 256); + + templ[255] = 0; + + templ[251] = 1; + templ[254] = 1; + templ[127] = 1; + templ[223] = 1; + templ[239] = 1; + templ[247] = 1; + templ[253] = 1; + templ[191] = 1; + + templ[249] = 2; + templ[63] = 2; + templ[111] = 2; + templ[215] = 2; + templ[235] = 2; + templ[246] = 2; + templ[252] = 2; + templ[159] = 2; + + templ[31] = 3; + templ[107] = 3; + templ[248] = 3; + templ[214] = 3; + templ[233] = 3; + templ[47] = 3; + templ[151] = 3; + templ[244] = 3; + + templ[23] = 4; + templ[240] = 4; + templ[212] = 4; + templ[105] = 4; + templ[150] = 4; + templ[43] = 4; + templ[15] = 4; + templ[232] = 4; + + templ[22] = 5; + templ[11] = 5; + templ[208] = 5; + templ[104] = 5; + templ[148] = 5; + templ[41] = 5; + templ[7] = 5; + templ[224] = 5; + + templ[20] = 6; + templ[3] = 6; + templ[192] = 6; + templ[40] = 6; + templ[144] = 6; + templ[9] = 6; + templ[6] = 6; + templ[96] = 6; + + v[0] = 1.0f; + v[1] = 0.75f; + v[2] = 0.625f; + v[3] = 0.5f; + v[4] = 0.375f; + v[5] = 0.25f; + v[6] = 0.125f; +} + +void imAnalyzeMeasurePerimArea(const imImage* image, float* area_data) +{ + static imbyte templ[256]; + static float vt[7]; + static int first = 1; + if (first) + { + iInitPerimAreaTemplate(templ, vt); + first = 0; + } + + imushort* map = (imushort*)image->data[0]; + + int width = image->width; + int height = image->height; + for (int y = 0; y < height; y++) + { + int offset_up = (y+1)*width; + int offset = y*width; + int offset_dw = (y-1)*width; + + for (int x = 0; x < width; x++) + { + imushort v = map[offset+x]; + if (v) + { + int T = 0; + if (x>0 && y0 && map[offset + x-1] == v) T |= 0x08; + if (x0 && y>0 && map[offset_dw + x-1] == v) T |= 0x20; + if (y>0 && map[offset_dw + x ] == v) T |= 0x40; + if (x0 && map[offset_dw + x+1] == v) T |= 0x80; + + if (T) + area_data[v-1] += vt[templ[T]]; + } + } + } +} + +void imProcessRemoveByArea(const imImage* image, imImage* NewImage, int connect, int start_size, int end_size, int inside) +{ + imImage *region_image = imImageCreate(image->width, image->height, IM_GRAY, IM_USHORT); + if (!region_image) + return; + + int region_count = imAnalyzeFindRegions(image, region_image, connect, 1); + if (!region_count) + { + imImageClear(NewImage); + imImageDestroy(region_image); + return; + } + + if (end_size == 0) + end_size = image->width*image->height; + + int outside=0; + if (!inside) outside = 1; + + int* area_data = (int*)malloc(region_count*sizeof(int)); + imAnalyzeMeasureArea(region_image, area_data, region_count); + + imushort* region_data = (imushort*)region_image->data[0]; + imbyte* img_data = (imbyte*)NewImage->data[0]; + + for (int i = 0; i < image->count; i++) + { + if (*region_data) + { + int area = area_data[(*region_data) - 1]; + if (area < start_size || area > end_size) + *img_data = (imbyte)outside; + else + *img_data = (imbyte)inside; + } + else + *img_data = 0; + + region_data++; + img_data++; + } + + free(area_data); + imImageDestroy(region_image); +} + +void imProcessFillHoles(const imImage* image, imImage* NewImage, int connect) +{ + // finding regions in the inverted image will isolate only the holes. + imProcessNegative(image, NewImage); + + imImage *region_image = imImageCreate(image->width, image->height, IM_GRAY, IM_USHORT); + if (!region_image) + return; + + int holes_count = imAnalyzeFindRegions(NewImage, region_image, connect, 0); + if (!holes_count) + { + imImageCopy(image, NewImage); + imImageDestroy(region_image); + return; + } + + imushort* region_data = (imushort*)region_image->data[0]; + imbyte* dst_data = (imbyte*)NewImage->data[0]; + + for (int i = 0; i < image->count; i++) + { + if (*region_data) + *dst_data = 1; + else + *dst_data = !(*dst_data); // Fix negative data. + + region_data++; + dst_data++; + } + + imImageDestroy(region_image); +} diff --git a/im/src/process/im_arithmetic_bin.cpp b/im/src/process/im_arithmetic_bin.cpp new file mode 100755 index 0000000..494b6c0 --- /dev/null +++ b/im/src/process/im_arithmetic_bin.cpp @@ -0,0 +1,587 @@ +/** \file + * \brief Binary Arithmetic Operations + * + * See Copyright Notice in im_lib.h + * $Id: im_arithmetic_bin.cpp,v 1.2 2009/10/01 02:56:58 scuri Exp $ + */ + + +#include +#include +#include +#include +#include + +#include "im_process_pon.h" +#include "im_math_op.h" + +#include +#include + + +template +static void DoBinaryOp(T1 *map1, T2 *map2, T3 *map, int count, int op) +{ + int i; + + switch(op) + { + case IM_BIN_ADD: + for (i = 0; i < count; i++) + map[i] = add_op((T3)map1[i], (T3)map2[i]); + break; + case IM_BIN_SUB: + for (i = 0; i < count; i++) + map[i] = sub_op((T3)map1[i], (T3)map2[i]); + break; + case IM_BIN_MUL: + for (i = 0; i < count; i++) + map[i] = mul_op((T3)map1[i], (T3)map2[i]); + break; + case IM_BIN_DIV: + for (i = 0; i < count; i++) + map[i] = div_op((T3)map1[i], (T3)map2[i]); + break; + case IM_BIN_DIFF: + for (i = 0; i < count; i++) + map[i] = diff_op((T3)map1[i], (T3)map2[i]); + break; + case IM_BIN_MIN: + for (i = 0; i < count; i++) + map[i] = min_op((T3)map1[i], (T3)map2[i]); + break; + case IM_BIN_MAX: + for (i = 0; i < count; i++) + map[i] = max_op((T3)map1[i], (T3)map2[i]); + break; + case IM_BIN_POW: + for (i = 0; i < count; i++) + map[i] = pow_op((T3)map1[i], (T3)map2[i]); + break; + } +} + +static void DoBinaryOpByte(imbyte *map1, imbyte *map2, imbyte *map, int count, int op) +{ + int i; + + switch(op) + { + case IM_BIN_ADD: + for (i = 0; i < count; i++) + map[i] = (imbyte)crop_byte(add_op((int)map1[i], (int)map2[i])); + break; + case IM_BIN_SUB: + for (i = 0; i < count; i++) + map[i] = (imbyte)crop_byte(sub_op((int)map1[i], (int)map2[i])); + break; + case IM_BIN_MUL: + for (i = 0; i < count; i++) + map[i] = (imbyte)crop_byte(mul_op((int)map1[i], (int)map2[i])); + break; + case IM_BIN_DIV: + for (i = 0; i < count; i++) + map[i] = (imbyte)crop_byte(div_op((int)map1[i], (int)map2[i])); + break; + case IM_BIN_DIFF: + for (i = 0; i < count; i++) + map[i] = (imbyte)crop_byte(diff_op((int)map1[i], (int)map2[i])); + break; + case IM_BIN_MIN: + for (i = 0; i < count; i++) + map[i] = (imbyte)crop_byte(min_op((int)map1[i], (int)map2[i])); + break; + case IM_BIN_MAX: + for (i = 0; i < count; i++) + map[i] = (imbyte)crop_byte(max_op((int)map1[i], (int)map2[i])); + break; + case IM_BIN_POW: + for (i = 0; i < count; i++) + map[i] = (imbyte)crop_byte(pow_op((int)map1[i], (int)map2[i])); + break; + } +} + +static void DoBinaryOpCpxReal(imcfloat *map1, float *map2, imcfloat *map, int count, int op) +{ + int i; + + switch(op) + { + case IM_BIN_ADD: + for (i = 0; i < count; i++) + map[i] = add_op(map1[i], map2[i]); + break; + case IM_BIN_SUB: + for (i = 0; i < count; i++) + map[i] = sub_op(map1[i], map2[i]); + break; + case IM_BIN_MUL: + for (i = 0; i < count; i++) + map[i] = mul_op(map1[i], map2[i]); + break; + case IM_BIN_DIV: + for (i = 0; i < count; i++) + map[i] = div_op(map1[i], (imcfloat)map2[i]); + break; + case IM_BIN_DIFF: + for (i = 0; i < count; i++) + map[i] = diff_op(map1[i], map2[i]); + break; + case IM_BIN_MIN: + for (i = 0; i < count; i++) + map[i] = min_op(map1[i], map2[i]); + break; + case IM_BIN_MAX: + for (i = 0; i < count; i++) + map[i] = max_op(map1[i], map2[i]); + break; + case IM_BIN_POW: + for (i = 0; i < count; i++) + map[i] = pow_op(map1[i], map2[i]); + break; + } +} + +void imProcessArithmeticOp(const imImage* src_image1, const imImage* src_image2, imImage* dst_image, int op) +{ + int count = src_image1->count; + + for (int i = 0; i < src_image1->depth; i++) + { + switch(src_image1->data_type) + { + case IM_BYTE: + if (dst_image->data_type == IM_FLOAT) + DoBinaryOp((imbyte*)src_image1->data[i], (imbyte*)src_image2->data[i], (float*)dst_image->data[i], count, op); + else if (dst_image->data_type == IM_USHORT) + DoBinaryOp((imbyte*)src_image1->data[i], (imbyte*)src_image2->data[i], (imushort*)dst_image->data[i], count, op); + else if (dst_image->data_type == IM_INT) + DoBinaryOp((imbyte*)src_image1->data[i], (imbyte*)src_image2->data[i], (int*)dst_image->data[i], count, op); + else + DoBinaryOpByte((imbyte*)src_image1->data[i], (imbyte*)src_image2->data[i], (imbyte*)dst_image->data[i], count, op); + break; + case IM_USHORT: + if (dst_image->data_type == IM_FLOAT) + DoBinaryOp((imushort*)src_image1->data[i], (imushort*)src_image2->data[i], (float*)dst_image->data[i], count, op); + else if (dst_image->data_type == IM_INT) + DoBinaryOp((imushort*)src_image1->data[i], (imushort*)src_image2->data[i], (int*)dst_image->data[i], count, op); + else + DoBinaryOp((imushort*)src_image1->data[i], (imushort*)src_image2->data[i], (imushort*)dst_image->data[i], count, op); + break; + case IM_INT: + if (dst_image->data_type == IM_FLOAT) + DoBinaryOp((int*)src_image1->data[i], (int*)src_image2->data[i], (float*)dst_image->data[i], count, op); + else + DoBinaryOp((int*)src_image1->data[i], (int*)src_image2->data[i], (int*)dst_image->data[i], count, op); + break; + case IM_FLOAT: + DoBinaryOp((float*)src_image1->data[i], (float*)src_image2->data[i], (float*)dst_image->data[i], count, op); + break; + case IM_CFLOAT: + if (src_image2->data_type == IM_FLOAT) + DoBinaryOpCpxReal((imcfloat*)src_image1->data[i], (float*)src_image2->data[i], (imcfloat*)dst_image->data[i], count, op); + else + DoBinaryOp((imcfloat*)src_image1->data[i], (imcfloat*)src_image2->data[i], (imcfloat*)dst_image->data[i], count, op); + break; + } + } +} + +template +static inline T blend_op(const T& v1, const T& v2, const float& alpha) +{ + return (T)(alpha*v1 + (1.0f - alpha)*v2); +} + +template +static void DoBlendConst(T *map1, T *map2, T *map, int count, float alpha) +{ + for (int i = 0; i < count; i++) + map[i] = blend_op(map1[i], map2[i], alpha); +} + +void imProcessBlendConst(const imImage* src_image1, const imImage* src_image2, imImage* dst_image, float alpha) +{ + int count = src_image1->count; + + for (int i = 0; i < src_image1->depth; i++) + { + switch(src_image1->data_type) + { + case IM_BYTE: + DoBlendConst((imbyte*)src_image1->data[i], (imbyte*)src_image2->data[i], (imbyte*)dst_image->data[i], count, alpha); + break; + case IM_USHORT: + DoBlendConst((imushort*)src_image1->data[i], (imushort*)src_image2->data[i], (imushort*)dst_image->data[i], count, alpha); + break; + case IM_INT: + DoBlendConst((int*)src_image1->data[i], (int*)src_image2->data[i], (int*)dst_image->data[i], count, alpha); + break; + case IM_FLOAT: + DoBlendConst((float*)src_image1->data[i], (float*)src_image2->data[i], (float*)dst_image->data[i], count, alpha); + break; + case IM_CFLOAT: + DoBlendConst((imcfloat*)src_image1->data[i], (imcfloat*)src_image2->data[i], (imcfloat*)dst_image->data[i], count, alpha); + break; + } + } +} + +template +static void DoBlend(T *map1, T *map2, TA *alpha, T *map, int count, TA max) +{ + for (int i = 0; i < count; i++) + map[i] = blend_op(map1[i], map2[i], ((float)alpha[i])/max); +} + +void imProcessBlend(const imImage* src_image1, const imImage* src_image2, const imImage* alpha, imImage* dst_image) +{ + int count = src_image1->count; + + for (int i = 0; i < src_image1->depth; i++) + { + switch(src_image1->data_type) + { + case IM_BYTE: + DoBlend((imbyte*)src_image1->data[i], (imbyte*)src_image2->data[i], (imbyte*)alpha->data[0], (imbyte*)dst_image->data[i], count, (imbyte)255); + break; + case IM_USHORT: + DoBlend((imushort*)src_image1->data[i], (imushort*)src_image2->data[i], (imushort*)alpha->data[0], (imushort*)dst_image->data[i], count, (imushort)65535); + break; + case IM_INT: + DoBlend((int*)src_image1->data[i], (int*)src_image2->data[i], (int*)alpha->data[0], (int*)dst_image->data[i], count, (int)2147483647); + break; + case IM_FLOAT: + DoBlend((float*)src_image1->data[i], (float*)src_image2->data[i], (float*)alpha->data[0], (float*)dst_image->data[i], count, 1.0f); + break; + case IM_CFLOAT: + DoBlend((imcfloat*)src_image1->data[i], (imcfloat*)src_image2->data[i], (float*)alpha->data[0], (imcfloat*)dst_image->data[i], count, 1.0f); + break; + } + } +} + +static void DoBinaryConstOpCpxReal(imcfloat *map1, float value, imcfloat *map, int count, int op) +{ + int i; + + switch(op) + { + case IM_BIN_ADD: + for (i = 0; i < count; i++) + map[i] = add_op(map1[i], value); + break; + case IM_BIN_SUB: + for (i = 0; i < count; i++) + map[i] = sub_op(map1[i], value); + break; + case IM_BIN_MUL: + for (i = 0; i < count; i++) + map[i] = mul_op(map1[i], value); + break; + case IM_BIN_DIV: + for (i = 0; i < count; i++) + map[i] = div_op(map1[i], (imcfloat)value); + break; + case IM_BIN_DIFF: + for (i = 0; i < count; i++) + map[i] = diff_op(map1[i], value); + break; + case IM_BIN_MIN: + for (i = 0; i < count; i++) + map[i] = min_op(map1[i], value); + break; + case IM_BIN_MAX: + for (i = 0; i < count; i++) + map[i] = max_op(map1[i], value); + break; + case IM_BIN_POW: + for (i = 0; i < count; i++) + map[i] = pow_op(map1[i], value); + break; + } +} + +template +static void DoBinaryConstOp(T1 *map1, T2 value, T3 *map, int count, int op) +{ + int i; + + switch(op) + { + case IM_BIN_ADD: + for (i = 0; i < count; i++) + map[i] = (T3)add_op((T2)map1[i], value); + break; + case IM_BIN_SUB: + for (i = 0; i < count; i++) + map[i] = (T3)sub_op((T2)map1[i], value); + break; + case IM_BIN_MUL: + for (i = 0; i < count; i++) + map[i] = (T3)mul_op((T2)map1[i], value); + break; + case IM_BIN_DIV: + for (i = 0; i < count; i++) + map[i] = (T3)div_op((T2)map1[i], value); + break; + case IM_BIN_DIFF: + for (i = 0; i < count; i++) + map[i] = (T3)diff_op((T2)map1[i], value); + break; + case IM_BIN_MIN: + for (i = 0; i < count; i++) + map[i] = (T3)min_op((T2)map1[i], value); + break; + case IM_BIN_MAX: + for (i = 0; i < count; i++) + map[i] = (T3)max_op((T2)map1[i], value); + break; + case IM_BIN_POW: + for (i = 0; i < count; i++) + map[i] = (T3)pow_op((T2)map1[i], value); + break; + } +} + +template +static void DoBinaryConstOpByte(T1 *map1, int value, imbyte *map, int count, int op) +{ + int i; + + switch(op) + { + case IM_BIN_ADD: + for (i = 0; i < count; i++) + map[i] = (imbyte)crop_byte(add_op((int)map1[i], value)); + break; + case IM_BIN_SUB: + for (i = 0; i < count; i++) + map[i] = (imbyte)crop_byte(sub_op((int)map1[i], value)); + break; + case IM_BIN_MUL: + for (i = 0; i < count; i++) + map[i] = (imbyte)crop_byte(mul_op((int)map1[i], value)); + break; + case IM_BIN_DIV: + for (i = 0; i < count; i++) + map[i] = (imbyte)crop_byte(div_op((int)map1[i], value)); + break; + case IM_BIN_DIFF: + for (i = 0; i < count; i++) + map[i] = (imbyte)crop_byte(diff_op((int)map1[i], value)); + break; + case IM_BIN_MIN: + for (i = 0; i < count; i++) + map[i] = (imbyte)crop_byte(min_op((int)map1[i], value)); + break; + case IM_BIN_MAX: + for (i = 0; i < count; i++) + map[i] = (imbyte)crop_byte(max_op((int)map1[i], value)); + break; + case IM_BIN_POW: + for (i = 0; i < count; i++) + map[i] = (imbyte)crop_byte(pow_op((int)map1[i], value)); + break; + } +} + +void imProcessArithmeticConstOp(const imImage* src_image1, float value, imImage* dst_image, int op) +{ + int count = src_image1->count; + + for (int i = 0; i < src_image1->depth; i++) + { + switch(src_image1->data_type) + { + case IM_BYTE: + if (dst_image->data_type == IM_FLOAT) + DoBinaryConstOp((imbyte*)src_image1->data[i], (float)value, (float*)dst_image->data[i], count, op); + else if (dst_image->data_type == IM_USHORT) + DoBinaryConstOp((imbyte*)src_image1->data[i], (imushort)value, (imushort*)dst_image->data[i], count, op); + else if (dst_image->data_type == IM_INT) + DoBinaryConstOp((imbyte*)src_image1->data[i], (int)value, (int*)dst_image->data[i], count, op); + else + DoBinaryConstOpByte((imbyte*)src_image1->data[i], (int)value, (imbyte*)dst_image->data[i], count, op); + break; + case IM_USHORT: + if (dst_image->data_type == IM_FLOAT) + DoBinaryConstOp((imushort*)src_image1->data[i], (float)value, (float*)dst_image->data[i], count, op); + else if (dst_image->data_type == IM_INT) + DoBinaryConstOp((imushort*)src_image1->data[i], (int)value, (int*)dst_image->data[i], count, op); + else if (dst_image->data_type == IM_BYTE) + DoBinaryConstOpByte((imushort*)src_image1->data[i], (int)value, (imbyte*)dst_image->data[i], count, op); + else + DoBinaryConstOp((imushort*)src_image1->data[i], (imushort)value, (imushort*)dst_image->data[i], count, op); + break; + case IM_INT: + if (dst_image->data_type == IM_FLOAT) + DoBinaryConstOp((int*)src_image1->data[i], (float)value, (float*)dst_image->data[i], count, op); + else if (dst_image->data_type == IM_USHORT) + DoBinaryConstOp((int*)src_image1->data[i], (int)value, (imushort*)dst_image->data[i], count, op); + else if (dst_image->data_type == IM_BYTE) + DoBinaryConstOpByte((int*)src_image1->data[i], (int)value, (imbyte*)dst_image->data[i], count, op); + else + DoBinaryConstOp((int*)src_image1->data[i], (int)value, (int*)dst_image->data[i], count, op); + break; + case IM_FLOAT: + DoBinaryConstOp((float*)src_image1->data[i], (float)value, (float*)dst_image->data[i], count, op); + break; + case IM_CFLOAT: + DoBinaryConstOpCpxReal((imcfloat*)src_image1->data[i], (float)value, (imcfloat*)dst_image->data[i], count, op); + break; + } + } +} + +void imProcessMultipleMean(const imImage** src_image_list, int src_image_count, imImage* dst_image) +{ + const imImage* image1 = src_image_list[0]; + + int data_type = image1->data_type; + if (image1->data_type == IM_BYTE) + data_type = IM_USHORT; + + imImage *acum_image = imImageCreate(image1->width, image1->height, image1->color_space, data_type); + if (!acum_image) + return; + + for(int i = 0; i < src_image_count; i++) + { + const imImage *image = src_image_list[i]; + imProcessArithmeticOp(image, acum_image, acum_image, IM_BIN_ADD); /* acum_image += image */ + + } + + imProcessArithmeticConstOp(acum_image, float(src_image_count), dst_image, IM_BIN_DIV); + + imImageDestroy(acum_image); +} + +void imProcessMultipleStdDev(const imImage** src_image_list, int src_image_count, const imImage *mean_image, imImage* dst_image) +{ + imImage* aux_image = imImageClone(dst_image); + if (!aux_image) + return; + + // sdtdev = sqrt( sum(sqr(x - m)) / N) + + // a = sum(sqr(x - m)) + for(int i = 0; i < src_image_count; i++) + { + // aux_image = image - mean_image + imProcessArithmeticOp(src_image_list[i], mean_image, aux_image, IM_BIN_SUB); + + // aux_image = aux_image * aux_image + imProcessUnArithmeticOp(aux_image, aux_image, IM_UN_SQR); + + // dst_image += aux_image + imProcessArithmeticOp(aux_image, dst_image, dst_image, IM_BIN_ADD); + } + + // dst_image = dst_image / src_image_count; + imProcessArithmeticConstOp(dst_image, float(src_image_count), dst_image, IM_BIN_DIV); + + // dst_image = sqrt(dst_image); + imProcessUnArithmeticOp(dst_image, dst_image, IM_UN_SQRT); + + imImageDestroy(aux_image); +} + +template +static float AutoCovCalc(int width, int height, DT *src_map, DT *mean_map, int x, int y, float count) +{ + float value = 0; + int ni = height - y; + int nj = width - x; + int offset, offset1; + int next = width*y + x; + + for (int i = 0; i < ni; i++) + { + for (int j = 0; j < nj; j++) + { + offset = width*i + j; + offset1 = offset + next; + value += float(src_map[offset] - mean_map[offset]) * float(src_map[offset1] - mean_map[offset1]); + } + } + + return (value/count); +} + +template +static int AutoCov(int width, int height, DT *src_map, DT *mean_map, float *dst_map, int counter) +{ + int count = width*height; + + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + *dst_map = AutoCovCalc(width, height, src_map, mean_map, x, y, (float)count); + dst_map++; + } + + if (!imCounterInc(counter)) + return 0; + } + + return 1; +} + +int imProcessAutoCovariance(const imImage* image, const imImage* mean_image, imImage* dst_image) +{ + int ret = 0; + + int counter = imCounterBegin("Auto Convariance"); + imCounterTotal(counter, image->depth*image->height, "Processing..."); + + for (int i = 0; i < image->depth; i++) + { + switch(image->data_type) + { + case IM_BYTE: + ret = AutoCov(image->width, image->height, (imbyte*)image->data[i], (imbyte*)mean_image->data[i], (float*)dst_image->data[i], counter); + break; + case IM_USHORT: + ret = AutoCov(image->width, image->height, (imushort*)image->data[i], (imushort*)mean_image->data[i], (float*)dst_image->data[i], counter); + break; + case IM_INT: + ret = AutoCov(image->width, image->height, (int*)image->data[i], (int*)mean_image->data[i], (float*)dst_image->data[i], counter); + break; + case IM_FLOAT: + ret = AutoCov(image->width, image->height, (float*)image->data[i], (float*)mean_image->data[i], (float*)dst_image->data[i], counter); + break; + } + + if (!ret) + break; + } + + imCounterEnd(counter); + + return ret; +} + +void imProcessMultiplyConj(const imImage* image1, const imImage* image2, imImage* NewImage) +{ + int total_count = image1->count*image1->depth; + + imcfloat* map = (imcfloat*)NewImage->data[0]; + imcfloat* map1 = (imcfloat*)image1->data[0]; + imcfloat* map2 = (imcfloat*)image2->data[0]; + imcfloat tmp; // this will allow an in-place operation + + for (int i = 0; i < total_count; i++) + { + tmp.real = map1->real * map2->real + map1->imag * map2->imag; + tmp.imag = map1->real * map2->imag - map1->imag * map2->real; + *map = tmp; + + map++; + map1++; + map2++; + } +} diff --git a/im/src/process/im_arithmetic_un.cpp b/im/src/process/im_arithmetic_un.cpp new file mode 100755 index 0000000..e4dba8a --- /dev/null +++ b/im/src/process/im_arithmetic_un.cpp @@ -0,0 +1,256 @@ +/** \file + * \brief Unary Arithmetic Operations + * + * See Copyright Notice in im_lib.h + * $Id: im_arithmetic_un.cpp,v 1.2 2009/10/01 02:56:58 scuri Exp $ + */ + + +#include +#include +#include +#include + +#include "im_process_pon.h" +#include "im_math_op.h" + +#include +#include + +// Fake complex operations for real types +static inline imbyte conj_op(const imbyte& v) {return v;} +static inline imushort conj_op(const imushort& v) {return v;} +static inline int conj_op(const int& v) {return v;} +static inline float conj_op(const float& v) {return v;} +static inline imbyte cpxnorm_op(const imbyte& v) {return v;} +static inline imushort cpxnorm_op(const imushort& v) {return v;} +static inline int cpxnorm_op(const int& v) {return v;} +static inline float cpxnorm_op(const float& v) {return v;} + +static inline imcfloat conj_op(const imcfloat& v) +{ + imcfloat r; + r.real = v.real; + r.imag = -v.imag; + return r; +} + +static inline imcfloat cpxnorm_op(const imcfloat& v) +{ + imcfloat r; + float rmag = cpxmag(v); + if (rmag != 0.0f) + { + r.real = v.real/rmag; + r.imag = v.imag/rmag; + } + else + { + r.real = 0.0f; + r.imag = 0.0f; + } + return r; +} + +template +static void DoUnaryOp(T1 *map, T2 *new_map, int count, int op) +{ + int i; + + switch(op) + { + case IM_UN_ABS: + for (i = 0; i < count; i++) + new_map[i] = abs_op((T2)map[i]); + break; + case IM_UN_INV: + for (i = 0; i < count; i++) + new_map[i] = inv_op((T2)map[i]); + break; + case IM_UN_EQL: + for (i = 0; i < count; i++) + new_map[i] = (T2)map[i]; + break; + case IM_UN_LESS: + for (i = 0; i < count; i++) + new_map[i] = less_op((T2)map[i]); + break; + case IM_UN_SQR: + for (i = 0; i < count; i++) + new_map[i] = sqr_op((T2)map[i]); + break; + case IM_UN_SQRT: + for (i = 0; i < count; i++) + new_map[i] = sqrt_op((T2)map[i]); + break; + case IM_UN_LOG: + for (i = 0; i < count; i++) + new_map[i] = log_op((T2)map[i]); + break; + case IM_UN_SIN: + for (i = 0; i < count; i++) + new_map[i] = sin_op((T2)map[i]); + break; + case IM_UN_COS: + for (i = 0; i < count; i++) + new_map[i] = cos_op((T2)map[i]); + break; + case IM_UN_EXP: + for (i = 0; i < count; i++) + new_map[i] = exp_op((T2)map[i]); + break; + case IM_UN_CONJ: + for (i = 0; i < count; i++) + new_map[i] = conj_op((T2)map[i]); + break; + case IM_UN_CPXNORM: + for (i = 0; i < count; i++) + new_map[i] = cpxnorm_op((T2)map[i]); + break; + } +} + +template +static void DoUnaryOpByte(T1 *map, imbyte *new_map, int count, int op) +{ + int i; + + switch(op) + { + case IM_UN_ABS: + for (i = 0; i < count; i++) + new_map[i] = (imbyte)crop_byte(abs_op((int)map[i])); + break; + case IM_UN_INV: + for (i = 0; i < count; i++) + new_map[i] = (imbyte)crop_byte(inv_op((int)map[i])); /* will always be 0 */ + break; + case IM_UN_EQL: + for (i = 0; i < count; i++) + new_map[i] = (imbyte)crop_byte((int)map[i]); + break; + case IM_UN_LESS: + for (i = 0; i < count; i++) + new_map[i] = (imbyte)crop_byte(less_op((int)map[i])); + break; + case IM_UN_SQR: + for (i = 0; i < count; i++) + new_map[i] = (imbyte)crop_byte(sqr_op((int)map[i])); + break; + case IM_UN_SQRT: + for (i = 0; i < count; i++) + new_map[i] = (imbyte)crop_byte(sqrt_op((int)map[i])); + break; + case IM_UN_LOG: + for (i = 0; i < count; i++) + new_map[i] = (imbyte)crop_byte(log_op((int)map[i])); + break; + case IM_UN_SIN: + for (i = 0; i < count; i++) + new_map[i] = (imbyte)crop_byte(sin_op((int)map[i])); + break; + case IM_UN_COS: + for (i = 0; i < count; i++) + new_map[i] = (imbyte)crop_byte(cos_op((int)map[i])); + break; + case IM_UN_EXP: + for (i = 0; i < count; i++) + new_map[i] = (imbyte)crop_byte(exp_op((int)map[i])); + break; + } +} + +void imProcessUnArithmeticOp(const imImage* src_image, imImage* dst_image, int op) +{ + int total_count = src_image->count * src_image->depth; + + switch(src_image->data_type) + { + case IM_BYTE: + if (dst_image->data_type == IM_FLOAT) + DoUnaryOp((imbyte*)src_image->data[0], (float*)dst_image->data[0], total_count, op); + else if (dst_image->data_type == IM_INT) + DoUnaryOp((imbyte*)src_image->data[0], (int*)dst_image->data[0], total_count, op); + else if (dst_image->data_type == IM_USHORT) + DoUnaryOp((imbyte*)src_image->data[0], (imushort*)dst_image->data[0], total_count, op); + else + DoUnaryOpByte((imbyte*)src_image->data[0], (imbyte*)dst_image->data[0], total_count, op); + break; + case IM_USHORT: + if (dst_image->data_type == IM_BYTE) + DoUnaryOpByte((imushort*)src_image->data[0], (imbyte*)dst_image->data[0], total_count, op); + else if (dst_image->data_type == IM_INT) + DoUnaryOp((imushort*)src_image->data[0], (int*)dst_image->data[0], total_count, op); + else if (dst_image->data_type == IM_FLOAT) + DoUnaryOp((imushort*)src_image->data[0], (float*)dst_image->data[0], total_count, op); + else + DoUnaryOp((imushort*)src_image->data[0], (imushort*)dst_image->data[0], total_count, op); + break; + case IM_INT: + if (dst_image->data_type == IM_BYTE) + DoUnaryOpByte((int*)src_image->data[0], (imbyte*)dst_image->data[0], total_count, op); + else if (dst_image->data_type == IM_USHORT) + DoUnaryOp((int*)src_image->data[0], (imushort*)dst_image->data[0], total_count, op); + else if (dst_image->data_type == IM_FLOAT) + DoUnaryOp((int*)src_image->data[0], (float*)dst_image->data[0], total_count, op); + else + DoUnaryOp((int*)src_image->data[0], (int*)dst_image->data[0], total_count, op); + break; + case IM_FLOAT: + DoUnaryOp((float*)src_image->data[0], (float*)dst_image->data[0], total_count, op); + break; + case IM_CFLOAT: + DoUnaryOp((imcfloat*)src_image->data[0], (imcfloat*)dst_image->data[0], total_count, op); + break; + } +} + +void imProcessSplitComplex(const imImage* image, imImage* NewImage1, imImage* NewImage2, int polar) +{ + int total_count = image->count*image->depth; + + imcfloat* map = (imcfloat*)image->data[0]; + float* map1 = (float*)NewImage1->data[0]; + float* map2 = (float*)NewImage2->data[0]; + + for (int i = 0; i < total_count; i++) + { + if (polar) + { + map1[i] = cpxmag(map[i]); + map2[i] = cpxphase(map[i]); + } + else + { + map1[i] = map[i].real; + map2[i] = map[i].imag; + } + } +} + +void imProcessMergeComplex(const imImage* image1, const imImage* image2, imImage* NewImage, int polar) +{ + int total_count = image1->count*image1->depth; + + imcfloat* map = (imcfloat*)NewImage->data[0]; + float* map1 = (float*)image1->data[0]; + float* map2 = (float*)image2->data[0]; + + for (int i = 0; i < total_count; i++) + { + if (polar) + { + float phase = map2[i]; + if (phase > 180) phase -= 360; + phase /= 57.2957795f; + + map[i].real = (float)(map1[i] * cos(phase)); + map[i].imag = (float)(map1[i] * sin(phase)); + } + else + { + map[i].real = map1[i]; + map[i].imag = map2[i]; + } + } +} diff --git a/im/src/process/im_canny.cpp b/im/src/process/im_canny.cpp new file mode 100755 index 0000000..d749fc0 --- /dev/null +++ b/im/src/process/im_canny.cpp @@ -0,0 +1,254 @@ +/** \file + * \brief Canny Edge Detector + * + * See Copyright Notice in im_lib.h + * $Id: im_canny.cpp,v 1.1 2008/10/17 06:16:33 scuri Exp $ + */ + +#include + +#include "im_process_loc.h" + +#include +#include +#include + +/* Scale floating point magnitudes to 8 bits */ +static float MAG_SCALE; + +/* Biggest possible filter mask */ +#define MAX_MASK_SIZE 100 + +static float ** f2d (int nr, int nc); +static float gauss(float x, float sigma); +static float dGauss (float x, float sigma); +static float meanGauss (float x, float sigma); +static void seperable_convolution (const imImage* im, float *gau, int width, float **smx, float **smy); +static void dxy_seperable_convolution (float** im, int nr, int nc, float *gau, int width, float **sm, int which); +static void nonmax_suppress (float **dx, float **dy, imImage* mag); + +void imProcessCanny(const imImage* im, imImage* NewImage, float stddev) +{ + int width = 1; + float **smx,**smy; + float **dx,**dy; + int i; + float gau[MAX_MASK_SIZE], dgau[MAX_MASK_SIZE]; + +/* Create a Gaussian and a derivative of Gaussian filter mask */ + for(i=0; iheight, im->width); + smy = f2d (im->height, im->width); + +/* Convolution of source image with a Gaussian in X and Y directions */ + seperable_convolution (im, gau, width, smx, smy); + + MAG_SCALE = 0; + +/* Now convolve smoothed data with a derivative */ + dx = f2d (im->height, im->width); + dxy_seperable_convolution (smx, im->height, im->width, dgau, width, dx, 1); + free(smx[0]); free(smx); + + dy = f2d (im->height, im->width); + dxy_seperable_convolution (smy, im->height, im->width, dgau, width, dy, 0); + free(smy[0]); free(smy); + + if (MAG_SCALE) + MAG_SCALE = 255.0f/(1.4142f*MAG_SCALE); + + /* Non-maximum suppression - edge pixels should be a local max */ + nonmax_suppress (dx, dy, NewImage); + + free(dx[0]); free(dx); + free(dy[0]); free(dy); +} + +static float norm (float x, float y) +{ + return (float) sqrt ( (double)(x*x + y*y) ); +} + +static float ** f2d (int nr, int nc) +{ + float **x, *y; + int i; + + x = (float **)calloc ( nr, sizeof (float *) ); + if (!x) + return NULL; + + y = (float *)calloc ( nr*nc, sizeof (float) ); + if (!y) + return NULL; + + for (i=0; idata[0]; + + nr = im->height; + nc = im->width; + + for (i=0; iwidth + j]; y = gau[0] * im_data[i*im->width + j]; + for (k=1; kwidth + j] + gau[k]*im_data[I2*im->width + j]; + I1 = (j+k)%nc; I2 = (j-k+nc)%nc; + x += gau[k]*im_data[i*im->width + I1] + gau[k]*im_data[i*im->width + I2]; + } + smx[i][j] = x; smy[i][j] = y; + } + } +} + +static void dxy_seperable_convolution (float** im, int nr, int nc, float *gau, int width, float **sm, int which) +{ + int i,j,k, I1, I2; + float x; + + for (i=0; i MAG_SCALE) + MAG_SCALE = x; + } + } +} + +static unsigned char tobyte(float x) +{ + if (x > 255) return 255; + return (unsigned char)x; +} + +static void nonmax_suppress (float **dx, float **dy, imImage* mag) +{ + int i,j; + float xx, yy, g2, g1, g3, g4, g, xc, yc; + unsigned char* mag_data = (unsigned char*)mag->data[0]; + + for (i=1; iheight-1; i++) + { + for (j=1; jwidth-1; j++) + { + /* Treat the x and y derivatives as components of a vector */ + xc = dx[i][j]; + yc = dy[i][j]; + if (fabs(xc)<0.01 && fabs(yc)<0.01) continue; + + g = norm (xc, yc); + + /* Follow the gradient direction, as indicated by the direction of + the vector (xc, yc); retain pixels that are a local maximum. */ + + if (fabs(yc) > fabs(xc)) + { + /* The Y component is biggest, so gradient direction is basically UP/DOWN */ + xx = (float)(fabs(xc)/fabs(yc)); + yy = 1.0; + + g2 = norm (dx[i-1][j], dy[i-1][j]); + g4 = norm (dx[i+1][j], dy[i+1][j]); + if (xc*yc > 0.0) + { + g3 = norm (dx[i+1][j+1], dy[i+1][j+1]); + g1 = norm (dx[i-1][j-1], dy[i-1][j-1]); + } + else + { + g3 = norm (dx[i+1][j-1], dy[i+1][j-1]); + g1 = norm (dx[i-1][j+1], dy[i-1][j+1]); + } + + } + else + { + /* The X component is biggest, so gradient direction is basically LEFT/RIGHT */ + xx = (float)(fabs(yc)/fabs(xc)); + yy = 1.0; + + g2 = norm (dx[i][j+1], dy[i][j+1]); + g4 = norm (dx[i][j-1], dy[i][j-1]); + if (xc*yc > 0.0) + { + g3 = norm (dx[i-1][j-1], dy[i-1][j-1]); + g1 = norm (dx[i+1][j+1], dy[i+1][j+1]); + } + else + { + g1 = norm (dx[i-1][j+1], dy[i-1][j+1]); + g3 = norm (dx[i+1][j-1], dy[i+1][j-1]); + } + } + + /* Compute the interpolated value of the gradient magnitude */ + if ( (g > (xx*g1 + (yy-xx)*g2)) && (g > (xx*g3 + (yy-xx)*g4)) ) + { + mag_data[i*mag->width + j] = tobyte(g*MAG_SCALE); + } + } + } +} diff --git a/im/src/process/im_color.cpp b/im/src/process/im_color.cpp new file mode 100755 index 0000000..b27d4b3 --- /dev/null +++ b/im/src/process/im_color.cpp @@ -0,0 +1,255 @@ +/** \file + * \brief Color Processing Operations + * + * See Copyright Notice in im_lib.h + * $Id: im_color.cpp,v 1.1 2008/10/17 06:16:33 scuri Exp $ + */ + +#include +#include +#include +#include + +#include "im_process_pon.h" + +#include +#include + + +static void rgb2yrgb(imbyte* r, imbyte* g, imbyte* b, imbyte* y) +{ + int ri,gi,bi; + + *y = (imbyte)((299*(*r) + 587*(*g) + 114*(*b)) / 1000); + ri = (*r) - (*y) + 128; + gi = (*g) - (*y) + 128; + bi = (*b) - (*y) + 128; + + if (ri < 0) ri = 0; + if (gi < 0) gi = 0; + if (bi < 0) bi = 0; + + *r = (imbyte)ri; + *g = (imbyte)gi; + *b = (imbyte)bi; +} + +void imProcessSplitYChroma(const imImage* src_image, imImage* y_image, imImage* chroma_image) +{ + imbyte Y, + *red=(imbyte*)src_image->data[0], + *green=(imbyte*)src_image->data[1], + *blue=(imbyte*)src_image->data[2], + *red2=(imbyte*)chroma_image->data[0], + *green2=(imbyte*)chroma_image->data[1], + *blue2=(imbyte*)chroma_image->data[2], + *map1=(imbyte*)y_image->data[0]; + + for (int i = 0; i < src_image->count; i++) + { + imbyte R = red[i]; + imbyte G = green[i]; + imbyte B = blue[i]; + + rgb2yrgb(&R, &G, &B, &Y); + + map1[i] = Y; + + red2[i] = R; + green2[i] = G; + blue2[i] = B; + } +} + +static void DoSplitHSIFloat(float** data, float* hue, float* saturation, float* intensity, int count) +{ + float *red=data[0], + *green=data[1], + *blue=data[2]; + + for (int i = 0; i < count; i++) + { + imColorRGB2HSI(red[i], green[i], blue[i], &hue[i], &saturation[i], &intensity[i]); + } +} + +static void DoSplitHSIByte(imbyte** data, float* hue, float* saturation, float* intensity, int count) +{ + imbyte *red=data[0], + *green=data[1], + *blue=data[2]; + + for (int i = 0; i < count; i++) + { + imColorRGB2HSIbyte(red[i], green[i], blue[i], &hue[i], &saturation[i], &intensity[i]); + } +} + +void imProcessSplitHSI(const imImage* image, imImage* image1, imImage* image2, imImage* image3) +{ + switch(image->data_type) + { + case IM_BYTE: + DoSplitHSIByte((imbyte**)image->data, (float*)image1->data[0], (float*)image2->data[0], (float*)image3->data[0], image->count); + break; + case IM_FLOAT: + DoSplitHSIFloat((float**)image->data, (float*)image1->data[0], (float*)image2->data[0], (float*)image3->data[0], image->count); + break; + } + + imImageSetPalette(image1, imPaletteHues(), 256); +} + +static void DoMergeHSIFloat(float** data, float* hue, float* saturation, float* intensity, int count) +{ + float *red=data[0], + *green=data[1], + *blue=data[2]; + + for (int i = 0; i < count; i++) + { + imColorHSI2RGB(hue[i], saturation[i], intensity[i], &red[i], &green[i], &blue[i]); + } +} + +static void DoMergeHSIByte(imbyte** data, float* hue, float* saturation, float* intensity, int count) +{ + imbyte *red=data[0], + *green=data[1], + *blue=data[2]; + + for (int i = 0; i < count; i++) + { + imColorHSI2RGBbyte(hue[i], saturation[i], intensity[i], &red[i], &green[i], &blue[i]); + } +} + +void imProcessMergeHSI(const imImage* image1, const imImage* image2, const imImage* image3, imImage* image) +{ + switch(image->data_type) + { + case IM_BYTE: + DoMergeHSIByte((imbyte**)image->data, (float*)image1->data[0], (float*)image2->data[0], (float*)image3->data[0], image->count); + break; + case IM_FLOAT: + DoMergeHSIFloat((float**)image->data, (float*)image1->data[0], (float*)image2->data[0], (float*)image3->data[0], image->count); + break; + } +} + +void imProcessSplitComponents(const imImage* src_image, imImage** dst_image) +{ + memcpy(dst_image[0]->data[0], src_image->data[0], src_image->plane_size); + memcpy(dst_image[1]->data[0], src_image->data[1], src_image->plane_size); + memcpy(dst_image[2]->data[0], src_image->data[2], src_image->plane_size); + if (imColorModeDepth(src_image->color_space) == 4) + memcpy(dst_image[3]->data[0], src_image->data[3], src_image->plane_size); +} + +void imProcessMergeComponents(const imImage** src_image, imImage* dst_image) +{ + memcpy(dst_image->data[0], src_image[0]->data[0], dst_image->plane_size); + memcpy(dst_image->data[1], src_image[1]->data[0], dst_image->plane_size); + memcpy(dst_image->data[2], src_image[2]->data[0], dst_image->plane_size); + if (imColorModeDepth(dst_image->color_space) == 4) + memcpy(dst_image->data[3], src_image[3]->data[0], dst_image->plane_size); +} + +template +static void DoNormalizeComp(T** src_data, float** dst_data, int count, int depth) +{ + int d; + T* src_pdata[4]; + float* dst_pdata[4]; + + for(d = 0; d < depth; d++) + { + dst_pdata[d] = dst_data[d]; + src_pdata[d] = src_data[d]; + } + + for (int i = 0; i < count; i++) + { + float sum = 0; + for(d = 0; d < depth; d++) + sum += (float)*(src_pdata[d]); + + for(d = 0; d < depth; d++) + { + if (sum == 0) + *(dst_pdata[d]) = 0; + else + *(dst_pdata[d]) = (float)*(src_pdata[d]) / sum; + + dst_pdata[d]++; + src_pdata[d]++; + } + } +} + +void imProcessNormalizeComponents(const imImage* src_image, imImage* dst_image) +{ + switch(src_image->data_type) + { + case IM_BYTE: + DoNormalizeComp((imbyte**)src_image->data, (float**)dst_image->data, src_image->count, src_image->depth); + break; + case IM_USHORT: + DoNormalizeComp((imushort**)src_image->data, (float**)dst_image->data, src_image->count, src_image->depth); + break; + case IM_INT: + DoNormalizeComp((int**)src_image->data, (float**)dst_image->data, src_image->count, src_image->depth); + break; + case IM_FLOAT: + DoNormalizeComp((float**)src_image->data, (float**)dst_image->data, src_image->count, src_image->depth); + break; + } +} + +template +static void DoReplaceColor(T *src_data, T *dst_data, int width, int height, int depth, float* src_color, float* dst_color) +{ + int d, count = width*height; + for (int i = 0; i < count; i++) + { + int equal = 1; + for (d = 0; d < depth; d++) + { + if (*(src_data+d*count) != (T)src_color[d]) + { + equal = 0; + break; + } + } + + for (d = 0; d < depth; d++) + { + if (equal) + *(dst_data+d*count) = (T)dst_color[d]; + else + *(dst_data+d*count) = *(src_data+d*count); + } + + src_data++; + dst_data++; + } +} + +void imProcessReplaceColor(const imImage* src_image, imImage* dst_image, float* src_color, float* dst_color) +{ + switch(src_image->data_type) + { + case IM_BYTE: + DoReplaceColor((imbyte*)src_image->data[0], (imbyte*)dst_image->data[0], src_image->width, src_image->height, src_image->depth, src_color, dst_color); + break; + case IM_USHORT: + DoReplaceColor((imushort*)src_image->data[0], (imushort*)dst_image->data[0], src_image->width, src_image->height, src_image->depth, src_color, dst_color); + break; + case IM_INT: + DoReplaceColor((int*)src_image->data[0], (int*)dst_image->data[0], src_image->width, src_image->height, src_image->depth, src_color, dst_color); + break; + case IM_FLOAT: + DoReplaceColor((float*)src_image->data[0], (float*)dst_image->data[0], src_image->width, src_image->height, src_image->depth, src_color, dst_color); + break; + } +} diff --git a/im/src/process/im_convolve.cpp b/im/src/process/im_convolve.cpp new file mode 100755 index 0000000..a88a25c --- /dev/null +++ b/im/src/process/im_convolve.cpp @@ -0,0 +1,1594 @@ +/** \file + * \brief Convolution Operations + * + * See Copyright Notice in im_lib.h + * $Id: im_convolve.cpp,v 1.2 2009/10/01 02:56:58 scuri Exp $ + */ + + +#include +#include +#include +#include +#include +#include +#include + +#include "im_process_loc.h" +#include "im_process_pon.h" + +#include +#include +#include +#include +#include + +/* Rotating Kernels +3x3 + 6 7 8 7 8 5 + 3 4 5 6 4 2 + 0 1 2 3 0 1 + +5x5 + 20 21 22 23 24 22 23 24 19 14 + 15 16 17 18 19 21 17 18 13 9 + 10 11 12 13 14 20 16 12 8 4 + 5 6 7 8 9 15 11 6 7 3 + 0 1 2 3 4 10 5 0 1 2 + +7x7 + 42 43 44 45 46 47 48 45 46 47 48 41 34 27 + 35 36 37 38 39 40 41 44 38 39 40 33 26 20 + 28 29 30 31 32 33 34 43 37 31 32 25 19 13 + 21 22 23 24 25 26 27 42 36 30 24 18 12 6 + 14 15 16 17 18 19 20 35 29 23 16 17 11 5 + 7 8 9 10 11 12 13 28 22 15 8 9 10 4 + 0 1 2 3 4 5 6 21 14 7 0 1 2 3 + + TO DO: a generic odd rotation function... +*/ + +template +static void iRotateKernel(KT* kernel_map, int kernel_size) +{ + KT temp; + + switch (kernel_size) + { + case 3: + { + temp = kernel_map[0]; + kernel_map[0] = kernel_map[3]; + kernel_map[3] = kernel_map[6]; + kernel_map[6] = kernel_map[7]; + kernel_map[7] = kernel_map[8]; + kernel_map[8] = kernel_map[5]; + kernel_map[5] = kernel_map[2]; + kernel_map[2] = kernel_map[1]; + kernel_map[1] = temp; + } + break; + case 5: + { + temp = kernel_map[0]; + kernel_map[0] = kernel_map[10]; + kernel_map[10] = kernel_map[20]; + kernel_map[20] = kernel_map[22]; + kernel_map[22] = kernel_map[24]; + kernel_map[24] = kernel_map[14]; + kernel_map[14] = kernel_map[4]; + kernel_map[4] = kernel_map[2]; + kernel_map[2] = temp; + + temp = kernel_map[5]; + kernel_map[5] = kernel_map[15]; + kernel_map[15] = kernel_map[21]; + kernel_map[21] = kernel_map[23]; + kernel_map[23] = kernel_map[19]; + kernel_map[19] = kernel_map[9]; + kernel_map[9] = kernel_map[3]; + kernel_map[3] = kernel_map[1]; + kernel_map[1] = temp; + + temp = kernel_map[6]; + kernel_map[6] = kernel_map[11]; + kernel_map[11] = kernel_map[16]; + kernel_map[16] = kernel_map[17]; + kernel_map[17] = kernel_map[18]; + kernel_map[18] = kernel_map[13]; + kernel_map[13] = kernel_map[8]; + kernel_map[8] = kernel_map[7]; + kernel_map[7] = temp; + } + break; + case 7: + { + temp = kernel_map[2]; + kernel_map[2] = kernel_map[7]; + kernel_map[7] = kernel_map[28]; + kernel_map[28] = kernel_map[43]; + kernel_map[43] = kernel_map[46]; + kernel_map[46] = kernel_map[41]; + kernel_map[41] = kernel_map[20]; + kernel_map[20] = kernel_map[5]; + kernel_map[5] = temp; + + temp = kernel_map[1]; + kernel_map[1] = kernel_map[14]; + kernel_map[14] = kernel_map[35]; + kernel_map[35] = kernel_map[44]; + kernel_map[44] = kernel_map[47]; + kernel_map[47] = kernel_map[34]; + kernel_map[34] = kernel_map[13]; + kernel_map[13] = kernel_map[4]; + kernel_map[4] = temp; + + temp = kernel_map[0]; + kernel_map[0] = kernel_map[21]; + kernel_map[21] = kernel_map[42]; + kernel_map[42] = kernel_map[45]; + kernel_map[45] = kernel_map[48]; + kernel_map[48] = kernel_map[27]; + kernel_map[27] = kernel_map[6]; + kernel_map[6] = kernel_map[3]; + kernel_map[3] = temp; + + temp = kernel_map[9]; + kernel_map[9] = kernel_map[15]; + kernel_map[15] = kernel_map[29]; + kernel_map[29] = kernel_map[37]; + kernel_map[37] = kernel_map[39]; + kernel_map[39] = kernel_map[33]; + kernel_map[33] = kernel_map[19]; + kernel_map[19] = kernel_map[11]; + kernel_map[11] = temp; + + temp = kernel_map[8]; + kernel_map[8] = kernel_map[22]; + kernel_map[22] = kernel_map[36]; + kernel_map[36] = kernel_map[38]; + kernel_map[38] = kernel_map[40]; + kernel_map[40] = kernel_map[26]; + kernel_map[26] = kernel_map[12]; + kernel_map[12] = kernel_map[10]; + kernel_map[10] = temp; + + temp = kernel_map[16]; + kernel_map[16] = kernel_map[23]; + kernel_map[23] = kernel_map[30]; + kernel_map[30] = kernel_map[31]; + kernel_map[31] = kernel_map[32]; + kernel_map[32] = kernel_map[25]; + kernel_map[25] = kernel_map[18]; + kernel_map[18] = kernel_map[17]; + kernel_map[17] = temp; + } + break; + } +} + +void imProcessRotateKernel(imImage* kernel) +{ + if (kernel->data_type == IM_INT) + iRotateKernel((int*)kernel->data[0], kernel->width); + else + iRotateKernel((float*)kernel->data[0], kernel->width); +} + +template +static int DoCompassConvolve(T* map, T* new_map, int width, int height, KT* orig_kernel_map, int kernel_size, int counter, CT) +{ + CT value; + KT total, *kernel_line, kvalue; + int offset, new_offset, i, j, x, y, kcount; + + // duplicate the kernel data so we can rotate it + kcount = kernel_size*kernel_size; + KT* kernel_map = (KT*)malloc(kcount*sizeof(KT)); + + int ks2 = kernel_size/2; + + total = 0; + for(j = 0; j < kcount; j++) + { + kvalue = orig_kernel_map[j]; + kernel_map[j] = kvalue; + total += kvalue; + } + + if (total == 0) + total = 1; + + for(j = 0; j < height; j++) + { + new_offset = j * width; + + for(i = 0; i < width; i++) + { + CT max_value = 0; + + for(int k = 0; k < 8; k++) // Rotate 8 times + { + value = 0; + + for(y = -ks2; y <= ks2; y++) + { + kernel_line = kernel_map + (y+ks2)*kernel_size; + + if (j + y < 0) // pass the bottom border + offset = -(y + j + 1) * width; + else if (j + y >= height) // pass the top border + offset = (2*height - 1 - (j + y)) * width; + else + offset = (j + y) * width; + + for(x = -ks2; x <= ks2; x++) + { + if (i + x < 0) // pass the left border + value += kernel_line[x+ks2] * map[offset - (i + x + 1)]; + else if (i + x >= width) // pass the right border + value += kernel_line[x+ks2] * map[offset + 2*width - 1 - (i + x)]; + else if (offset != -1) + value += kernel_line[x+ks2] * map[offset + (i + x)]; + } + } + + if (abs_op(value) > max_value) + max_value = abs_op(value); + + iRotateKernel(kernel_map, kernel_size); + } + + max_value /= total; + + int size_of = sizeof(imbyte); + if (sizeof(T) == size_of) + new_map[new_offset + i] = (T)IM_BYTECROP(max_value); + else + new_map[new_offset + i] = (T)max_value; + } + + if (!imCounterInc(counter)) + { + free(kernel_map); + return 0; + } + } + + free(kernel_map); + return 1; +} + +int imProcessCompassConvolve(const imImage* src_image, imImage* dst_image, imImage *kernel) +{ + int ret = 0; + + int counter = imCounterBegin("Compass Convolution"); + const char* msg = (const char*)imImageGetAttribute(kernel, "Description", NULL, NULL); + if (!msg) msg = "Filtering..."; + imCounterTotal(counter, src_image->depth*src_image->height, msg); + + for (int i = 0; i < src_image->depth; i++) + { + switch(src_image->data_type) + { + case IM_BYTE: + if (kernel->data_type == IM_INT) + ret = DoCompassConvolve((imbyte*)src_image->data[i], (imbyte*)dst_image->data[i], src_image->width, src_image->height, (int*)kernel->data[0], kernel->width, counter, (int)0); + else + ret = DoCompassConvolve((imbyte*)src_image->data[i], (imbyte*)dst_image->data[i], src_image->width, src_image->height, (float*)kernel->data[0], kernel->width, counter, (float)0); + break; + case IM_USHORT: + if (kernel->data_type == IM_INT) + ret = DoCompassConvolve((imushort*)src_image->data[i], (imushort*)dst_image->data[i], src_image->width, src_image->height, (int*)kernel->data[0], kernel->width, counter, (int)0); + else + ret = DoCompassConvolve((imushort*)src_image->data[i], (imushort*)dst_image->data[i], src_image->width, src_image->height, (float*)kernel->data[0], kernel->width, counter, (float)0); + break; + case IM_INT: + if (kernel->data_type == IM_INT) + ret = DoCompassConvolve((int*)src_image->data[i], (int*)dst_image->data[i], src_image->width, src_image->height, (int*)kernel->data[0], kernel->width, counter, (int)0); + else + ret = DoCompassConvolve((int*)src_image->data[i], (int*)dst_image->data[i], src_image->width, src_image->height, (float*)kernel->data[0], kernel->width, counter, (float)0); + break; + case IM_FLOAT: + if (kernel->data_type == IM_INT) + ret = DoCompassConvolve((float*)src_image->data[i], (float*)dst_image->data[i], src_image->width, src_image->height, (int*)kernel->data[0], kernel->width, counter, (float)0); + else + ret = DoCompassConvolve((float*)src_image->data[i], (float*)dst_image->data[i], src_image->width, src_image->height, (float*)kernel->data[0], kernel->width, counter, (float)0); + break; + } + + if (!ret) + break; + } + + imCounterEnd(counter); + + return ret; +} + +template +static int DoConvolveDual(T* map, T* new_map, int width, int height, KT* kernel_map1, KT* kernel_map2, int kernel_width, int kernel_height, int counter, CT) +{ + CT value1, value2, value; + KT total1, total2, *kernel_line; + int offset, new_offset, i, j, x, y; + + int kh2 = kernel_height/2; + int kw2 = kernel_width/2; + + if (kernel_height % 2 == 0) kh2--; + if (kernel_width % 2 == 0) kw2--; + + total1 = 0; + for(j = 0; j < kernel_height; j++) + { + for(i = 0; i < kernel_width; i++) + total1 += kernel_map1[j*kernel_width + i]; + } + + if (total1 == 0) + total1 = 1; + + total2 = 0; + for(j = 0; j < kernel_height; j++) + { + for(i = 0; i < kernel_width; i++) + total2 += kernel_map2[j*kernel_width + i]; + } + + if (total2 == 0) + total2 = 1; + + for(j = 0; j < height; j++) + { + new_offset = j * width; + + for(i = 0; i < width; i++) + { + value1 = 0; + value2 = 0; + + for(y = -kh2; y <= kh2; y++) + { + if (j + y < 0) // pass the bottom border + offset = -(y + j + 1) * width; + else if (j + y >= height) // pass the top border + offset = (2*height - 1 - (j + y)) * width; + else + offset = (j + y) * width; + + kernel_line = kernel_map1 + (y+kh2)*kernel_width; + for(x = -kw2; x <= kw2; x++) + { + if (i + x < 0) // pass the left border + value1 += kernel_line[x+kw2] * map[offset - (i + x + 1)]; + else if (i + x >= width) // pass the right border + value1 += kernel_line[x+kw2] * map[offset + 2*width - 1 - (i + x)]; + else if (offset != -1) + value1 += kernel_line[x+kw2] * map[offset + (i + x)]; + } + + kernel_line = kernel_map2 + (y+kh2)*kernel_width; + for(x = -kw2; x <= kw2; x++) + { + if (i + x < 0) // pass the left border + value2 += kernel_line[x+kw2] * map[offset - (i + x + 1)]; + else if (i + x >= width) // pass the right border + value2 += kernel_line[x+kw2] * map[offset + 2*width - 1 - (i + x)]; + else if (offset != -1) + value2 += kernel_line[x+kw2] * map[offset + (i + x)]; + } + } + + value1 /= total1; + value2 /= total2; + + value = (CT)sqrt((double)(value1*value1 + value2*value2)); + + int size_of = sizeof(imbyte); + if (sizeof(T) == size_of) + new_map[new_offset + i] = (T)IM_BYTECROP(value); + else + new_map[new_offset + i] = (T)value; + } + + if (!imCounterInc(counter)) + return 0; + } + + return 1; +} + +template +static int DoConvolveDualCpx(imcfloat* map, imcfloat* new_map, int width, int height, KT* kernel_map1, KT* kernel_map2, int kernel_width, int kernel_height, int counter) +{ + imcfloat value1, value2; + KT total1, total2, *kernel_line; + int offset, new_offset, i, j, x, y; + + int kh2 = kernel_height/2; + int kw2 = kernel_width/2; + + if (kernel_height % 2 == 0) kh2--; + if (kernel_width % 2 == 0) kw2--; + + total1 = 0; + for(j = 0; j < kernel_height; j++) + { + for(i = 0; i < kernel_width; i++) + total1 += kernel_map1[j*kernel_width + i]; + } + + if (total1 == 0) + total1 = 1; + + total2 = 0; + for(j = 0; j < kernel_height; j++) + { + for(i = 0; i < kernel_width; i++) + total2 += kernel_map1[j*kernel_width + i]; + } + + if (total2 == 0) + total2 = 1; + + for(j = 0; j < height; j++) + { + new_offset = j * width; + + for(i = 0; i < width; i++) + { + value1 = 0; + value2 = 0; + + for(y = -kh2; y <= kh2; y++) + { + if (j + y < 0) // pass the bottom border + offset = -(y + j + 1) * width; + else if (j + y >= height) // pass the top border + offset = (2*height - 1 - (j + y)) * width; + else + offset = (j + y) * width; + + kernel_line = kernel_map1 + (y+kh2)*kernel_width; + for(x = -kw2; x <= kw2; x++) + { + if (i + x < 0) // pass the left border + value1 += map[offset - (i + x + 1)] * (float)kernel_line[x+kw2]; + else if (i + x >= width) // pass the right border + value1 += map[offset + 2*width - 1 - (i + x)] * (float)kernel_line[x+kw2]; + else if (offset != -1) + value1 += map[offset + (i + x)] * (float)kernel_line[x+kw2]; + } + + kernel_line = kernel_map2 + (y+kh2)*kernel_width; + for(x = -kw2; x <= kw2; x++) + { + if (i + x < 0) // pass the left border + value2 += map[offset - (i + x + 1)] * (float)kernel_line[x+kw2]; + else if (i + x >= width) // pass the right border + value2 += map[offset + 2*width - 1 - (i + x)] * (float)kernel_line[x+kw2]; + else if (offset != -1) + value2 += map[offset + (i + x)] * (float)kernel_line[x+kw2]; + } + } + + value1 /= (float)total1; + value2 /= (float)total2; + + new_map[new_offset + i] = sqrt(value1*value1 + value2*value2); + } + + if (!imCounterInc(counter)) + return 0; + } + + return 1; +} + +int imProcessConvolveDual(const imImage* src_image, imImage* dst_image, const imImage *kernel1, const imImage *kernel2) +{ + int counter = imCounterBegin("Convolution"); + const char* msg = (const char*)imImageGetAttribute(kernel1, "Description", NULL, NULL); + if (!msg) msg = "Filtering..."; + imCounterTotal(counter, src_image->depth*src_image->height, msg); + + int ret = 0; + + for (int i = 0; i < src_image->depth; i++) + { + switch(src_image->data_type) + { + case IM_BYTE: + if (kernel1->data_type == IM_INT) + ret = DoConvolveDual((imbyte*)src_image->data[i], (imbyte*)dst_image->data[i], src_image->width, src_image->height, (int*)kernel1->data[0], (int*)kernel2->data[0], kernel1->width, kernel1->height, counter, (int)0); + else + ret = DoConvolveDual((imbyte*)src_image->data[i], (imbyte*)dst_image->data[i], src_image->width, src_image->height, (float*)kernel1->data[0], (float*)kernel2->data[0], kernel1->width, kernel1->height, counter, (float)0); + break; + case IM_USHORT: + if (kernel1->data_type == IM_INT) + ret = DoConvolveDual((imushort*)src_image->data[i], (imushort*)dst_image->data[i], src_image->width, src_image->height, (int*)kernel1->data[0], (int*)kernel2->data[0], kernel1->width, kernel1->height, counter, (int)0); + else + ret = DoConvolveDual((imushort*)src_image->data[i], (imushort*)dst_image->data[i], src_image->width, src_image->height, (float*)kernel1->data[0], (float*)kernel2->data[0], kernel1->width, kernel1->height, counter, (float)0); + break; + case IM_INT: + if (kernel1->data_type == IM_INT) + ret = DoConvolveDual((int*)src_image->data[i], (int*)dst_image->data[i], src_image->width, src_image->height, (int*)kernel1->data[0], (int*)kernel2->data[0], kernel1->width, kernel1->height, counter, (int)0); + else + ret = DoConvolveDual((int*)src_image->data[i], (int*)dst_image->data[i], src_image->width, src_image->height, (float*)kernel1->data[0], (float*)kernel2->data[0], kernel1->width, kernel1->height, counter, (float)0); + break; + case IM_FLOAT: + if (kernel1->data_type == IM_INT) + ret = DoConvolveDual((float*)src_image->data[i], (float*)dst_image->data[i], src_image->width, src_image->height, (int*)kernel1->data[0], (int*)kernel2->data[0], kernel1->width, kernel1->height, counter, (float)0); + else + ret = DoConvolveDual((float*)src_image->data[i], (float*)dst_image->data[i], src_image->width, src_image->height, (float*)kernel1->data[0], (float*)kernel2->data[0], kernel1->width, kernel1->height, counter, (float)0); + break; + case IM_CFLOAT: + if (kernel1->data_type == IM_INT) + ret = DoConvolveDualCpx((imcfloat*)src_image->data[i], (imcfloat*)dst_image->data[i], src_image->width, src_image->height, (int*)kernel1->data[0], (int*)kernel2->data[0], kernel1->width, kernel1->height, counter); + else + ret = DoConvolveDualCpx((imcfloat*)src_image->data[i], (imcfloat*)dst_image->data[i], src_image->width, src_image->height, (float*)kernel1->data[0], (float*)kernel2->data[0], kernel1->width, kernel1->height, counter); + break; + } + + if (!ret) + break; + } + + imCounterEnd(counter); + + return ret; +} + +template +static int DoConvolve(T* map, T* new_map, int width, int height, KT* kernel_map, int kernel_width, int kernel_height, int counter, CT) +{ + CT value; + KT total, *kernel_line; + int offset, new_offset, i, j, x, y; + + int kh2 = kernel_height/2; + int kw2 = kernel_width/2; + + if (kernel_height % 2 == 0) kh2--; + if (kernel_width % 2 == 0) kw2--; + + total = 0; + for(j = 0; j < kernel_height; j++) + { + for(i = 0; i < kernel_width; i++) + total += kernel_map[j*kernel_width + i]; + } + + if (total == 0) + total = 1; + + for(j = 0; j < height; j++) + { + new_offset = j * width; + + for(i = 0; i < width; i++) + { + value = 0; + + for(y = -kh2; y <= kh2; y++) + { + kernel_line = kernel_map + (y+kh2)*kernel_width; + + if (j + y < 0) // pass the bottom border + offset = -(y + j + 1) * width; + else if (j + y >= height) // pass the top border + offset = (2*height - 1 - (j + y)) * width; + else + offset = (j + y) * width; + + for(x = -kw2; x <= kw2; x++) + { + if (i + x < 0) // pass the left border + value += kernel_line[x+kw2] * map[offset - (i + x + 1)]; + else if (i + x >= width) // pass the right border + value += kernel_line[x+kw2] * map[offset + 2*width - 1 - (i + x)]; + else if (offset != -1) + value += kernel_line[x+kw2] * map[offset + (i + x)]; + } + } + + value /= total; + + int size_of = sizeof(imbyte); + if (sizeof(T) == size_of) + new_map[new_offset + i] = (T)IM_BYTECROP(value); + else + new_map[new_offset + i] = (T)value; + } + + if (!imCounterInc(counter)) + return 0; + } + + return 1; +} + +template +static int DoConvolveCpx(imcfloat* map, imcfloat* new_map, int width, int height, KT* kernel_map, int kernel_width, int kernel_height, int counter) +{ + imcfloat value; + KT total, *kernel_line; + int offset, new_offset, i, j, x, y; + + int kh2 = kernel_height/2; + int kw2 = kernel_width/2; + + if (kernel_height % 2 == 0) kh2--; + if (kernel_width % 2 == 0) kw2--; + + total = 0; + for(j = 0; j < kernel_height; j++) + { + for(i = 0; i < kernel_width; i++) + total += kernel_map[j*kernel_width + i]; + } + + if (total == 0) + total = 1; + + for(j = 0; j < height; j++) + { + new_offset = j * width; + + for(i = 0; i < width; i++) + { + value = 0; + + for(y = -kh2; y <= kh2; y++) + { + kernel_line = kernel_map + (y+kh2)*kernel_width; + + if (j + y < 0) // pass the bottom border + offset = -(y + j + 1) * width; + else if (j + y >= height) // pass the top border + offset = (2*height - 1 - (j + y)) * width; + else + offset = (j + y) * width; + + for(x = -kw2; x <= kw2; x++) + { + if (i + x < 0) // pass the left border + value += map[offset - (i + x + 1)] * (float)kernel_line[x+kw2]; + else if (i + x >= width) // pass the right border + value += map[offset + 2*width - 1 - (i + x)] * (float)kernel_line[x+kw2]; + else if (offset != -1) + value += map[offset + (i + x)] * (float)kernel_line[x+kw2]; + } + } + + value /= (float)total; + + new_map[new_offset + i] = value; + } + + if (!imCounterInc(counter)) + return 0; + } + + return 1; +} + +static int DoConvolveStep(const imImage* src_image, imImage* dst_image, const imImage *kernel, int counter) +{ + int ret = 0; + + for (int i = 0; i < src_image->depth; i++) + { + switch(src_image->data_type) + { + case IM_BYTE: + if (kernel->data_type == IM_INT) + ret = DoConvolve((imbyte*)src_image->data[i], (imbyte*)dst_image->data[i], src_image->width, src_image->height, (int*)kernel->data[0], kernel->width, kernel->height, counter, (int)0); + else + ret = DoConvolve((imbyte*)src_image->data[i], (imbyte*)dst_image->data[i], src_image->width, src_image->height, (float*)kernel->data[0], kernel->width, kernel->height, counter, (float)0); + break; + case IM_USHORT: + if (kernel->data_type == IM_INT) + ret = DoConvolve((imushort*)src_image->data[i], (imushort*)dst_image->data[i], src_image->width, src_image->height, (int*)kernel->data[0], kernel->width, kernel->height, counter, (int)0); + else + ret = DoConvolve((imushort*)src_image->data[i], (imushort*)dst_image->data[i], src_image->width, src_image->height, (float*)kernel->data[0], kernel->width, kernel->height, counter, (float)0); + break; + case IM_INT: + if (kernel->data_type == IM_INT) + ret = DoConvolve((int*)src_image->data[i], (int*)dst_image->data[i], src_image->width, src_image->height, (int*)kernel->data[0], kernel->width, kernel->height, counter, (int)0); + else + ret = DoConvolve((int*)src_image->data[i], (int*)dst_image->data[i], src_image->width, src_image->height, (float*)kernel->data[0], kernel->width, kernel->height, counter, (float)0); + break; + case IM_FLOAT: + if (kernel->data_type == IM_INT) + ret = DoConvolve((float*)src_image->data[i], (float*)dst_image->data[i], src_image->width, src_image->height, (int*)kernel->data[0], kernel->width, kernel->height, counter, (float)0); + else + ret = DoConvolve((float*)src_image->data[i], (float*)dst_image->data[i], src_image->width, src_image->height, (float*)kernel->data[0], kernel->width, kernel->height, counter, (float)0); + break; + case IM_CFLOAT: + if (kernel->data_type == IM_INT) + ret = DoConvolveCpx((imcfloat*)src_image->data[i], (imcfloat*)dst_image->data[i], src_image->width, src_image->height, (int*)kernel->data[0], kernel->width, kernel->height, counter); + else + ret = DoConvolveCpx((imcfloat*)src_image->data[i], (imcfloat*)dst_image->data[i], src_image->width, src_image->height, (float*)kernel->data[0], kernel->width, kernel->height, counter); + break; + } + + if (!ret) + break; + } + + return ret; +} + +int imProcessConvolve(const imImage* src_image, imImage* dst_image, const imImage *kernel) +{ + int counter = imCounterBegin("Convolution"); + const char* msg = (const char*)imImageGetAttribute(kernel, "Description", NULL, NULL); + if (!msg) msg = "Filtering..."; + imCounterTotal(counter, src_image->depth*src_image->height, msg); + + int ret = DoConvolveStep(src_image, dst_image, kernel, counter); + + imCounterEnd(counter); + + return ret; +} + +int imProcessConvolveRep(const imImage* src_image, imImage* dst_image, const imImage *kernel, int ntimes) +{ + imImage *AuxImage = imImageClone(dst_image); + if (!AuxImage) + return 0; + + int counter = imCounterBegin("Repeated Convolution"); + const char* msg = (const char*)imImageGetAttribute(kernel, "Description", NULL, NULL); + if (!msg) msg = "Filtering..."; + imCounterTotal(counter, src_image->depth*src_image->height*ntimes, msg); + + const imImage *image1 = src_image; + imImage *image2 = dst_image; + + for (int i = 0; i < ntimes; i++) + { + if (!DoConvolveStep(image1, image2, kernel, counter)) + { + imCounterEnd(counter); + imImageDestroy(AuxImage); + return 0; + } + + image1 = image2; + + if (image1 == dst_image) + image2 = AuxImage; + else + image2 = dst_image; + } + + // The result is in image1, if in the Aux swap the data + if (image1 == AuxImage) + { + void** temp = (void**)dst_image->data; + dst_image->data = AuxImage->data; + AuxImage->data = (void**)temp; + } + + imCounterEnd(counter); + imImageDestroy(AuxImage); + + return 1; +} + +template +static int DoConvolveSep(T* map, T* new_map, int width, int height, KT* kernel_map, int kernel_width, int kernel_height, int counter, CT) +{ + CT value; + KT totalV, totalH, *kernel_line; + T* aux_line; + int offset, new_offset, i, j; + + int kh2 = kernel_height/2; + int kw2 = kernel_width/2; + + if (kernel_height % 2 == 0) kh2--; + if (kernel_width % 2 == 0) kw2--; + + // use only the first line and the first column of the kernel + + totalV = 0; + for(j = 0; j < kernel_height; j++) + totalV += kernel_map[j*kernel_width]; + + if (totalV == 0) + totalV = 1; + + totalH = 0; + for(i = 0; i < kernel_width; i++) + totalH += kernel_map[i]; + + if (totalH == 0) + totalH = 1; + + aux_line = (T*)malloc(width*sizeof(T)); + + for(j = 0; j < height; j++) + { + new_offset = j * width; + + for(i = 0; i < width; i++) + { + int y; + value = 0; + + // first pass, only for columns + + for(y = -kh2; y <= kh2; y++) + { + kernel_line = kernel_map + (y+kh2)*kernel_width; + + if (j + y < 0) // pass the bottom border + offset = -(y + j + 1) * width; + else if (j + y >= height) // pass the top border + offset = (2*height - 1 - (j + y)) * width; + else + offset = (j + y) * width; + + if (offset != -1) + value += kernel_line[0] * map[offset + i]; + } + + value /= totalV; + + int size_of = sizeof(imbyte); + if (sizeof(T) == size_of) + new_map[new_offset + i] = (T)IM_BYTECROP(value); + else + new_map[new_offset + i] = (T)value; + } + + if (!imCounterInc(counter)) + { + free(aux_line); + return 0; + } + } + + for(j = 0; j < height; j++) + { + offset = new_offset = j * width; + + for(i = 0; i < width; i++) + { + int x; + value = 0; + + // second pass, only for lines, but has to use an auxiliar buffer + + kernel_line = kernel_map; + + for(x = -kw2; x <= kw2; x++) + { + if (i + x < 0) // pass the left border + value += kernel_line[x+kw2] * new_map[offset - (i + x + 1)]; + else if (i + x >= width) // pass the right border + value += kernel_line[x+kw2] * new_map[offset + 2*width - 1 - (i + x)]; + else + value += kernel_line[x+kw2] * new_map[offset + (i + x)]; + } + + value /= totalH; + + int size_of = sizeof(imbyte); + if (sizeof(T) == size_of) + aux_line[i] = (T)IM_BYTECROP(value); + else + aux_line[i] = (T)value; + } + + memcpy(new_map + new_offset, aux_line, width*sizeof(T)); + + if (!imCounterInc(counter)) + { + free(aux_line); + return 0; + } + } + + free(aux_line); + return 1; +} + + +template +static int DoConvolveSepCpx(imcfloat* map, imcfloat* new_map, int width, int height, KT* kernel_map, int kernel_width, int kernel_height, int counter) +{ + imcfloat value; + KT totalV, totalH, *kernel_line; + imcfloat* aux_line; + int offset, new_offset, i, j; + + int kh2 = kernel_height/2; + int kw2 = kernel_width/2; + + if (kernel_height % 2 == 0) kh2--; + if (kernel_width % 2 == 0) kw2--; + + // use only the first line and the first column of the kernel + + totalV = 0; + for(j = 0; j < kernel_height; j++) + totalV += kernel_map[j*kernel_width]; + + if (totalV == 0) + totalV = 1; + + totalH = 0; + for(i = 0; i < kernel_width; i++) + totalH += kernel_map[i]; + + if (totalH == 0) + totalH = 1; + + aux_line = (imcfloat*)malloc(width*sizeof(imcfloat)); + + for(j = 0; j < height; j++) + { + new_offset = j * width; + + for(i = 0; i < width; i++) + { + int y; + value = 0; + + // first pass, only for columns + + for(y = -kh2; y <= kh2; y++) + { + kernel_line = kernel_map + (y+kh2)*kernel_width; + + if (j + y < 0) // pass the bottom border + offset = -(y + j + 1) * width; + else if (j + y >= height) // pass the top border + offset = (2*height - 1 - (j + y)) * width; + else + offset = (j + y) * width; + + if (offset != -1) + value += map[offset + i] * (float)kernel_line[0]; + } + + value /= (float)totalV; + + new_map[new_offset + i] = value; + } + + if (!imCounterInc(counter)) + { + free(aux_line); + return 0; + } + } + + for(j = 0; j < height; j++) + { + offset = new_offset = j * width; + + for(i = 0; i < width; i++) + { + int x; + value = 0; + + // second pass, only for lines, but has to use an auxiliar buffer + + kernel_line = kernel_map; + + for(x = -kw2; x <= kw2; x++) + { + if (i + x < 0) // pass the left border + value += new_map[offset - (i + x + 1)] * (float)kernel_line[x+kw2]; + else if (i + x >= width) // pass the right border + value += new_map[offset + 2*width - 1 - (i + x)] * (float)kernel_line[x+kw2]; + else if (offset != -1) + value += new_map[offset + (i + x)] * (float)kernel_line[x+kw2]; + } + + value /= (float)totalH; + + aux_line[i] = value; + } + + memcpy(new_map + new_offset, aux_line, width*sizeof(imcfloat)); + + if (!imCounterInc(counter)) + { + free(aux_line); + return 0; + } + } + + free(aux_line); + return 1; +} + +int imProcessConvolveSep(const imImage* src_image, imImage* dst_image, const imImage *kernel) +{ + int counter = imCounterBegin("Separable Convolution"); + const char* msg = (const char*)imImageGetAttribute(kernel, "Description", NULL, NULL); + if (!msg) msg = "Filtering..."; + imCounterTotal(counter, 2*src_image->depth*src_image->height, msg); + + int ret = 0; + + for (int i = 0; i < src_image->depth; i++) + { + switch(src_image->data_type) + { + case IM_BYTE: + if (kernel->data_type == IM_INT) + ret = DoConvolveSep((imbyte*)src_image->data[i], (imbyte*)dst_image->data[i], src_image->width, src_image->height, (int*)kernel->data[0], kernel->width, kernel->height, counter, (int)0); + else + ret = DoConvolveSep((imbyte*)src_image->data[i], (imbyte*)dst_image->data[i], src_image->width, src_image->height, (float*)kernel->data[0], kernel->width, kernel->height, counter, (float)0); + break; + case IM_USHORT: + if (kernel->data_type == IM_INT) + ret = DoConvolveSep((imushort*)src_image->data[i], (imushort*)dst_image->data[i], src_image->width, src_image->height, (int*)kernel->data[0], kernel->width, kernel->height, counter, (int)0); + else + ret = DoConvolveSep((imushort*)src_image->data[i], (imushort*)dst_image->data[i], src_image->width, src_image->height, (float*)kernel->data[0], kernel->width, kernel->height, counter, (float)0); + break; + case IM_INT: + if (kernel->data_type == IM_INT) + ret = DoConvolveSep((int*)src_image->data[i], (int*)dst_image->data[i], src_image->width, src_image->height, (int*)kernel->data[0], kernel->width, kernel->height, counter, (int)0); + else + ret = DoConvolveSep((int*)src_image->data[i], (int*)dst_image->data[i], src_image->width, src_image->height, (float*)kernel->data[0], kernel->width, kernel->height, counter, (float)0); + break; + case IM_FLOAT: + if (kernel->data_type == IM_INT) + ret = DoConvolveSep((float*)src_image->data[i], (float*)dst_image->data[i], src_image->width, src_image->height, (int*)kernel->data[0], kernel->width, kernel->height, counter, (float)0); + else + ret = DoConvolveSep((float*)src_image->data[i], (float*)dst_image->data[i], src_image->width, src_image->height, (float*)kernel->data[0], kernel->width, kernel->height, counter, (float)0); + break; + case IM_CFLOAT: + if (kernel->data_type == IM_INT) + ret = DoConvolveSepCpx((imcfloat*)src_image->data[i], (imcfloat*)dst_image->data[i], src_image->width, src_image->height, (int*)kernel->data[0], kernel->width, kernel->height, counter); + else + ret = DoConvolveSepCpx((imcfloat*)src_image->data[i], (imcfloat*)dst_image->data[i], src_image->width, src_image->height, (float*)kernel->data[0], kernel->width, kernel->height, counter); + break; + } + + if (!ret) + break; + } + + imCounterEnd(counter); + + return ret; +} + +/* +Description: + Can be used to find zero crossing of second derivative, + laplace. Can also be used to determine any other kind + of crossing. Pixels below or equal to 't' are set if the pixel + to the right or below is above 't', pixels above 't' are + set if the pixel to the right or below is below or equal to + 't'. Pixels that are "set" are set to the maximum absolute + difference of the two neighbours, to indicate the strength + of the edge. + + | IF (crossing t) + | out(x,y) = MAX(ABS(in(x,y)-in(x+1,y)), ABS(in(x,y)-in(x,y+1))) + | ELSE + | out(x,y) = 0 + +Author: Tor Lønnestad, BLAB, Ifi, UiO + +Copyright 1991, Blab, UiO +Image processing lab, Department of Informatics +University of Oslo +*/ +template +static void do_crossing(T* iband, T* oband, int width, int height, T t) +{ + int x, y, offset00 = 0, offset10 = 0, offset01 = 0; + T v, diff; + + for (y=0; y < height-1; y++) + { + offset00 = y*width; + offset10 = (y+1)*width; + offset01 = offset00 + 1; + + for (x=0; x < width-1; x++) + { + v = 0; + + if (iband[offset00] <= t) + { + if (iband[offset10] > t) + v = iband[offset10]-iband[offset00]; + + if (iband[offset01] > t) + { + diff = iband[offset01]-iband[offset00]; + if (diff > v) v = diff; + } + } + else + { + if (iband[offset10] <= t) + v = iband[offset00]-iband[offset10]; + + if (iband[offset01] <= t) + { + diff = iband[offset00]-iband[offset01]; + if (diff > v) v = diff; + } + } + + oband[offset00] = v; + + offset00++; + offset10++; + offset01++; + } + + /* last pixel on line */ + offset00++; + offset10++; + + v = 0; + + if (iband[offset00] <= t) + { + if (iband[offset10] > t) + v = iband[offset10]-iband[offset00]; + } + else + { + if (iband[offset10] <= t) + v = iband[offset00]-iband[offset10]; + } + + oband[offset00] = v; + } + + /* last line */ + offset00 = y*width; + offset01 = offset00 + 1; + + for (x=0; x < width-1; x++) + { + v = 0; + + if (iband[offset00] <= t) + { + if (iband[offset01] > t) + v = iband[offset01]-iband[offset00]; + } + else + { + if (iband[offset01] <= t) + v = iband[offset00]-iband[offset01]; + } + + oband[offset00] = v; + + offset00++; + offset01++; + } + + offset00++; + + /* last pixel */ + oband[offset00] = 0; +} + +void imProcessZeroCrossing(const imImage* src_image, imImage* dst_image) +{ + for (int i = 0; i < src_image->depth; i++) + { + switch(src_image->data_type) + { + case IM_INT: + do_crossing((int*)src_image->data[i], (int*)dst_image->data[i], src_image->width, src_image->height, 0); + break; + case IM_FLOAT: + do_crossing((float*)src_image->data[i], (float*)dst_image->data[i], src_image->width, src_image->height, 0.0f); + break; + } + } +} + +int imProcessBarlettConvolve(const imImage* src_image, imImage* dst_image, int kernel_size) +{ + imImage* kernel = imImageCreate(kernel_size, kernel_size, IM_GRAY, IM_INT); + if (!kernel) + return 0; + + imImageSetAttribute(kernel, "Description", IM_BYTE, -1, (void*)"Barlett"); + + int* kernel_data = (int*)kernel->data[0]; + int half = kernel_size / 2; + for (int i = 0; i < kernel_size; i++) + { + if (i <= half) + kernel_data[i] = i+1; + else + kernel_data[i] = kernel_size-i; + } + for (int j = 0; j < kernel_size; j++) + { + if (j <= half) + kernel_data[j*kernel_size] = j+1; + else + kernel_data[j*kernel_size] = kernel_size-j; + } + + int ret = imProcessConvolveSep(src_image, dst_image, kernel); + + imImageDestroy(kernel); + + return ret; +} + +int imProcessSobelConvolve(const imImage* src_image, imImage* dst_image) +{ + int ret = 0; + + imImage* kernel1 = imKernelSobel(); + imImage* kernel2 = imImageCreate(3, 3, IM_GRAY, IM_INT); + imProcessRotate90(kernel1, kernel2, 1); + + ret = imProcessConvolveDual(src_image, dst_image, kernel1, kernel2); + + imImageDestroy(kernel1); + imImageDestroy(kernel2); + + return ret; +} + +int imProcessPrewittConvolve(const imImage* src_image, imImage* dst_image) +{ + int ret = 0; + + imImage* kernel1 = imKernelPrewitt(); + imImage* kernel2 = imImageClone(kernel1); + imProcessRotate90(kernel1, kernel2, 1); + + ret = imProcessConvolveDual(src_image, dst_image, kernel1, kernel2); + + imImageDestroy(kernel1); + imImageDestroy(kernel2); + + return ret; +} + +int imProcessSplineEdgeConvolve(const imImage* src_image, imImage* dst_image) +{ + int ret = 0; + + imImage* tmp_image = imImageClone(src_image); + if (!tmp_image) return 0; + + imImage* kernel1 = imImageCreate(5, 5, IM_GRAY, IM_INT); + imImageSetAttribute(kernel1, "Description", IM_BYTE, -1, (void*)"SplineEdge"); + + int* kernel_data = (int*)kernel1->data[0]; + kernel_data[10] = -1; + kernel_data[11] = 8; + kernel_data[12] = 0; + kernel_data[13] = -8; + kernel_data[14] = 1; + + imImage* kernel2 = imImageClone(kernel1); + imProcessRotate90(kernel1, kernel2, 1); + + imImage* kernel3 = imImageClone(kernel1); + imProcessRotateKernel(kernel3); + + imImage* kernel4 = imImageClone(kernel1); + imProcessRotate90(kernel3, kernel4, 1); + + ret = imProcessConvolveDual(src_image, tmp_image, kernel1, kernel2); + ret = imProcessConvolveDual(src_image, dst_image, kernel3, kernel4); + + imProcessArithmeticConstOp(tmp_image, (float)sqrt(2.0), tmp_image, IM_BIN_MUL); + imProcessArithmeticOp(tmp_image, dst_image, dst_image, IM_BIN_ADD); + + imImageDestroy(kernel1); + imImageDestroy(kernel2); + imImageDestroy(kernel3); + imImageDestroy(kernel4); + imImageDestroy(tmp_image); + + return ret; +} + +int imGaussianStdDev2KernelSize(float stddev) +{ + if (stddev < 0) + return (int)-stddev; + else + { + int width = (int)(3.35*stddev + 0.3333); + return 2*width + 1; + } +} + +float imGaussianKernelSize2StdDev(int kernel_size) +{ + int width = (kernel_size - 1)/2; + return (width - 0.3333f)/3.35f; +} + +int imProcessGaussianConvolve(const imImage* src_image, imImage* dst_image, float stddev) +{ + int kernel_size = imGaussianStdDev2KernelSize(stddev); + + imImage* kernel = imImageCreate(kernel_size, kernel_size, IM_GRAY, IM_FLOAT); + if (!kernel) + return 0; + + imImageSetAttribute(kernel, "Description", IM_BYTE, -1, (void*)"Gaussian"); + imProcessRenderGaussian(kernel, stddev); + + int ret = imProcessConvolveSep(src_image, dst_image, kernel); + + imImageDestroy(kernel); + + return ret; +} + +int imProcessLapOfGaussianConvolve(const imImage* src_image, imImage* dst_image, float stddev) +{ + int kernel_size = imGaussianStdDev2KernelSize(stddev); + + imImage* kernel = imImageCreate(kernel_size, kernel_size, IM_GRAY, IM_FLOAT); + if (!kernel) + return 0; + + imImageSetAttribute(kernel, "Description", IM_BYTE, -1, (void*)"Laplacian Of Gaussian"); + imProcessRenderLapOfGaussian(kernel, stddev); + + int ret; + if (src_image->data_type == IM_BYTE || src_image->data_type == IM_USHORT) + { + imImage* aux_image = imImageClone(dst_image); + if (!aux_image) + { + imImageDestroy(kernel); + return 0; + } + + imProcessUnArithmeticOp(src_image, aux_image, IM_UN_EQL); // Convert to IM_INT + ret = imProcessConvolve(aux_image, dst_image, kernel); + imImageDestroy(aux_image); + } + else + ret = imProcessConvolve(src_image, dst_image, kernel); + + imImageDestroy(kernel); + + return ret; +} + +int imProcessDiffOfGaussianConvolve(const imImage* src_image, imImage* dst_image, float stddev1, float stddev2) +{ + imImage* aux_image1 = imImageClone(src_image); + imImage* aux_image2 = imImageClone(src_image); + if (!aux_image1 || !aux_image2) + { + if (aux_image1) imImageDestroy(aux_image1); + return 0; + } + + int kernel_size1 = imGaussianStdDev2KernelSize(stddev1); + int kernel_size2 = imGaussianStdDev2KernelSize(stddev2); + int size = kernel_size1; + if (kernel_size1 < kernel_size2) size = kernel_size2; + + imImage* kernel1 = imImageCreate(size, size, IM_GRAY, IM_FLOAT); + imImage* kernel2 = imImageCreate(size, size, IM_GRAY, IM_FLOAT); + if (!kernel1 || !kernel2) + { + if (kernel1) imImageDestroy(kernel1); + if (kernel2) imImageDestroy(kernel2); + imImageDestroy(aux_image1); + imImageDestroy(aux_image2); + return 0; + } + + imImageSetAttribute(kernel1, "Description", IM_BYTE, -1, (void*)"Gaussian1"); + imImageSetAttribute(kernel2, "Description", IM_BYTE, -1, (void*)"Gaussian2"); + + imProcessRenderGaussian(kernel1, stddev1); + imProcessRenderGaussian(kernel2, stddev2); + + if (!imProcessConvolve(src_image, aux_image1, kernel1) || + !imProcessConvolve(src_image, aux_image2, kernel2)) + { + imImageDestroy(kernel1); + imImageDestroy(kernel2); + imImageDestroy(aux_image1); + imImageDestroy(aux_image2); + return 0; + } + + imProcessArithmeticOp(aux_image1, aux_image2, dst_image, IM_BIN_SUB); + + imImageDestroy(kernel1); + imImageDestroy(kernel2); + imImageDestroy(aux_image1); + imImageDestroy(aux_image2); + + return 1; +} + +int imProcessMeanConvolve(const imImage* src_image, imImage* dst_image, int ks) +{ + int counter = imCounterBegin("Mean Convolve"); + imCounterTotal(counter, src_image->depth*src_image->height, "Filtering..."); + + imImage* kernel = imImageCreate(ks, ks, IM_GRAY, IM_INT); + + int* kernel_data = (int*)kernel->data[0]; + + int ks2 = ks/2; + for(int ky = 0; ky < ks; ky++) + { + int ky2 = ky-ks2; + ky2 = ky2*ky2; + for(int kx = 0; kx < ks; kx++) + { + int kx2 = kx-ks2; + kx2 = kx2*kx2; + int radius = imRound(sqrt(double(kx2 + ky2))); + if (radius <= ks2) + kernel_data[ky*ks + kx] = 1; + } + } + + int ret = DoConvolveStep(src_image, dst_image, kernel, counter); + + imImageDestroy(kernel); + imCounterEnd(counter); + + return ret; +} + +template +static void DoSharpOp(T1 *src_map, T1 *dst_map, int count, float amount, T2 threshold, int gauss) +{ + int i; + T1 min, max; + + int size_of = sizeof(imbyte); + if (sizeof(T1) == size_of) + { + min = 0; + max = 255; + } + else + { + imMinMax(src_map, count, min, max); + + if (min == max) + { + max = min + 1; + + if (min != 0) + min = min - 1; + } + } + + for (i = 0; i < count; i++) + { + T2 diff; + + if (gauss) + diff = 20*(src_map[i] - dst_map[i]); /* dst_map contains a gaussian filter of the source image, must compensate for small edge values */ + else + diff = dst_map[i]; /* dst_map contains a laplacian filter of the source image */ + + if (threshold && abs_op(2*diff) < threshold) + diff = 0; + + T2 value = (T2)(src_map[i] + amount*diff); + if (value < min) + value = min; + else if (value > max) + value = max; + + dst_map[i] = (T1)value; + } +} + +static void doSharp(const imImage* src_image, imImage* dst_image, float amount, float threshold, int gauss) +{ + int count = src_image->count; + + for (int i = 0; i < src_image->depth; i++) + { + switch(src_image->data_type) + { + case IM_BYTE: + DoSharpOp((imbyte*)src_image->data[i], (imbyte*)dst_image->data[i], count, amount, (int)threshold, gauss); + break; + case IM_USHORT: + DoSharpOp((imushort*)src_image->data[i], (imushort*)dst_image->data[i], count, amount, (int)threshold, gauss); + break; + case IM_INT: + DoSharpOp((int*)src_image->data[i], (int*)dst_image->data[i], count, amount, (int)threshold, gauss); + break; + case IM_FLOAT: + DoSharpOp((float*)src_image->data[i], (float*)dst_image->data[i], count, amount, (float)threshold, gauss); + break; + } + } +} + +int imProcessUnsharp(const imImage* src_image, imImage* dst_image, float stddev, float amount, float threshold) +{ + int kernel_size = imGaussianStdDev2KernelSize(stddev); + + imImage* kernel = imImageCreate(kernel_size, kernel_size, IM_GRAY, IM_FLOAT); + if (!kernel) + return 0; + + imImageSetAttribute(kernel, "Description", IM_BYTE, -1, (void*)"Unsharp"); + imProcessRenderGaussian(kernel, stddev); + + int ret = imProcessConvolveSep(src_image, dst_image, kernel); + doSharp(src_image, dst_image, amount, threshold, 1); + + imImageDestroy(kernel); + + return ret; +} + +int imProcessSharp(const imImage* src_image, imImage* dst_image, float amount, float threshold) +{ + imImage* kernel = imKernelLaplacian8(); + if (!kernel) + return 0; + + int ret = imProcessConvolve(src_image, dst_image, kernel); + doSharp(src_image, dst_image, amount, threshold, 0); + + imImageDestroy(kernel); + + return ret; +} + +static int iProcessCheckKernelType(const imImage* kernel) +{ + if (kernel->data_type == IM_INT) + { + int* kernel_data = (int*)kernel->data[0]; + for (int i = 0; i < kernel->count; i++) + { + if (kernel_data[i] < 0) /* if there are negative values, assume kernel is an edge detector */ + return 0; + } + } + else if (kernel->data_type == IM_FLOAT) + { + float* kernel_data = (float*)kernel->data[0]; + for (int i = 0; i < kernel->count; i++) + { + if (kernel_data[i] < 0) /* if there are negative values, assume kernel is an edge detector */ + return 0; + } + } + return 1; /* default is kernel is a smooth filter */ +} + +int imProcessSharpKernel(const imImage* src_image, const imImage* kernel, imImage* dst_image, float amount, float threshold) +{ + int ret = imProcessConvolve(src_image, dst_image, kernel); + doSharp(src_image, dst_image, amount, threshold, iProcessCheckKernelType(kernel)); + return ret; +} + diff --git a/im/src/process/im_convolve_rank.cpp b/im/src/process/im_convolve_rank.cpp new file mode 100755 index 0000000..5488a78 --- /dev/null +++ b/im/src/process/im_convolve_rank.cpp @@ -0,0 +1,701 @@ +/** \file + * \brief Rank Convolution Operations + * + * See Copyright Notice in im_lib.h + * $Id: im_convolve_rank.cpp,v 1.1 2008/10/17 06:16:33 scuri Exp $ + */ + + +#include +#include +#include +#include + +#include "im_process_loc.h" + +#include +#include +#include +#include +#include + + +template +static int DoConvolveRankFunc(T *map, DT* new_map, int width, int height, int kw, int kh, T (*func)(T* value, int count, int center), int counter) +{ + T* value = new T[kw*kh]; + int offset, new_offset, i, j, x, y, v, c; + int kh1, kw1, kh2, kw2; + + kh2 = kh/2; + kw2 = kw/2; + kh1 = -kh2; + kw1 = -kw2; + if (kh%2==0) kh2--; // if not odd decrease 1 + if (kw%2==0) kw2--; + + for(j = 0; j < height; j++) + { + new_offset = j * width; + + for(i = 0; i < width; i++) + { + v = 0; c = 0; + + for(y = kh1; y <= kh2; y++) + { + if ((j + y < 0) || // pass the bottom border + (j + y >= height)) // pass the top border + continue; + + offset = (j + y) * width; + + for(x = kw1; x <= kw2; x++) + { + if ((i + x < 0) || // pass the left border + (i + x >= width)) // pass the right border + continue; + + if (x == 0 && y == 0) + c = v; + + value[v] = map[offset + (i + x)]; + v++; + } + } + + new_map[new_offset + i] = (DT)func(value, v, c); + } + + if (!imCounterInc(counter)) + { + delete[] value; + return 0; + } + } + + delete[] value; + return 1; +} + +static int compare_imReal(const void *elem1, const void *elem2) +{ + float* v1 = (float*)elem1; + float* v2 = (float*)elem2; + + if (*v1 < *v2) + return -1; + + if (*v1 > *v2) + return 1; + + return 0; +} + +static int compare_imInt(const void *elem1, const void *elem2) +{ + int* v1 = (int*)elem1; + int* v2 = (int*)elem2; + + if (*v1 < *v2) + return -1; + + if (*v1 > *v2) + return 1; + + return 0; +} + +static int compare_imUShort(const void *elem1, const void *elem2) +{ + imushort* v1 = (imushort*)elem1; + imushort* v2 = (imushort*)elem2; + + if (*v1 < *v2) + return -1; + + if (*v1 > *v2) + return 1; + + return 0; +} + +static int compare_imByte(const void *elem1, const void *elem2) +{ + imbyte* v1 = (imbyte*)elem1; + imbyte* v2 = (imbyte*)elem2; + + if (*v1 < *v2) + return -1; + + if (*v1 > *v2) + return 1; + + return 0; +} + +static imbyte median_op_byte(imbyte* value, int count, int center) +{ + (void)center; + qsort(value, count, sizeof(imbyte), compare_imByte); + return value[count/2]; +} + +static imushort median_op_ushort(imushort* value, int count, int center) +{ + (void)center; + qsort(value, count, sizeof(imushort), compare_imUShort); + return value[count/2]; +} + +static int median_op_int(int* value, int count, int center) +{ + (void)center; + qsort(value, count, sizeof(int), compare_imInt); + return value[count/2]; +} + +static float median_op_real(float* value, int count, int center) +{ + (void)center; + qsort(value, count, sizeof(float), compare_imReal); + return value[count/2]; +} + +int imProcessMedianConvolve(const imImage* src_image, imImage* dst_image, int ks) +{ + int i, ret = 0; + int counter; + + counter = imCounterBegin("Median Filter"); + imCounterTotal(counter, src_image->depth*src_image->height, "Filtering..."); + + for (i = 0; i < src_image->depth; i++) + { + switch(src_image->data_type) + { + case IM_BYTE: + ret = DoConvolveRankFunc((imbyte*)src_image->data[i], (imbyte*)dst_image->data[i], + src_image->width, src_image->height, ks, ks, median_op_byte, counter); + break; + case IM_USHORT: + ret = DoConvolveRankFunc((imushort*)src_image->data[i], (imushort*)dst_image->data[i], + src_image->width, src_image->height, ks, ks, median_op_ushort, counter); + break; + case IM_INT: + ret = DoConvolveRankFunc((int*)src_image->data[i], (int*)dst_image->data[i], + src_image->width, src_image->height, ks, ks, median_op_int, counter); + break; + case IM_FLOAT: + ret = DoConvolveRankFunc((float*)src_image->data[i], (float*)dst_image->data[i], + src_image->width, src_image->height, ks, ks, median_op_real, counter); + break; + } + + if (!ret) + break; + } + + imCounterEnd(counter); + + return ret; +} + +static imbyte range_op_byte(imbyte* value, int count, int center) +{ + imbyte min, max; + (void)center; + imMinMax(value, count, min, max); + return max-min; +} + +static imushort range_op_ushort(imushort* value, int count, int center) +{ + imushort min, max; + (void)center; + imMinMax(value, count, min, max); + return max-min; +} + +static int range_op_int(int* value, int count, int center) +{ + int min, max; + (void)center; + imMinMax(value, count, min, max); + return max-min; +} + +static float range_op_real(float* value, int count, int center) +{ + float min, max; + (void)center; + imMinMax(value, count, min, max); + return max-min; +} + +int imProcessRangeConvolve(const imImage* src_image, imImage* dst_image, int ks) +{ + int i, ret = 0; + int counter; + + counter = imCounterBegin("Range Filter"); + imCounterTotal(counter, src_image->depth*src_image->height, "Filtering..."); + + for (i = 0; i < src_image->depth; i++) + { + switch(src_image->data_type) + { + case IM_BYTE: + ret = DoConvolveRankFunc((imbyte*)src_image->data[i], (imbyte*)dst_image->data[i], + src_image->width, src_image->height, ks, ks, range_op_byte, counter); + break; + case IM_USHORT: + ret = DoConvolveRankFunc((imushort*)src_image->data[i], (imushort*)dst_image->data[i], + src_image->width, src_image->height, ks, ks, range_op_ushort, counter); + break; + case IM_INT: + ret = DoConvolveRankFunc((int*)src_image->data[i], (int*)dst_image->data[i], + src_image->width, src_image->height, ks, ks, range_op_int, counter); + break; + case IM_FLOAT: + ret = DoConvolveRankFunc((float*)src_image->data[i], (float*)dst_image->data[i], + src_image->width, src_image->height, ks, ks, range_op_real, counter); + break; + } + + if (!ret) + break; + } + + imCounterEnd(counter); + + return ret; +} + +/* +Local variable threshold by the method of Bernsen. + +Description: + If the difference between the largest and the smallest + pixel value within the 'dx'*'dy' window is greater than + or equal to 'cmin' (local contrast threshold), the average + of the two values is used as threshold. + + Pixels in homogenous areas (difference below 'cmin') + are assumed to be below the threshold. + +Reference: + Bernsen, J: "Dynamic thresholding of grey-level images" + Proc. of the 8th ICPR, Paris, Oct 1986, 1251-1255. + +Author: Oivind Due Trier + +Copyright 1990, Blab, UiO +Image processing lab, Department of Informatics +University of Oslo +*/ + +static int thresAux = 0; + +static imbyte contrast_thres_op_byte(imbyte* value, int count, int center) +{ + int c, t; + imbyte v = value[center], min, max; + + imMinMax(value, count, min, max); + + c = max-min; + + if (c < thresAux) + return 0; + else + { + t = ((int)max + (int)min) / 2; + + if (v >= t) + return 1; + else + return 0; + } +} + +static imushort contrast_thres_op_ushort(imushort* value, int count, int center) +{ + int c, t; + imushort v = value[center], min, max; + + imMinMax(value, count, min, max); + + c = max-min; + + if (c < thresAux) + return 0; + else + { + t = ((int)max + (int)min) / 2; + + if (v >= t) + return 1; + else + return 0; + } +} + +static int contrast_thres_op_int(int* value, int count, int center) +{ + int c, t; + int v = value[center], min, max; + + imMinMax(value, count, min, max); + + c = max-min; + + if (c < thresAux) + return 0; + else + { + t = ((int)max + (int)min) / 2; + + if (v >= t) + return 1; + else + return 0; + } +} + +int imProcessRangeContrastThreshold(const imImage* src_image, imImage* dst_image, int ks, int min_range) +{ + int ret = 0; + int counter = imCounterBegin("Range Contrast Threshold"); + imCounterTotal(counter, src_image->depth*src_image->height, "Filtering..."); + + thresAux = min_range; + + switch(src_image->data_type) + { + case IM_BYTE: + ret = DoConvolveRankFunc((imbyte*)src_image->data[0], (imbyte*)dst_image->data[0], + src_image->width, src_image->height, ks, ks, contrast_thres_op_byte, counter); + break; + case IM_USHORT: + ret = DoConvolveRankFunc((imushort*)src_image->data[0], (imbyte*)dst_image->data[0], + src_image->width, src_image->height, ks, ks, contrast_thres_op_ushort, counter); + break; + case IM_INT: + ret = DoConvolveRankFunc((int*)src_image->data[0], (imbyte*)dst_image->data[0], + src_image->width, src_image->height, ks, ks, contrast_thres_op_int, counter); + break; + } + + imCounterEnd(counter); + + return ret; +} + +static imbyte max_thres_op_byte(imbyte* value, int count, int center) +{ + imbyte v = value[center], min, max; + + if (v < thresAux) + return 0; + + imMinMax(value, count, min, max); + + if (v < max) + return 0; + + return 1; +} + +static imushort max_thres_op_ushort(imushort* value, int count, int center) +{ + imushort v = value[center], min, max; + + if (v < thresAux) + return 0; + + imMinMax(value, count, min, max); + + if (v < max) + return 0; + + return 1; +} + +static int max_thres_op_int(int* value, int count, int center) +{ + int v = value[center], min, max; + + if (v < thresAux) + return 0; + + imMinMax(value, count, min, max); + + if (v < max) + return 0; + + return 1; +} + +int imProcessLocalMaxThreshold(const imImage* src_image, imImage* dst_image, int ks, int min_thres) +{ + int ret = 0; + int counter = imCounterBegin("Local Max Threshold"); + imCounterTotal(counter, src_image->depth*src_image->height, "Filtering..."); + + thresAux = min_thres; + + switch(src_image->data_type) + { + case IM_BYTE: + ret = DoConvolveRankFunc((imbyte*)src_image->data[0], (imbyte*)dst_image->data[0], + src_image->width, src_image->height, ks, ks, max_thres_op_byte, counter); + break; + case IM_USHORT: + ret = DoConvolveRankFunc((imushort*)src_image->data[0], (imbyte*)dst_image->data[0], + src_image->width, src_image->height, ks, ks, max_thres_op_ushort, counter); + break; + case IM_INT: + ret = DoConvolveRankFunc((int*)src_image->data[0], (imbyte*)dst_image->data[0], + src_image->width, src_image->height, ks, ks, max_thres_op_int, counter); + break; + } + + imCounterEnd(counter); + + return ret; +} + +static imbyte rank_closest_op_byte(imbyte* value, int count, int center) +{ + imbyte v = value[center]; + imbyte min, max; + + imMinMax(value, count, min, max); + + if (v - min < max - v) + return min; + else + return max; +} + +static imushort rank_closest_op_ushort(imushort* value, int count, int center) +{ + imushort v = value[center]; + imushort min, max; + + imMinMax(value, count, min, max); + + if (v - min < max - v) + return min; + else + return max; +} + +static int rank_closest_op_int(int* value, int count, int center) +{ + int v = value[center]; + int min, max; + + imMinMax(value, count, min, max); + + if (v - min < max - v) + return min; + else + return max; +} + +static float rank_closest_op_real(float* value, int count, int center) +{ + float v = value[center]; + float min, max; + + imMinMax(value, count, min, max); + + if (v - min < max - v) + return min; + else + return max; +} + + +int imProcessRankClosestConvolve(const imImage* src_image, imImage* dst_image, int ks) +{ + int i, ret = 0; + int counter; + + counter = imCounterBegin("Rank Closest"); + imCounterTotal(counter, src_image->depth*src_image->height, "Filtering..."); + + for (i = 0; i < src_image->depth; i++) + { + switch(src_image->data_type) + { + case IM_BYTE: + ret = DoConvolveRankFunc((imbyte*)src_image->data[i], (imbyte*)dst_image->data[i], + src_image->width, src_image->height, ks, ks, rank_closest_op_byte, counter); + break; + case IM_USHORT: + ret = DoConvolveRankFunc((imushort*)src_image->data[i], (imushort*)dst_image->data[i], + src_image->width, src_image->height, ks, ks, rank_closest_op_ushort, counter); + break; + case IM_INT: + ret = DoConvolveRankFunc((int*)src_image->data[i], (int*)dst_image->data[i], + src_image->width, src_image->height, ks, ks, rank_closest_op_int, counter); + break; + case IM_FLOAT: + ret = DoConvolveRankFunc((float*)src_image->data[i], (float*)dst_image->data[i], + src_image->width, src_image->height, ks, ks, rank_closest_op_real, counter); + break; + } + + if (!ret) + break; + } + + imCounterEnd(counter); + + return ret; +} + +static imbyte rank_max_op_byte(imbyte* value, int count, int center) +{ + imbyte min, max; + (void)center; + imMinMax(value, count, min, max); + return max; +} + +static imushort rank_max_op_ushort(imushort* value, int count, int center) +{ + imushort min, max; + (void)center; + imMinMax(value, count, min, max); + return max; +} + +static int rank_max_op_int(int* value, int count, int center) +{ + int min, max; + (void)center; + imMinMax(value, count, min, max); + return max; +} + +static float rank_max_op_real(float* value, int count, int center) +{ + float min, max; + (void)center; + imMinMax(value, count, min, max); + return max; +} + +int imProcessRankMaxConvolve(const imImage* src_image, imImage* dst_image, int ks) +{ + int i, ret = 0; + int counter; + + counter = imCounterBegin("Rank Max"); + imCounterTotal(counter, src_image->depth*src_image->height, "Filtering..."); + + for (i = 0; i < src_image->depth; i++) + { + switch(src_image->data_type) + { + case IM_BYTE: + ret = DoConvolveRankFunc((imbyte*)src_image->data[i], (imbyte*)dst_image->data[i], + src_image->width, src_image->height, ks, ks, rank_max_op_byte, counter); + break; + case IM_USHORT: + ret = DoConvolveRankFunc((imushort*)src_image->data[i], (imushort*)dst_image->data[i], + src_image->width, src_image->height, ks, ks, rank_max_op_ushort, counter); + break; + case IM_INT: + ret = DoConvolveRankFunc((int*)src_image->data[i], (int*)dst_image->data[i], + src_image->width, src_image->height, ks, ks, rank_max_op_int, counter); + break; + case IM_FLOAT: + ret = DoConvolveRankFunc((float*)src_image->data[i], (float*)dst_image->data[i], + src_image->width, src_image->height, ks, ks, rank_max_op_real, counter); + break; + } + + if (!ret) + break; + } + + imCounterEnd(counter); + + return ret; +} + +static imbyte rank_min_op_byte(imbyte* value, int count, int center) +{ + imbyte min, max; + (void)center; + imMinMax(value, count, min, max); + return min; +} + +static imushort rank_min_op_ushort(imushort* value, int count, int center) +{ + imushort min, max; + (void)center; + imMinMax(value, count, min, max); + return min; +} + +static int rank_min_op_int(int* value, int count, int center) +{ + int min, max; + (void)center; + imMinMax(value, count, min, max); + return min; +} + +static float rank_min_op_real(float* value, int count, int center) +{ + float min, max; + (void)center; + imMinMax(value, count, min, max); + return min; +} + +int imProcessRankMinConvolve(const imImage* src_image, imImage* dst_image, int ks) +{ + int i, ret = 0; + int counter; + + counter = imCounterBegin("Rank Min"); + imCounterTotal(counter, src_image->depth*src_image->height, "Filtering..."); + + for (i = 0; i < src_image->depth; i++) + { + switch(src_image->data_type) + { + case IM_BYTE: + ret = DoConvolveRankFunc((imbyte*)src_image->data[i], (imbyte*)dst_image->data[i], + src_image->width, src_image->height, ks, ks, rank_min_op_byte, counter); + break; + case IM_USHORT: + ret = DoConvolveRankFunc((imushort*)src_image->data[i], (imushort*)dst_image->data[i], + src_image->width, src_image->height, ks, ks, rank_min_op_ushort, counter); + break; + case IM_INT: + ret = DoConvolveRankFunc((int*)src_image->data[i], (int*)dst_image->data[i], + src_image->width, src_image->height, ks, ks, rank_min_op_int, counter); + break; + case IM_FLOAT: + ret = DoConvolveRankFunc((float*)src_image->data[i], (float*)dst_image->data[i], + src_image->width, src_image->height, ks, ks, rank_min_op_real, counter); + break; + } + + if (!ret) + break; + } + + imCounterEnd(counter); + + return ret; +} diff --git a/im/src/process/im_distance.cpp b/im/src/process/im_distance.cpp new file mode 100755 index 0000000..019356d --- /dev/null +++ b/im/src/process/im_distance.cpp @@ -0,0 +1,512 @@ +/** \file + * \brief Distance Transform + * + * See Copyright Notice in im_lib.h + * $Id: im_distance.cpp,v 1.1 2008/10/17 06:16:33 scuri Exp $ + */ + +#include +#include + +#include "im_process_glo.h" + +#include +#include +#include + +const float DT_ONE = 1.0f; // 1x0 +const float DT_SQRT2 = 1.414213562373f; // 1x1 +const float DT_SQRT5 = 2.2360679775f; // 2x1 +const float DT_SQRT10 = 3.1622776601684f; // 3x1 +const float DT_SQRT13 = 3.605551275464f; // 3x2 +const float DT_SQRT17 = 4.12310562562f; // 4x1 +const float DT_SQRT25 = 5.0f; // 4x3 + +static inline void setValue(int r, int r1, int r2, int r3, int r4, float *image_data, int f) +{ + float v; + float minv = image_data[r]; // (x,y) + + if (f) + v = image_data[r - 1] + DT_ONE; // (x-1,y) + else + v = image_data[r + 1] + DT_ONE; // (x+1,y) + if (v < minv) minv = v; + + v = image_data[r1] + DT_ONE; // (x,y-1) (x,y+1) + if (v < minv) minv = v; + + if (minv < DT_SQRT2) + goto min_attrib; + + v = image_data[r1 - 1] + DT_SQRT2; // (x-1,y-1) (x-1,y+1) + if (v < minv) minv = v; + + v = image_data[r1 + 1] + DT_SQRT2; // (x+1,y-1) (x+1,y+1) + if (v < minv) minv = v; + + if (minv < DT_SQRT5) + goto min_attrib; + + v = image_data[r1 + 2] + DT_SQRT5; // (x+2,y-1) (x+2,y+1) + if (v < minv) minv = v; + + v = image_data[r1 - 2] + DT_SQRT5; // (x-2,y-1) (x-2,y+1) + if (v < minv) minv = v; + + v = image_data[r2 - 1] + DT_SQRT5; // (x-1,y-2) (x-1,y+2) + if (v < minv) minv = v; + + v = image_data[r2 + 1] + DT_SQRT5; // (x+1,y-2) (x+1,y+2) + if (v < minv) minv = v; + + if (minv < DT_SQRT10) + goto min_attrib; + + v = image_data[r1 + 3] + DT_SQRT10; // (x+3,y-1) (x+3,y+1) + if (v < minv) minv = v; + + v = image_data[r1 - 3] + DT_SQRT10; // (x-3,y-1) (x-3,y+1) + if (v < minv) minv = v; + + v = image_data[r3 - 1] + DT_SQRT10; // (x-1,y-3) (x-1,y+3) + if (v < minv) minv = v; + + v = image_data[r3 + 1] + DT_SQRT10; // (x+1,y-3) (x+1,y+3) + if (v < minv) minv = v; + + if (minv < DT_SQRT13) + goto min_attrib; + + v = image_data[r2 - 3] + DT_SQRT13; // (x-3,y-2) (x-3,y+2) + if (v < minv) minv = v; + + v = image_data[r2 + 3] + DT_SQRT13; // (x+3,y-2) (x+3,y+2) + if (v < minv) minv = v; + + v = image_data[r3 + 2] + DT_SQRT13; // (x+2,y-3) (x+2,y+3) + if (v < minv) minv = v; + + v = image_data[r3 - 2] + DT_SQRT13; // (x-2,y-3) (x-2,y+3) + if (v < minv) minv = v; + + if (minv < DT_SQRT17) + goto min_attrib; + + v = image_data[r1 + 4] + DT_SQRT17; // (x+4,y-1) (x+4,y+1) + if (v < minv) minv = v; + + v = image_data[r1 - 4] + DT_SQRT17; // (x-4,y-1) (x-4,y+1) + if (v < minv) minv = v; + + v = image_data[r4 - 1] + DT_SQRT17; // (x-1,y-4) (x-1,y+4) + if (v < minv) minv = v; + + v = image_data[r4 + 1] + DT_SQRT17; // (x+1,y-4) (x+1,y+4) + if (v < minv) minv = v; + + if (minv < DT_SQRT25) + goto min_attrib; + + v = image_data[r3 - 4] + DT_SQRT25; // (x-4,y-3) (x-4,y+3) + if (v < minv) minv = v; + + v = image_data[r3 + 4] + DT_SQRT25; // (x+4,y-3) (x+4,y+3) + if (v < minv) minv = v; + + v = image_data[r4 + 3] + DT_SQRT25; // (x+3,y-4) (x+3,y+4) + if (v < minv) minv = v; + + v = image_data[r4 - 3] + DT_SQRT25; // (x-3,y-4) (x-3,y+4) + if (v < minv) minv = v; + +min_attrib: + image_data[r] = minv; +} + +static inline void setValueForwardEdge(int r, int r1, int r2, int width, int x, int y, float *image_data) +{ + float v; + float minv = image_data[r]; // (x,y) + + if (y > 0) + { + v = image_data[r1] + DT_ONE; // (x,y-1) + if (v < minv) minv = v; + } + + if (x > 0) + { + v = image_data[r - 1] + DT_ONE; // (x-1,y) + if (v < minv) minv = v; + } + + if (x > 0 && y > 0) + { + v = image_data[r1 - 1] + DT_SQRT2; // (x-1,y-1) + if (v < minv) minv = v; + } + + if (x < width-2 && y > 0) + { + v = image_data[r1 + 1] + DT_SQRT2; // (x+1,y-1) + if (v < minv) minv = v; + } + + if (x > 0 && y > 1) + { + v = image_data[r2 - 1] + DT_SQRT5; // (x-1,y-2) + if (v < minv) minv = v; + } + + if (x < width-2 && y > 1) + { + v = image_data[r2 + 1] + DT_SQRT5; // (x+1,y-2) + if (v < minv) minv = v; + } + + if (x < width-3 && y > 0) + { + v = image_data[r1 + 2] + DT_SQRT5; // (x+2,y-1) + if (v < minv) minv = v; + } + + if (x > 1 && y > 0) + { + v = image_data[r1 - 2] + DT_SQRT5; // (x-2,y-1) + if (v < minv) minv = v; + } + + image_data[r] = minv; +} + +static inline void setValueBackwardEdge(int r, int r1, int r2, int width, int height, int x, int y, float *image_data) +{ + float v; + float minv = image_data[r]; // (x,y) + + if (x < width-2) + { + v = image_data[r + 1] + DT_ONE; // (x+1,y) + if (v < minv) minv = v; + } + + if (y < height-2) + { + v = image_data[r1] + DT_ONE; // (x,y+1) + if (v < minv) minv = v; + } + + if (y < height-2 && x > 0) + { + v = image_data[r1 - 1] + DT_SQRT2; // (x-1,y+1) + if (v < minv) minv = v; + } + + if (y < height-2 && x < width-2) + { + v = image_data[r1 + 1] + DT_SQRT2; // (x+1,y+1) + if (v < minv) minv = v; + } + + if (y < height-2 && x < width-3) + { + v = image_data[r1 + 2] + DT_SQRT5; // (x+2,y+1) + if (v < minv) minv = v; + } + + if (y < height-3 && x < width-2) + { + v = image_data[r2 + 1] + DT_SQRT5; // (x+1,y+2) + if (v < minv) minv = v; + } + + if (y < height-3 && x > 0) + { + v = image_data[r2 - 1] + DT_SQRT5; // (x-1,y+2) + if (v < minv) minv = v; + } + + if (y < height-2 && x > 1) + { + v = image_data[r1 - 2] + DT_SQRT5; // (x-2,y+1) + if (v < minv) minv = v; + } + + image_data[r] = minv; +} + +void imProcessDistanceTransform(const imImage* src_image, imImage* dst_image) +{ + int i, x, y, + offset, offset1, offset2, offset3, offset4, + width = src_image->width, + height = src_image->height; + + imbyte* src_data = (imbyte*)src_image->data[0]; + float* dst_data = (float*)dst_image->data[0]; + + float max_dist = (float)sqrt(double(width*width + height*height)); + + for (i = 0; i < src_image->count; i++) + { + // if pixel is background, then distance is zero. + if (src_data[i]) + dst_data[i] = max_dist; + } + + /* down->top, left->right */ + for (y = 0; y < height; y++) + { + offset = y * width; + offset1 = offset - width; + offset2 = offset - 2*width; + offset3 = offset - 3*width; + offset4 = offset - 4*width; + + for (x = 0; x < width; x++) + { + if (src_data[offset]) + { + if (x < 4 || x > width-5 || y < 4 || y > height-5) + setValueForwardEdge(offset, offset1, offset2, width, x, y, dst_data); + else + setValue(offset, offset1, offset2, offset3, offset4, dst_data, 1); + } + + offset++; + offset1++; + offset2++; + offset3++; + offset4++; + } + } + + /* top->down, right->left */ + for (y = height-1; y >= 0; y--) + { + offset = y * width + width-1; + offset1 = offset + width; + offset2 = offset + 2*width; + offset3 = offset + 3*width; + offset4 = offset + 4*width; + + for (x = width-1; x >= 0; x--) + { + if (src_data[offset]) + { + if (x < 4 || x > width-5 || y < 4 || y > height-5) + setValueBackwardEdge(offset, offset1, offset2, width, height, x, y, dst_data); + else + setValue(offset, offset1, offset2, offset3, offset4, dst_data, 0); + } + + offset--; + offset1--; + offset2--; + offset3--; + offset4--; + } + } +} + +static void iFillValue(imbyte* img_data, int x, int y, int width, int value) +{ + int r = y * width + x; + int r1a = r - width; + int r1b = r + width; + int v; + + int old_value = img_data[r]; + img_data[r] = (imbyte)value; + + v = img_data[r1a]; // (x,y-1) + if (v == old_value) + iFillValue(img_data, x, y-1, width, value); + + v = img_data[r - 1]; // (x-1,y) + if (v == old_value) + iFillValue(img_data, x-1, y, width, value); + + v = img_data[r1a - 1]; // (x-1,y-1) + if (v == old_value) + iFillValue(img_data, x-1, y-1, width, value); + + v = img_data[r1a + 1]; // (x+1,y-1) + if (v == old_value) + iFillValue(img_data, x+1, y-1, width, value); + + v = img_data[r + 1]; // (x+1,y) + if (v == old_value) + iFillValue(img_data, x+1, y, width, value); + + v = img_data[r1b]; // (x,y+1) + if (v == old_value) + iFillValue(img_data, x, y+1, width, value); + + v = img_data[r1b - 1]; // (x-1,y+1) + if (v == old_value) + iFillValue(img_data, x-1, y+1, width, value); + + v = img_data[r1b + 1]; // (x+1,y+1) + if (v == old_value) + iFillValue(img_data, x+1, y+1, width, value); +} + +static inline int iCheckFalseMaximum(int r, int r2a, int r2b, int width, float *src_data) +{ + /* we are ignoring valeys of 1 pixel. */ + /* this is not 100% fail proof */ + float v; + float maxv = src_data[r]; // (x,y) + int r1a = r - width; + int r1b = r + width; + + v = src_data[r2a - 1]; // (x-1,y-2) + if (v > maxv) return 1; + + v = src_data[r2a]; // (x,y-2) + if (v > maxv) return 1; + + v = src_data[r2a + 1]; // (x+1,y-2) + if (v > maxv) return 1; + + v = src_data[r2b - 1]; // (x-1,y+2) + if (v > maxv) return 1; + + v = src_data[r2b]; // (x,y+2) + if (v > maxv) return 1; + + v = src_data[r2b + 1]; // (x+1,y+2) + if (v > maxv) return 1; + + + v = src_data[r2b - 2]; // (x-2,y+2) + if (v > maxv) return 1; + + v = src_data[r1b - 2]; // (x-2,y+1) + if (v > maxv) return 1; + + v = src_data[r - 2]; // (x-2,y) + if (v > maxv) return 1; + + v = src_data[r1a - 2]; // (x-2,y-1) + if (v > maxv) return 1; + + v = src_data[r2a - 2]; // (x-2,y-2) + if (v > maxv) return 1; + + + v = src_data[r2a + 2]; // (x+2,y-2) + if (v > maxv) return 1; + + v = src_data[r1a + 2]; // (x+2,y-1) + if (v > maxv) return 1; + + v = src_data[r + 2]; // (x+2,y) + if (v > maxv) return 1; + + v = src_data[r1b + 2]; // (x+2,y+1) + if (v > maxv) return 1; + + v = src_data[r2b + 2]; // (x+2,y+2) + if (v > maxv) return 1; + + return 0; +} + +static inline void iCheckMaximum(int r, int r1a, int r1b, float *src_data, imbyte* dst_data) +{ + int unique = 1; + float v; + float maxv = src_data[r]; // (x,y) + + v = src_data[r1a]; // (x,y-1) + if (v >= maxv) { maxv = v; unique = 0; } + + v = src_data[r - 1]; // (x-1,y) + if (v >= maxv) { maxv = v; unique = 0; } + + v = src_data[r1a - 1]; // (x-1,y-1) + if (v >= maxv) { maxv = v; unique = 0; } + + v = src_data[r1a + 1]; // (x+1,y-1) + if (v >= maxv) { maxv = v; unique = 0; } + + v = src_data[r + 1]; // (x+1,y) + if (v >= maxv) { maxv = v; unique = 0; } + + v = src_data[r1b]; // (x,y+1) + if (v >= maxv) { maxv = v; unique = 0; } + + v = src_data[r1b - 1]; // (x-1,y+1) + if (v >= maxv) { maxv = v; unique = 0; } + + v = src_data[r1b + 1]; // (x+1,y+1) + if (v >= maxv) { maxv = v; unique = 0; } + + if (src_data[r] < maxv) // not a maximum + dst_data[r] = 0; + else + { + if (unique) // unique maximum + dst_data[r] = 1; + else // can be maximum + dst_data[r] = 2; + } +} + +void imProcessRegionalMaximum(const imImage* src_image, imImage* dst_image) +{ + int i, x, y, offset, offsetA, offsetB, + width = src_image->width, + height = src_image->height; + + float* src_data = (float*)src_image->data[0]; + imbyte* dst_data = (imbyte*)dst_image->data[0]; + + for (y = 1; y < height-1; y++) + { + offset = y * width + 1; + offsetA = offset - width; + offsetB = offset + width; + + for (x = 1; x < width-1; x++) + { + if (src_data[offset]) + iCheckMaximum(offset, offsetA, offsetB, src_data, dst_data); + + offset++; + offsetA++; + offsetB++; + } + } + + // remove false maximum + for (y = 2; y < height-2; y++) + { + offset = y * width + 2; + offsetA = offset - 2*width; + offsetB = offset + 2*width; + + for (x = 2; x < width-2; x++) + { + if (dst_data[offset] == 2) + { + if (iCheckFalseMaximum(offset, offsetA, offsetB, width, src_data)) + iFillValue(dst_data, x, y, width, 0); + } + + offset++; + offsetA++; + offsetB++; + } + } + + // update destiny with remaining maximum + for (i = 0; i < src_image->count; i++) + { + if (dst_data[i] == 2) + dst_data[i] = 1; + } +} diff --git a/im/src/process/im_effects.cpp b/im/src/process/im_effects.cpp new file mode 100755 index 0000000..7f65ce6 --- /dev/null +++ b/im/src/process/im_effects.cpp @@ -0,0 +1,86 @@ +/** \file + * \brief Effects + * + * See Copyright Notice in im_lib.h + * $Id: im_effects.cpp,v 1.1 2008/10/17 06:16:33 scuri Exp $ + */ + + +#include +#include +#include +#include + +#include "im_process_pon.h" +#include "im_math_op.h" + +#include +#include + +static unsigned char BoxMean(imbyte *map, int offset, int shift, int hbox_size, int vbox_size) +{ + map += offset; + int acum = 0; + for (int i = 0; i < vbox_size; i++) + { + for (int j = 0; j < hbox_size; j++) + { + acum += *map++; + } + + map += shift; + } + + return (unsigned char)(acum / (vbox_size*hbox_size)); +} + +static void BoxSet(imbyte *map, int offset, int shift, int hbox_size, int vbox_size, unsigned char value) +{ + map += offset; + for (int i = 0; i < vbox_size; i++) + { + for (int j = 0; j < hbox_size; j++) + { + *map++ = value; + } + + map += shift; + } +} + +void imProcessPixelate(const imImage* src_image, imImage* dst_image, int box_size) +{ + int hbox = ((src_image->width + box_size-1)/ box_size); + int vbox = ((src_image->height + box_size-1)/ box_size); + + for (int i = 0; i < src_image->depth; i++) + { + imbyte *src_map=(imbyte*)src_image->data[i]; + imbyte *dst_map=(imbyte*)dst_image->data[i]; + int vbox_size = box_size; + + for (int bv = 0; bv < vbox; bv++) + { + int bv_pos = bv*box_size; + if (bv == vbox-1) vbox_size = src_image->height - bv_pos; + int hbox_size = box_size; + + for (int bh = 0; bh < hbox; bh++) + { + int bh_pos = bh*box_size; + if (bh == hbox-1) hbox_size = src_image->width - bh_pos; + int offset = bv_pos*src_image->width + bh_pos; + int shift = src_image->width - hbox_size; + unsigned char mean = BoxMean(src_map, offset, shift, hbox_size, vbox_size); + BoxSet(dst_map, offset, shift, hbox_size, vbox_size, mean); + } + } + } +} + +void imProcessPosterize(const imImage* src_image, imImage* dst_image, int level) +{ + unsigned char mask = (unsigned char)(0xFF << level); + imProcessBitMask(src_image, dst_image, mask, IM_BIT_AND); +} + diff --git a/im/src/process/im_fft.cpp b/im/src/process/im_fft.cpp new file mode 100755 index 0000000..2a36880 --- /dev/null +++ b/im/src/process/im_fft.cpp @@ -0,0 +1,198 @@ +/** \file + * \brief Fast Fourier Transform using FFTW library + * + * See Copyright Notice in im_lib.h + * $Id: im_fft.cpp,v 1.2 2009/08/20 12:37:11 scuri Exp $ + */ + +#include +#include +#include +#include + +#include "im_process.h" + +#include +#include +#include + +#ifdef USE_FFTW3 +#include "fftw3.h" +#else +#include "fftw.h" +#endif + +static void iCopyCol(imcfloat *map1, imcfloat *map2, int height, int width1, int width2) +{ + int i; + for(i = 0; i < height; i++) + { + *map1 = *map2; + map1 += width1; + map2 += width2; + } +} + +static void iCenterFFT(imcfloat *map, int width, int height, int inverse) +{ + imcfloat *map1, *map2, *map3, *tmp; + int i, half1_width, half2_width, half1_height, half2_height; + + if (inverse) + { + half1_width = width/2; + half1_height = height/2; + + half2_width = (width+1)/2; + half2_height = (height+1)/2; + } + else + { + half1_width = (width+1)/2; + half1_height = (height+1)/2; + + half2_width = width/2; + half2_height = height/2; + } + + tmp = (imcfloat*)malloc(half1_width*sizeof(imcfloat)); + + map1 = map; + map2 = map + half1_width; + map3 = map + half2_width; + for(i = 0; i < height; i++) + { + memcpy(tmp, map1, half1_width*sizeof(imcfloat)); + memcpy(map1, map2, half2_width*sizeof(imcfloat)); + memcpy(map3, tmp, half1_width*sizeof(imcfloat)); + + map1 += width; + map2 += width; + map3 += width; + } + + free(tmp); + + tmp = (imcfloat*)malloc(half1_height*sizeof(imcfloat)); + + map1 = map; + map2 = map + half1_height*width; + map3 = map + half2_height*width; + for(i = 0; i < width; i++) + { + iCopyCol(tmp, map1, half1_height, 1, width); + iCopyCol(map1, map2, half2_height, width, width); + iCopyCol(map3, tmp, half1_height, width, 1); + + map1++; + map2++; + map3++; + } + + free(tmp); +} + +static void iDoFFT(void *map, int width, int height, int inverse, int center, int normalize) +{ + if (inverse && center) + iCenterFFT((imcfloat*)map, width, height, inverse); + +#ifdef USE_FFTW3 + fftwf_plan plan = fftwf_plan_dft_2d(height, width, + (fftwf_complex*)map, (fftwf_complex*)map, // in-place transform + inverse?FFTW_BACKWARD:FFTW_FORWARD, FFTW_ESTIMATE); + fftwf_execute(plan); + fftwf_destroy_plan(plan); +#else + fftwnd_plan plan = fftw2d_create_plan(height, width, inverse?FFTW_BACKWARD:FFTW_FORWARD, FFTW_ESTIMATE|FFTW_IN_PLACE); + fftwnd(plan, 1, (FFTW_COMPLEX*)map, 1, 0, 0, 0, 0); + fftwnd_destroy_plan(plan); +#endif + + if (!inverse && center) + iCenterFFT((imcfloat*)map, width, height, inverse); + + if (normalize) + { + float NM = (float)(width * height); + int count = (int)(2*NM); + + if (normalize == 1) + NM = (float)sqrt(NM); + + float *fmap = (float*)map; + for (int i = 0; i < count; i++) + *fmap++ /= NM; + } +} + +void imProcessSwapQuadrants(imImage* image, int inverse) +{ + for (int i = 0; i < image->depth; i++) + iCenterFFT((imcfloat*)image->data[i], image->width, image->height, inverse); +} + +void imProcessFFTraw(imImage* image, int inverse, int center, int normalize) +{ + for (int i = 0; i < image->depth; i++) + iDoFFT(image->data[i], image->width, image->height, inverse, center, normalize); +} + +void imProcessFFT(const imImage* src_image, imImage* dst_image) +{ + if (src_image->data_type != IM_CFLOAT) + imConvertDataType(src_image, dst_image, 0, 0, 0, 0); + else + imImageCopy(src_image, dst_image); + + imProcessFFTraw(dst_image, 0, 1, 0); // forward, centered, unnormalized +} + +void imProcessIFFT(const imImage* src_image, imImage* dst_image) +{ + imImageCopy(src_image, dst_image); + + imProcessFFTraw(dst_image, 1, 1, 2); // inverse, uncentered, double normalized +} + +void imProcessCrossCorrelation(const imImage* src_image1, const imImage* src_image2, imImage* dst_image) +{ + imImage *tmp_image = imImageCreate(src_image2->width, src_image2->height, src_image2->color_space, IM_CFLOAT); + if (!tmp_image) + return; + + if (src_image2->data_type != IM_CFLOAT) + imConvertDataType(src_image2, tmp_image, 0, 0, 0, 0); + else + imImageCopy(src_image2, tmp_image); + + if (src_image1->data_type != IM_CFLOAT) + imConvertDataType(src_image1, dst_image, 0, 0, 0, 0); + else + imImageCopy(src_image1, dst_image); + + imProcessFFTraw(tmp_image, 0, 1, 1); // forward, centered, normalized + imProcessFFTraw(dst_image, 0, 1, 1); + + imProcessMultiplyConj(dst_image, tmp_image, dst_image); + + imProcessFFTraw(dst_image, 1, 1, 1); // inverse, uncentered, normalized + imProcessSwapQuadrants(dst_image, 0); // from origin to center + + imImageDestroy(tmp_image); +} + +void imProcessAutoCorrelation(const imImage* src_image, imImage* dst_image) +{ + if (src_image->data_type != IM_CFLOAT) + imConvertDataType(src_image, dst_image, 0, 0, 0, 0); + else + imImageCopy(src_image, dst_image); + + imProcessFFTraw(dst_image, 0, 0, 1); // forward, at origin, normalized + + imProcessMultiplyConj(dst_image, dst_image, dst_image); + + imProcessFFTraw(dst_image, 1, 0, 1); // inverse, at origin, normalized + imProcessSwapQuadrants(dst_image, 0); // from origin to center +} diff --git a/im/src/process/im_geometric.cpp b/im/src/process/im_geometric.cpp new file mode 100755 index 0000000..a0b5129 --- /dev/null +++ b/im/src/process/im_geometric.cpp @@ -0,0 +1,724 @@ +/** \file + * \brief Geometric Operations + * + * See Copyright Notice in im_lib.h + * $Id: im_geometric.cpp,v 1.1 2008/10/17 06:16:33 scuri Exp $ + */ + + +#include +#include +#include + +#include "im_process_loc.h" +#include "im_math_op.h" + +#include +#include + +static inline void imRect2Polar(float x, float y, float *radius, float *theta) +{ + *radius = sqrtf(x*x + y*y); + *theta = atan2f(y, x); +} + +static inline void imPolar2Rect(float radius, float theta, float *x, float *y) +{ + *x = radius * cosf(theta); + *y = radius * sinf(theta); +} + +static inline void swirl_invtransf(int x, int y, float *xl, float *yl, float k, float xc, float yc) +{ + float radius, theta; + x -= (int)xc; + y -= (int)yc; + + imRect2Polar((float)x, (float)y, &radius, &theta); + + theta += k * radius; + + imPolar2Rect(radius, theta, xl, yl); + + *xl += xc; + *yl += yc; +} + +template +static int Swirl(int width, int height, DT *src_map, DT *dst_map, + float k, int counter, DTU Dummy, int order) +{ + float xl, yl; + float xc = float(width/2.); + float yc = float(height/2.); + + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + swirl_invtransf(x, y, &xl, &yl, k, xc, yc); + + // if inside the original image broad area + if (xl > 0.0 && yl > 0.0 && xl < width && yl < height) + { + if (order == 1) + *dst_map = imBilinearInterpolation(width, height, src_map, xl, yl); + else if (order == 3) + *dst_map = imBicubicInterpolation(width, height, src_map, xl, yl, Dummy); + else + *dst_map = imZeroOrderInterpolation(width, height, src_map, xl, yl); + } + + dst_map++; + } + + if (!imCounterInc(counter)) + return 0; + } + + return 1; +} + +static inline void radial_invtransf(int x, int y, float *xl, float *yl, float k1, float xc, float yc) +{ + float aux; + x -= (int)xc; + y -= (int)yc; + aux = 1.0f + k1*(x*x + y*y); + *xl = x*aux + xc; + *yl = y*aux + yc; +} + +template +static int Radial(int width, int height, DT *src_map, DT *dst_map, + float k1, int counter, DTU Dummy, int order) +{ + float xl, yl; + float xc = float(width/2.); + float yc = float(height/2.); + int diag = (int)sqrt(float(width*width + height*height)); + + k1 /= (diag * diag); + + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + radial_invtransf(x, y, &xl, &yl, k1, xc, yc); + + // if inside the original image broad area + if (xl > 0.0 && yl > 0.0 && xl < width && yl < height) + { + if (order == 1) + *dst_map = imBilinearInterpolation(width, height, src_map, xl, yl); + else if (order == 3) + *dst_map = imBicubicInterpolation(width, height, src_map, xl, yl, Dummy); + else + *dst_map = imZeroOrderInterpolation(width, height, src_map, xl, yl); + } + + dst_map++; + } + + if (!imCounterInc(counter)) + return 0; + } + + return 1; +} + +//******************************************************************************************* +//rotate_invtransf +// shift the center to the origin of the destiny image +// rotates centrered in the origin +// shift the origin back to the center of the original image +//******************************************************************************************* + +inline void rotate_invtransf(int x, int y, float *xl, float *yl, double cos0, double sin0, float dcx, float dcy, float scx, float scy) +{ + double xr = x+0.5 - dcx; + double yr = y+0.5 - dcy; + *xl = float(xr * cos0 - yr * sin0 + scx); + *yl = float(xr * sin0 + yr * cos0 + scy); +} + +template +static int RotateCenter(int src_width, int src_height, DT *src_map, + int dst_width, int dst_height, DT *dst_map, + double cos0, double sin0, int counter, DTU Dummy, int order) +{ + float xl, yl; + float dcx = float(dst_width/2.); + float dcy = float(dst_height/2.); + float scx = float(src_width/2.); + float scy = float(src_height/2.); + + for (int y = 0; y < dst_height; y++) + { + for (int x = 0; x < dst_width; x++) + { + rotate_invtransf(x, y, &xl, &yl, cos0, sin0, dcx, dcy, scx, scy); + + // if inside the original image broad area + if (xl > 0.0 && yl > 0.0 && xl < src_width && yl < src_height) + { + if (order == 1) + *dst_map = imBilinearInterpolation(src_width, src_height, src_map, xl, yl); + else if (order == 3) + *dst_map = imBicubicInterpolation(src_width, src_height, src_map, xl, yl, Dummy); + else + *dst_map = imZeroOrderInterpolation(src_width, src_height, src_map, xl, yl); + } + + dst_map++; + } + + if (!imCounterInc(counter)) + return 0; + } + + return 1; +} + +template +static int Rotate(int src_width, int src_height, DT *src_map, + int dst_width, int dst_height, DT *dst_map, + double cos0, double sin0, int ref_x, int ref_y, int to_origin, + int counter, DTU Dummy, int order) +{ + float xl, yl; + float sx = float(ref_x); + float sy = float(ref_y); + float dx = sx; + float dy = sy; + if (to_origin) + { + dx = 0; + dy = 0; + } + + for (int y = 0; y < dst_height; y++) + { + for (int x = 0; x < dst_width; x++) + { + rotate_invtransf(x, y, &xl, &yl, cos0, sin0, dx, dy, sx, sy); + + // if inside the original image broad area + if (xl > 0.0 && yl > 0.0 && xl < src_width && yl < src_height) + { + if (order == 1) + *dst_map = imBilinearInterpolation(src_width, src_height, src_map, xl, yl); + else if (order == 3) + *dst_map = imBicubicInterpolation(src_width, src_height, src_map, xl, yl, Dummy); + else + *dst_map = imZeroOrderInterpolation(src_width, src_height, src_map, xl, yl); + } + + dst_map++; + } + + if (!imCounterInc(counter)) + return 0; + } + + return 1; +} + +template +static void Rotate90(int src_width, + int src_height, + DT *src_map, + int dst_width, + int dst_height, + DT *dst_map, + int dir) +{ + int xd,yd,x,y; + + if (dir == 1) + xd = 0; + else + xd = dst_width - 1; + + for(y = 0 ; y < src_height ; y++) + { + if (dir == 1) + yd = dst_height - 1; + else + yd = 0; + + for(x = 0 ; x < src_width ; x++) + { + dst_map[yd * dst_width + xd] = src_map[y * src_width + x]; + + if (dir == 1) + yd--; + else + yd++; + } + + if (dir == 1) + xd++; + else + xd--; + } +} + +template +static void Rotate180(int src_width, + int src_height, + DT *src_map, + int dst_width, + int dst_height, + DT *dst_map) +{ + int xd,yd,x,y; + + yd = dst_height - 1; + + for(y = 0 ; y < src_height ; y++) + { + xd = dst_width - 1; + + for(x = 0 ; x < src_width ; x++) + { + dst_map[yd * dst_width + xd] = src_map[y * src_width + x]; + xd--; + } + + yd--; + } +} + +template +static void Mirror(int src_width, + int src_height, + DT *src_map, + int dst_width, + int dst_height, + DT *dst_map) +{ + int xd,x,y; + (void)dst_height; + + if (src_map == dst_map) // check of in-place operation + { + int half_width = src_width/2; + for(y = 0 ; y < src_height; y++) + { + xd = dst_width - 1; + + for(x = 0 ; x < half_width; x++) + { + DT temp_value = src_map[y * dst_width + xd]; + src_map[y * dst_width + xd] = src_map[y * src_width + x]; + src_map[y * src_width + x] = temp_value; + xd--; + } + } + } + else + { + for(y = 0 ; y < src_height; y++) + { + xd = dst_width - 1; + + for(x = 0 ; x < src_width; x++) + { + dst_map[y * dst_width + xd] = src_map[y * src_width + x]; + xd--; + } + } + } +} + +template +static void Flip(int src_width, + int src_height, + DT *src_map, + int dst_width, + int dst_height, + DT *dst_map) +{ + int yd,y; + + yd = dst_height - 1; + + if (src_map == dst_map) // check of in-place operation + { + DT* temp_line = (DT*)malloc(src_width*sizeof(DT)); + int half_height = src_height/2; + + for(y = 0 ; y < half_height; y++) + { + memcpy(temp_line, dst_map+yd*dst_width, src_width * sizeof(DT)); + memcpy(dst_map+yd*dst_width, src_map+y*src_width, src_width * sizeof(DT)); + memcpy(src_map+y*src_width, temp_line,src_width * sizeof(DT)); + yd--; + } + + free(temp_line); + } + else + { + for(y = 0 ; y < src_height; y++) + { + memcpy(dst_map+yd*dst_width,src_map+y*src_width,src_width * sizeof(DT)); + yd--; + } + } +} + +template +static void InterlaceSplit(int src_width, + int src_height, + DT *src_map, + int dst_width, + DT *dst_map1, + DT *dst_map2) +{ + int yd = 0, y; + + for(y = 0; y < src_height; y++) + { + if (y%2) + { + memcpy(dst_map2+yd*dst_width, src_map+y*src_width, src_width * sizeof(DT)); + yd++; // increment only when odd + } + else + memcpy(dst_map1+yd*dst_width, src_map+y*src_width, src_width * sizeof(DT)); + } +} + +void imProcessRotate90(const imImage* src_image, imImage* dst_image, int dir) +{ + for (int i = 0; i < src_image->depth; i++) + { + switch(src_image->data_type) + { + case IM_BYTE: + Rotate90(src_image->width, src_image->height, (imbyte*)src_image->data[i], dst_image->width, dst_image->height, (imbyte*)dst_image->data[i], dir); + break; + case IM_USHORT: + Rotate90(src_image->width, src_image->height, (imushort*)src_image->data[i], dst_image->width, dst_image->height, (imushort*)dst_image->data[i], dir); + break; + case IM_INT: + Rotate90(src_image->width, src_image->height, (int*)src_image->data[i], dst_image->width, dst_image->height, (int*)dst_image->data[i], dir); + break; + case IM_FLOAT: + Rotate90(src_image->width, src_image->height, (float*)src_image->data[i], dst_image->width, dst_image->height, (float*)dst_image->data[i], dir); + break; + case IM_CFLOAT: + Rotate90(src_image->width, src_image->height, (imcfloat*)src_image->data[i], dst_image->width, dst_image->height, (imcfloat*)dst_image->data[i], dir); + break; + } + } +} + +void imProcessRotate180(const imImage* src_image, imImage* dst_image) +{ + for (int i = 0; i < src_image->depth; i++) + { + switch(src_image->data_type) + { + case IM_BYTE: + Rotate180(src_image->width, src_image->height, (imbyte*)src_image->data[i], dst_image->width, dst_image->height, (imbyte*)dst_image->data[i]); + break; + case IM_USHORT: + Rotate180(src_image->width, src_image->height, (imushort*)src_image->data[i], dst_image->width, dst_image->height, (imushort*)dst_image->data[i]); + break; + case IM_INT: + Rotate180(src_image->width, src_image->height, (int*)src_image->data[i], dst_image->width, dst_image->height, (int*)dst_image->data[i]); + break; + case IM_FLOAT: + Rotate180(src_image->width, src_image->height, (float*)src_image->data[i], dst_image->width, dst_image->height, (float*)dst_image->data[i]); + break; + case IM_CFLOAT: + Rotate180(src_image->width, src_image->height, (imcfloat*)src_image->data[i], dst_image->width, dst_image->height, (imcfloat*)dst_image->data[i]); + break; + } + } +} + +int imProcessRadial(const imImage* src_image, imImage* dst_image, float k1, int order) +{ + int ret = 0; + + int counter = imCounterBegin("Radial Distort"); + imCounterTotal(counter, dst_image->depth*dst_image->height, "Processing..."); + + for (int i = 0; i < src_image->depth; i++) + { + switch(src_image->data_type) + { + case IM_BYTE: + ret = Radial(src_image->width, src_image->height, (imbyte*)src_image->data[i], (imbyte*)dst_image->data[i], k1, counter, float(0), order); + break; + case IM_USHORT: + ret = Radial(src_image->width, src_image->height, (imushort*)src_image->data[i], (imushort*)dst_image->data[i], k1, counter, float(0), order); + break; + case IM_INT: + ret = Radial(src_image->width, src_image->height, (int*)src_image->data[i], (int*)dst_image->data[i], k1, counter, float(0), order); + break; + case IM_FLOAT: + ret = Radial(src_image->width, src_image->height, (float*)src_image->data[i], (float*)dst_image->data[i], k1, counter, float(0), order); + break; + case IM_CFLOAT: + ret = Radial(src_image->width, src_image->height, (imcfloat*)src_image->data[i], (imcfloat*)dst_image->data[i], k1, counter, imcfloat(0,0), order); + break; + } + + if (!ret) + break; + } + + imCounterEnd(counter); + + return ret; +} + +int imProcessSwirl(const imImage* src_image, imImage* dst_image, float k, int order) +{ + int ret = 0; + + int counter = imCounterBegin("Swirl Distort"); + imCounterTotal(counter, dst_image->depth*dst_image->height, "Processing..."); + + for (int i = 0; i < src_image->depth; i++) + { + switch(src_image->data_type) + { + case IM_BYTE: + ret = Swirl(src_image->width, src_image->height, (imbyte*)src_image->data[i], (imbyte*)dst_image->data[i], k, counter, float(0), order); + break; + case IM_USHORT: + ret = Swirl(src_image->width, src_image->height, (imushort*)src_image->data[i], (imushort*)dst_image->data[i], k, counter, float(0), order); + break; + case IM_INT: + ret = Swirl(src_image->width, src_image->height, (int*)src_image->data[i], (int*)dst_image->data[i], k, counter, float(0), order); + break; + case IM_FLOAT: + ret = Swirl(src_image->width, src_image->height, (float*)src_image->data[i], (float*)dst_image->data[i], k, counter, float(0), order); + break; + case IM_CFLOAT: + ret = Swirl(src_image->width, src_image->height, (imcfloat*)src_image->data[i], (imcfloat*)dst_image->data[i], k, counter, imcfloat(0,0), order); + break; + } + + if (!ret) + break; + } + + imCounterEnd(counter); + + return ret; +} + +//******************************************************************************************* +//rotate_transf +// In this case shift to the origin, rotate, but do NOT shift back +//******************************************************************************************* + +static void rotate_transf(float cx, float cy, int x, int y, float *xl, float *yl, double cos0, double sin0) +{ + double xr = x+0.5 - cx; + double yr = y+0.5 - cy; + *xl = float( xr*cos0 + yr*sin0); + *yl = float(-xr*sin0 + yr*cos0); +} + +void imProcessCalcRotateSize(int width, int height, int *new_width, int *new_height, double cos0, double sin0) +{ + float xl, yl, xmin, xmax, ymin, ymax; + float wd2 = float(width)/2; + float hd2 = float(height)/2; + + rotate_transf(wd2, hd2, 0, 0, &xl, &yl, cos0, sin0); + xmin = xl; ymin = yl; + xmax = xl; ymax = yl; + + rotate_transf(wd2, hd2, width-1, height-1, &xl, &yl, cos0, sin0); + xmin = min_op(xmin, xl); ymin = min_op(ymin, yl); + xmax = max_op(xmax, xl); ymax = max_op(ymax, yl); + + rotate_transf(wd2, hd2, 0, height-1, &xl, &yl, cos0, sin0); + xmin = min_op(xmin, xl); ymin = min_op(ymin, yl); + xmax = max_op(xmax, xl); ymax = max_op(ymax, yl); + + rotate_transf(wd2, hd2, width-1, 0, &xl, &yl, cos0, sin0); + xmin = min_op(xmin, xl); ymin = min_op(ymin, yl); + xmax = max_op(xmax, xl); ymax = max_op(ymax, yl); + + *new_width = (int)(xmax - xmin + 2.0); + *new_height = (int)(ymax - ymin + 2.0); +} + +int imProcessRotate(const imImage* src_image, imImage* dst_image, double cos0, double sin0, int order) +{ + int ret = 0; + + int counter = imCounterBegin("Rotate"); + imCounterTotal(counter, dst_image->depth*dst_image->height, "Processing..."); + + if (src_image->color_space == IM_MAP) + { + ret = RotateCenter(src_image->width, src_image->height, (imbyte*)src_image->data[0], dst_image->width, dst_image->height, (imbyte*)dst_image->data[0], cos0, sin0, counter, float(0), 0); + } + else + { + for (int i = 0; i < src_image->depth; i++) + { + switch(src_image->data_type) + { + case IM_BYTE: + ret = RotateCenter(src_image->width, src_image->height, (imbyte*)src_image->data[i], dst_image->width, dst_image->height, (imbyte*)dst_image->data[i], cos0, sin0, counter, float(0), order); + break; + case IM_USHORT: + ret = RotateCenter(src_image->width, src_image->height, (imushort*)src_image->data[i], dst_image->width, dst_image->height, (imushort*)dst_image->data[i], cos0, sin0, counter, float(0), order); + break; + case IM_INT: + ret = RotateCenter(src_image->width, src_image->height, (int*)src_image->data[i], dst_image->width, dst_image->height, (int*)dst_image->data[i], cos0, sin0, counter, float(0), order); + break; + case IM_FLOAT: + ret = RotateCenter(src_image->width, src_image->height, (float*)src_image->data[i], dst_image->width, dst_image->height, (float*)dst_image->data[i], cos0, sin0, counter, float(0), order); + break; + case IM_CFLOAT: + ret = RotateCenter(src_image->width, src_image->height, (imcfloat*)src_image->data[i], dst_image->width, dst_image->height, (imcfloat*)dst_image->data[i], cos0, sin0, counter, imcfloat(0,0), order); + break; + } + + if (!ret) + break; + } + } + + imCounterEnd(counter); + + return ret; +} + +int imProcessRotateRef(const imImage* src_image, imImage* dst_image, double cos0, double sin0, int x, int y, int to_origin, int order) +{ + int ret = 0; + + int counter = imCounterBegin("RotateRef"); + imCounterTotal(counter, dst_image->depth*dst_image->height, "Processing..."); + + if (src_image->color_space == IM_MAP) + { + ret = Rotate(src_image->width, src_image->height, (imbyte*)src_image->data[0], dst_image->width, dst_image->height, (imbyte*)dst_image->data[0], cos0, sin0, x, y, to_origin, counter, float(0), 0); + } + else + { + for (int i = 0; i < src_image->depth; i++) + { + switch(src_image->data_type) + { + case IM_BYTE: + ret = Rotate(src_image->width, src_image->height, (imbyte*)src_image->data[i], dst_image->width, dst_image->height, (imbyte*)dst_image->data[i], cos0, sin0, x, y, to_origin, counter, float(0), order); + break; + case IM_USHORT: + ret = Rotate(src_image->width, src_image->height, (imushort*)src_image->data[i], dst_image->width, dst_image->height, (imushort*)dst_image->data[i], cos0, sin0, x, y, to_origin, counter, float(0), order); + break; + case IM_INT: + ret = Rotate(src_image->width, src_image->height, (int*)src_image->data[i], dst_image->width, dst_image->height, (int*)dst_image->data[i], cos0, sin0, x, y, to_origin, counter, float(0), order); + break; + case IM_FLOAT: + ret = Rotate(src_image->width, src_image->height, (float*)src_image->data[i], dst_image->width, dst_image->height, (float*)dst_image->data[i], cos0, sin0, x, y, to_origin, counter, float(0), order); + break; + case IM_CFLOAT: + ret = Rotate(src_image->width, src_image->height, (imcfloat*)src_image->data[i], dst_image->width, dst_image->height, (imcfloat*)dst_image->data[i], cos0, sin0, x, y, to_origin, counter, imcfloat(0,0), order); + break; + } + + if (!ret) + break; + } + } + + imCounterEnd(counter); + + return ret; +} + +void imProcessMirror(const imImage* src_image, imImage* dst_image) +{ + int i; + + for (i = 0; i < src_image->depth; i++) + { + switch(src_image->data_type) + { + case IM_BYTE: + Mirror(src_image->width, src_image->height, (imbyte*)src_image->data[i], dst_image->width, dst_image->height, (imbyte*)dst_image->data[i]); + break; + case IM_USHORT: + Mirror(src_image->width, src_image->height, (imushort*)src_image->data[i], dst_image->width, dst_image->height, (imushort*)dst_image->data[i]); + break; + case IM_INT: + Mirror(src_image->width, src_image->height, (int*)src_image->data[i], dst_image->width, dst_image->height, (int*)dst_image->data[i]); + break; + case IM_FLOAT: + Mirror(src_image->width, src_image->height, (float*)src_image->data[i], dst_image->width, dst_image->height, (float*)dst_image->data[i]); + break; + case IM_CFLOAT: + Mirror(src_image->width, src_image->height, (imcfloat*)src_image->data[i], dst_image->width, dst_image->height, (imcfloat*)dst_image->data[i]); + break; + } + } +} + +void imProcessFlip(const imImage* src_image, imImage* dst_image) +{ + int i; + + for (i = 0; i < src_image->depth; i++) + { + switch(src_image->data_type) + { + case IM_BYTE: + Flip(src_image->width, src_image->height, (imbyte*)src_image->data[i], dst_image->width, dst_image->height, (imbyte*)dst_image->data[i]); + break; + case IM_USHORT: + Flip(src_image->width, src_image->height, (imushort*)src_image->data[i], dst_image->width, dst_image->height, (imushort*)dst_image->data[i]); + break; + case IM_INT: + Flip(src_image->width, src_image->height, (int*)src_image->data[i], dst_image->width, dst_image->height, (int*)dst_image->data[i]); + break; + case IM_FLOAT: + Flip(src_image->width, src_image->height, (float*)src_image->data[i], dst_image->width, dst_image->height, (float*)dst_image->data[i]); + break; + case IM_CFLOAT: + Flip(src_image->width, src_image->height, (imcfloat*)src_image->data[i], dst_image->width, dst_image->height, (imcfloat*)dst_image->data[i]); + break; + } + } +} + +void imProcessInterlaceSplit(const imImage* src_image, imImage* dst_image1, imImage* dst_image2) +{ + int i; + + for (i = 0; i < src_image->depth; i++) + { + switch(src_image->data_type) + { + case IM_BYTE: + InterlaceSplit(src_image->width, src_image->height, (imbyte*)src_image->data[i], dst_image1->width, (imbyte*)dst_image1->data[i], (imbyte*)dst_image2->data[i]); + break; + case IM_USHORT: + InterlaceSplit(src_image->width, src_image->height, (imushort*)src_image->data[i], dst_image1->width, (imushort*)dst_image1->data[i], (imushort*)dst_image2->data[i]); + break; + case IM_INT: + InterlaceSplit(src_image->width, src_image->height, (int*)src_image->data[i], dst_image1->width, (int*)dst_image1->data[i], (int*)dst_image2->data[i]); + break; + case IM_FLOAT: + InterlaceSplit(src_image->width, src_image->height, (float*)src_image->data[i], dst_image1->width, (float*)dst_image1->data[i], (float*)dst_image2->data[i]); + break; + case IM_CFLOAT: + InterlaceSplit(src_image->width, src_image->height, (imcfloat*)src_image->data[i], dst_image1->width, (imcfloat*)dst_image1->data[i], (imcfloat*)dst_image2->data[i]); + break; + } + } +} diff --git a/im/src/process/im_histogram.cpp b/im/src/process/im_histogram.cpp new file mode 100755 index 0000000..e6796fe --- /dev/null +++ b/im/src/process/im_histogram.cpp @@ -0,0 +1,105 @@ +/** \file + * \brief Histogram Based Operations + * + * See Copyright Notice in im_lib.h + * $Id: im_histogram.cpp,v 1.1 2008/10/17 06:16:33 scuri Exp $ + */ + + +#include +#include +#include + +#include "im_process_pon.h" +#include "im_process_ana.h" + +#include +#include + +static void iExpandHistogram(const imImage* src_image, imImage* dst_image, int low_level, int high_level) +{ + int i, value; + + imbyte re_map[256]; + memset(re_map, 0, 256); + + int range = high_level-low_level+1; + float factor = 256.0f / (float)range; + + for (i = 0; i < 256; i++) + { + if (i < low_level) + re_map[i] = 0; + else if (i > high_level) + re_map[i] = 255; + else + { + value = imResample(i - low_level, factor); + re_map[i] = (imbyte)IM_BYTECROP(value); + } + } + + imbyte* dst_map = (imbyte*)dst_image->data[0]; + imbyte* src_map = (imbyte*)src_image->data[0]; + int total_count = src_image->count*src_image->depth; + for (i = 0; i < total_count; i++) + dst_map[i] = re_map[src_map[i]]; +} + +void imProcessExpandHistogram(const imImage* src_image, imImage* dst_image, float percent) +{ + unsigned long histo[256]; + imCalcGrayHistogram(src_image, histo, 0); + + unsigned long acum, cut = (unsigned long)((src_image->count * percent) / 100.0f); + int low_level, high_level; + + acum = 0; + for (low_level = 0; low_level < 256; low_level++) + { + acum += histo[low_level]; + if (acum > cut) + break; + } + + acum = 0; + for (high_level = 255; high_level > 0; high_level--) + { + acum += histo[high_level]; + if (acum > cut) + break; + } + + if (low_level >= high_level) + { + low_level = 0; + high_level = 255; + } + + iExpandHistogram(src_image, dst_image, low_level, high_level); +} + +void imProcessEqualizeHistogram(const imImage* src_image, imImage* dst_image) +{ + int i, value; + + imbyte re_map[256]; + memset(re_map, 0, 256); + + unsigned long histo[256]; + imCalcGrayHistogram(src_image, histo, 1); + + float factor = 256.0f / (float)src_image->count; + + for (i = 0; i < 256; i++) + { + value = imResample(histo[i], factor); + re_map[i] = (imbyte)IM_BYTECROP(value); + } + + imbyte* dst_map = (imbyte*)dst_image->data[0]; + imbyte* src_map = (imbyte*)src_image->data[0]; + int total_count = src_image->count*src_image->depth; + for (i = 0; i < total_count; i++) + dst_map[i] = re_map[src_map[i]]; +} diff --git a/im/src/process/im_houghline.cpp b/im/src/process/im_houghline.cpp new file mode 100755 index 0000000..6ead982 --- /dev/null +++ b/im/src/process/im_houghline.cpp @@ -0,0 +1,435 @@ +/** \file + * \brief Hough Transform + * + * See Copyright Notice in im_lib.h + * $Id: im_houghline.cpp,v 1.1 2008/10/17 06:16:33 scuri Exp $ + */ + +#include +#include +#include +#include +#include + +#include "im_process_glo.h" + +#include +#include + + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +static double *costab=NULL, *sintab=NULL; + +static int hgAbs(int x) +{ + return x < 0? -x: x; +} + +typedef struct _point +{ + int rho, theta, count; +} point; + +typedef struct _listnode +{ + struct _listnode *next; + point pt; +} listnode; + +static listnode* listnew(point *pt) +{ + listnode* node = (listnode*)malloc(sizeof(listnode)); + node->next = NULL; + node->pt = *pt; + return node; +} + +static listnode* listadd(listnode* node, point *pt) +{ + node->next = listnew(pt); + return node->next; +} + +/* minimum angle to match similar angles */ +#define THETA_DELTA1 0.05 /* radians */ +#define THETA_DELTA2 3 /* degrees */ + +static int ptNear(point* pt1, point* pt2, int rho_delta) +{ + int theta_diff = hgAbs(pt1->theta - pt2->theta); + if ((hgAbs(pt1->rho - pt2->rho) < rho_delta && theta_diff < THETA_DELTA2) || + (hgAbs(pt1->rho + pt2->rho) < rho_delta && 180-theta_diff < THETA_DELTA2)) + { + if (pt2->count > pt1->count) + return 2; /* replace the line */ + else + return 1; + } + else + return 0; +} + +static listnode* listadd_filtered(listnode* list, listnode* cur_node, point *pt, int rho_delta) +{ + int ret; + listnode* lt = list; + while (lt) + { + ret = ptNear(<->pt, pt, rho_delta); + if (ret) + { + if (ret == 2) + lt->pt = *pt; /* replace the line */ + return cur_node; + } + lt = lt->next; + } + + cur_node->next = listnew(pt); + return cur_node->next; +} + +/*C* Initial version from XITE + + houghLine + $Id: im_houghline.cpp,v 1.1 2008/10/17 06:16:33 scuri Exp $ + Copyright 1990, Blab, UiO + Image processing lab, Department of Informatics + University of Oslo + E-mail: blab@ifi.uio.no +________________________________________________________________ + + houghLine - Hough transform for line detection + + Description: + Performs a Hough transform to detect lines. Every band in the + input image 'inimage' is transformed to a two dimensional + Hough space, a (theta, rho) space. + + After creating the transform, the Hough space may be searched + for local maxima. Within each band, only the largest local + maximum (maxima) within a 'ws'x'ws' area is registered. + Besides, only maxima with number of updates above a limit + given by the ul option are used. + + updateLimit determines the minimum number of updates for a maximum + to be used. The minimum number is determined from 'updateLimit' + and the size of the hough space image: + | updateLimit * MAX(horizontal size, vertical size) + Default: 0.1. + + All pixels above zero in the 'input' band are + transformed to (theta,rho) space in the 'output' + band. The 'input' band may have any size, while + the 'output' band currently must be at least + | xsize: 180 + | ysize: 2 * sqrt(inputXsize*inputXsize + + | inputYsize*inputYsize) + 1 + + Notice that band x coordinates 1..180 correspond + to angles theta = 0 .. 179, and y coordinates + 1..YSIZE correspond to rho = -(ysize/2) .. ysize/2. + + Restrictions: + 'input' must have pixel type imbyte. + 'output' must have pixel type int. + + Author: Tor Lønnestad, BLAB, Ifi, UiO +*/ + + +static int houghLine(const imImage* input, imImage* output, int counter) +{ + int ixsize, iysize, ixhalf, iyhalf, thetamax, x, y, rho, theta, rhomax; + imbyte *input_map = (imbyte*)input->data[0]; + int *output_map = (int*)output->data[0]; + + ixsize = input->width; + iysize = input->height; + ixhalf = ixsize/2; + iyhalf = iysize/2; + + thetamax = output->width; /* theta max = 180 */ + rhomax = output->height/2; /* rho shift to 0, -rmax <= r <= +rmax */ + + costab = (double*)malloc(thetamax*sizeof(double)); + sintab = (double*)malloc(thetamax*sizeof(double)); + + for (theta=0; theta < thetamax; theta++) + { + double th = (M_PI*theta)/thetamax; + costab[theta] = cos(th); + sintab[theta] = sin(th); + } + + for (y=0; y < iysize; y++) + { + for (x=0; x < ixsize; x++) + { + if (input_map[y*ixsize + x]) + { + for (theta=0; theta < thetamax; theta++) + { + rho = imRound((x-ixhalf)*costab[theta] + (y-iyhalf)*sintab[theta]); + if (rho > rhomax) continue; + if (rho < -rhomax) continue; + output_map[(rho+rhomax)*thetamax + theta]++; + } + } + } + + if (!imCounterInc(counter)) + { + free(costab); costab = NULL; + free(sintab); sintab = NULL; + return 0; + } + } + + free(costab); costab = NULL; + free(sintab); sintab = NULL; + + return 1; +} + +static listnode* findMaxima(const imImage* hough_points, int *line_count, const imImage* hough) +{ + int x, y, xsize, ysize, rhomax, offset, rho_delta = 0; + listnode* maxima = NULL, *cur_node = NULL; + point pt; + imbyte *map = (imbyte*)hough_points->data[0]; + int *hough_map = NULL; + + xsize = hough_points->width; /* X = theta */ + ysize = hough_points->height; /* Y = rho */ + rhomax = ysize/2; + + if (hough) + { + hough_map = (int*)hough->data[0]; + rho_delta = (int)(rhomax*tan(THETA_DELTA1)); + } + + for (y=0; y < ysize; y++) + { + for (x=0; x < xsize; x++) + { + offset = y*xsize + x; + + if (map[offset]) + { + pt.theta = x; + pt.rho = y-rhomax; + + if (!maxima) + { + cur_node = maxima = listnew(&pt); + (*line_count)++; + } + else + { + if (hough_map) + { + listnode* old_node = cur_node; + pt.count = hough_map[offset]; + cur_node = listadd_filtered(maxima, cur_node, &pt, rho_delta); + if (cur_node != old_node) + (*line_count)++; + } + else + { + cur_node = listadd(cur_node, &pt); + (*line_count)++; + } + } + } + } + } + + return maxima; +} + +#define SWAPINT(a, b) {int t = a; a = b; b = t; } + +static void drawLine(imImage* image, int theta, int rho) +{ + int xsize, ysize, xstart, xstop, ystart, ystop, xhalf, yhalf; + float a, b; + imbyte *map = (imbyte*)image->data[0]; + + xsize = image->width; + ysize = image->height; + xhalf = xsize/2; + yhalf = ysize/2; + + if (theta == 0) /* vertical line */ + { + int y; + if (rho+xhalf < 0 || rho+xhalf > xsize-1) return; + for (y=0; y < ysize; y++) + map[y*xsize + rho+xhalf]=254; + + return; + } + + if (theta == 90) /* horizontal line */ + { + int x; + if (rho+yhalf < 0 || rho+yhalf > ysize-1) return; + for (x=0; x < xsize; x++) + map[(rho+yhalf)*xsize + x]=254; + + return; + } + + a = (float)(-costab[theta]/sintab[theta]); + b = (float)((rho + xhalf*costab[theta] + yhalf*sintab[theta])/sintab[theta]); + + { + int x[2]; + int y[2]; + int c = 0; + int y1 = imRound(b); /* x = 0 */ + int y2 = imRound(a*(xsize-1)+b); /* x = xsize-1 */ + + int x1 = imRound(-b/a); /* y = 0 */ + int x2 = imRound((ysize-1-b)/a); /* y = ysize-1 */ + + if (y1 >= 0 && y1 < ysize) + { + y[c] = y1; + x[c] = 0; + c++; + } + + if (y2 >= 0 && y2 < ysize) + { + y[c] = y2; + x[c] = xsize-1; + c++; + } + + if (c < 2 && x1 >= 0 && x1 < xsize) + { + x[c] = x1; + y[c] = 0; + c++; + } + + if (c < 2 && x2 >= 0 && x2 < xsize) + { + x[c] = x2; + y[c] = ysize-1; + c++; + } + + if (c < 2) return; + + ystart = y[0]; + xstart = x[0]; + ystop = y[1]; + xstop = x[1]; + } + + { + int x, y; + if (45 <= theta && theta <= 135) + { + if (xstart > xstop) + SWAPINT(xstart, xstop); + + for (x=xstart; x <= xstop; x++) + { + y = imRound(a*x + b); + if (y < 0) continue; + if (y > ysize-1) continue; + map[y*xsize + x]=254; + } + } + else + { + if (ystart > ystop) + SWAPINT(ystart, ystop); + + for (y=ystart; y <= ystop; y++) + { + x = imRound((y-b)/a); + if (x < 0) continue; + if (x > xsize-1) continue; + map[y*xsize + x]=254; + } + } + } +} + +int imProcessHoughLines(const imImage* image, imImage *NewImage) +{ + int counter = imCounterBegin("Hough Line Transform"); + imCounterTotal(counter, image->height, "Processing..."); + + int ret = houghLine(image, NewImage, counter); + + imCounterEnd(counter); + + return ret; +} + +static void DrawPoints(imImage *image, listnode* maxima) +{ + listnode* cur_node; + while (maxima) + { + cur_node = maxima; + drawLine(image, cur_node->pt.theta, cur_node->pt.rho); + maxima = cur_node->next; + free(cur_node); + } +} + +static void ReplaceColor(imImage* NewImage) +{ + int i; + imbyte* map = (imbyte*)NewImage->data[0]; + + NewImage->color_space = IM_MAP; + NewImage->palette[254] = imColorEncode(255, 0, 0); + + for (i = 0; i < NewImage->count; i++) + { + if (map[i] == 254) + map[i] = 255; + } +} + +int imProcessHoughLinesDraw(const imImage* original_image, const imImage *hough, const imImage *hough_points, imImage *NewImage) +{ + int theta, line_count = 0; + + if (original_image != NewImage) + imImageCopyData(original_image, NewImage); + + listnode* maxima = findMaxima(hough_points, &line_count, hough); + + ReplaceColor(NewImage); + + costab = (double*)malloc(180*sizeof(double)); + sintab = (double*)malloc(180*sizeof(double)); + + for (theta=0; theta < 180; theta++) + { + double th = (M_PI*theta)/180.; + costab[theta] = cos(th); + sintab[theta] = sin(th); + } + + DrawPoints(NewImage, maxima); + + free(costab); costab = NULL; + free(sintab); sintab = NULL; + + return line_count; +} + diff --git a/im/src/process/im_kernel.cpp b/im/src/process/im_kernel.cpp new file mode 100755 index 0000000..d5e976e --- /dev/null +++ b/im/src/process/im_kernel.cpp @@ -0,0 +1,293 @@ +/** \file + * \brief Kernel Generators + * Creates several known kernels + * + * See Copyright Notice in im_lib.h + * $Id: im_kernel.cpp,v 1.1 2008/10/17 06:16:33 scuri Exp $ + */ + +#include "im.h" +#include "im_util.h" +#include "im_image.h" +#include "im_kernel.h" + +#include +#include +#include +#include + + +static imImage* iKernelCreate(int w, int h, int* data, char* desc) +{ + imImage* kernel = imImageCreate(w, h, IM_GRAY, IM_INT); + int* kernel_data = (int*)kernel->data[0]; + memcpy(kernel_data, data, kernel->size); + imImageSetAttribute(kernel, "Description", IM_BYTE, -1, (void*)desc); + return kernel; +} + +imImage* imKernelSobel(void) +{ + int kernel_data[3*3] = { + -1, -2, -1, + 0, 0, 0, + 1, 2, 1 + }; + + return iKernelCreate(3, 3, kernel_data, "Sobel"); +} + +imImage* imKernelPrewitt(void) +{ + int kernel_data[3*3] = { + -1, -1, -1, + 0, 0, 0, + 1, 1, 1 + }; + + return iKernelCreate(3, 3, kernel_data, "Prewitt"); +} + +imImage* imKernelKirsh(void) +{ + int kernel_data[3*3] = { + -3, -3, -3, + -3, 0, -3, + 5, 5, 5 + }; + + return iKernelCreate(3, 3, kernel_data, "Kirsh"); +} + +imImage* imKernelLaplacian4(void) +{ + int kernel_data[3*3] = { + 0, -1, 0, + -1, 4, -1, + 0, -1, 0 + }; + + return iKernelCreate(3, 3, kernel_data, "Laplacian4"); +} + +imImage* imKernelLaplacian8(void) +{ + int kernel_data[3*3] = { + -1, -1, -1, + -1, 8, -1, + -1, -1, -1 + }; + + return iKernelCreate(3, 3, kernel_data, "Laplacian8"); +} + +imImage* imKernelLaplacian5x5(void) +{ + int kernel_data[5*5] = { + 0, -1, -1, -1, 0, + -1, 0, 1, 0, -1, + -1, 1, 8, 1, -1, + -1, 0, 1, 0, -1, + 0, -1, -1, -1, 0 + }; + + return iKernelCreate(5, 5, kernel_data, "Laplacian5x5"); +} + +imImage* imKernelLaplacian7x7(void) +{ + int kernel_data[7*7] = { + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 48, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1 + }; + + return iKernelCreate(7, 7, kernel_data, "Laplacian7x7"); +} + +imImage* imKernelGradian3x3(void) +{ + int kernel_data[3*3] = { + 0, -1, 0, + 0, 1, 0, + 0, 0, 0 + }; + + return iKernelCreate(3, 3, kernel_data, "Gradian3x3"); +} + +imImage* imKernelGradian7x7(void) +{ + int kernel_data[7*7] = { + 0, -1, -1, 0, 1, 1, 0, + -1, -2, -2, 0, 2, 2, 1, + -1, -2, -3, 0, 3, 2, 1, + -1, -2, -3, 0, 3, 2, 1, + -1, -2, -3, 0, 3, 2, 1, + -1, -2, -2, 0, 2, 2, 1, + 0, -1, -1, 0, 1, 1, 0 + }; + + return iKernelCreate(7, 7, kernel_data, "Gradian7x7"); +} + +imImage* imKernelSculpt(void) +{ + int kernel_data[3*3] = { + 0, 0, 1, + 0, 0, 0, + -1, 0, 0 + }; + + return iKernelCreate(3, 3, kernel_data, "Sculpt"); +} + +imImage* imKernelMean3x3(void) +{ + int kernel_data[3*3] = { + 1, 1, 1, + 1, 1, 1, + 1, 1, 1 + }; + + return iKernelCreate(3, 3, kernel_data, "Mean3x3"); +} + +imImage* imKernelMean5x5(void) +{ + int kernel_data[5*5] = { + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + }; + + return iKernelCreate(5, 5, kernel_data, "Mean5x5"); +} + +imImage* imKernelCircularMean5x5(void) +{ + int kernel_data[5*5] = { + 0, 1, 1, 1, 0, + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, + 0, 1, 1, 1, 0 + }; + + return iKernelCreate(5, 5, kernel_data, "CircularMean5x5"); +} + +imImage* imKernelMean7x7(void) +{ + int kernel_data[7*7] = { + 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1 + }; + + return iKernelCreate(7, 7, kernel_data, "Mean7x7"); +} + +imImage* imKernelCircularMean7x7(void) +{ + int kernel_data[7*7] = { + 0, 0, 1, 1, 1, 0, 0, + 0, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 0, + 0, 0, 1, 1, 1, 0, 0 + }; + + return iKernelCreate(7, 7, kernel_data, "CircularMean7x7"); +} + +imImage* imKernelGaussian3x3(void) +{ + int kernel_data[3*3] = { + 1, 2, 1, + 2, 4, 2, + 1, 2, 1 + }; + + return iKernelCreate(3, 3, kernel_data, "Gaussian3x3"); +} + +imImage* imKernelGaussian5x5(void) +{ + int kernel_data[5*5] = { + 1, 4, 6, 4, 1, + 4, 16, 24, 16, 4, + 6, 24, 36, 24, 6, + 4, 16, 24, 16, 4, + 1, 4, 6, 4, 1 + }; + + return iKernelCreate(5, 5, kernel_data, "Gaussian5x5"); +} + +imImage* imKernelBarlett5x5(void) +{ + int kernel_data[5*5] = { + 1, 2, 3, 2, 1, + 2, 4, 6, 4, 2, + 3, 6, 9, 6, 3, + 2, 4, 6, 4, 2, + 1, 2, 3, 2, 1 + }; + + return iKernelCreate(5, 5, kernel_data, "Barlett5x5"); +} + +imImage* imKernelTopHat5x5(void) +{ + int kernel_data[5*5] = { + 0, -1, -1, -1, 0, + -1, -1, 3, -1, -1, + -1, 3, 4, 3, -1, + -1, -1, 3, -1, -1, + 0, -1, -1, -1, 0 + }; + + return iKernelCreate(5, 5, kernel_data, "TopHat5x5"); +} + +imImage* imKernelTopHat7x7(void) +{ + int kernel_data[7*7] = { + 0, 0, -1, -1, -1, 0, 0, + 0, -1, -1, -1, -1, -1, 0, + -1, -1, 3, 3, 3, -1, -1, + -1, -1, 3, 4, 3, -1, -1, + -1, -1, 3, 3, 3, -1, -1, + 0, -1, -1, -1, -1, -1, 0, + 0, 0, -1, -1, -1, 0, 0 + }; + + return iKernelCreate(7, 7, kernel_data, "TopHat7x7"); +} + +imImage* imKernelEnhance(void) +{ + int kernel_data[5*5] = { + 0, -1, -2, -1, 0, + -1, -4, 0, -4, -1, + -2, 0, 40, 0, -2, + -1, -4, 0, -4, -1, + 0, -1, -2, -1, 0 + }; + + return iKernelCreate(5, 5, kernel_data, "Enhance"); +} + diff --git a/im/src/process/im_logic.cpp b/im/src/process/im_logic.cpp new file mode 100755 index 0000000..82e607d --- /dev/null +++ b/im/src/process/im_logic.cpp @@ -0,0 +1,136 @@ +/** \file + * \brief Logical Arithmetic Operations + * + * See Copyright Notice in im_lib.h + * $Id: im_logic.cpp,v 1.1 2008/10/17 06:16:33 scuri Exp $ + */ + + +#include +#include + +#include "im_process_pon.h" + +#include +#include + +template +static void DoBitwiseOp(T *map1, T *map2, T *map, int count, int op) +{ + int i; + + switch(op) + { + case IM_BIT_AND: + for (i = 0; i < count; i++) + map[i] = map1[i] & map2[i]; + break; + case IM_BIT_OR: + for (i = 0; i < count; i++) + map[i] = map1[i] | map2[i]; + break; + case IM_BIT_XOR: + for (i = 0; i < count; i++) + map[i] = (T)~(map1[i] | map2[i]); + break; + } +} + +void imProcessBitwiseOp(const imImage* src_image1, const imImage* src_image2, imImage* dst_image, int op) +{ + int count = src_image1->count*src_image1->depth; + + switch(src_image1->data_type) + { + case IM_BYTE: + DoBitwiseOp((imbyte*)src_image1->data[0], (imbyte*)src_image2->data[0], (imbyte*)dst_image->data[0], count, op); + break; + case IM_USHORT: + DoBitwiseOp((imushort*)src_image1->data[0], (imushort*)src_image2->data[0], (imushort*)dst_image->data[0], count, op); + break; + case IM_INT: + DoBitwiseOp((int*)src_image1->data[0], (int*)src_image2->data[0], (int*)dst_image->data[0], count, op); + break; + } +} + +template +static void DoBitwiseNot(T *map1, T *map, int count) +{ + for (int i = 0; i < count; i++) + map[i] = ~map1[i]; +} + +static void DoBitwiseNotBin(imbyte *map1, imbyte *map, int count) +{ + for (int i = 0; i < count; i++) + map[i] = map1[i]? 0: 1; +} + +void imProcessBitwiseNot(const imImage* src_image, imImage* dst_image) +{ + int count = src_image->count*src_image->depth; + + if (dst_image->color_space == IM_BINARY) + { + DoBitwiseNotBin((imbyte*)src_image->data[0], (imbyte*)dst_image->data[0], count); + return; + } + + switch(src_image->data_type) + { + case IM_BYTE: + DoBitwiseNot((imbyte*)src_image->data[0], (imbyte*)dst_image->data[0], count); + break; + case IM_USHORT: + DoBitwiseNot((imushort*)src_image->data[0], (imushort*)dst_image->data[0], count); + break; + case IM_INT: + DoBitwiseNot((int*)src_image->data[0], (int*)dst_image->data[0], count); + break; + } +} + +void imProcessBitMask(const imImage* src_image, imImage* dst_image, unsigned char mask, int op) +{ + imbyte* src_map = (imbyte*)src_image->data[0]; + imbyte* dst_map = (imbyte*)dst_image->data[0]; + int i; + int count = dst_image->count * dst_image->depth; + switch(op) + { + case IM_BIT_AND: + for (i = 0; i < count; i++) + *dst_map++ = *src_map++ & mask; + break; + case IM_BIT_OR: + for (i = 0; i < count; i++) + *dst_map++ = *src_map++ | mask; + break; + case IM_BIT_XOR: + for (i = 0; i < count; i++) + *dst_map++ = (imbyte)~(*src_map++ | mask); + break; + } + + if ((op == IM_BIT_XOR || op == IM_BIT_OR) && dst_image->color_space == IM_BINARY && mask > 1) + dst_image->color_space = IM_GRAY; +} + +void imProcessBitPlane(const imImage* src_image, imImage* dst_image, int plane, int reset) +{ + imbyte mask = imbyte(0x01 << plane); + if (reset) mask = ~mask; + imbyte* src_map = (imbyte*)src_image->data[0]; + imbyte* dst_map = (imbyte*)dst_image->data[0]; + int count = dst_image->count * dst_image->depth; + for (int i = 0; i < count; i++) + { + if (reset) + *dst_map++ = *src_map & mask; + else + *dst_map++ = (*src_map & mask)? 1: 0; + + src_map++; + } +} diff --git a/im/src/process/im_morphology_bin.cpp b/im/src/process/im_morphology_bin.cpp new file mode 100755 index 0000000..9405ff6 --- /dev/null +++ b/im/src/process/im_morphology_bin.cpp @@ -0,0 +1,317 @@ +/** \file + * \brief Morphology Operations for Binary Images + * + * See Copyright Notice in im_lib.h + * $Id: im_morphology_bin.cpp,v 1.1 2008/10/17 06:16:33 scuri Exp $ + */ + + +#include +#include +#include + +#include "im_process_loc.h" +#include "im_process_pon.h" + +#include +#include +#include +#include +#include + +static int DoBinMorphConvolve(imbyte *map, imbyte* new_map, int width, int height, const imImage* kernel, int counter, int hit_value, int miss_value) +{ + int *kernel_line; + int offset, new_offset, i, j, x, y; + int kh, kw, kh2, kw2, hit; + + kh = kernel->height; + kw = kernel->width; + kh2 = kernel->height/2; + kw2 = kernel->width/2; + + int* kernel_data = (int*)kernel->data[0]; + + for(j = 0; j < height; j++) + { + new_offset = j * width; + + for(i = 0; i < width; i++) + { + hit = 1; + + for(y = -kh2; y <= kh2 && hit; y++) + { + kernel_line = kernel_data + (y+kh2)*kernel->width; + + if ((j + y < 0) || // pass the bottom border + (j + y >= height)) // pass the top border + offset = -1; + else + offset = (j + y) * width; + + for(x = -kw2; x <= kw2; x++) + { + if ((offset == -1) || + (i + x < 0) || // pass the left border + (i + x >= width)) // pass the right border + { + if(kernel_line[x+kw2] != -1 && kernel_line[x+kw2] != 0) // 0 extension beyond borders + hit = 0; + } + else + { + if(kernel_line[x+kw2] != -1 && kernel_line[x+kw2] != map[offset + (i + x)]) + hit = 0; + } + } + } + + new_map[new_offset + i] = (imbyte)(hit? hit_value: miss_value); + } + + if (!imCounterInc(counter)) + return 0; + } + + return 1; +} + +int imProcessBinMorphConvolve(const imImage* src_image, imImage* dst_image, const imImage *kernel, int hit_white, int iter) +{ + int j, ret = 0, hit_value, miss_value; + void *tmp = NULL; + int counter; + + if (hit_white) + { + hit_value = 1; + miss_value = 0; + } + else + { + hit_value = 0; + miss_value = 1; + } + + counter = imCounterBegin("Binary Morphological Convolution"); + const char* msg = (const char*)imImageGetAttribute(kernel, "Description", NULL, NULL); + if (!msg) msg = "Processing..."; + imCounterTotal(counter, src_image->height*iter, msg); + + if (iter > 1) + tmp = malloc(src_image->size); + + for (j = 0; j < iter; j++) + { + if (j == 0) + ret = DoBinMorphConvolve((imbyte*)src_image->data[0], (imbyte*)dst_image->data[0], src_image->width, src_image->height, kernel, counter, hit_value, miss_value); + else + { + memcpy(tmp, dst_image->data[0], src_image->size); + ret = DoBinMorphConvolve((imbyte*)tmp, (imbyte*)dst_image->data[0], src_image->width, src_image->height, kernel, counter, hit_value, miss_value); + } + + if (!ret) + break; + } + + if (tmp) free(tmp); + imCounterEnd(counter); + + return ret; +} + +int imProcessBinMorphErode(const imImage* src_image, imImage* dst_image, int kernel_size, int iter) +{ + imImage* kernel = imImageCreate(kernel_size, kernel_size, IM_GRAY, IM_INT); + imImageSetAttribute(kernel, "Description", IM_BYTE, -1, (void*)"Erode"); + + int* kernel_data = (int*)kernel->data[0]; + for(int i = 0; i < kernel->count; i++) + kernel_data[i] = 1; + + int ret = imProcessBinMorphConvolve(src_image, dst_image, kernel, 1, iter); + imImageDestroy(kernel); + return ret; +} + +int imProcessBinMorphDilate(const imImage* src_image, imImage* dst_image, int kernel_size, int iter) +{ + imImage* kernel = imImageCreate(kernel_size, kernel_size, IM_GRAY, IM_INT); + imImageSetAttribute(kernel, "Description", IM_BYTE, -1, (void*)"Dilate"); + // Kernel is all zeros + int ret = imProcessBinMorphConvolve(src_image, dst_image, kernel, 0, iter); + imImageDestroy(kernel); + return ret; +} + +int imProcessBinMorphOpen(const imImage* src_image, imImage* dst_image, int kernel_size, int iter) +{ + imImage*temp = imImageClone(src_image); + if (!temp) + return 0; + + if (!imProcessBinMorphErode(src_image, temp, kernel_size, iter)) {imImageDestroy(temp); return 0;} + if (!imProcessBinMorphDilate(temp, dst_image, kernel_size, iter)) {imImageDestroy(temp); return 0;} + + imImageDestroy(temp); + return 1; +} + +int imProcessBinMorphClose(const imImage* src_image, imImage* dst_image, int kernel_size, int iter) +{ + imImage*temp = imImageClone(src_image); + if (!temp) + return 0; + + if (!imProcessBinMorphDilate(src_image, temp, kernel_size, iter)) {imImageDestroy(temp); return 0;} + if (!imProcessBinMorphErode(temp, dst_image, kernel_size, iter)) {imImageDestroy(temp); return 0;} + + imImageDestroy(temp); + return 1; +} + +int imProcessBinMorphOutline(const imImage* src_image, imImage* dst_image, int kernel_size, int iter) +{ + if (!imProcessBinMorphErode(src_image, dst_image, kernel_size, iter)) return 0; + imProcessArithmeticOp(src_image, dst_image, dst_image, IM_BIN_DIFF); + return 1; +} + +/* Direction masks: */ +/* N S W E */ +static int masks[] = { 0200, 0002, 0040, 0010 }; + +/* True if pixel neighbor map indicates the pixel is 8-simple and */ +/* not an end point and thus can be deleted. The neighborhood */ +/* map is defined as an integer of bits abcdefghi with a non-zero */ +/* bit representing a non-zero pixel. The bit assignment for the */ +/* neighborhood is: */ +/* */ +/* a b c */ +/* d e f */ +/* g h i */ + +static unsigned char isdelete[512] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +}; + +static void DoThinImage(imbyte *map, int xsize, int ysize) +{ + int x, y; /* Pixel location */ + int i; /* Pass index */ + int pc = 0; /* Pass count */ + int count = 1; /* Deleted pixel count */ + int p, q; /* Neighborhood maps of adjacent cells */ + imbyte *qb; /* Neighborhood maps of previous scanline */ + int m; /* Deletion direction mask */ + + qb = (imbyte *) malloc(xsize); + qb[xsize-1] = 0; /* Used for lower-right pixel */ + + while ( count ) + { + /* Scan src_image while deletions */ + pc++; + count = 0; + + for ( i = 0 ; i < 4 ; i++ ) + { + m = masks[i]; + + /* Build initial previous scan buffer. */ + + p = map[0] != 0; + for (x = 0 ; x < xsize-1 ; x++) + { + p = ((p<<1)&0006) | (map[x+1] != 0); + qb[x] = (imbyte)p; + } + + /* Scan src_image for pixel deletion candidates. */ + + for ( y = 0 ; y < ysize-1 ; y++ ) + { + q = qb[0]; + p = ((q<<3)&0110) | (map[(y+1)*xsize] != 0); + + for ( x = 0 ; x < xsize-1 ; x++ ) + { + q = qb[x]; + p = ((p<<1)&0666) | ((q<<3)&0110) | (map[(y+1)*xsize + x+1] != 0); + qb[x] = (imbyte)p; + + if (((p&m) == 0) && isdelete[p] ) + { + count++; + map[y*xsize + x] = 0; + } + } + + /* Process right edge pixel. */ + + p = (p<<1)&0666; + if ( (p&m) == 0 && isdelete[p] ) + { + count++; + map[y*xsize + xsize-1] = 0; + } + } + + /* Process bottom scan line. */ + + for ( x = 0 ; x < xsize ; x++ ) + { + q = qb[x]; + p = ((p<<1)&0666) | ((q<<3)&0110); + + if ( (p&m) == 0 && isdelete[p] ) + { + count++; + map[(ysize-1)*xsize + x] = 0; + } + } + } + } + + free (qb); +} + +void imProcessBinMorphThin(const imImage* src_image, imImage* dst_image) +{ + imImageCopyData(src_image, dst_image); + DoThinImage((imbyte*)dst_image->data[0], dst_image->width, dst_image->height); +} diff --git a/im/src/process/im_morphology_gray.cpp b/im/src/process/im_morphology_gray.cpp new file mode 100755 index 0000000..c3c9d45 --- /dev/null +++ b/im/src/process/im_morphology_gray.cpp @@ -0,0 +1,231 @@ +/** \file + * \brief Morphology Operations for Gray Images + * + * See Copyright Notice in im_lib.h + * $Id: im_morphology_gray.cpp,v 1.1 2008/10/17 06:16:33 scuri Exp $ + */ + + +#include +#include +#include +#include + +#include "im_process_loc.h" +#include "im_process_pon.h" + +#include +#include +#include +#include +#include + + +template +static int DoGrayMorphConvolve(T *map, T* new_map, int width, int height, const imImage* kernel, int counter, int ismax, DT) +{ + DT value, *kernel_line, max = 0, min = 0; + int offset, new_offset, i, j, x, y, init; + int kh, kw, kh2, kw2; + + kh = kernel->height; + kw = kernel->width; + kh2 = kernel->height/2; + kw2 = kernel->width/2; + + DT* kernel_data = (DT*)kernel->data[0]; + + for(j = 0; j < height; j++) + { + new_offset = j * width; + + for(i = 0; i < width; i++) + { + init = 0; + + for(y = -kh2; y <= kh2; y++) + { + kernel_line = kernel_data + (y+kh2)*kw; + + if ((j + y < 0) || // pass the bottom border + (j + y >= height)) // pass the top border + continue; + else + offset = (j + y) * width; + + for(x = -kw2; x <= kw2; x++) + { + if (kernel_line[x+kw2] != -1) + { + if ((i + x < 0) || // pass the left border + (i + x >= width)) // pass the right border + continue; + else + value = kernel_line[x+kw2] + map[offset + (i + x)]; + + if (init == 0) // first time here for each pass + { + if (ismax) + max = value; + else + min = value; + + init = 1; + } + else + { + if (ismax && value > max) + max = value; + + if (!ismax && value < min) + min = value; + } + } + } + } + + int size_of = sizeof(imbyte); + if (sizeof(T) == size_of) + { + if (ismax) + new_map[new_offset + i] = (T)IM_BYTECROP(max); + else + new_map[new_offset + i] = (T)IM_BYTECROP(min); + } + else + { + if (ismax) + new_map[new_offset + i] = (T)max; + else + new_map[new_offset + i] = (T)min; + } + } + + if (!imCounterInc(counter)) + return 0; + } + + return 1; +} + +int imProcessGrayMorphConvolve(const imImage* src_image, imImage* dst_image, const imImage *kernel, int ismax) +{ + int ret = 0; + + int counter = imCounterBegin("Gray Morphological Convolution"); + const char* msg = (const char*)imImageGetAttribute(kernel, "Description", NULL, NULL); + if (!msg) msg = "Processing..."; + imCounterTotal(counter, src_image->depth*src_image->height, msg); + + imImage* fkernel = NULL; + + if (src_image->data_type == IM_FLOAT && kernel->data_type != IM_FLOAT) + { + fkernel = imImageCreate(kernel->width, kernel->height, IM_GRAY, IM_FLOAT); + imConvertDataType(kernel, fkernel, 0, 0, 0, IM_CAST_DIRECT); + kernel = fkernel; + } + + for (int i = 0; i < src_image->depth; i++) + { + switch(src_image->data_type) + { + case IM_BYTE: + ret = DoGrayMorphConvolve((imbyte*)src_image->data[i], (imbyte*)dst_image->data[i], src_image->width, src_image->height, kernel, counter, ismax, (int)0); + break; + case IM_USHORT: + ret = DoGrayMorphConvolve((imushort*)src_image->data[i], (imushort*)dst_image->data[i], src_image->width, src_image->height, kernel, counter, ismax, (int)0); + break; + case IM_INT: + ret = DoGrayMorphConvolve((int*)src_image->data[i], (int*)dst_image->data[i], src_image->width, src_image->height, kernel, counter, ismax, (int)0); + break; + case IM_FLOAT: + ret = DoGrayMorphConvolve((float*)src_image->data[i], (float*)dst_image->data[i], src_image->width, src_image->height, kernel, counter, ismax, (float)0); + break; + } + + if (!ret) + break; + } + + if (fkernel) imImageDestroy(fkernel); + imCounterEnd(counter); + + return ret; +} + +int imProcessGrayMorphErode(const imImage* src_image, imImage* dst_image, int kernel_size) +{ + imImage* kernel = imImageCreate(kernel_size, kernel_size, IM_GRAY, IM_INT); + imImageSetAttribute(kernel, "Description", IM_BYTE, -1, (void*)"Erode"); + // Kernel is all zeros + int ret = imProcessGrayMorphConvolve(src_image, dst_image, kernel, 0); + imImageDestroy(kernel); + return ret; +} + +int imProcessGrayMorphDilate(const imImage* src_image, imImage* dst_image, int kernel_size) +{ + imImage* kernel = imImageCreate(kernel_size, kernel_size, IM_GRAY, IM_INT); + imImageSetAttribute(kernel, "Description", IM_BYTE, -1, (void*)"Dilate"); + // Kernel is all zeros + int ret = imProcessGrayMorphConvolve(src_image, dst_image, kernel, 1); + imImageDestroy(kernel); + return ret; +} + +int imProcessGrayMorphOpen(const imImage* src_image, imImage* dst_image, int kernel_size) +{ + imImage*temp = imImageClone(src_image); + if (!temp) + return 0; + + if (!imProcessGrayMorphErode(src_image, temp, kernel_size)) {imImageDestroy(temp); return 0;} + if (!imProcessGrayMorphDilate(temp, dst_image, kernel_size)) {imImageDestroy(temp); return 0;} + + imImageDestroy(temp); + return 1; +} + +int imProcessGrayMorphClose(const imImage* src_image, imImage* dst_image, int kernel_size) +{ + imImage*temp = imImageClone(src_image); + if (!temp) + return 0; + + if (!imProcessGrayMorphDilate(src_image, temp, kernel_size)) {imImageDestroy(temp); return 0;} + if (!imProcessGrayMorphErode(temp, dst_image, kernel_size)) {imImageDestroy(temp); return 0;} + + imImageDestroy(temp); + return 1; +} + +int imProcessGrayMorphTopHat(const imImage* src_image, imImage* dst_image, int kernel_size) +{ + if (!imProcessGrayMorphOpen(src_image, dst_image, kernel_size)) return 0; + imProcessArithmeticOp(src_image, dst_image, dst_image, IM_BIN_DIFF); + return 1; +} + +int imProcessGrayMorphWell(const imImage* src_image, imImage* dst_image, int kernel_size) +{ + if (!imProcessGrayMorphClose(src_image, dst_image, kernel_size)) return 0; + imProcessArithmeticOp(src_image, dst_image, dst_image, IM_BIN_DIFF); + return 1; +} + +int imProcessGrayMorphGradient(const imImage* src_image, imImage* dst_image, int kernel_size) +{ + imImage*temp = imImageClone(src_image); + if (!temp) + return 0; + + if (!imProcessGrayMorphDilate(src_image, temp, kernel_size)) {imImageDestroy(temp); return 0;} + if (!imProcessGrayMorphErode(src_image, dst_image, kernel_size)) {imImageDestroy(temp); return 0;} + + imProcessArithmeticOp(temp, dst_image, dst_image, IM_BIN_DIFF); + + imImageDestroy(temp); + return 1; +} + diff --git a/im/src/process/im_quantize.cpp b/im/src/process/im_quantize.cpp new file mode 100755 index 0000000..de78cf4 --- /dev/null +++ b/im/src/process/im_quantize.cpp @@ -0,0 +1,64 @@ +/** \file + * \brief Additional Image Quantization Operations + * + * See Copyright Notice in im_lib.h + * $Id: im_quantize.cpp,v 1.2 2009/09/25 18:40:32 scuri Exp $ + */ + + +#include +#include +#include +#include + +#include "im_process_pon.h" + +#include +#include + + +void imProcessQuantizeRGBUniform(const imImage* src_image, imImage* dst_image, int dither) +{ + imbyte *dst_map=(imbyte*)dst_image->data[0], + *red_map=(imbyte*)src_image->data[0], + *green_map=(imbyte*)src_image->data[1], + *blue_map=(imbyte*)src_image->data[2]; + + imImageSetPalette(dst_image, imPaletteUniform(), 256); + + for (int y = 0; y < src_image->height; y++) + { + for (int x = 0; x < src_image->width; x++) + { + if (dither) + *dst_map++ = (imbyte)imPaletteUniformIndexHalftoned(imColorEncode(*red_map++, *green_map++, *blue_map++), x, y); + else + *dst_map++ = (imbyte)imPaletteUniformIndex(imColorEncode(*red_map++, *green_map++, *blue_map++)); + } + } +} + +void imProcessQuantizeGrayUniform(const imImage* src_image, imImage* dst_image, int grays) +{ + int i, value; + + imbyte *dst_map=(imbyte*)dst_image->data[0], + *src_map=(imbyte*)src_image->data[0]; + + imbyte re_map[256]; + memset(re_map, 0, 256); + + float factor = (float)grays/256.0f; + float factor256 = 256.0f/(float)grays; + + for (i = 0; i < 256; i++) + { + value = imResample(i, factor); + value = imResample(value, factor256); + re_map[i] = (imbyte)IM_BYTECROP(value); + } + + int total_count = src_image->count*src_image->depth; + for (i = 0; i < total_count; i++) + dst_map[i] = re_map[src_map[i]]; +} diff --git a/im/src/process/im_render.cpp b/im/src/process/im_render.cpp new file mode 100755 index 0000000..f5d296f --- /dev/null +++ b/im/src/process/im_render.cpp @@ -0,0 +1,532 @@ +/** \file + * \brief Synthetic Image Render + * + * See Copyright Notice in im_lib.h + * $Id: im_render.cpp,v 1.1 2008/10/17 06:16:33 scuri Exp $ + */ + + +#include +#include +#include +#include + +#include "im_process_pon.h" + +#include +#include +#include +#include + +static float iGetFactor(int data_type) +{ + if (data_type == IM_BYTE) + return 255.0f; + else if (data_type == IM_INT || data_type == IM_USHORT) + return 65535.0f; + else + return 1.0f; +} + +template +static int DoRenderCondOp(T *map, int width, int height, int d, imRenderCondFunc render_func, float* param, int counter) +{ + int offset, cond = 1; + T Value; + + for(int y = 0; y < height; y++) + { + offset = y * width; + + for(int x = 0; x < width; x++) + { + Value = (T)(render_func(x, y, d, &cond, param)); + if (cond) map[offset + x] = Value; + } + + if (!imCounterInc(counter)) + return 0; + } + + return 1; +} + +int imProcessRenderCondOp(imImage* image, imRenderCondFunc render_func, char* render_name, float* param) +{ + int ret = 0; + + int counter = imCounterBegin(render_name); + imCounterTotal(counter, image->depth*image->height, "Rendering..."); + + for (int d = 0; d < image->depth; d++) + { + switch(image->data_type) + { + case IM_BYTE: + ret = DoRenderCondOp((imbyte*)image->data[d], image->width, image->height, d, render_func, param, counter); + break; + case IM_USHORT: + ret = DoRenderCondOp((imushort*)image->data[d], image->width, image->height, d, render_func, param, counter); + break; + case IM_INT: + ret = DoRenderCondOp((int*)image->data[d], image->width, image->height, d, render_func, param, counter); + break; + case IM_FLOAT: + ret = DoRenderCondOp((float*)image->data[d], image->width, image->height, d, render_func, param, counter); + break; + } + + if (!ret) + break; + } + + imCounterEnd(counter); + + return ret; +} + +template +static int DoRenderOp(T *map, int width, int height, int d, imRenderFunc render_func, float* param, int counter, int plus) +{ + int offset; + + for(int y = 0; y < height; y++) + { + offset = y * width; + + for(int x = 0; x < width; x++) + { + if (plus) + { + int size_of = sizeof(imbyte); + float value = map[offset + x] + render_func(x, y, d, param); + if (sizeof(T) == size_of) + map[offset + x] = (T)IM_BYTECROP(value); + else + map[offset + x] = (T)value; + + } + else + map[offset + x] = (T)render_func(x, y, d, param); + } + + if (!imCounterInc(counter)) + return 0; + } + + return 1; +} + +int imProcessRenderOp(imImage* image, imRenderFunc render_func, char* render_name, float* param, int plus) +{ + int ret = 0; + + int counter = imCounterBegin(render_name); + imCounterTotal(counter, image->depth*image->height, "Rendering..."); + + for (int d = 0; d < image->depth; d++) + { + switch(image->data_type) + { + case IM_BYTE: + ret = DoRenderOp((imbyte*)image->data[d], image->width, image->height, d, render_func, param, counter, plus); + break; + case IM_USHORT: + ret = DoRenderOp((imushort*)image->data[d], image->width, image->height, d, render_func, param, counter, plus); + break; + case IM_INT: + ret = DoRenderOp((int*)image->data[d], image->width, image->height, d, render_func, param, counter, plus); + break; + case IM_FLOAT: + ret = DoRenderOp((float*)image->data[d], image->width, image->height, d, render_func, param, counter, plus); + break; + } + + if (!ret) + break; + } + + imCounterEnd(counter); + + return ret; +} + +static float do_add_specklenoise(int, int, int, int *cond, float* param) +{ + float rnd = float(rand()) / RAND_MAX; + if (rnd < param[1]) + { + *cond = 1; + return (rand() * param[0]) / RAND_MAX; + } + else + { + *cond = 0; + return 0; + } +} + +int imProcessRenderAddSpeckleNoise(const imImage* src_image, imImage* dst_image, float percent) +{ + float param[2]; + param[0] = iGetFactor(src_image->data_type); + param[1] = percent / 100.0f; + srand((unsigned)time(NULL)); + imImageCopyData(src_image, dst_image); + return imProcessRenderCondOp(dst_image, do_add_specklenoise, "Add Speckle Noise", param); +} + +static float do_add_gaussiannoise(int, int, int, float* param) +{ + float rnd, x1, x2; + + do + { + x1 = float(rand()) / RAND_MAX; /* [0,1] */ + x2 = float(rand()) / RAND_MAX; /* [0,1] */ + x1 = 2*x1 - 1; /* [-1,1] */ + x2 = 2*x2 - 1; /* [-1,1] */ + rnd = x1*x1 + x2*x2; + } while( rnd >= 1 || rnd == 0); + + rnd = (float)sqrt(-2 * log(rnd) / rnd) * x1; + return rnd * param[1] + param[0]; +} + +int imProcessRenderAddGaussianNoise(const imImage* src_image, imImage* dst_image, float mean, float stddev) +{ + float param[2]; + param[0] = mean; + param[1] = stddev; + srand((unsigned)time(NULL)); + imImageCopyData(src_image, dst_image); + return imProcessRenderOp(dst_image, do_add_gaussiannoise, "Add Gaussian Noise", param, 1); +} + +static float do_add_uniformnoise(int, int, int, float* param) +{ + float rnd = float(rand()) / RAND_MAX; + rnd = 2*rnd - 1; /* [-1,1] */ + return 1.7320508f * rnd * param[1] + param[0]; +} + +int imProcessRenderAddUniformNoise(const imImage* src_image, imImage* dst_image, float mean, float stddev) +{ + float param[2]; + param[0] = mean; + param[1] = stddev; + srand((unsigned)time(NULL)); + imImageCopyData(src_image, dst_image); + return imProcessRenderOp(dst_image, do_add_uniformnoise, "Add Uniform Noise", param, 1); +} + +static float do_const(int, int, int d, float* param) +{ + return param[d]; +} + +int imProcessRenderConstant(imImage* image, float* value) +{ + return imProcessRenderOp(image, do_const, "Constant", value, 0); +} + +static float do_noise(int, int, int, float* param) +{ + return (rand() * param[0]) / RAND_MAX; +} + +int imProcessRenderRandomNoise(imImage* image) +{ + static float param[1]; + param[0] = iGetFactor(image->data_type); + srand((unsigned)time(NULL)); + return imProcessRenderOp(image, do_noise, "Random Noise", param, 0); +} + +static float do_cosine(int x, int y, int, float* param) +{ + return float((cos(param[1]*(x-param[3])) * cos(param[2]*(y-param[4])) + param[5]) * param[0]); +} + +int imProcessRenderCosine(imImage* image, float xperiod, float yperiod) +{ + float param[6]; + param[0] = iGetFactor(image->data_type); + + if (xperiod == 0.0f) param[1] = 0.0; + else param[1] = 2.0f * 3.1416f / xperiod; + + if (yperiod == 0.0f) param[2] = 0.0; + else param[2] = 2.0f * 3.1416f / yperiod; + + param[3] = image->width/2.0f; + param[4] = image->height/2.0f; + + if (image->data_type < IM_FLOAT) + param[0] = param[0] / 2.0f; + + if (image->data_type == IM_BYTE) + param[5] = 1.0f; + else + param[5] = 0.0f; + + return imProcessRenderOp(image, do_cosine, "Cosine", param, 0); +} + +static float do_gaussian(int x, int y, int, float* param) +{ + int xd = x - (int)param[2]; + int yd = y - (int)param[3]; + xd *= xd; + yd *= yd; + return float(exp((xd + yd)*param[1])*param[0]); +} + +int imProcessRenderGaussian(imImage* image, float stddev) +{ + float param[4]; + param[0] = iGetFactor(image->data_type); + param[1] = -1.0f / (2.0f * stddev * stddev); + param[2] = image->width/2.0f; + param[3] = image->height/2.0f; + return imProcessRenderOp(image, do_gaussian, "Gaussian", param, 0); +} + +static float do_lapgauss(int x, int y, int, float* param) +{ + int xd = x - (int)param[2]; + int yd = y - (int)param[3]; + xd *= xd; + yd *= yd; + xd += yd; + return float((xd - param[4])*exp(xd*param[1])*param[0]); +} + +int imProcessRenderLapOfGaussian(imImage* image, float stddev) +{ + float param[5]; + param[0] = iGetFactor(image->data_type); + param[1] = -1.0f / (2.0f * stddev * stddev); + param[2] = image->width/2.0f; + param[3] = image->height/2.0f; + param[4] = 2.0f * stddev * stddev; + param[0] /= param[4]; + return imProcessRenderOp(image, do_lapgauss, "Laplacian of Gaussian", param, 0); +} + +static inline float sinc(float x) +{ + if (x == 0.0f) + return 1.0f; + else + return float(sin(x)/x); +} + +static float do_sinc(int x, int y, int, float* param) +{ + return float((sinc((x - param[3])*param[1])*sinc((y - param[4])*param[2]) + param[5])*param[0]); +} + +int imProcessRenderSinc(imImage* image, float xperiod, float yperiod) +{ + float param[6]; + param[0] = iGetFactor(image->data_type); + + if (xperiod == 0.0f) param[1] = 0.0; + else param[1] = 2.0f * 3.1416f / xperiod; + + if (yperiod == 0.0f) param[2] = 0.0; + else param[2] = 2.0f * 3.1416f / yperiod; + + param[3] = image->width/2.0f; + param[4] = image->height/2.0f; + + if (image->data_type < IM_FLOAT) + param[0] = param[0] / 1.3f; + + if (image->data_type == IM_BYTE) + param[5] = 0.3f; + else + param[5] = 0.0f; + + return imProcessRenderOp(image, do_sinc, "Sinc", param, 0); +} + +static float do_box(int x, int y, int, float* param) +{ + int xr = x - (int)param[3]; + int yr = y - (int)param[4]; + if (xr < -(int)param[1] || xr > (int)param[1] || + yr < -(int)param[2] || yr > (int)param[2]) + return 0; + else + return param[0]; +} + +int imProcessRenderBox(imImage* image, int width, int height) +{ + float param[5]; + param[0] = iGetFactor(image->data_type); + param[1] = width/2.0f; + param[2] = height/2.0f; + param[3] = image->width/2.0f; + param[4] = image->height/2.0f; + return imProcessRenderOp(image, do_box, "Box", param, 0); +} + +static float do_ramp(int x, int y, int, float* param) +{ + if (param[3]) + { + if (y < param[1]) + return 0; + if (y > param[2]) + return 0; + + return (y-param[1])*param[0]; + } + else + { + if (x < param[1]) + return 0; + if (x > param[2]) + return 0; + + return (x-param[1])*param[0]; + } +} + +int imProcessRenderRamp(imImage* image, int start, int end, int dir) +{ + float param[4]; + param[0] = iGetFactor(image->data_type); + param[1] = (float)start; + param[2] = (float)end; + param[3] = (float)dir; + param[0] /= float(end-start); + return imProcessRenderOp(image, do_ramp, "Ramp", param, 0); +} + +static inline int Tent(int t, int T) +{ + if (t < 0) + return (t + T); + else + return (T - t); +} + +static float do_tent(int x, int y, int, float* param) +{ + int xr = x - (int)param[3]; + int yr = y - (int)param[4]; + if (xr < -(int)param[1] || xr > (int)param[1] || + yr < -(int)param[2] || yr > (int)param[2]) + return 0; + else + return Tent(xr, (int)param[1]) * Tent(yr, (int)param[2]) * param[0]; +} + +int imProcessRenderTent(imImage* image, int width, int height) +{ + float param[5]; + param[0] = iGetFactor(image->data_type); + param[1] = width/2.0f; + param[2] = height/2.0f; + param[0] /= param[1]*param[2]; + param[3] = image->width/2.0f; + param[4] = image->height/2.0f; + return imProcessRenderOp(image, do_tent, "Tent", param, 0); +} + +static float do_cone(int x, int y, int, float* param) +{ + int xr = x - (int)param[2]; + int yr = y - (int)param[3]; + int radius = imRound(sqrt((double)(xr*xr + yr*yr))); + if (radius > (int)param[1]) + return 0; + else + return ((int)param[1] - radius)*param[0]; +} + +int imProcessRenderCone(imImage* image, int radius) +{ + float param[4]; + param[0] = iGetFactor(image->data_type); + param[1] = (float)radius; + param[0] /= param[1]; + param[2] = image->width/2.0f; + param[3] = image->height/2.0f; + return imProcessRenderOp(image, do_cone, "Cone", param, 0); +} + +static float do_wheel(int x, int y, int, float* param) +{ + int xr = x - (int)param[3]; + int yr = y - (int)param[4]; + int radius = imRound(sqrt((double)(xr*xr + yr*yr))); + if (radius < (int)param[1] || radius > (int)param[2]) + return 0; + else + return param[0]; +} + +int imProcessRenderWheel(imImage* image, int int_radius, int ext_radius) +{ + float param[5]; + param[0] = iGetFactor(image->data_type); + param[1] = (float)int_radius; + param[2] = (float)ext_radius; + param[3] = image->width/2.0f; + param[4] = image->height/2.0f; + return imProcessRenderOp(image, do_wheel, "Wheel", param, 0); +} + +static float do_grid(int x, int y, int, float* param) +{ + int xr = x - (int)param[3]; + int yr = y - (int)param[4]; + if (xr % (int)param[1] == 0 && yr % (int)param[2] == 0) + return param[0]; + else + return 0; +} + +int imProcessRenderGrid(imImage* image, int x_space, int y_space) +{ + float param[5]; + param[0] = iGetFactor(image->data_type); + param[1] = (float)x_space; + param[2] = (float)y_space; + param[3] = image->width/2.0f; + param[4] = image->height/2.0f; + return imProcessRenderOp(image, do_grid, "Grid", param, 0); +} + +static float do_chessboard(int x, int y, int, float* param) +{ + int xr = x - (int)param[3]; + int yr = y - (int)param[4]; + int xp = xr % (int)param[1]; + int yp = yr % (int)param[2]; + int xc = (int)param[1]/2; + int yc = (int)param[2]/2; + if (xr < 0) xc = -xc; + if (yr < 0) yc = -yc; + if ((xp < xc && yp < yc) || + (xp > xc && yp > yc)) + return param[0]; + else + return 0; +} + +int imProcessRenderChessboard(imImage* image, int x_space, int y_space) +{ + float param[5]; + param[0] = iGetFactor(image->data_type); + param[1] = (float)x_space*2; + param[2] = (float)y_space*2; + param[3] = image->width/2.0f; + param[4] = image->height/2.0f; + return imProcessRenderOp(image, do_chessboard, "Chessboard", param, 0); +} diff --git a/im/src/process/im_resize.cpp b/im/src/process/im_resize.cpp new file mode 100755 index 0000000..ddf6e47 --- /dev/null +++ b/im/src/process/im_resize.cpp @@ -0,0 +1,332 @@ +/** \file + * \brief Image Resize + * + * See Copyright Notice in im_lib.h + * $Id: im_resize.cpp,v 1.1 2008/10/17 06:16:33 scuri Exp $ + */ + + +#include +#include +#include +#include +#include + +#include "im_process_loc.h" + +#include +#include + + +static inline void iResizeInverse(int x, int y, float *xl, float *yl, float x_invfactor, float y_invfactor) +{ + *xl = (x + 0.5f) * x_invfactor; + *yl = (y + 0.5f) * y_invfactor; +} + +template +static int iResize(int src_width, int src_height, const DT *src_map, + int dst_width, int dst_height, DT *dst_map, + DTU Dummy, int order, int counter) +{ + float xl, yl; + float x_invfactor = float(src_width)/float(dst_width); + float y_invfactor = float(src_height)/float(dst_height); + + for (int y = 0; y < dst_height; y++) + { + for (int x = 0; x < dst_width; x++) + { + iResizeInverse(x, y, &xl, &yl, x_invfactor, y_invfactor); + + // if inside the original image + if (xl > 0.0 && yl > 0.0 && xl < src_width && yl < src_height) + { + if (order == 1) + *dst_map = imBilinearInterpolation(src_width, src_height, src_map, xl, yl); + else if (order == 3) + *dst_map = imBicubicInterpolation(src_width, src_height, src_map, xl, yl, Dummy); + else + *dst_map = imZeroOrderInterpolation(src_width, src_height, src_map, xl, yl); + } + + dst_map++; + } + + if (!imCounterInc(counter)) + return 0; + } + + return 1; +} + +template +static int iReduce(int src_width, int src_height, const DT *src_map, + int dst_width, int dst_height, DT *dst_map, + DTU Dummy, int order, int counter) +{ + float xl, yl; + float x_invfactor = float(src_width)/float(dst_width); + float y_invfactor = float(src_height)/float(dst_height); + + iResizeInverse(1, 1, &xl, &yl, x_invfactor, y_invfactor); + float xl0 = xl, yl0 = yl; + iResizeInverse(2, 2, &xl, &yl, x_invfactor, y_invfactor); + float xl1 = xl, yl1 = yl; + + float box_width = xl1 - xl0; + float box_height = yl1 - yl0; + + for (int y = 0; y < dst_height; y++) + { + for (int x = 0; x < dst_width; x++) + { + iResizeInverse(x, y, &xl, &yl, x_invfactor, y_invfactor); + + // if inside the original image + if (xl > 0.0 && yl > 0.0 && xl < src_width && yl < src_height) + { + if (order == 0) + *dst_map = imZeroOrderDecimation(src_width, src_height, src_map, xl, yl, box_width, box_height, Dummy); + else + *dst_map = imBilinearDecimation(src_width, src_height, src_map, xl, yl, box_width, box_height, Dummy); + } + + dst_map++; + } + + if (!imCounterInc(counter)) + return 0; + } + return 1; +} + +int imProcessReduce(const imImage* src_image, imImage* dst_image, int order) +{ + int ret = 0; + int counter = imCounterBegin("Reduce Size"); + const char* int_msg = (order == 1)? "Bilinear Decimation": "Zero Order Decimation"; + imCounterTotal(counter, src_image->depth*dst_image->height, int_msg); + + for (int i = 0; i < src_image->depth; i++) + { + switch(src_image->data_type) + { + case IM_BYTE: + ret = iReduce(src_image->width, src_image->height, (const imbyte*)src_image->data[i], + dst_image->width, dst_image->height, (imbyte*)dst_image->data[i], + float(0), order, counter); + break; + case IM_USHORT: + ret = iReduce(src_image->width, src_image->height, (const imushort*)src_image->data[i], + dst_image->width, dst_image->height, (imushort*)dst_image->data[i], + float(0), order, counter); + break; + case IM_INT: + ret = iReduce(src_image->width, src_image->height, (const int*)src_image->data[i], + dst_image->width, dst_image->height, (int*)dst_image->data[i], + float(0), order, counter); + break; + case IM_FLOAT: + ret = iReduce(src_image->width, src_image->height, (const float*)src_image->data[i], + dst_image->width, dst_image->height, (float*)dst_image->data[i], + float(0), order, counter); + break; + case IM_CFLOAT: + ret = iReduce(src_image->width, src_image->height, (const imcfloat*)src_image->data[i], + dst_image->width, dst_image->height, (imcfloat*)dst_image->data[i], + imcfloat(0,0), order, counter); + break; + } + } + + imCounterEnd(counter); + return ret; +} + +int imProcessResize(const imImage* src_image, imImage* dst_image, int order) +{ + int ret = 0; + int counter = imCounterBegin("Resize"); + const char* int_msg = (order == 3)? "Bicubic Interpolation": (order == 1)? "Bilinear Interpolation": "Zero Order Interpolation"; + imCounterTotal(counter, src_image->depth*dst_image->height, int_msg); + + for (int i = 0; i < src_image->depth; i++) + { + switch(src_image->data_type) + { + case IM_BYTE: + ret = iResize(src_image->width, src_image->height, (const imbyte*)src_image->data[i], + dst_image->width, dst_image->height, (imbyte*)dst_image->data[i], + float(0), order, counter); + break; + case IM_USHORT: + ret = iResize(src_image->width, src_image->height, (const imushort*)src_image->data[i], + dst_image->width, dst_image->height, (imushort*)dst_image->data[i], + float(0), order, counter); + break; + case IM_INT: + ret = iResize(src_image->width, src_image->height, (const int*)src_image->data[i], + dst_image->width, dst_image->height, (int*)dst_image->data[i], + float(0), order, counter); + break; + case IM_FLOAT: + ret = iResize(src_image->width, src_image->height, (const float*)src_image->data[i], + dst_image->width, dst_image->height, (float*)dst_image->data[i], + float(0), order, counter); + break; + case IM_CFLOAT: + ret = iResize(src_image->width, src_image->height, (const imcfloat*)src_image->data[i], + dst_image->width, dst_image->height, (imcfloat*)dst_image->data[i], + imcfloat(0,0), order, counter); + break; + } + } + + imCounterEnd(counter); + return ret; +} + +template +static void ReduceBy4(int src_width, + int src_height, + DT *src_map, + int dst_width, + int dst_height, + DT *dst_map) +{ + int x,y,yd,xd; + (void)dst_height; + + // make an even size + int height = (src_height/2)*2; + int width = (src_width/2)*2; + + for(y = 0 ; y < height ; y += 2) + { + yd = y/2; + for(x = 0 ; x < width ; x += 2) + { + xd = x/2; + dst_map[yd * dst_width + xd] = ((src_map[y * src_width + x] + + src_map[y * src_width + (x+1)] + + src_map[(y+1) * src_width + x] + + src_map[(y+1) * src_width + (x+1)])/4); + } + } +} + +void imProcessReduceBy4(const imImage* src_image, imImage* dst_image) +{ + int i; + + for (i = 0; i < src_image->depth; i++) + { + switch(src_image->data_type) + { + case IM_BYTE: + ReduceBy4(src_image->width, src_image->height, (imbyte*)src_image->data[i], dst_image->width, dst_image->height, (imbyte*)dst_image->data[i]); + break; + case IM_USHORT: + ReduceBy4(src_image->width, src_image->height, (imushort*)src_image->data[i], dst_image->width, dst_image->height, (imushort*)dst_image->data[i]); + break; + case IM_INT: + ReduceBy4(src_image->width, src_image->height, (int*)src_image->data[i], dst_image->width, dst_image->height, (int*)dst_image->data[i]); + break; + case IM_FLOAT: + ReduceBy4(src_image->width, src_image->height, (float*)src_image->data[i], dst_image->width, dst_image->height, (float*)dst_image->data[i]); + break; + case IM_CFLOAT: + ReduceBy4(src_image->width, src_image->height, (imcfloat*)src_image->data[i], dst_image->width, dst_image->height, (imcfloat*)dst_image->data[i]); + break; + } + } +} + +void imProcessCrop(const imImage* src_image, imImage* dst_image, int xmin, int ymin) +{ + int type_size = imDataTypeSize(src_image->data_type); + for (int i = 0; i < src_image->depth; i++) + { + imbyte *src_map = (imbyte*)src_image->data[i]; + imbyte *dst_map = (imbyte*)dst_image->data[i]; + + for (int y = 0; y < dst_image->height; y++) + { + int src_offset = (y + ymin)*src_image->line_size + xmin*type_size; + int dst_offset = y*dst_image->line_size; + + memcpy(&dst_map[dst_offset], &src_map[src_offset], dst_image->line_size); + } + } +} + +void imProcessInsert(const imImage* src_image, const imImage* rgn_image, imImage* dst_image, int xmin, int ymin) +{ + int type_size = imDataTypeSize(src_image->data_type); + int dst_size1 = xmin*type_size; + int dst_size2 = src_image->line_size - (rgn_image->line_size + dst_size1); + int dst_offset2 = dst_size1+rgn_image->line_size; + int ymax = ymin+rgn_image->height-1; + int rgn_size = rgn_image->line_size; + + if (dst_size2 < 0) + { + dst_size2 = 0; + rgn_size = src_image->line_size - dst_size1; + dst_offset2 = dst_size1+rgn_size; + } + + if (ymax > src_image->height-1) + ymax = src_image->height-1; + + for (int i = 0; i < src_image->depth; i++) + { + imbyte *src_map = (imbyte*)src_image->data[i]; + imbyte *rgn_map = (imbyte*)rgn_image->data[i]; + imbyte *dst_map = (imbyte*)dst_image->data[i]; + + for (int y = 0; y < src_image->height; y++) + { + if (y < ymin || y > ymax) + { + memcpy(dst_map, src_map, src_image->line_size); + } + else + { + if (dst_size1) + memcpy(dst_map, src_map, dst_size1); + + memcpy(dst_map + dst_size1, rgn_map, rgn_size); + + if (dst_size2) + memcpy(dst_map + dst_offset2, + src_map + dst_offset2, dst_size2); + + rgn_map += rgn_image->line_size; + } + + src_map += src_image->line_size; + dst_map += dst_image->line_size; + } + } +} + +void imProcessAddMargins(const imImage* src_image, imImage* dst_image, int xmin, int ymin) +{ + int type_size = imDataTypeSize(src_image->data_type); + for (int i = 0; i < src_image->depth; i++) + { + imbyte *dst_map = (imbyte*)dst_image->data[i]; + imbyte *src_map = (imbyte*)src_image->data[i]; + + for (int y = 0; y < src_image->height; y++) + { + int src_offset = y*src_image->line_size; + int dst_offset = (y + ymin)*dst_image->line_size + xmin*type_size; + + memcpy(&dst_map[dst_offset], &src_map[src_offset], src_image->line_size); + } + } +} + diff --git a/im/src/process/im_statistics.cpp b/im/src/process/im_statistics.cpp new file mode 100755 index 0000000..b9f086d --- /dev/null +++ b/im/src/process/im_statistics.cpp @@ -0,0 +1,341 @@ +/** \file + * \brief Image Statistics Calculations + * + * See Copyright Notice in im_lib.h + * $Id: im_statistics.cpp,v 1.1 2008/10/17 06:16:33 scuri Exp $ + */ + + +#include +#include +#include + +#include "im_process_ana.h" + +#include +#include +#include + +static unsigned long count_map(const imImage* image) +{ + unsigned long histo[256]; + int size = image->width * image->height; + imCalcHistogram((imbyte*)image->data[0], size, histo, 0); + unsigned long numcolor = 0; + + for (int i = 0; i < 256; i++) + { + if(histo[i] != 0) + numcolor++; + } + + return numcolor; +} + +// will count also all the 3 components color spaces +static unsigned long count_rgb(const imImage* image) +{ + imbyte *count = (imbyte*)calloc(sizeof(imbyte), 1 << 21 ); /* (2^24)/8=2^21 ~ 2Mb */ + if (!count) + return (unsigned long)-1; + + int size = image->width * image->height; + imbyte *red = (imbyte*)image->data[0]; + imbyte *green = (imbyte*)image->data[1]; + imbyte *blue = (imbyte*)image->data[2]; + + int index; + unsigned long numcolor = 0; + + for(int i = 0; i < size; i++) + { + index = red[i] << 16 | green[i] << 8 | blue[i]; + + if(imDataBitGet(count, index) == 0) + numcolor++; + + imDataBitSet(count, index, 1); + } + + free(count); + + return numcolor; +} + +unsigned long imCalcCountColors(const imImage* image) +{ + if (imColorModeDepth(image->color_space) > 1) + return count_rgb(image); + else + return count_map(image); +} + +void imCalcHistogram(const imbyte* map, int size, unsigned long* histo, int cumulative) +{ + int i; + + memset(histo, 0, 256 * sizeof(unsigned long)); + + for (i = 0; i < size; i++) + histo[*map++]++; + + if (cumulative) + { + /* make cumulative histogram */ + for (i = 1; i < 256; i++) + histo[i] += histo[i-1]; + } +} + +void imCalcUShortHistogram(const imushort* map, int size, unsigned long* histo, int cumulative) +{ + int i; + + memset(histo, 0, 65535 * sizeof(unsigned long)); + + for (i = 0; i < size; i++) + histo[*map++]++; + + if (cumulative) + { + /* make cumulative histogram */ + for (i = 1; i < 65535; i++) + histo[i] += histo[i-1]; + } +} + +void imCalcGrayHistogram(const imImage* image, unsigned long* histo, int cumulative) +{ + int i; + + memset(histo, 0, 256 * sizeof(unsigned long)); + + if (image->color_space == IM_GRAY) + { + imbyte* map = (imbyte*)image->data[0]; + for (i = 0; i < image->count; i++) + histo[*map++]++; + } + else if (image->color_space == IM_MAP || image->color_space == IM_BINARY) + { + imbyte* map = (imbyte*)image->data[0]; + imbyte gray_map[256], r, g, b; + + for (i = 0; i < image->palette_count; i++) + { + imColorDecode(&r, &g, &b, image->palette[i]); + gray_map[i] = (imbyte)((299*r + 587*g + 114*b) / 1000); + } + + for (i = 0; i < image->count; i++) + { + int index = *map++; + histo[gray_map[index]]++; + } + } + else + { + imbyte gray; + imbyte* r = (imbyte*)image->data[0]; + imbyte* g = (imbyte*)image->data[1]; + imbyte* b = (imbyte*)image->data[2]; + for (i = 0; i < image->count; i++) + { + gray = (imbyte)((299*(*r++) + 587*(*g++) + 114*(*b++)) / 1000); + histo[gray]++; + } + } + + if (cumulative) + { + /* make cumulative histogram */ + for (i = 1; i < 256; i++) + histo[i] += histo[i-1]; + } +} + +template +static void DoStats(T* data, int count, imStats* stats) +{ + memset(stats, 0, sizeof(imStats)); + + stats->min = (float)data[0]; + stats->max = (float)data[0]; + + for (int i = 0; i < count; i++) + { + if (data[i] < stats->min) + stats->min = (float)data[i]; + + if (data[i] > stats->max) + stats->max = (float)data[i]; + + if (data[i] > 0) + stats->positive++; + + if (data[i] < 0) + stats->negative++; + + if (data[i] == 0) + stats->zeros++; + + stats->mean += (float)data[i]; + stats->stddev += ((float)data[i])*((float)data[i]); + } + + stats->mean /= float(count); + stats->stddev = (float)sqrt((stats->stddev - count * stats->mean*stats->mean)/(count-1.0)); +} + +void imCalcImageStatistics(const imImage* image, imStats* stats) +{ + int count = image->width * image->height; + + for (int i = 0; i < image->depth; i++) + { + switch(image->data_type) + { + case IM_BYTE: + DoStats((imbyte*)image->data[i], count, &stats[i]); + break; + case IM_USHORT: + DoStats((imushort*)image->data[i], count, &stats[i]); + break; + case IM_INT: + DoStats((int*)image->data[i], count, &stats[i]); + break; + case IM_FLOAT: + DoStats((float*)image->data[i], count, &stats[i]); + break; + } + } +} + +void imCalcHistogramStatistics(const imImage* image, imStats* stats) +{ + int image_size = image->width * image->height; + unsigned long histo[256]; + + for (int d = 0; d < image->depth; d++) + { + imCalcHistogram((imbyte*)image->data[d], image_size, histo, 0); + DoStats((unsigned long*)histo, 256, &stats[d]); + } +} + +void imCalcHistoImageStatistics(const imImage* image, int* median, int* mode) +{ + unsigned long histo[256]; + + for (int d = 0; d < image->depth; d++) + { + int i; + imCalcHistogram((imbyte*)image->data[d], image->count, histo, 0); + + unsigned long half = image->count/2; + unsigned long count = histo[0]; + for (i = 1; i < 256; i++) + { + if (count > half) + { + median[d] = i-1; + break; + } + + count += histo[i]; + } + + unsigned long max = histo[0]; + for (i = 1; i < 256; i++) + { + if (max < histo[i]) + max = histo[i]; + } + + int found_mode = 0; + for (i = 0; i < 256; i++) + { + if (histo[i] == max) + { + if (found_mode) + { + mode[d] = -1; + break; + } + + mode[d] = i; + found_mode = 1; + } + } + } +} + +float imCalcSNR(const imImage* image, const imImage* noise_image) +{ + imStats stats[3]; + imCalcImageStatistics((imImage*)image, stats); + + imStats noise_stats[3]; + imCalcImageStatistics((imImage*)noise_image, noise_stats); + + if (image->color_space == IM_RGB) + { + noise_stats[0].stddev += noise_stats[1].stddev; + noise_stats[0].stddev += noise_stats[2].stddev; + noise_stats[0].stddev /= 3; + stats[0].stddev += stats[1].stddev; + stats[0].stddev += stats[2].stddev; + stats[0].stddev /= 3; + } + + if (noise_stats[0].stddev == 0) + return 0; + + return float(20.*log10(stats[0].stddev / noise_stats[0].stddev)); +} + +template +static float DoRMSOp(T *map1, T *map2, int count) +{ + float rmserror = 0.0f; + float diff; + + for (int i = 0; i < count; i++) + { + diff = float(map1[i] - map2[i]); + rmserror += diff * diff; + } + + return rmserror; +} + +float imCalcRMSError(const imImage* image1, const imImage* image2) +{ + float rmserror = 0.0f; + + int count = image1->count*image1->depth; + + switch(image1->data_type) + { + case IM_BYTE: + rmserror = DoRMSOp((imbyte*)image1->data[0], (imbyte*)image2->data[0], count); + break; + case IM_USHORT: + rmserror = DoRMSOp((imushort*)image1->data[0], (imushort*)image2->data[0], count); + break; + case IM_INT: + rmserror = DoRMSOp((int*)image1->data[0], (int*)image2->data[0], count); + break; + case IM_FLOAT: + rmserror = DoRMSOp((float*)image1->data[0], (float*)image2->data[0], count); + break; + case IM_CFLOAT: + rmserror = DoRMSOp((float*)image1->data[0], (float*)image2->data[0], 2*count); + break; + } + + rmserror = float(sqrt(rmserror / float((count * image1->depth)))); + + return rmserror; +} + diff --git a/im/src/process/im_threshold.cpp b/im/src/process/im_threshold.cpp new file mode 100755 index 0000000..4af72ee --- /dev/null +++ b/im/src/process/im_threshold.cpp @@ -0,0 +1,391 @@ +/** \file + * \brief Threshold Operations + * + * See Copyright Notice in im_lib.h + * $Id: im_threshold.cpp,v 1.1 2008/10/17 06:16:33 scuri Exp $ + */ + + +#include +#include + +#include "im_process_pon.h" +#include "im_process_ana.h" + +#include +#include +#include +#include +#include + + +void imProcessSliceThreshold(const imImage* src_image, imImage* dst_image, int start_level, int end_level) +{ + float params[3]; + params[0] = (float)start_level; + params[1] = (float)end_level; + params[2] = (float)1; /* binarize 0-255 */ + imProcessToneGamut(src_image, dst_image, IM_GAMUT_SLICE, params); + imImageMakeBinary(dst_image); /* this compensates the returned values in IM_GAMUT_SLICE */ +} + +void imProcessThresholdByDiff(const imImage* image1, const imImage* image2, imImage* NewImage) +{ + imbyte *src_map1 = (imbyte*)image1->data[0]; + imbyte *src_map2 = (imbyte*)image2->data[0]; + imbyte *dst_map = (imbyte*)NewImage->data[0]; + int size = image1->count; + + for (int i = 0; i < size; i++) + { + if (*src_map1++ <= *src_map2++) + *dst_map++ = 0; + else + *dst_map++ = 1; + } +} + +template +static void doThreshold(T *src_map, imbyte *dst_map, int count, int level, int value) +{ + for (int i = 0; i < count; i++) + { + if (*src_map++ <= level) + *dst_map++ = 0; + else + *dst_map++ = (imbyte)value; + } +} + +void imProcessThreshold(const imImage* src_image, imImage* dst_image, int level, int value) +{ + switch(src_image->data_type) + { + case IM_BYTE: + doThreshold((imbyte*)src_image->data[0], (imbyte*)dst_image->data[0], + src_image->count, level, value); + break; + case IM_USHORT: + doThreshold((imushort*)src_image->data[0], (imbyte*)dst_image->data[0], + src_image->count, level, value); + break; + case IM_INT: + doThreshold((int*)src_image->data[0], (imbyte*)dst_image->data[0], + src_image->count, level, value); + break; + } +} + +static int compare_int(const void *elem1, const void *elem2) +{ + int* v1 = (int*)elem1; + int* v2 = (int*)elem2; + + if (*v1 < *v2) + return -1; + + if (*v1 > *v2) + return 1; + + return 0; +} + +static int thresUniErr(unsigned char* band, int width, int height) +{ + int x, y, i, bottom, top, ant2x2, maks1, maks2, maks4, t; + int xsize, ysize, offset1, offset2; + double a, b, c, phi; + int g[4], tab1[256], tab2[256], tab4[256]; + + memset(tab1, 0, sizeof(int)*256); + memset(tab2, 0, sizeof(int)*256); + memset(tab4, 0, sizeof(int)*256); + + xsize = width; + ysize = height; + + if (xsize%2 != 0) + xsize--; + + if (ysize%2 != 0) + ysize--; + + /* examine all 2x2 neighborhoods */ + + for (y=0; y=0; i--) + { + tab1[i] += tab1[i+1]; + tab2[i] += tab2[i+1]; + tab4[i] += tab4[i+1]; + } + + /* Tables are ready, find threshold */ + bottom = 0; top = 255; + ant2x2 = (xsize/2)*(ysize/2); + maks1 = tab1[0]; /* = ant2x2 * 4; */ + maks2 = tab2[0]; /* = ant2x2 * 6; */ + maks4 = tab4[0]; /* = ant2x2; */ + + /* binary search */ + t = 0; + while (bottom != top-1) + { + t = (int) ((bottom+top)/2); + + /* Calculate probabilities */ + a = (double) tab1[t+1]/maks1; + b = (double) tab2[t+1]/maks2; + c = (double) tab4[t+1]/maks4; + + phi = sqrt((b*b - c) / (a*a - b)); + + if (phi> 1) + bottom = t; + else + top = t; + } + + return t; +} + +int imProcessUniformErrThreshold(const imImage* image, imImage* NewImage) +{ + int level = thresUniErr((imbyte*)image->data[0], image->width, image->height); + imProcessThreshold(image, NewImage, level, 1); + return level; +} + +static void do_dither_error(imbyte* data1, imbyte* data2, int size, int t, int value) +{ + int i, error; + float scale = (float)(t/(255.0-t)); + + error = 0; /* always in [-127,127] */ + + for (i = 0; i < size; i++) + { + if ((int)(*data1 + error) > t) + { + error -= (int)(((int)255 - (int)*data1++)*scale); + *data2++ = (imbyte)value; + } + else + { + error += (int)*data1++; + *data2++ = (imbyte)0; + } + } +} + +void imProcessDifusionErrThreshold(const imImage* image, imImage* NewImage, int level) +{ + int value = image->depth > 1? 255: 1; + int size = image->width * image->height; + for (int i = 0; i < image->depth; i++) + { + do_dither_error((imbyte*)image->data[i], (imbyte*)NewImage->data[i], size, level, value); + } +} + +int imProcessPercentThreshold(const imImage* image, imImage* NewImage, float percent) +{ + unsigned long histo[256], cut; + + cut = (int)((image->width * image->height * percent)/100.); + + imCalcHistogram((imbyte*)image->data[0], image->width * image->height, histo, 1); + + int i; + for (i = 0; i < 256; i++) + { + if (histo[i] > cut) + break; + } + + int level = (i==0? 0: i==256? 254: i-1); + + imProcessThreshold(image, NewImage, level, 1); + return level; +} + +static int MaximizeDiscriminantFunction(double * p) +{ + double mi_255 = 0; + int k; + for (k=0; k<256; k++) + mi_255 += k*p[k]; + + int index = 0; + double max = 0; + double mi_k = 0; + double w_k = 0; + double value; + for (k=0; k<256; k++) + { + mi_k += k*p[k]; + w_k += p[k]; + value = ((w_k == 0) || (w_k == 1))? -1 : ((mi_255*w_k - mi_k)*(mi_255*w_k - mi_k))/(w_k*(1-w_k)); + if (value >= max) + { + index = k; + max = value; + } + } + + return index; +} + +static unsigned char Otsu(const imImage *image) +{ + unsigned long histo[256]; + imCalcHistogram((imbyte*)image->data[0], image->count, histo, 0); + + double totalPixels = image->count; + double p[256]; + for (int i=0; i<256; i++) + p[i] = histo[i]/totalPixels; + + return (unsigned char)MaximizeDiscriminantFunction(p); +} + +int imProcessOtsuThreshold(const imImage* image, imImage* NewImage) +{ + int level = Otsu(image); + imProcessThreshold(image, NewImage, level, 1); + return level; +} + +int imProcessMinMaxThreshold(const imImage* image, imImage* NewImage) +{ + imStats stats; + imCalcImageStatistics(image, &stats); + int level = (int)((stats.max - stats.min)/2.0f); + imProcessThreshold(image, NewImage, level, 1); + return level; +} + +void imProcessHysteresisThresEstimate(const imImage* image, int *low_thres, int *high_thres) +{ + unsigned long hist[256]; + imCalcHistogram((imbyte*)image->data[0], image->count, hist, 0); + + /* The high threshold should be > 80 or 90% of the pixels */ + unsigned long cut = (int)(0.1*image->count); + + int k = 255; + unsigned long count = hist[255]; + while (count < cut) + { + k--; + count += hist[k]; + } + *high_thres = k; + + k=0; + while (hist[k]==0) k++; + + *low_thres = (int)((*high_thres + k)/2.0) + k; +} + +void imProcessHysteresisThreshold(const imImage* image, imImage* NewImage, int low_thres, int high_thres) +{ + imbyte *src_map = (imbyte*)image->data[0]; + imbyte *dst_map = (imbyte*)NewImage->data[0]; + int i, j, size = image->count; + + for (i = 0; i < size; i++) + { + if (*src_map > high_thres) + *dst_map++ = 1; + else if (*src_map > low_thres) + *dst_map++ = 2; // mark for future replace + else + *dst_map++ = 0; + + src_map++; + } + + // now loop multiple times until there is no "2"s or no one was changed + dst_map = (imbyte*)NewImage->data[0]; + int changed = 1; + while (changed) + { + changed = 0; + for (j=1; jheight-1; j++) + { + for (i=1; iwidth-1; i++) + { + int offset = i+j*image->width; + if (dst_map[offset] == 2) + { + // if there is an edge neighbor mark this as edge too + if (dst_map[offset+1] == 1 || dst_map[offset-1] == 1 || + dst_map[offset+image->width] == 1 || dst_map[offset-image->width] == 1 || + dst_map[offset+image->width-1] == 1 || dst_map[offset+image->width+1] == 1 || + dst_map[offset-image->width-1] == 1 || dst_map[offset-image->width+1] == 1) + { + dst_map[offset] = 1; + changed = 1; + } + } + } + } + } + + // Clear the remaining "2"s + dst_map = (imbyte*)NewImage->data[0]; + for (i = 0; i < size; i++) + { + if (*dst_map == 2) + *dst_map = 0; + dst_map++; + } +} + +void imProcessLocalMaxThresEstimate(const imImage* image, int *thres) +{ + unsigned long hist[256]; + imCalcHistogram((imbyte*)image->data[0], image->count, hist, 0); + + int high_count = 0; + int index = 255; + while (high_count < 10 && index > 0) + { + if (hist[index] != 0) + high_count++; + + index--; + } + *thres = index+1; +} + diff --git a/im/src/process/im_tonegamut.cpp b/im/src/process/im_tonegamut.cpp new file mode 100755 index 0000000..cf63350 --- /dev/null +++ b/im/src/process/im_tonegamut.cpp @@ -0,0 +1,322 @@ +/** \file + * \brief Tone Gamut Operations + * + * See Copyright Notice in im_lib.h + * $Id: im_tonegamut.cpp,v 1.1 2008/10/17 06:16:33 scuri Exp $ + */ + + +#include +#include +#include + +#include "im_process_pon.h" + +#include +#include +#include +#include +#include + + +template +static inline T line_op(const T& v, const T& min, const T& max, const float& a, const float& b) +{ + float r = v * a + b; + if (r > (float)max) return max; + if (r < (float)min) return min; + return (T)r; +} + +template +static inline T normal_op(const T& v, const T& min, const T& range) +{ + return (T)(float(v - min) / float(range)); +} + +template +static inline T zerostart_op(const T& v, const T& min) +{ + return (T)(v - min); +} + +template +static inline float invert_op(const T& v, const T& min, const T& range) +{ + return 1.0f - float(v - min) / float(range); +} + +template +static inline T solarize_op(const T& v, const T& level, const float& A, const float& B) +{ + if (v > level) + return (T)(v * A + B); + else + return v; +} + +template +static inline T slice_op(const T& v, const T& min, const T& max, const T& start, const T& end, int bin) +{ + if (v < start || v > end) + return min; + else + { + if (bin) + return max; + else + return v; + } +} + +template +static inline T tonecrop_op(const T& v, const T& start, const T& end) +{ + if (v < start) + return start; + if (v > end) + return end; + else + return v; +} + +template +static inline T expand_op(const T& v, const T& min, const T& max, const T& start, const float& norm) +{ + float r = (v - start)*norm + min; + if (r > (float)max) return max; + if (r < (float)min) return min; + return (T)r; +} + +template +static inline float norm_pow_op(const T& v, const T& min, const T& range, const float& gamma) +{ + return (float)pow(float(v - min) / float(range), gamma); +} + +template +static inline float norm_log_op(const T& v, const T& min, const T& range, const float& norm, const float& K) +{ + return (float)(log(K * float(v - min) / float(range) + 1) / norm); +} + +template +static inline float norm_exp_op(const T& v, const T& min, const T& range, const float& norm, const float& K) +{ + return (float)((exp(K * float(v - min) / float(range)) - 1) / norm); +} + +template +static void DoNormalizedUnaryOp(T *map, T *new_map, int count, int op, float *args) +{ + int i; + T min, max, range; + + int size_of = sizeof(imbyte); + if (sizeof(T) == size_of) + { + min = 0; + max = 255; + } + else + { + imMinMax(map, count, min, max); + + if (min == max) + { + max = min + 1; + + if (min != 0) + min = min - 1; + } + } + + range = max-min; + + switch(op) + { + case IM_GAMUT_NORMALIZE: + { + if (min >= 0 && max <= 1) + { + for (i = 0; i < count; i++) + new_map[i] = (T)map[i]; + } + else + { + for (i = 0; i < count; i++) + new_map[i] = normal_op(map[i], min, range); + } + break; + } + case IM_GAMUT_INVERT: + for (i = 0; i < count; i++) + new_map[i] = (T)(invert_op(map[i], min, range)*range + min); + break; + case IM_GAMUT_ZEROSTART: + for (i = 0; i < count; i++) + new_map[i] = (T)zerostart_op(map[i], min); + break; + case IM_GAMUT_SOLARIZE: + { + T level = (T)(((100 - args[0]) * range) / 100.0f + min); + float A = float(level - min) / float(level - max); + float B = float(level * range) / float(max - level); + for (i = 0; i < count; i++) + new_map[i] = solarize_op(map[i], level, A, B); + break; + } + case IM_GAMUT_POW: + for (i = 0; i < count; i++) + new_map[i] = (T)(norm_pow_op(map[i], min, range, args[0])*range + min); + break; + case IM_GAMUT_LOG: + { + float norm = float(log(args[0] + 1)); + for (i = 0; i < count; i++) + new_map[i] = (T)(norm_log_op(map[i], min, range, norm, args[0])*range + min); + break; + } + case IM_GAMUT_EXP: + { + float norm = float(exp(args[0]) - 1); + for (i = 0; i < count; i++) + new_map[i] = (T)(norm_exp_op(map[i], min, range, norm, args[0])*range + min); + break; + } + case IM_GAMUT_SLICE: + { + if (args[0] > args[1]) { float tmp = args[1]; args[1] = args[0]; args[0] = tmp; } + if (args[1] > max) args[1] = (float)max; + if (args[0] < min) args[0] = (float)min; + for (i = 0; i < count; i++) + new_map[i] = slice_op(map[i], min, max, (T)args[0], (T)args[1], (int)args[2]); + break; + } + case IM_GAMUT_CROP: + { + if (args[0] > args[1]) { float tmp = args[1]; args[1] = args[0]; args[0] = tmp; } + if (args[1] > max) args[1] = (float)max; + if (args[0] < min) args[0] = (float)min; + for (i = 0; i < count; i++) + new_map[i] = tonecrop_op(map[i], (T)args[0], (T)args[1]); + break; + } + case IM_GAMUT_EXPAND: + { + if (args[0] > args[1]) { float tmp = args[1]; args[1] = args[0]; args[0] = tmp; } + if (args[1] > max) args[1] = (float)max; + if (args[0] < min) args[0] = (float)min; + float norm = float(max - min)/(args[1] - args[0]); + for (i = 0; i < count; i++) + new_map[i] = expand_op(map[i], min, max, (T)args[0], norm); + break; + } + case IM_GAMUT_BRIGHTCONT: + { + float bs = (args[0] * range) / 100.0f; + float a = (float)tan((45+args[1]*0.449999)/57.2957795); + float b = bs + (float)range*(1.0f - a)/2.0f; + for (i = 0; i < count; i++) + new_map[i] = line_op(map[i], min, max, a, b); + break; + } + } +} + +void imProcessToneGamut(const imImage* src_image, imImage* dst_image, int op, float *args) +{ + int count = src_image->count*src_image->depth; + + switch(src_image->data_type) + { + case IM_BYTE: + DoNormalizedUnaryOp((imbyte*)src_image->data[0], (imbyte*)dst_image->data[0], count, op, args); + break; + case IM_USHORT: + DoNormalizedUnaryOp((imushort*)src_image->data[0], (imushort*)dst_image->data[0], count, op, args); + break; + case IM_INT: + DoNormalizedUnaryOp((int*)src_image->data[0], (int*)dst_image->data[0], count, op, args); + break; + case IM_FLOAT: + DoNormalizedUnaryOp((float*)src_image->data[0], (float*)dst_image->data[0], count, op, args); + break; + } +} + +void imProcessUnNormalize(const imImage* image, imImage* NewImage) +{ + int count = image->count*image->depth; + + float* map = (float*)image->data[0]; + imbyte* new_map = (imbyte*)NewImage->data[0]; + + for (int i = 0; i < count; i++) + { + if (map[i] > 1) + new_map[i] = (imbyte)255; + else if (map[i] < 0) + new_map[i] = (imbyte)0; + else + new_map[i] = (imbyte)(map[i]*255); + } +} + +template +static void DoDirectConv(T* map, imbyte* new_map, int count) +{ + for (int i = 0; i < count; i++) + { + if (map[i] > 255) + new_map[i] = (imbyte)255; + else if (map[i] < 0) + new_map[i] = (imbyte)0; + else + new_map[i] = (imbyte)(map[i]); + } +} + +void imProcessDirectConv(const imImage* image, imImage* NewImage) +{ + int count = image->count*image->depth; + + switch(image->data_type) + { + case IM_USHORT: + DoDirectConv((imushort*)image->data[0], (imbyte*)NewImage->data[0], count); + break; + case IM_INT: + DoDirectConv((int*)image->data[0], (imbyte*)NewImage->data[0], count); + break; + case IM_FLOAT: + DoDirectConv((float*)image->data[0], (imbyte*)NewImage->data[0], count); + break; + } +} + +void imProcessNegative(const imImage* src_image, imImage* dst_image) +{ + if (src_image->color_space == IM_MAP) + { + unsigned char r, g, b; + for (int i = 0; i < src_image->palette_count; i++) + { + imColorDecode(&r, &g, &b, src_image->palette[i]); + r = ~r; g = ~g; b = ~b; + dst_image->palette[i] = imColorEncode(r, g, b); + } + + imImageCopyData(src_image, dst_image); + } + else if (src_image->color_space == IM_BINARY) + { + imbyte* map1 = (imbyte*)src_image->data[0]; + imbyte* map = (imbyte*)dst_image->data[0]; + for (int i = 0; i < src_image->count; i++) + map[i] = map1[i]? 0: 1; + } + else + imProcessToneGamut(src_image, dst_image, IM_GAMUT_INVERT, NULL); +} diff --git a/im/src/tecmake_compact.mak b/im/src/tecmake_compact.mak new file mode 100755 index 0000000..d4fe0af --- /dev/null +++ b/im/src/tecmake_compact.mak @@ -0,0 +1,1170 @@ +#-------------------------------------------------------------------------# +#- Tecmake (Compact Version) -# +#- Generic Makefile to build applications and libraries at TeCGraf -# +#- The user makefile usually has the name "config.mak". -# +#-------------------------------------------------------------------------# + +# Tecmake Version +VERSION = 3.19 + +# First target +.PHONY: build +build: tecmake + + +#---------------------------------# +# System Variables Definitions + +# Base Defintions +TEC_SYSNAME:=$(shell uname -s) +TEC_SYSVERSION:=$(shell uname -r|cut -f1 -d.) +TEC_SYSMINOR:=$(shell uname -r|cut -f2 -d.) +TEC_SYSARCH:=$(shell uname -m) + +# Fixes +ifeq ($(TEC_SYSNAME), SunOS) + TEC_SYSARCH:=$(shell uname -p) +endif +ifeq ($(TEC_SYSNAME), IRIX) + TEC_SYSARCH:=$(shell uname -p) +endif +ifeq ($(TEC_SYSNAME), FreeBSD) + TEC_SYSMINOR:=$(shell uname -r|cut -f2 -d.|cut -f1 -d-) +endif +ifeq ($(TEC_SYSNAME), AIX) + TEC_SYSVERSION:=$(shell uname -v) + TEC_SYSMINOR:=$(shell uname -r) + TEC_SYSARCH:=ppc +endif +ifeq ($(TEC_SYSNAME), Darwin) + TEC_SYSARCH:=$(shell uname -p) +endif + +ifeq ($(TEC_SYSARCH), powerpc) + TEC_SYSARCH:=ppc +endif +ifeq ($(TEC_SYSARCH), i686) + TEC_SYSARCH:=x86 +endif +ifeq ($(TEC_SYSARCH), i386) + TEC_SYSARCH:=x86 +endif +ifeq ($(TEC_SYSARCH), x86_64) + TEC_SYSARCH:=x64 +endif + +# Compose +TEC_SYSRELEASE:=$(TEC_SYSVERSION).$(TEC_SYSMINOR) +TEC_UNAME:=$(TEC_SYSNAME)$(TEC_SYSVERSION)$(TEC_SYSMINOR) + +# Linux 2.4 and GCC 3.x +ifeq ($(TEC_UNAME), Linux24) + GCCVER:=$(shell gcc -dumpversion|cut -f1 -d.) + ifeq ($(GCCVER), 3) + TEC_UNAME:=$(TEC_UNAME)g3 + endif +endif + +# Linux 2.6 and GCC 4.x +ifeq ($(TEC_UNAME), Linux26) + GCCVER:=$(shell gcc -dumpversion|cut -f1 -d.) + ifeq ($(GCCVER), 4) + TEC_UNAME:=$(TEC_UNAME)g4 + endif +endif + +# Linux and PowerPC +ifeq ($(TEC_SYSNAME), Linux) + ifeq ($(TEC_SYSARCH), ppc) + TEC_UNAME:=$(TEC_UNAME)ppc + endif +endif + +# 64-bits Linux +ifeq ($(TEC_SYSARCH), x64) + BUILD_64=Yes + TEC_UNAME:=$(TEC_UNAME)_64 +endif + +ifeq ($(TEC_SYSARCH), ia64) + BUILD_64=Yes + TEC_UNAME:=$(TEC_UNAME)_ia64 +endif + +# Solaris and Intel +ifeq ($(TEC_SYSNAME), SunOS) + ifeq ($(TEC_SYSARCH) , x86) + TEC_UNAME:=$(TEC_UNAME)x86 + endif +endif + +# Darwin and Intel +ifeq ($(TEC_SYSNAME), Darwin) +ifeq ($(TEC_SYSARCH), x86) + TEC_UNAME:=$(TEC_UNAME)x86 + endif +endif + +# System Info +.PHONY: sysinfo +sysinfo: + @echo ''; echo 'Tecmake - System Info' + @echo 'TEC_SYSNAME = $(TEC_SYSNAME)' + @echo 'TEC_SYSVERSION = $(TEC_SYSVERSION)' + @echo 'TEC_SYSMINOR = $(TEC_SYSMINOR)' + @echo 'TEC_SYSARCH = $(TEC_SYSARCH)' + @echo 'TEC_UNAME = $(TEC_UNAME)'; echo '' + +#---------------------------------# +# Directories Definitions +PROJDIR = .. +SRCDIR = . +OBJROOT = $(PROJDIR)/obj + + +#---------------------------------# +# Byte Order and Word Size + +ifneq ($(findstring x86, $(TEC_SYSARCH)), ) + TEC_BYTEORDER = TEC_LITTLEENDIAN +else +ifeq ($(TEC_SYSARCH), arm) + TEC_BYTEORDER = TEC_LITTLEENDIAN +else + TEC_BYTEORDER = TEC_BIGENDIAN +endif +endif + +ifeq ($(TEC_SYSARCH), x64) + TEC_WORDSIZE = TEC_64 +else +ifdef BUILD_64 + TEC_WORDSIZE = TEC_64 +else + TEC_WORDSIZE = TEC_32 +endif +endif + +# Itanium Exception +ifeq ($(TEC_SYSARCH), ia64) + TEC_BYTEORDER = TEC_LITTLEENDIAN + TEC_WORDSIZE = TEC_64 +endif + + +#---------------------------------# +# Compilation Flags +STDFLAGS := -Wall +STDDEFS := -DTEC_UNAME=$(TEC_UNAME) -DTEC_SYSNAME=$(TEC_SYSNAME) -D$(TEC_SYSNAME)=$(TEC_SYSRELEASE) -D$(TEC_BYTEORDER) -D$(TEC_WORDSIZE) -DFUNCPROTO=15 +STDINCS := +OPTFLAGS := -O2 +STDLFLAGS := r +DEBUGFLAGS := -g +STDLDFLAGS := -shared +DLIBEXT := so + +ifneq ($(findstring Linux, $(TEC_UNAME)), ) + GTK_DEFAULT = Yes +endif +ifneq ($(findstring Darwin, $(TEC_UNAME)), ) + GTK_DEFAULT = Yes +endif +ifneq ($(findstring FreeBSD, $(TEC_UNAME)), ) + GTK_DEFAULT = Yes +endif +ifneq ($(findstring Linux24, $(TEC_UNAME)), ) + GTK_DEFAULT := +endif + +#---------------------------------# +# Build Tools + +CC := $(TEC_TOOLCHAIN)gcc +CPPC := $(TEC_TOOLCHAIN)g++ +FF := $(TEC_TOOLCHAIN)g77 +RANLIB := $(TEC_TOOLCHAIN)ranlib +AR := $(TEC_TOOLCHAIN)ar +DEBUGGER := $(TEC_TOOLCHAIN)gdb +RCC := $(TEC_TOOLCHAIN)windres +LD := $(TEC_TOOLCHAIN)gcc + +ifeq ($(TEC_UNAME), gcc2) + ifdef USE_GCC_2 + CC := $(CC)-2 + CPPC := $(CPPC)-2 + FF := $(FF)-2 + endif +endif + + +#---------------------------------# +# User Configuration File + +MAKENAME = config.mak + +ifdef MF + MAKENAME = $(MF).mak +endif + +################### +include $(MAKENAME) +################### + + +#---------------------------------# +# Definitions of public variables + +ifdef LIBNAME + TARGETNAME = $(LIBNAME) + MAKETYPE = LIB +else + TARGETNAME = $(APPNAME) + MAKETYPE = APP +endif + +ifndef TARGETNAME + $(error LIBNAME nor APPNAME defined in $(MAKENAME)) +endif + +PROJNAME ?= $(TARGETNAME) + +DEPEND := $(TARGETNAME).dep + +ifdef DEPENDDIR + DEPEND := $(DEPENDDIR)/$(TARGETNAME).dep.$(TEC_UNAME) +endif + +SRCLUADIR ?= $(SRCDIR) +LOHDIR ?= $(SRCLUADIR) + +ifeq ($(MAKETYPE), APP) + TARGETROOT ?= $(PROJDIR)/bin +else + TARGETROOT ?= $(PROJDIR)/lib +endif + +ifneq ($(PROJNAME), $(TARGETNAME)) + OBJROOT := $(OBJROOT)/$(TARGETNAME) +endif + +ifdef DBG + STDFLAGS += $(DEBUGFLAGS) + STDDEFS += -DDEBUG +else + STDDEFS += -DNDEBUG + ifdef OPT + STDFLAGS += $(OPTFLAGS) + ifeq ($(findstring gcc, $(TEC_UNAME)), ) + STRIP ?= Yes + endif + endif +endif + +ifdef BUILD_64 + ifneq ($(findstring SunOS, $(TEC_UNAME)), ) + USE_CC = Yes + BUILD_64_DIR = Yes + endif + ifneq ($(findstring AIX, $(TEC_UNAME)), ) + USE_CC = Yes + BUILD_64_DIR = Yes + endif + ifneq ($(findstring IRIX, $(TEC_UNAME)), ) + USE_CC = Yes + BUILD_64_DIR = Yes + endif +endif + +ifdef USE_CC + CC := cc + CPPC := CC + STDFLAGS = + ifdef USE_CC_DIR + TEC_UNAME := $(TEC_UNAME)cc + endif +endif + +ifdef BUILD_64 + ifdef BUILD_64_DIR + TEC_UNAME := $(TEC_UNAME)_64 + endif +endif + +ifneq ($(findstring gcc, $(TEC_UNAME)), ) + ifeq ($(MAKETYPE), APP) + TEC_UNAME_DIR ?= $(TEC_SYSNAME) + endif +endif + +TEC_UNAME_DIR ?= $(TEC_UNAME) +ifdef DBG + ifdef DBG_DIR + TEC_UNAME_DIR := $(TEC_UNAME_DIR)d + endif +endif + +OBJDIR := $(OBJROOT)/$(TEC_UNAME_DIR) +TARGETDIR := $(TARGETROOT)/$(TEC_UNAME_DIR) + +# Change linker if any C++ source +ifndef LINKER + ifneq "$(findstring .cpp, $(SRC))" "" + LINKER := $(CPPC) + else + LINKER := $(CC) + endif +endif + + +#---------------------------------# +# LO and LOH Suffix + +ifeq ($(TEC_BYTEORDER), TEC_BIGENDIAN) + ifeq ($(TEC_WORDSIZE), TEC_64) + LO_SUFFIX ?= _be64 + else + LO_SUFFIX ?= _be32 + endif +else + ifeq ($(TEC_WORDSIZE), TEC_64) + LO_SUFFIX ?= _le64 + else + LO_SUFFIX ?= + endif +endif + + +#---------------------------------# +# Platform specific variables + +# Definicoes para o X11 +X11_LIBS := Xmu Xt Xext X11 +#X11_LIB := +#X11_INC := #include + +# Definicoes para o OpenGL +OPENGL_LIBS := GLU GL +#OPENGL_LIB := +#OPENGL_INC := #include and possibly +MOTIFGL_LIB := GLw #include + +# Definicoes para o Motif +#MOTIF_LIB := +#MOTIF_INC := #include + +# Definicoes para o GLUT +#GLUT_LIB := +#GLUT_INC := + + +ifneq ($(findstring cygw, $(TEC_UNAME)), ) + NO_DYNAMIC ?= Yes + ifdef BUILD_64 + X11_LIB := /usr/X11R6/lib64 + else + X11_LIB := /usr/X11R6/lib + endif + X11_INC := /usr/X11R6/include + MOTIFGL_LIB := +endif + +ifneq ($(findstring Linux, $(TEC_UNAME)), ) + ifdef BUILD_64 + ifeq ($(TEC_SYSARCH), ia64) + STDFLAGS += -fPIC + X11_LIB := /usr/X11R6/lib + else + STDFLAGS += -m64 -fPIC + X11_LIB := /usr/X11R6/lib64 + endif + else + X11_LIB := /usr/X11R6/lib + endif + X11_INC := /usr/X11R6/include + MOTIFGL_LIB := +endif + +ifneq ($(findstring IRIX, $(TEC_UNAME)), ) # any IRIX + LD = ld + STDLDFLAGS := -elf -shared -rdata_shared -soname lib$(TARGETNAME).so + RANLIB := /bin/true + X11_LIBS := Xmu Xt X11 + ifdef BUILD_64 + ifdef USE_CC + STDFLAGS += -64 -KPIC + STDLDFLAGS += -64 + LINKER += -64 + endif + X11_LIB := /usr/lib64 + MOTIF_LIB := /usr/Motif-2.1/lib64 + else + X11_LIB := /usr/lib32 + MOTIF_LIB := /usr/Motif-2.1/lib32 + endif + MOTIF_INC = /usr/Motif-2.1/include +endif + +ifneq ($(findstring AIX, $(TEC_UNAME)), ) + NO_DYNAMIC ?= Yes + ifdef BUILD_64 + ifdef USE_CC + STDFLAGS += -q64 # to compilers C and C++ + STDLFLAGS := -X64 $(STDLFLAGS) # to librarian + STDLDFLAGS += -64 + LINKER += -q64 # to linker + endif + endif +endif + +ifneq ($(findstring HP-UX, $(TEC_UNAME)), ) + NO_DYNAMIC ?= Yes + MOTIF_INC := /usr/include/Motif2.1 + X11_LIBS := Xt Xext X11 + OPENGL_LIB := /opt/graphics/OpenGL/lib + OPENGL_INC := /opt/graphics/OpenGL/include + STDDEFS := -DTEC_UNAME=$(TEC_UNAME) -DTEC_SYSNAME=$(TEC_SYSNAME) -D$(TEC_BYTEORDER) -D$(TEC_WORDSIZE) -DFUNCPROTO=15 + CC := aCC + CPPC := aCC + LINKER := aCC +endif + +ifneq ($(findstring SunOS, $(TEC_UNAME)), ) + LD = ld + STDLDFLAGS := -G + X11_INC := /usr/openwin/share/include + X11_LIB := /usr/openwin/lib + MOTIF_INC := /usr/dt/share/include + MOTIF_LIB := /usr/dt/lib + OPENGL_INC := /usr/openwin/share/include/X11 + GLUT_LIB := /usr/local/glut-3.7/lib/glut + GLUT_INC := /usr/local/glut-3.7/include + ifdef BUILD_64 + ifdef USE_CC + STDFLAGS += -xarch=v9 -KPIC + # have to force these PATHs because of a conflict with standard PATHs + STDLDFLAGS += -64 -L/usr/lib/64 -L/usr/ucblib/sparcv9 + LINKER += -xarch=v9 + endif + endif +endif + +ifneq ($(findstring Darwin, $(TEC_UNAME)), ) + X11_LIBS := Xmu Xp Xt Xext X11 + X11_LIB := /usr/X11R6/lib + X11_INC := /usr/X11R6/include + MOTIF_INC := /usr/OpenMotif/include + MOTIF_LIB := /usr/OpenMotif/lib + ifdef BUILD_DYLIB + STDLDFLAGS := -dynamiclib -install_name lib$(TARGETNAME).dylib + DLIBEXT := dylib + else + STDLDFLAGS := -bundle -undefined dynamic_lookup + endif +endif + +ifneq ($(findstring FreeBSD, $(TEC_UNAME)), ) + X11_LIB := /usr/X11R6/lib + X11_INC := /usr/X11R6/include +endif + + +################################ +# Allows an extra configuration file. +ifdef EXTRA_CONFIG +include $(EXTRA_CONFIG) +endif +################################ + + +#---------------------------------# +# Tecgraf Libraries Location +TECTOOLS_HOME ?= ../.. + +IUP ?= $(TECTOOLS_HOME)/iup +CD ?= $(TECTOOLS_HOME)/cd +IM ?= $(TECTOOLS_HOME)/im +LUA ?= $(TECTOOLS_HOME)/lua +LUA51 ?= $(TECTOOLS_HOME)/lua5.1 + + +#---------------------------------# +# Pre-defined libraries + +# Library order: +# user + iupcd + cd + iup + motif + X +# Library path order is the oposite + +ifdef USE_LUA + LUASUFX := + LIBLUASUFX := 3 +endif + +ifdef USE_LUA4 + LUASUFX := 4 + LIBLUASUFX := 4 + override USE_LUA = Yes + LUA := $(LUA4) +endif + +ifdef USE_LUA5 + LUASUFX := 5 + LIBLUASUFX := 5 + override USE_LUA = Yes + LUA := $(LUA5) +endif + +ifdef USE_LUA50 + LUASUFX := 50 + LIBLUASUFX := 5 + override USE_LUA = Yes + LUA := $(LUA50) + NO_LUALIB := Yes +endif + +ifdef USE_LUA51 + LUASUFX := 5.1 + LIBLUASUFX := 51 + override USE_LUA = Yes + LUA := $(LUA51) + NO_LUALIB := Yes +endif + +ifdef USE_IUP3 + override USE_IUP = Yes +endif + +ifdef USE_IUP3BETA + IUP := $(IUP)3 +endif + +ifdef USE_IUPBETA + IUP := $(IUP)/beta +endif + +ifdef USE_CDBETA + CD := $(CD)/beta +endif + +ifdef USE_IMBETA + IM := $(IM)/beta +endif + +ifdef USE_GLUT + override USE_OPENGL = Yes +endif + +ifdef USE_IUPCONTROLS + override USE_CD = Yes + override USE_IUP = Yes + ifdef USE_IUPLUA + ifdef USE_STATIC + SLIB += $(IUP)/lib/$(TEC_UNAME)/libiupluacontrols$(LIBLUASUFX).a + else + LIBS += iupluacontrols$(LIBLUASUFX) + endif + override USE_CDLUA = Yes + endif + ifdef USE_STATIC + SLIB += $(IUP)/lib/$(TEC_UNAME)/libiupcontrols.a + else + LIBS += iupcontrols + endif +endif + +ifdef USE_IMLUA + override USE_IM = Yes + ifdef USE_STATIC + SLIB += $(IM)/lib/$(TEC_UNAME)/libimlua$(LIBLUASUFX).a + else + LIBS += imlua$(LIBLUASUFX) + endif +endif + +ifdef USE_CDLUA + override USE_CD = Yes + ifdef USE_STATIC + ifdef USE_IUP + ifdef USE_OLDNAMES + SLIB += $(CD)/lib/$(TEC_UNAME)/libcdluaiup$(LIBLUASUFX).a + endif + endif + SLIB += $(CD)/lib/$(TEC_UNAME)/libcdlua$(LIBLUASUFX).a + else + ifdef USE_IUP + ifdef USE_OLDNAMES + LIBS += cdluaiup$(LIBLUASUFX) + endif + endif + LIBS += cdlua$(LIBLUASUFX) + endif +endif + +ifdef USE_IUPLUA + override USE_IUP = Yes + ifdef USE_STATIC + ifdef USE_CD + ifndef USE_OLDNAMES + SLIB += $(IUP)/lib/$(TEC_UNAME)/libiupluacd$(LIBLUASUFX).a + endif + endif + ifdef USE_OPENGL + SLIB += $(IUP)/lib/$(TEC_UNAME)/libiupluagl$(LIBLUASUFX).a + endif + SLIB += $(IUP)/lib/$(TEC_UNAME)/libiuplua$(LIBLUASUFX).a + else + ifdef USE_CD + ifndef USE_OLDNAMES + LIBS += iupluacd$(LIBLUASUFX) + endif + endif + ifdef USE_OPENGL + LIBS += iupluagl$(LIBLUASUFX) + endif + LIBS += iuplua$(LIBLUASUFX) + endif +endif + +ifdef USE_LUA + LUA_LIB ?= $(LUA)/lib/$(TEC_UNAME) + ifdef USE_STATIC + ifndef NO_LUALIB + SLIB += $(LUA_LIB)/liblualib$(LUASUFX).a + endif + SLIB += $(LUA_LIB)/liblua$(LUASUFX).a + else + ifndef NO_LUALIB + LIBS += lualib$(LUASUFX) + endif + ifndef NO_LUALINK + LIBS += lua$(LUASUFX) + LDIR += $(LUA_LIB) + endif + endif + + LUA_INC ?= $(LUA)/include + INCLUDES += $(LUA_INC) + + LUA_BIN ?= $(LUA)/bin/$(TEC_UNAME) + BIN2C := $(LUA_BIN)/bin2c$(LUASUFX) + LUAC := $(LUA_BIN)/luac$(LUASUFX) + LUABIN := $(LUA_BIN)/lua$(LUASUFX) +endif + +ifdef USE_IUP + IUPSUFX := + ifdef USE_IUP3 + ifdef GTK_DEFAULT + ifdef USE_MOTIF + IUPSUFX := mot + else + override USE_GTK = Yes + endif + else + ifdef USE_GTK + IUPSUFX := gtk + else + override USE_MOTIF = Yes + endif + endif + else + override USE_MOTIF = Yes + endif + ifdef USE_STATIC + ifdef USE_CD + ifndef USE_OLDNAMES + SLIB += $(IUP)/lib/$(TEC_UNAME)/libiupcd.a + endif + endif + ifdef USE_OPENGL + SLIB += $(IUP)/lib/$(TEC_UNAME)/libiupgl.a + endif + SLIB += $(IUP)/lib/$(TEC_UNAME)/libiup$(IUPSUFX).a + else + ifdef USE_CD + ifndef USE_OLDNAMES + LIBS += iupcd + endif + endif + ifdef USE_OPENGL + LIBS += iupgl + endif + LIBS += iup$(IUPSUFX) + LDIR += $(IUP)/lib/$(TEC_UNAME) + endif + INCLUDES += $(IUP)/include +endif + +ifdef USE_CD + override USE_X11 = Yes + ifdef USE_STATIC + ifdef USE_IUP + ifdef USE_OLDNAMES + SLIB += $(CD)/lib/$(TEC_UNAME)/libcdiup.a + endif + endif + ifdef USE_XRENDER + ifdef USE_OLDNAMES + SLIB += $(CD)/lib/$(TEC_UNAME)/libcdxrender.a + else + SLIB += $(CD)/lib/$(TEC_UNAME)/libcdcontextplus.a + endif + endif + SLIB += $(CD)/lib/$(TEC_UNAME)/libcd.a + ifdef USE_XRENDER + LIBS += Xrender Xft + else + ifndef USE_GTK + ifndef USE_OLDNAMES + # Freetype is included in GTK + SLIB += $(CD)/lib/$(TEC_UNAME)/libfreetype.a + endif + endif + endif + else + ifdef USE_XRENDER + ifdef USE_OLDNAMES + LIBS += cdxrender + else + LIBS += cdcontextplus + endif + endif + LIBS += cd + LDIR += $(CD)/lib/$(TEC_UNAME) + ifdef USE_XRENDER + LIBS += Xrender Xft + else + ifndef USE_GTK + ifndef USE_OLDNAMES + # Freetype is included in GTK + LIBS += freetype + endif + endif + endif + endif + INCLUDES += $(CD)/include +endif + +ifdef USE_IM + ifdef USE_STATIC + SLIB += $(IM)/lib/$(TEC_UNAME)/libim.a + else + LIBS += im + LDIR += $(IM)/lib/$(TEC_UNAME) + endif + INCLUDES += $(IM)/include +endif + +# All except gcc in Windows (Cygwin) +ifeq ($(findstring gcc, $(TEC_UNAME)), ) + +ifdef USE_GLUT + LIBS += glut + LDIR += $(GLUT_LIB) + STDINCS += $(GLUT_INC) +endif + +ifdef USE_OPENGL + override USE_X11 = Yes + ifdef USE_MOTIF + LIBS += $(MOTIFGL_LIB) + endif + LIBS += $(OPENGL_LIBS) + LDIR += $(OPENGL_LIB) + STDINCS += $(OPENGL_INC) +endif + +ifdef USE_MOTIF + override USE_X11 = Yes + LIBS += Xm + LDIR += $(MOTIF_LIB) + STDINCS += $(MOTIF_INC) + ifneq ($(findstring Linux, $(TEC_UNAME)), ) + X11_LIBS := Xpm $(X11_LIBS) + endif + ifneq ($(findstring cygw, $(TEC_UNAME)), ) + X11_LIBS := Xpm $(X11_LIBS) + endif +endif + +ifdef USE_GTK +# ifneq ($(findstring Darwin, $(TEC_UNAME)), ) +# STDINCS += /Library/Frameworks/Gtk.framework/Headers +# STDINCS += /Library/Frameworks/GLib.framework/Headers +# STDINCS += /Library/Frameworks/Cairo.framework/Headers +# LFLAGS += -framework Gtk +# else + ifneq ($(findstring Darwin, $(TEC_UNAME)), ) + GTK_BASE := /sw + LDIR += /sw/lib + LIBS += freetype + else + GTK_BASE := /usr + endif + override USE_X11 = Yes + LIBS += gtk-x11-2.0 gdk-x11-2.0 gdk_pixbuf-2.0 pango-1.0 pangox-1.0 gobject-2.0 gmodule-2.0 glib-2.0 + STDINCS += $(GTK_BASE)/include/atk-1.0 $(GTK_BASE)/include/gtk-2.0 $(GTK_BASE)/include/cairo $(GTK_BASE)/include/pango-1.0 $(GTK_BASE)/include/glib-2.0 + ifeq ($(TEC_SYSARCH), x64) + STDINCS += $(GTK_BASE)/lib64/glib-2.0/include $(GTK_BASE)/lib64/gtk-2.0/include + else + ifeq ($(TEC_SYSARCH), ia64) + STDINCS += $(GTK_BASE)/lib64/glib-2.0/include $(GTK_BASE)/lib64/gtk-2.0/include + else + STDINCS += $(GTK_BASE)/lib/glib-2.0/include $(GTK_BASE)/lib/gtk-2.0/include + endif + endif + ifneq ($(findstring FreeBSD, $(TEC_UNAME)), ) + STDINCS += /lib/X11R6/include/gtk-2.0 + endif +# endif +endif + +ifdef USE_QT + override USE_X11 = Yes + LIBS += QtGui QtCore + QT_BASE_INC := /usr/include/qt4 + STDINCS += $(QT_BASE_INC) $(QT_BASE_INC)/QtCore $(QT_BASE_INC)/QtGui + STDDEFS += -DQT_DLL -DQT_QT3SUPPORT_LIB -DQT3_SUPPORT -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT +endif + +ifdef USE_X11 + LIBS += $(X11_LIBS) + LDIR += $(X11_LIB) + STDINCS += $(X11_INC) +endif + +LIBS += m + +else + # gcc in Windows + NO_DYNAMIC ?= Yes + STDDEFS += -DWIN32 + + ifdef USE_NOCYGWIN + STDFLAGS += -mno-cygwin + endif + + ifdef USE_GLUT + LIBS += glut32 + endif + + ifdef USE_OPENGL + LIBS += opengl32 glu32 glaux + endif + + LIBS += gdi32 winspool comdlg32 comctl32 ole32 + + ifdef USE_GTK + LIBS += gtk-win32-2.0 gdk-win32-2.0 gdk_pixbuf-2.0 pango-1.0 pangowin32-1.0 gobject-2.0 gmodule-2.0 glib-2.0 + #LDIR += $(GTK)/lib + GTK_INC = /usr + STDINCS += $(GTK_INC)/include/atk-1.0 $(GTK_INC)/include/gtk-2.0 $(GTK_INC)/include/cairo $(GTK_INC)/include/pango-1.0 $(GTK_INC)/include/glib-2.0 $(GTK_INC)/lib/glib-2.0/include $(GTK_INC)/lib/gtk-2.0/include + endif + + APPTYPE ?= windows + + ifeq ($(APPTYPE), windows) + LFLAGS += -mwindows + + ifdef USE_NOCYGWIN + LFLAGS += -mno-cygwin + endif + endif +endif + + +#---------------------------------# +# Building compilation flags that are sets + +INCLUDES := $(addprefix -I, $(INCLUDES)) +STDINCS := $(addprefix -I, $(STDINCS)) +EXTRAINCS := $(addprefix -I, $(EXTRAINCS)) +DEFINES := $(addprefix -D, $(DEFINES)) + +LIBS := $(addprefix -l, $(LIBS)) +ifdef LDIR + LDIR := $(addprefix -L, $(LDIR)) +endif + + +#---------------------------------# +# Definitions of private variables + +# Library flags for application and dynamic library linker +LFLAGS += $(LDIR) $(LIBS) +# C compiler flags +CFLAGS = $(FLAGS) $(STDFLAGS) $(INCLUDES) $(STDINCS) $(EXTRAINCS) $(DEFINES) $(STDDEFS) +# C++ compiler flags +CXXFLAGS = $(CPPFLAGS) $(STDFLAGS) $(INCLUDES) $(STDINCS) $(EXTRAINCS) $(DEFINES) $(STDDEFS) + +# Sources with relative path +SOURCES := $(addprefix $(SRCDIR)/, $(SRC)) + +# Target for applications or libraries +ifeq ($(MAKETYPE), APP) + TARGET := $(TARGETDIR)/$(TARGETNAME) +else + ifeq ($(NO_DYNAMIC), Yes) + TARGET := $(TARGETDIR)/lib$(TARGETNAME).a + else + TARGET := $(TARGETDIR)/lib$(TARGETNAME).a $(TARGETDIR)/lib$(TARGETNAME).$(DLIBEXT) + endif +endif + +# OBJ: list of .o, without path +# OBJS: list of .o with relative path +OBJ = $(notdir $(SRC)) +OBJ := $(OBJ:.c=.o) +OBJ := $(OBJ:.cpp=.o) +OBJ := $(OBJ:.cxx=.o) +OBJ := $(OBJ:.cc=.o) +OBJ := $(OBJ:.f=.o) +OBJ := $(OBJ:.for=.o) +OBJ := $(OBJ:.rc=.ro) +OBJS = $(addprefix $(OBJDIR)/, $(OBJ)) + +# LOH: list of .loh, without path +# LOHS: list of .loh, with relative path +LO = $(notdir $(SRCLUA)) +LO := $(LO:.lua=$(LO_SUFFIX).lo) +LOS = $(addprefix $(OBJROOT)/, $(LO)) + +LOH = $(notdir $(SRCLUA)) +LOH := $(LOH:.lua=$(LO_SUFFIX).loh) +LOHS = $(addprefix $(LOHDIR)/, $(LOH)) + +# Construct VPATH variable +P-SRC = $(dir $(SRC)) +P-SRC += $(dir $(SRCLUA)) +VPATH = .:$(foreach dir,$(P-SRC),$(if $(dir)="./",:$(dir))) + + +#---------------------------------# +# Main Rule - Build Everything that it is necessary + +.PHONY: tecmake +ifeq ($(MAKETYPE), APP) + tecmake: print-start directories application scripts +else + ifeq ($(NO_DYNAMIC), Yes) + tecmake: print-start directories static-lib + else + tecmake: print-start directories static-lib dynamic-lib + endif +endif + +.PHONY: print-start +print-start: + @echo ''; echo 'Tecmake - Starting [ $(TARGETNAME):$(TEC_UNAME) ]' + + +#---------------------------------# +# Dynamic Library Build + +.PHONY: dynamic-lib +dynamic-lib: $(TARGETDIR)/lib$(TARGETNAME).$(DLIBEXT) + +$(TARGETDIR)/lib$(TARGETNAME).$(DLIBEXT) : $(LOHS) $(OBJS) $(EXTRADEPS) + $(LD) $(STDLDFLAGS) -o $@ $(OBJS) $(SLIB) $(LFLAGS) + @echo 'Tecmake - Dynamic Library ($@) Done.'; echo '' + + +#---------------------------------# +# Static Library Build + +.PHONY: static-lib +static-lib: $(TARGETDIR)/lib$(TARGETNAME).a + +$(TARGETDIR)/lib$(TARGETNAME).a : $(LOHS) $(OBJS) $(EXTRADEPS) + $(AR) $(STDLFLAGS) $@ $(OBJS) $(SLIB) $(LCFLAGS) + -$(RANLIB) $@ + @echo 'Tecmake - Static Library ($@) Done.'; echo '' + + +#---------------------------------# +# Application Build + +.PHONY: application +application: $(TARGETDIR)/$(TARGETNAME) + +$(TARGETDIR)/$(TARGETNAME) : $(LOHS) $(OBJS) $(EXTRADEPS) + $(LINKER) -o $@ $(OBJS) $(SLIB) $(LFLAGS) + @if [ ! -z "$(STRIP)" ]; then \ + echo "Striping debug information" ;\ + strip $@ ;\ + fi + @echo 'Tecmake - Application ($@) Done.'; echo '' + + +#---------------------------------# +# Application Scripts + +# Script name +SRELEASE := $(SRCDIR)/$(TARGETNAME) + +.PHONY: scripts +ifdef NO_SCRIPTS + scripts: ; +else + scripts: $(SRELEASE) ; +endif + +$(SRELEASE): $(MAKENAME) + @echo 'Building script $(@F)' + @echo "#!/bin/csh" > $@ + @echo "# Script generated automatically by tecmake v$(VERSION)" >> $@ + @echo "# Remove the comment bellow to set the LD_LIBRARY_PATH if needed." >> $@ + @echo '#setenv LD_LIBRARY_PATH $(MYLIB1)/lib/$${TEC_UNAME}:$(MYLIB2)/lib/$${TEC_UNAME}:$$LD_LIBRARY_PATH' >> $@ + @echo 'if ( -r app.env ) source app.env' >> $@ + @echo 'exec $(TARGETROOT)/$$TEC_UNAME/$(TARGETNAME) $$*' >> $@ + @chmod a+x $@ + + +#---------------------------------# +# Directories Creation + +.PHONY: directories +directories: $(OBJDIR) $(TARGETDIR) $(EXTRADIR) $(LOHDIR) + +$(OBJDIR) $(TARGETDIR): + if [ ! -d $@ ] ; then mkdir -p $@ ; fi + +ifdef EXTRADIR + $(EXTRADIR): + if [ ! -d $@ ] ; then mkdir -p $@ ; fi +else + $(EXTRADIR): ; +endif + +ifdef LOHDIR + $(LOHDIR): + if [ ! -d $@ ] ; then mkdir -p $@ ; fi +else + $(LOHDIR): ; +endif + + +#---------------------------------# +# Compilation Rules + +$(OBJDIR)/%.o: $(SRCDIR)/%.c + @echo Compiling $( $@ + +$(OBJROOT)/%$(LO_SUFFIX).lo: $(SRCLUADIR)/%.lua + @echo Compiling $( $(DEPEND) + @which $(CPPC) 2> /dev/null 1>&2 ;\ + if [ $$? -eq 0 ]; then \ + echo "Building dependencies... (can be slow)" ;\ + $(CPPC) $(INCLUDES) $(DEFINES) $(STDDEFS) -MM $(SOURCES) | \ + sed -e '1,$$s/^\([^ ]\)/$$(OBJDIR)\/\1/' > $(DEPEND) ;\ + else \ + echo "" ;\ + echo "$(CPPC) not found. Dependencies can not be built." ;\ + echo "Must set USE_NODEPEND=Yes." ;\ + echo "" ;\ + exit 1 ;\ + fi + endif + +################### +ifndef USE_NODEPEND +include $(DEPEND) +endif +################### + + +#---------------------------------# +# Management Rules + +# make clean-extra +# Remove extra files +.PHONY: clean-extra +clean-extra: + rm -f $(DEPEND) $(SRELEASE) so_locations + +# make clean-lohs +# Remove Lua object inclusion files +.PHONY: clean-lohs +clean-lohs: + rm -f $(LOS) $(LOHS) + +# make clean-obj +# Remove object files +.PHONY: clean-obj +clean-obj: + rm -f $(OBJS) + +# make clean-target +# Remove target +.PHONY: clean-target +clean-target: + rm -f $(TARGET) + +# make clean +# Remove target and object files +.PHONY: clean +clean: clean-target clean-obj + +# make rebuild +# Remove symbols from executables +.PHONY: strip +strip: + test -r $(TARGETDIR)/$(TARGETNAME) && strip $(TARGETDIR)/$(TARGETNAME) + +# make rebuild +# Rebuild target and object files +.PHONY: rebuild +rebuild: clean-extra clean-lohs clean-obj clean-target tecmake + +# make relink +# Rebuild target without rebuilding object files +.PHONY: relink +relink: clean-target tecmake + +.PHONY: version +version: + @echo "Tecmake Compact Version $(VERSION)" + +#---------------------------------# diff --git a/im/test/glut_capture.c b/im/test/glut_capture.c new file mode 100644 index 0000000..80aadd2 --- /dev/null +++ b/im/test/glut_capture.c @@ -0,0 +1,415 @@ +/* GLUT Capture Sample + + Uses GLUT for user interface + OpenGL for drawing + IM for image I/O and capture + + Needs "opengl32.lib", "glu32.lib", "glut32.lib", "vfw32.lib", "strmiids.lib", + "im.lib", "im_capture.lib", "im_avi.lib" and "im_process.lib". + + Control Keys: + + - Terminates + - Activates/Deactivates the capturing. + , , , etc - Shows capture configuration dialogs, in general 2, but can have more. + - Starts to save every frame in an AVI file. + - Process a background image using an average of N frames. + - Saves the background image in a BMP file. + <1>, <2>, etc - Activates an processing operation. + Only operation 1 is working, it subtracts the background image if one was created. + <0> - Deactivates all the processing operations. + + ATENTION: These keys works at the GLUT window. + But the text input in done at the console window. + Check the correct window focus before typing keys. +*/ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +/* Global Variables */ +imVideoCapture* myVideoCap; /* capture control */ +imImage* image = NULL; /* capture buffer */ +unsigned char* gl_data = NULL; /* opengl display buffer */ + +char video_filename[512] = ""; +imFile* video_file = NULL; + +imImage* back_image = NULL; /* background image */ +imImage* back_acum = NULL; /* aux image for background image calculation */ +int back_count = 0; /* number of images to average */ +int back_index = 0; /* average image counter */ + +int user_key[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; + +static void SimpleBackSub(imbyte *map, imbyte *back_map, int count, float tol) +{ + int i; + for (i = 0; i < count; i++) + { + int diff = map[i] - back_map[i]; + if (diff < 0) diff = -diff; + + if(diff <= tol) + map[i] = 0; + } +} + +static float tol = 10; /* you should use some key to change this */ + +void capture_process(int* user_key, imImage* image, imImage* back_image) +{ + if (user_key[0] && back_image) /* '1' */ + { + int i; + for (i = 0; i < image->depth; i++) /* notice that here depth is always 3 */ + { + SimpleBackSub((imbyte*)image->data[i], (imbyte*)back_image->data[i], image->count, tol); + } + } + + /***** call other operations here ******/ +} + + +/* Aux to draw a number in the display */ +void display_number(int num) +{ + int i; + char msg[30]; + sprintf(msg,"%4d", num); + glColor3f(1.0f,0.0f,0.0f); + glRasterPos2f(10.f,10.f); + for(i = 0; msg[i]; i++) + glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, msg[i]); +} + +/* GLUT display callback */ +/* called everytime the window needs to be updated */ +void display(void) +{ + if (!image) + return; + + /* Draws the captured image at (0,0) */ + glRasterPos2f(0.f, 0.f); + glDrawPixels(image->width, image->height, GL_RGB, GL_UNSIGNED_BYTE, gl_data); + + glutSwapBuffers(); +} + + +/* GLUT reshape callback */ +/* called everytime the window changes its size */ +void reshape(int w, int h) +{ + glViewport(0, 0, w, h); +} + + +/* GLUT idle callback */ +/* called when there is no events to be processed */ +void idle(void) +{ + if (imVideoCaptureLive(myVideoCap, -1)) + { + imVideoCaptureFrame(myVideoCap, image->data[0], IM_RGB, 1000); + + if (back_image && back_index < back_count) + { + /* calculating the background image */ + + imProcessUnArithmeticOp(image, back_acum, IM_UN_INC); /* back_image += image */ + back_index++; + + if (back_index == back_count) /* last sum, divide by N */ + { + imProcessArithmeticConstOp(back_acum, (float)back_count, back_image, IM_BIN_DIV); + printf("Background image updated.\n"); + } + } + else + { + /* call some processing */ + capture_process(user_key, image, back_image); + + if (video_file) + { + imFileWriteImageInfo(video_file, image->width, image->height, IM_RGB, IM_BYTE); + imFileWriteImageData(video_file, image->data[0]); + } + } + + imConvertPacking(image->data[0], gl_data, image->width, image->height, image->depth, image->data_type, 0); + display(); + } +} + + +/* OpenGL initialization */ +void glinit(void) +{ + if (!image) + return; + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluOrtho2D (0.0, (GLdouble)image->width, 0.0, (GLdouble)image->height); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); +} + + +/* updates the capture image size and display buffer size */ +void updatebuffer(void) +{ + int width, height; + + /* retrieve the image size */ + imVideoCaptureGetImageSize(myVideoCap, &width, &height); + + if (width != image->width || height != image->height) + { + /* fix the buffer size */ + imImageReshape(image, width, height); + gl_data = realloc(gl_data, image->size); + + /* fix the window size */ + glutReshapeWindow(image->width, image->height); + + /* re-inititalizes the OpenGL */ + glinit(); + } +} + + +/* GLUT function key callback */ +/* called everytime a function key is pressed */ +void parsefunckey(int key, int x, int y) +{ + switch (key) { + case GLUT_KEY_F1: /* F1, F2, F.. = shows the capture configuration dialogs */ + case GLUT_KEY_F2: + case GLUT_KEY_F3: + case GLUT_KEY_F4: + case GLUT_KEY_F5: + case GLUT_KEY_F6: + case GLUT_KEY_F7: + case GLUT_KEY_F8: + imVideoCaptureLive(myVideoCap, 0); /* deactivate the capture before calling the dialog */ + imVideoCaptureShowDialog(myVideoCap, key - GLUT_KEY_F1, NULL); + updatebuffer(); + imVideoCaptureLive(myVideoCap, 1); + break; + } +} + +/* GLUT key callback */ +/* called everytime an ASCII key is pressed */ +void parsekey(unsigned char key, int x, int y) +{ + int error, index; + switch (key) { + case 27: /* Esc = terminates */ + printf("\nTerminating...\n"); + imVideoCaptureDisconnect(myVideoCap); + imVideoCaptureDestroy(myVideoCap); + imImageDestroy(image); + if (video_file) + { + imFileClose(video_file); + printf("AVI file created.\n"); + } + free(gl_data); + exit(1); + case ' ': /* Space = activates/deactivates the capturing */ + if (imVideoCaptureLive(myVideoCap, -1)) + imVideoCaptureLive(myVideoCap, 0); + else + imVideoCaptureLive(myVideoCap, 1); + break; + case 'v': + if (video_file) + { + imFileClose(video_file); + printf("AVI file created.\n"); + video_file = NULL; + break; + } + printf("Enter the AVI file name:\n >"); + scanf("%s", video_filename); + video_file = imFileNew(video_filename, "AVI", &error); + if (!video_file) + printf("Error creating video file.\n"); + else + { + imFileSetInfo(video_file, "CUSTOM"); /* shows the compression options dialog */ + imFileWriteImageInfo(video_file, image->width, image->height, IM_RGB, IM_BYTE); + } + break; + case 'b': + if (back_image) + { + imImageDestroy(back_image); + imImageDestroy(back_acum); + } + printf("Enter the number of images to average:\n >"); + scanf("%d", &back_count); + back_acum = imImageCreate(image->width, image->height, IM_RGB, IM_USHORT); + back_image = imImageClone(image); + back_index = 0; + break; + case 's': + if (back_image) + { + char filename[512]; + imFile* ifile; + printf("Enter the BMP file name:\n >"); + scanf("%s", filename); + ifile = imFileNew(filename, "BMP", &error); + if (!ifile) { + printf("Error creating image file.\n"); return; + } + imFileSaveImage(ifile, back_image); + imFileClose(ifile); + printf("BMP file created.\n"); + } + break; + case '0': + memset(user_key, 0, 9*sizeof(int)); + break; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + index = key - '1'; + user_key[index] = user_key[index]? 0: 1; /* switch state */ + if (user_key[index]) + printf("Processing %c activated. \n", key); + else + printf("Processing %c deactivated. \n", key); + return; + default: + glutPostRedisplay(); + return; + } +} + + +/* Returns a capture device */ +int getcapture(void) +{ + int i; + int cap_count = imVideoCaptureDeviceCount(); + if (cap_count == 1) /* only one device */ + return 0; + + printf("Enter the capture device number to use:\n"); + for (i = 0; i < cap_count; i++) + { + printf(" %s\n", imVideoCaptureDeviceDesc(i)); + } + + printf(" > "); + scanf("%d", &i); + if (i < 0 || i >= cap_count) + return 0; + + return i; +} + + +/* Initializes the capture device */ +int initcapture(void) +{ + int width, height; + + /* creates an IM video capture manager */ + myVideoCap = imVideoCaptureCreate(); + if (!myVideoCap) { + printf("No capture device found.\n"); return 0; + } + + /* connects the device */ + if (!imVideoCaptureConnect(myVideoCap, getcapture())) { + imVideoCaptureDestroy(myVideoCap); + printf("Can not connect to capture device.\n"); return 0; + } + + if (!imVideoCaptureLive(myVideoCap, 1)) { + imVideoCaptureDisconnect(myVideoCap); + imVideoCaptureDestroy(myVideoCap); + printf("Can not activate capturing.\n"); return 0; + } + + /* retrieve the image size */ + imVideoCaptureGetImageSize(myVideoCap, &width, &height); + + /* alocates the buffers */ + image = imImageCreate(width, height, IM_RGB, IM_BYTE); + gl_data = malloc(image->size); + + return 1; +} + + +int main(int argc, char* argv[]) +{ + printf("GLUT Capture\n"); + printf(" - Terminates.\n" + " - Activates/Deactivates the capturing.\n" + " , , , ... - Shows capture configuration dialogs.\n" + " - Starts to save every frame in an AVI file.\n" + " - Process a background image using an average of N frames.\n" + " - Saves the background image in a BMP file.\n" + " <1>, <2>, ... - Activates an processing operation.\n" + " <0> - Deactivates all the processing operations.\n\n"); + + /* Initializes the capture device */ + if (!initcapture()) + return 1; + + imFormatRegisterAVI(); + + /* GLUT initialization */ + glutInit(&argc, argv); + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); + glutInitWindowPosition(100, 100); + glutInitWindowSize(image->width, image->height); + glutCreateWindow("GLUT Capture"); + + glClearColor(0., 0., 0., 1.0); /* window background */ + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); /* data alignment is 1 */ + + /* register GLUT callbacks */ + glutDisplayFunc(display); + glutReshapeFunc(reshape); + glutKeyboardFunc(parsekey); + glutSpecialFunc(parsefunckey); + glutIdleFunc(idle); + + /* OpenGL initialization */ + glinit(); + + /* GLUT message loop */ + glutMainLoop(); + + return 0; +} diff --git a/im/test/im_copy.cpp b/im/test/im_copy.cpp new file mode 100755 index 0000000..5b4c8cd --- /dev/null +++ b/im/test/im_copy.cpp @@ -0,0 +1,145 @@ +/* IM 3 sample that copies an image from one file to another. + It is good to test the file formats read and write. + If the destiny does not supports the input image it aborts and returns an error. + + Needs "im.lib". + + Usage: im_copy [ [ +#include +#include +#include + +#include +#include + + +void PrintError(int error) +{ + switch (error) + { + case IM_ERR_OPEN: + printf("Error Opening File.\n"); + break; + case IM_ERR_MEM: + printf("Insuficient memory.\n"); + break; + case IM_ERR_ACCESS: + printf("Error Accessing File.\n"); + break; + case IM_ERR_DATA: + printf("Image type not Suported.\n"); + break; + case IM_ERR_FORMAT: + printf("Invalid Format.\n"); + break; + case IM_ERR_COMPRESS: + printf("Invalid or unsupported compression.\n"); + break; + default: + printf("Unknown Error.\n"); + } +} + +int main(int argc, char* argv[]) +{ + if (argc < 3) + { + printf("Invalid number of arguments.\n"); + return 0; + } + +// imFormatRegisterAVI(); +// imFormatRegisterWMV(); + + void* data = NULL; + imFile* ifile = NULL; + imFile* ofile = NULL; + + int error; + ifile = imFileOpen(argv[1], &error); + if (!ifile) + goto man_error; + + char format[10]; + char compression[20]; + int image_count; + imFileGetInfo(ifile, format, compression, &image_count); + + ofile = imFileNew(argv[2], (argc < 3)? format: argv[3], &error); + if (!ofile) + goto man_error; + + if (argc < 4) + imFileSetInfo(ofile, compression); + else + imFileSetInfo(ofile, argv[4]); + + for (int i = 0; i < image_count; i++) + { + int size, max_size = 0; + int width, height, color_mode, data_type; + error = imFileReadImageInfo(ifile, i, &width, &height, &color_mode, &data_type); + if (error != IM_ERR_NONE) + goto man_error; + + size = imImageDataSize(width, height, color_mode, data_type); + + if (size > max_size) + { + data = realloc(data, size); + max_size = size; + } + + error = imFileReadImageData(ifile, data, 0, -1); + if (error != IM_ERR_NONE) + goto man_error; + + char* attrib_list[50]; + int attrib_list_count; + imFileGetAttributeList(ifile, attrib_list, &attrib_list_count); + + for (int a = 0; a < attrib_list_count; a++) + { + int attrib_data_type, attrib_count; + const void* attrib_data = imFileGetAttribute(ifile, attrib_list[a], &attrib_data_type, &attrib_count); + imFileSetAttribute(ofile, attrib_list[a], attrib_data_type, attrib_count, attrib_data); + } + + if (imColorModeSpace(color_mode) == IM_MAP) + { + long palette[256]; + int palette_count; + imFileGetPalette(ifile, palette, &palette_count); + imFileSetPalette(ifile, palette, palette_count); + } + + error = imFileWriteImageInfo(ofile, width, height, color_mode, data_type); + if (error != IM_ERR_NONE) + goto man_error; + + error = imFileWriteImageData(ofile, data); + if (error != IM_ERR_NONE) + goto man_error; + + printf("."); + } + printf("done"); + + free(data); + imFileClose(ifile); + imFileClose(ofile); + + return 1; + +man_error: + PrintError(error); + if (data) free(data); + if (ifile) imFileClose(ifile); + if (ofile) imFileClose(ofile); + return 0; +} diff --git a/im/test/im_info.cpp b/im/test/im_info.cpp new file mode 100644 index 0000000..89ec8c4 --- /dev/null +++ b/im/test/im_info.cpp @@ -0,0 +1,211 @@ +/* IM 3 sample that returns information about a file. + + Needs "im.lib". + + Usage: im_info + + Example: im_info test.tif +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +void PrintError(int error) +{ + switch (error) + { + case IM_ERR_OPEN: + printf("Error Opening File.\n"); + break; + case IM_ERR_MEM: + printf("Insuficient memory.\n"); + break; + case IM_ERR_ACCESS: + printf("Error Accessing File.\n"); + break; + case IM_ERR_DATA: + printf("Image type not Suported.\n"); + break; + case IM_ERR_FORMAT: + printf("Invalid Format.\n"); + break; + case IM_ERR_COMPRESS: + printf("Invalid or unsupported compression.\n"); + break; + default: + printf("Unknown Error.\n"); + } +} + +int FindZero(imbyte* data, int count) +{ + for (int i = 0; i < count; i++) + { + if (data[i] == 0) + return 1; + } + return 0; +} + +char* AttribData2Str(const void* data, int data_type) +{ + static char data_str[50] = ""; + + switch(data_type) + { + case IM_BYTE: + sprintf(data_str, "%3d", (int)(*((imbyte*)data))); + break; + case IM_USHORT: + sprintf(data_str, "%5d", (int)(*((imushort*)data))); + break; + case IM_INT: + sprintf(data_str, "%5d", *((int*)data)); + break; + case IM_FLOAT: + sprintf(data_str, "%5.2f", (double)(*((float*)data))); + break; + case IM_CFLOAT: + { + float *c = (float*)data; + sprintf(data_str, "%5.2g, %5.2f", (double)*c, (double)*(c+1)); + } + break; + } + + return data_str; +} + +char* GetSizeDesc(double *size) +{ + char* size_desc; + + if (*size < 1024) + size_desc = "b"; + else + { + *size /= 1024; + + if (*size < 1024) + size_desc = "Kb"; + else + { + *size /= 1024; + size_desc = "Mb"; + } + } + + return size_desc; +} + +unsigned long FileSize(const char* file_name) +{ + imBinFile* bfile = imBinFileOpen(file_name); + if (!bfile) return 0; + + unsigned long file_size = imBinFileSize(bfile); + + imBinFileClose(bfile); + return file_size; +} + +void PrintImageInfo(const char* file_name) +{ + printf("IM Info\n"); + printf(" File Name:\n %s\n", file_name); + + int error; + imFile* ifile = imFileOpen(file_name, &error); + if (!ifile) + { + PrintError(error); + return; + } + + double file_size = FileSize(file_name); + printf(" File Size: %.2f %s\n", file_size, GetSizeDesc(&file_size)); + + char format[10]; + char compression[20]; + int image_count; + imFileGetInfo(ifile, format, compression, &image_count); + + char format_desc[50]; + imFormatInfo(format, format_desc, NULL, NULL); + printf(" Format: %s - %s\n", format, format_desc); + printf(" Compression: %s\n", compression); + printf(" Image Count: %d\n", image_count); + + for (int i = 0; i < image_count; i++) + { + int width, height, color_mode, data_type; + + error = imFileReadImageInfo(ifile, i, &width, &height, &color_mode, &data_type); + if (error != IM_ERR_NONE) + { + PrintError(error); + imFileClose(ifile); + return; + } + + printf(" Image #%d\n", i); + printf(" Width: %d\n", width); + printf(" Height: %d\n", height); + printf(" Color Space: %s\n", imColorModeSpaceName(color_mode)); + printf(" Has Alpha: %s\n", imColorModeHasAlpha(color_mode)? "Yes": "No"); + printf(" Is Packed: %s\n", imColorModeIsPacked(color_mode)? "Yes": "No"); + printf(" Is Top Down: %s\n", imColorModeIsTopDown(color_mode)? "Yes": "No"); + printf(" Data Type: %s\n", imDataTypeName(data_type)); + + double image_size = imImageDataSize(width, height, color_mode, data_type); + printf(" Data Size: %.2f %s\n", image_size, GetSizeDesc(&image_size)); + + char* attrib_list[50]; // should be dynamic allocated + int attrib_list_count; + imFileGetAttributeList(ifile, attrib_list, &attrib_list_count); + + for (int a = 0; a < attrib_list_count; a++) + { + if (a == 0) + printf(" Attributes:\n"); + + int attrib_data_type, attrib_count; + const void* attrib_data = imFileGetAttribute(ifile, attrib_list[a], &attrib_data_type, &attrib_count); + + if (attrib_count == 1) + printf(" %s: %s\n", attrib_list[a], AttribData2Str(attrib_data, attrib_data_type)); + else if (attrib_data_type == IM_BYTE && FindZero((imbyte*)attrib_data, attrib_count)) + printf(" %s: %s\n", attrib_list[a], attrib_data); + else + printf(" %s: %s %s ...\n", attrib_list[a], AttribData2Str(attrib_data, attrib_data_type), AttribData2Str((imbyte*)attrib_data + imDataTypeSize(attrib_data_type), attrib_data_type)); + } + } + + imFileClose(ifile); +} + +int main(int argc, char* argv[]) +{ +// imFormatRegisterJP2(); +// imFormatRegisterAVI(); +// imFormatRegisterWMV(); + + if (argc < 2) + { + printf("Invalid number of arguments.\n"); + return 0; + } + + PrintImageInfo(argv[1]); + + return 1; +} + diff --git a/im/test/im_info.mak b/im/test/im_info.mak new file mode 100755 index 0000000..211e7af --- /dev/null +++ b/im/test/im_info.mak @@ -0,0 +1,11 @@ +APPNAME = im_info +APPTYPE = CONSOLE +LINKER = g++ + +SRC = im_info.cpp + +USE_IM = Yes + +IM = .. + +USE_STATIC = Yes diff --git a/im/test/im_view.c b/im/test/im_view.c new file mode 100644 index 0000000..e271394 --- /dev/null +++ b/im/test/im_view.c @@ -0,0 +1,182 @@ +/* IM 3 sample that shows an image. + + Needs "im.lib", "iup.lib", "cd.lib" and "cdiup.lib". + + Usage: im_view + + Example: im_view test.tif + + + Click on image to open another file. +*/ + +#include +#include +#include +#include +#include + +#include +#include + + +static int disable_repaint = 0; /* used to optimize repaint, while opening a new file */ + +static void PrintError(int error) +{ + switch (error) + { + case IM_ERR_OPEN: + IupMessage("IM", "Error Opening File."); + break; + case IM_ERR_MEM: + IupMessage("IM", "Insuficient memory."); + break; + case IM_ERR_ACCESS: + IupMessage("IM", "Error Accessing File."); + break; + case IM_ERR_DATA: + IupMessage("IM", "Image type not Suported."); + break; + case IM_ERR_FORMAT: + IupMessage("IM", "Invalid Format."); + break; + case IM_ERR_COMPRESS: + IupMessage("IM", "Invalid or unsupported compression."); + break; + default: + IupMessage("IM", "Unknown Error."); + } +} + +static int cbRepaint(Ihandle* iup_canvas) +{ + cdCanvas* cd_canvas = (cdCanvas*)IupGetAttribute(iup_canvas, "cdCanvas"); + imImage* image = (imImage*)IupGetAttribute(iup_canvas, "imImage"); + + if (!cd_canvas || disable_repaint) + return IUP_DEFAULT; + + cdCanvasActivate(cd_canvas); + cdCanvasClear(cd_canvas); + + if (!image) + return IUP_DEFAULT; + + imcdCanvasPutImage(cd_canvas, image, 0, 0, image->width, image->height, 0, 0, 0, 0); + + cdCanvasFlush(cd_canvas); + + return IUP_DEFAULT; +} + +static void ShowImage(char* file_name, Ihandle* iup_dialog) +{ + int error; + imImage* image = (imImage*)IupGetAttribute(iup_dialog, "imImage"); + if (image) imImageDestroy(image); + IupSetAttribute(iup_dialog, "imImage", NULL); + + image = imFileImageLoadBitmap(file_name, 0, &error); + if (error) PrintError(error); + if (!image) return; + + IupSetAttribute(iup_dialog, "imImage", (char*)image); + IupStoreAttribute(iup_dialog, "TITLE", file_name); + + cbRepaint(iup_dialog); /* we can do this because canvas inherit attributes from the dialog */ +} + +static int cbButton(Ihandle* iup_canvas, int but, int pressed) +{ + char file_name[200] = "*.*"; + + if (but != IUP_BUTTON1 || !pressed) + return IUP_DEFAULT; + + disable_repaint = 1; + if (IupGetFile(file_name) != 0) + { + disable_repaint = 0; + return IUP_DEFAULT; + } + + disable_repaint = 0; + ShowImage(file_name, IupGetDialog(iup_canvas)); + + return IUP_DEFAULT; +} + +static int cbClose(Ihandle* iup_dialog) +{ + cdCanvas* cd_canvas = (cdCanvas*)IupGetAttribute(iup_dialog, "cdCanvas"); + imImage* image = (imImage*)IupGetAttribute(iup_dialog, "imImage"); + + if (cd_canvas) cdKillCanvas(cd_canvas); + if (image) imImageDestroy(image); + + IupSetAttribute(iup_dialog, "cdCanvas", NULL); + IupSetAttribute(iup_dialog, "imImage", NULL); + + return IUP_CLOSE; +} + +static Ihandle* CreateDialog(void) +{ + Ihandle *iup_dialog; + Ihandle *iup_canvas; + cdCanvas* cd_canvas; + + iup_canvas = IupCanvas("do_nothing"); + IupSetAttribute(iup_canvas, IUP_BUTTON_CB, "cbButton"); + IupSetAttribute(iup_canvas, IUP_ACTION, "cbRepaint"); + + iup_dialog = IupDialog(iup_canvas); + IupSetAttribute(iup_dialog, IUP_CLOSE_CB, "cbClose"); + IupSetAttribute(iup_dialog, IUP_SIZE, "HALFxHALF"); + + IupSetFunction("cbRepaint", (Icallback)cbRepaint); + IupSetFunction("cbButton", (Icallback)cbButton); + IupSetFunction("cbClose", (Icallback)cbClose); + + IupMap(iup_dialog); + + cd_canvas = cdCreateCanvas(CD_IUP, iup_canvas); + IupSetAttribute(iup_dialog, "cdCanvas", (char*)cd_canvas); + + return iup_dialog; +} + +//#include "im_format_avi.h" + +int main(int argc, char* argv[]) +{ + Ihandle* dlg; + + //imFormatRegisterAVI(); + IupOpen(&argc, &argv); + + dlg = CreateDialog(); + + IupShow(dlg); + + /* Try to get a file name from the command line. */ + if (argc > 1) + { + ShowImage(argv[1], dlg); + } + else + { + char file_name[1024] = "*.*"; + if (IupGetFile(file_name) == 0) + { + ShowImage(file_name, dlg); + } + } + + IupMainLoop(); + IupDestroy(dlg); + IupClose(); + + return 1; +} diff --git a/im/test/im_view.mak b/im/test/im_view.mak new file mode 100644 index 0000000..45e4363 --- /dev/null +++ b/im/test/im_view.mak @@ -0,0 +1,14 @@ +APPNAME = im_view + +LINKER = g++ + +SRC = im_view.c + +USE_CD = Yes +USE_IUPCONTROLS = Yes +USE_IUP3 = Yes +USE_IM = Yes + +IM = .. + +USE_STATIC = Yes diff --git a/im/test/iupglview.c b/im/test/iupglview.c new file mode 100644 index 0000000..93e0054 --- /dev/null +++ b/im/test/iupglview.c @@ -0,0 +1,237 @@ + +#ifdef WIN32 +#include /* necessary because of the Microsoft OpenGL headers dependency */ +#endif + +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +int app_repaint_cb(Ihandle* self) +{ + unsigned char* gl_data = (unsigned char*)IupGetAttribute(self, "APP_GL_DATA"); + int width = IupGetInt(self, "APP_GL_WIDTH"); + int height = IupGetInt(self, "APP_GL_HEIGHT"); + IupGLMakeCurrent(self); /* activates this GL Canvas as the current drawing area. */ + glClear(GL_COLOR_BUFFER_BIT); /* clears the back buffer */ + + if (gl_data) + { + /* Draws the captured image at (0,0) */ + glRasterPos2f(0.f, 0.f); + glDrawPixels(width, height, GL_RGB, GL_UNSIGNED_BYTE, gl_data); + } + + IupGLSwapBuffers(self); /* swap data from back buffer to front buffer */ + return IUP_DEFAULT; +} + +void appGLInit(int width, int height) +{ + glClearColor(0., 0., 0., 1.0); /* window background */ + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); /* data alignment is 1 */ + + glViewport(0, 0, width, height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluOrtho2D (0.0, (GLdouble)width, 0.0, (GLdouble)height); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); +} + +int app_resize_cb(Ihandle* self, int width, int height) +{ + IupGLMakeCurrent(self); + appGLInit(width, height); + return IUP_DEFAULT; +} + +/* OpenGL does not supports palette based images, so convert to RGB */ +/* this function can also be use for RGBA images */ +void ConvertMapToGLData(unsigned char* data, int count, int depth, long* palette, int palette_count) +{ + int c, i; + unsigned char r[256], g[256], b[256]; + + unsigned char* src_data = data + count-1; + unsigned char* dst_data = data + depth*(count-1); + + for (c = 0; c < palette_count; c++) + imColorDecode(&r[c], &g[c], &b[c], palette[c]); + + for (i = 0; i < count; i++) + { + int index = *src_data; + *dst_data = r[index]; + *(dst_data+1) = g[index]; + *(dst_data+2) = b[index]; + + dst_data -= depth; + src_data--; + } +} + +int app_open_cb(Ihandle* self) +{ + imFile* ifile; /* file input */ + int ret, error; + unsigned char* gl_data = (unsigned char*)IupGetAttribute(self, "APP_GL_DATA"); + char filename[1024] = ".\\*.*"; + + /* get a file name */ + ret = IupGetFile(filename); + if (ret == -1) + return IUP_DEFAULT; + + ifile = imFileOpen(filename, &error); + if (!ifile) + { + IupMessage("Error", "Error reading image file."); + return IUP_DEFAULT; + } + + { + int width = 0, height = 0, file_color_mode, color_space; + Ihandle* dialog = IupGetDialog(self); + imFileReadImageInfo(ifile, 0, &width, &height, &file_color_mode, NULL); + + /* alocates the buffers */ + if (gl_data) free(gl_data); + gl_data = malloc(width*height*3); + IupSetAttribute(dialog, "APP_GL_DATA", gl_data); + IupSetfAttribute(dialog, "APP_GL_WIDTH", "%d", width); + IupSetfAttribute(dialog, "APP_GL_HEIGHT", "%d", height); + + imFileReadImageData(ifile, gl_data, 1, IM_PACKED); + + color_space = imColorModeSpace(file_color_mode); + if (color_space == IM_MAP || color_space == IM_GRAY || color_space == IM_BINARY) + { + long palette[256]; + int palette_count; + imFileGetPalette(ifile, palette, &palette_count); + ConvertMapToGLData(gl_data, width*height, 3, palette, palette_count); + } + } + + imFileClose(ifile); + + return IUP_DEFAULT; +} + +int app_exit_cb(Ihandle *self) +{ + unsigned char* gl_data = (unsigned char*)IupGetAttribute(self, "APP_GL_DATA"); + + /* destroy buffers */ + if (gl_data) + free(gl_data); + + return IUP_CLOSE; +} + +int app_about_cb(Ihandle *self) +{ + IupMessagef("About", "IUPGLView 1.0\n" + "Tecgraf/PUC-Rio\n" + " ---------------- \n" + "IUP Version %s\n" + "IM Version %s\n" + " ---------------- \n" + "OpenGL:\n" + " Vendor: %s\n" + " Renderer: %s\n" + " Version: %s\n" + , IUP_RELEASE_VERSION, IM_VERSION, + glGetString(GL_VENDOR),glGetString(GL_RENDERER),glGetString(GL_VERSION)); + return IUP_DEFAULT; +} + +void mainMenuCreate(void) +{ + Ihandle* file_menu = IupMenu( + IupItem( "Open...", "app_open_cb"), + IupSeparator(), + IupItem( "Exit", "app_exit_cb"), + NULL + ); + + Ihandle* menu = IupMenu( + IupSubmenu("File", file_menu), + NULL + ); + + /* this will be used by the dialog */ + IupSetHandle("app_menu", menu); + + IupSetFunction("app_open_cb", (Icallback)app_open_cb); + IupSetFunction("app_exit_cb", (Icallback)app_exit_cb); +} + +void mainDialogCreate(void) +{ + Ihandle *dialog, *box, *canvas; + + /* initialize interface */ + + /* canvas for the image */ + + canvas = IupGLCanvas("app_repaint_cb"); + IupSetAttribute(canvas, "BORDER", "NO"); + IupSetAttribute(canvas, "BUFFER", "DOUBLE"); /* use double buffer */ + IupSetAttribute(canvas, "RESIZE_CB", "app_resize_cb"); /* configure the resize callback */ + + IupSetFunction("app_resize_cb", (Icallback)app_resize_cb); + IupSetFunction("app_repaint_cb", (Icallback)app_repaint_cb); + + /* this is the most external box that puts together + the toolbar, the two canvas and the status bar */ + box = IupSetAttributes(IupHbox( + canvas, + NULL), "MARGIN=10x10"); + + /* create the dialog and set its attributes */ + + mainMenuCreate(); + + dialog = IupDialog(box); + IupSetAttribute(dialog, "MENU", "app_menu"); /* configure the menu */ + IupSetAttribute(dialog, "CLOSE_CB", "app_exit_cb"); + IupSetAttribute(dialog, "TITLE", "IUPGLView"); + IupSetAttribute(dialog, "RASTERSIZE", "680x380"); /* initial size */ + IupSetAttribute(dialog, "SHRINK", "YES"); + IupSetHandle("app_dialog", dialog); + + IupShowXY(dialog, IUP_CENTER, IUP_CENTER); +} + +int main(int argc, char* argv[]) +{ + /* IUP initialization */ + IupOpen(); + IupGLCanvasOpen(); + + /* Create and show the main dialog */ + mainDialogCreate(); + + /* IUP event loop */ + IupMainLoop(); + + /* IUP closing */ + IupClose(); + + return 0; +} -- cgit v1.2.3